diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..13fd0fbd44e0b4247d1d4b0805e264f0b93763a1 --- /dev/null +++ b/.clang-format @@ -0,0 +1,11 @@ +# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting +BasedOnStyle: GNU +AlwaysBreakAfterDefinitionReturnType: All +BreakBeforeBinaryOperators: None +BinPackParameters: false +SpaceAfterCStyleCast: true +# Our column limit is actually 80, but setting that results in clang-format +# making a lot of dubious hanging-indent choices; disable it and assume the +# developer will line wrap appropriately. clang-format will still check +# existing hanging indents. +ColumnLimit: 0 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6b1ad6a7e668165807dd8b2a4696cf6a0f22a4f3..0000000000000000000000000000000000000000 --- a/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -# for all subdirectories -TAGS -tags -.libs -.deps -*.o -*.lo -*.la -*.pc -.*.swp -.sw? -*.rc -*.gcno -*.gcda -*.gcov -*.sourcefiles -*.stp -*.exe -*.def -*.test -*.log -*.trs - -INSTALL -/glib-lcov.info -/glib-lcov/ - -# Meson -/meson-build/ -/subprojects/*/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 0f091e76140446d1dbb0c4a900a285b56c10e5ac..0000000000000000000000000000000000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,355 +0,0 @@ -stages: - - build - - coverage - - analysis - - deploy - -cache: - paths: - - _ccache/ - -variables: - MESON_TEST_TIMEOUT_MULTIPLIER: 2 - G_MESSAGES_DEBUG: all - MESON_COMMON_OPTIONS: "--buildtype debug --fatal-meson-warnings" - -fedora-x86_64: - image: registry.gitlab.gnome.org/gnome/glib/fedora:v3 - stage: build - except: - - tags - variables: - CFLAGS: "-coverage -ftest-coverage -fprofile-arcs" - script: - - meson ${MESON_COMMON_OPTIONS} - --werror - --default-library=both - --prefix=$HOME/glib-installed - --libdir=lib - -Dsystemtap=true - -Ddtrace=true - -Dfam=true - -Dinstalled_tests=true - _build - - ninja -C _build - - mkdir -p _coverage - - lcov --config-file .gitlab-ci/lcovrc --directory _build --capture --initial --output-file "_coverage/${CI_JOB_NAME}-baseline.lcov" - - .gitlab-ci/run-tests.sh - - lcov --config-file .gitlab-ci/lcovrc --directory _build --capture --output-file "_coverage/${CI_JOB_NAME}.lcov" - # FIXME: We should run all installed tests, but do only this one for now - # because it cannot run uninstalled. Reconfigure with dtrace disabled - # because it breaks static link. - - meson configure -Ddtrace=false _build - - ninja -C _build install - - GLIB_TEST_COMPILATION=1 $HOME/glib-installed/libexec/installed-tests/glib/static-link.py $HOME/glib-installed/lib/pkgconfig - artifacts: - reports: - junit: "_build/${CI_JOB_NAME}-report.xml" - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/config.h" - - "_build/glib/glibconfig.h" - - "_build/meson-logs" - - "_build/${CI_JOB_NAME}-report.xml" - - "_coverage" - -debian-stable-x86_64: - image: registry.gitlab.gnome.org/gnome/glib/debian-stable:v3 - stage: build - except: - - tags - script: - - meson ${MESON_COMMON_OPTIONS} - --werror - --default-library=both - --prefix=$HOME/glib-installed - --libdir=lib - -Dsystemtap=true - -Ddtrace=true - -Dfam=true - -Dinstalled_tests=true - _build - - ninja -C _build - - .gitlab-ci/run-tests.sh - artifacts: - reports: - junit: "_build/${CI_JOB_NAME}-report.xml" - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/config.h" - - "_build/glib/glibconfig.h" - - "_build/meson-logs" - - "_build/${CI_JOB_NAME}-report.xml" - -G_DISABLE_ASSERT: - image: registry.gitlab.gnome.org/gnome/glib/fedora:v3 - stage: build - except: - - tags - variables: - CPPFLAGS: "-DG_DISABLE_ASSERT" - script: - - meson ${MESON_COMMON_OPTIONS} - --werror - -Dsystemtap=true - -Ddtrace=true - -Dfam=true - -Dinstalled_tests=true - _build - - ninja -C _build - - bash -x ./.gitlab-ci/run-tests.sh - artifacts: - reports: - junit: "_build/${CI_JOB_NAME}-report.xml" - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/config.h" - - "_build/glib/glibconfig.h" - - "_build/meson-logs" - - "_build/${CI_JOB_NAME}-report.xml" - -valgrind: - image: registry.gitlab.gnome.org/gnome/glib/fedora:v3 - stage: analysis - except: - - tags - variables: - MESON_TEST_TIMEOUT_MULTIPLIER: 10 - script: - - meson ${MESON_COMMON_OPTIONS} - --werror - -Dsystemtap=true - -Ddtrace=true - -Dfam=true - -Dinstalled_tests=true - _build - - ninja -C _build - - bash -x ./.gitlab-ci/run-tests.sh - --log-file _build/meson-logs/testlog-valgrind.json - --wrap "valgrind --tool=memcheck --error-exitcode=1 --track-origins=yes --leak-check=full --leak-resolution=high --num-callers=50 --show-leak-kinds=definite,possible --show-error-list=yes --suppressions=${CI_PROJECT_DIR}/glib.supp" - --no-suite no-valgrind - --no-suite slow - # FIXME: Remove this when we have zero valgrind leaks. - # https://gitlab.gnome.org/GNOME/glib/issues/333 - allow_failure: true - artifacts: - reports: - junit: "_build/${CI_JOB_NAME}-report.xml" - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/config.h" - - "_build/glib/glibconfig.h" - - "_build/meson-logs" - -.cross-template: &cross-template - stage: build - except: - - tags - artifacts: - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/meson-logs" - -cross-android_api21_arm64: - <<: *cross-template - image: registry.gitlab.gnome.org/gnome/glib/android-ndk:v1 - script: - # FIXME: add --werror - # We use -Diconv=auto to test that we successfully detect that iconv is not - # provided by android api 21, and detect the external iconv instead. - - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_21.txt -Diconv=auto -Dinternal_pcre=true _build - - ninja -C _build - -cross-android_api28_arm64: - <<: *cross-template - image: registry.gitlab.gnome.org/gnome/glib/android-ndk:v1 - script: - # FIXME: add --werror - - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_28.txt -Dinternal_pcre=true _build - - ninja -C _build - -cross-mingw64: - <<: *cross-template - image: registry.gitlab.gnome.org/gnome/glib/mingw:v1 - script: - # FIXME: Add --werror - - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_mingw64.txt _build - - ninja -C _build - -msys2-mingw32: - stage: build - except: - - tags - tags: - - win32 - variables: - MSYSTEM: "MINGW32" - CHERE_INVOKING: "yes" - script: - - C:\msys64\usr\bin\pacman --noconfirm -Syyuu --ask 20 - - C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh" - artifacts: - reports: - junit: "_build/%CI_JOB_NAME%-report.xml" - name: "glib-%CI_JOB_NAME%-%CI_COMMIT_REF_NAME%" - when: always - paths: - - _build/meson-logs - - "_build/%CI_JOB_NAME%-report.xml" - - _coverage/ - -vs2017-x64: - stage: build - except: - - tags - tags: - - win32 - script: - - .gitlab-ci/test-msvc.bat - artifacts: - reports: - junit: "_build/%CI_JOB_NAME%-report.xml" - name: "glib-%CI_JOB_NAME%-%CI_COMMIT_REF_NAME%" - when: always - paths: - - _build/meson-logs - - "_build/%CI_JOB_NAME%-report.xml" - -freebsd-11-x86_64: - stage: build - only: - - branches@GNOME/glib - tags: - # To run a FreeBSD builder, install gitlab-runner package and start both - # gitlab-runner and dbus service because we need /var/lib/dbus/machine-id. - # To compile GLib, you still have to install the following packages: - # desktop-file-utils gettext libiconv meson pkgconf python3 shared-mime-info - - freebsd-11 - variables: - # CPPFLAGS is required because libintl doesn't use pkg-config. - CPPFLAGS: -I/usr/local/include - # FIXME: Workaround meson inability to set LD_LIBRARY_PATH. - # https://github.com/mesonbuild/meson/issues/1383 - # https://github.com/mesonbuild/meson/issues/1635 - # https://github.com/mesonbuild/meson/issues/2881 - LDFLAGS: -L/usr/local/lib -Wl,--disable-new-dtags - # FreeBSD doesn't have C.UTF-8 locale. - LANG: en_US.UTF-8 - script: - # We cannot use -Wl,--no-undefined because GLib uses 'environ' variable. - # FreeBSD iconv doesn't handle transliteration, so we use (external) GNU libiconv here. - # FreeBSD supports xattr, but its API is different from Linux xattr. - # FIXME: extattr(2) support: https://gitlab.gnome.org/GNOME/glib/issues/1404 - - meson ${MESON_COMMON_OPTIONS} -Db_lundef=false -Diconv=external -Dxattr=false _build - - ninja -C _build - - bash -x ./.gitlab-ci/run-tests.sh - except: - - tags - artifacts: - reports: - junit: "_build/${CI_JOB_NAME}-report.xml" - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/config.h" - - "_build/glib/glibconfig.h" - - "_build/meson-logs" - - "_build/${CI_JOB_NAME}-report.xml" - -freebsd-12-x86_64: - stage: build - only: - - branches@GNOME/glib - tags: - - freebsd-12 - variables: - CPPFLAGS: -I/usr/local/include - LDFLAGS: -L/usr/local/lib -Wl,--disable-new-dtags - LANG: en_US.UTF-8 - script: - - meson ${MESON_COMMON_OPTIONS} -Db_lundef=false -Diconv=external -Dxattr=false _build - - ninja -C _build - - bash -x ./.gitlab-ci/run-tests.sh - except: - - tags - artifacts: - reports: - junit: "_build/${CI_JOB_NAME}-report.xml" - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_build/config.h" - - "_build/glib/glibconfig.h" - - "_build/meson-logs" - - "_build/${CI_JOB_NAME}-report.xml" - -coverage: - image: registry.gitlab.gnome.org/gnome/glib/fedora:v3 - stage: coverage - except: - - tags - artifacts: - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - paths: - - _coverage/ - script: - - bash -x ./.gitlab-ci/coverage-docker.sh - coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/' - -scan-build: - image: registry.gitlab.gnome.org/gnome/glib/fedora:v3 - stage: analysis - except: - - tags - script: - - meson ${MESON_COMMON_OPTIONS} - --werror - --default-library=both - --prefix=$HOME/glib-installed - --libdir=lib - -Dsystemtap=true - -Ddtrace=true - -Dfam=true - -Dinstalled_tests=true - _scan_build - - ninja -C _scan_build scan-build - artifacts: - name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" - when: always - paths: - - "_scan_build/meson-logs/scanbuild" - -pages: - stage: deploy - only: - - master - script: - - mv _coverage/ public/ - artifacts: - paths: - - public - -dist-job: - image: registry.gitlab.gnome.org/gnome/glib/fedora:v3 - stage: build - only: - - tags - script: - - meson --buildtype release --fatal-meson-warnings -Dgtk_doc=true -Dman=true _build - - cd _build - - ninja dist - - ninja glib-doc gobject-doc gio-doc - - tar -c -f "glib-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/glib html - - tar -c -f "gobject-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/gobject html - - tar -c -f "gio-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/gio html - artifacts: - paths: - - "${CI_PROJECT_DIR}/_build/glib-docs.tar.xz" - - "${CI_PROJECT_DIR}/_build/gobject-docs.tar.xz" - - "${CI_PROJECT_DIR}/_build/gio-docs.tar.xz" - - "${CI_PROJECT_DIR}/_build/meson-dist/glib-*.tar.xz" diff --git a/.gitlab-ci/README.md b/.gitlab-ci/README.md deleted file mode 100644 index dc6c82131568512713d95db5442bf1594b080222..0000000000000000000000000000000000000000 --- a/.gitlab-ci/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# CI support stuff - -## Docker image - -GitLab CI jobs run in a Docker image, defined here. To update that image -(perhaps to install some more packages): - -1. Edit `.gitlab-ci/Dockerfile` with the changes you want -1. Run `.gitlab-ci/run-docker.sh build --base=debian --base-version=1` to build - the new image (bump the version as needed) -1. Run `.gitlab-ci/run-docker.sh push --base=debian --base-version=1` to upload - the new image to the GNOME GitLab Docker registry - * If this is the first time you're doing this, you'll need to log into the - registry - * If you use 2-factor authentication on your GNOME GitLab account, you'll - need to [create a personal access token][pat] and use that rather than - your normal password -1. Edit `.gitlab-ci.yml` (in the root of this repository) to use your new - image - -[pat]: https://gitlab.gnome.org/profile/personal_access_tokens diff --git a/.gitlab-ci/android-download-ndk.sh b/.gitlab-ci/android-download-ndk.sh deleted file mode 100755 index 785ee0189bdf4043a10d18f3e493dbd592a4053c..0000000000000000000000000000000000000000 --- a/.gitlab-ci/android-download-ndk.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# -# Copyright 2018 Collabora ltd. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# -# Author: Xavier Claessens -# - -set -e - -# Download Android NDK -ANDROID_NDK_VERSION="r17b" -ANDROID_NDK_SHA512="062fac12f747730f5563995089a8b4abab683fbbc621aa8582fdf35fe327daee5d69ed2437af257c10ec4ef54ecd3805a8f134a1400eb8f34ee76f55c8dc9ae9" -wget --quiet https://dl.google.com/android/repository/android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip -echo "$ANDROID_NDK_SHA512 android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip" | sha512sum -c -unzip android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip -rm android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip -mv android-ndk-$ANDROID_NDK_VERSION $ANDROID_NDK_PATH diff --git a/.gitlab-ci/android-ndk.Dockerfile b/.gitlab-ci/android-ndk.Dockerfile deleted file mode 100644 index 9d85a9dfb56dfb98c3cc22b21f1ee16b67a5ac21..0000000000000000000000000000000000000000 --- a/.gitlab-ci/android-ndk.Dockerfile +++ /dev/null @@ -1,75 +0,0 @@ -FROM fedora:28 - -RUN dnf -y install \ - autoconf \ - automake \ - bindfs \ - clang \ - clang-analyzer \ - desktop-file-utils \ - elfutils-libelf-devel \ - findutils \ - fuse \ - gamin-devel \ - gcc \ - gcc-c++ \ - gettext \ - git \ - glibc-devel \ - glibc-headers \ - glibc-langpack-de \ - glibc-langpack-el \ - glibc-langpack-el \ - glibc-langpack-en \ - glibc-langpack-es \ - glibc-langpack-es \ - glibc-langpack-fa \ - glibc-langpack-fr \ - glibc-langpack-hr \ - glibc-langpack-ja \ - glibc-langpack-lt \ - glibc-langpack-pl \ - glibc-langpack-ru \ - glibc-langpack-tr \ - gtk-doc \ - itstool \ - lcov \ - libattr-devel \ - libffi-devel \ - libmount-devel \ - libselinux-devel \ - libtool \ - libxslt \ - make \ - ncurses-compat-libs \ - ninja-build \ - pcre-devel \ - python3 \ - python3-pip \ - python3-wheel \ - systemtap-sdt-devel \ - unzip \ - wget \ - xz \ - zlib-devel \ - && dnf clean all - -WORKDIR /opt -ENV ANDROID_NDK_PATH /opt/android-ndk -COPY android-download-ndk.sh . -RUN ./android-download-ndk.sh -COPY android-setup-env.sh . -RUN ./android-setup-env.sh arm64 21 -RUN ./android-setup-env.sh arm64 28 -RUN rm -rf $ANDROID_NDK_PATH - -RUN pip3 install meson==0.49.2 - -ARG HOST_USER_ID=5555 -ENV HOST_USER_ID ${HOST_USER_ID} -RUN useradd -u $HOST_USER_ID -ms /bin/bash user - -USER user -WORKDIR /home/user - -ENV LANG C.UTF-8 diff --git a/.gitlab-ci/android-setup-env.sh b/.gitlab-ci/android-setup-env.sh deleted file mode 100755 index 510056f667b76a751d1c457f4ba43951b43d74a2..0000000000000000000000000000000000000000 --- a/.gitlab-ci/android-setup-env.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash - -# -# Copyright 2018 Collabora ltd. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# -# Author: Xavier Claessens -# - -set -e - -arch=$1 -api=$2 -toolchain_path=$(pwd)/android-toolchain-$arch-$api -prefix_path=$(pwd)/android-$arch-$api - -# Create standalone toolchains -$ANDROID_NDK_PATH/build/tools/make_standalone_toolchain.py --arch $arch --api $api --install-dir $toolchain_path - -target_host=aarch64-linux-android -export AR=$target_host-ar -export AS=$target_host-clang -export CC=$target_host-clang -export CXX=$target_host-clang++ -export LD=$target_host-ld -export STRIP=$target_host-strip -export PATH=$PATH:$toolchain_path/bin - -# Cross build libiconv when using API level <= 28. -# Newer Android has it in its libc already. -if [ "$api" -lt "28" ]; then - wget --quiet http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz - echo "1233fe3ca09341b53354fd4bfe342a7589181145a1232c9919583a8c9979636855839049f3406f253a9d9829908816bb71fd6d34dd544ba290d6f04251376b1a libiconv-1.15.tar.gz" | sha512sum -c - tar xzf libiconv-1.15.tar.gz - pushd libiconv-1.15 - ./configure --host=$target_host --prefix=$prefix_path --libdir=$prefix_path/lib64 - make - make install - popd - rm libiconv-1.15.tar.gz - rm -r libiconv-1.15 -fi - -# Cross build libffi -wget --quiet https://github.com/libffi/libffi/releases/download/v3.3-rc0/libffi-3.3-rc0.tar.gz -echo "e6e695d32cd6eb7d65983f32986fccdfc786a593d2ea18af30ce741f58cfa1eb264b1a8d09df5084cb916001aea15187b005c2149a0620a44397a4453b6137d4 libffi-3.3-rc0.tar.gz" | sha512sum -c -tar xzf libffi-3.3-rc0.tar.gz -pushd libffi-3.3-rc0 -./configure --host=$target_host --prefix=$prefix_path --libdir=$prefix_path/lib64 -make -make install -popd -rm libffi-3.3-rc0.tar.gz -rm -r libffi-3.3-rc0 - -# Create a pkg-config wrapper that won't pick fedora libraries -mkdir -p $prefix_path/bin -export PKG_CONFIG=$prefix_path/bin/pkg-config -cat > $PKG_CONFIG <<- EOM -#!/bin/sh -SYSROOT=${prefix_path} -export PKG_CONFIG_DIR= -export PKG_CONFIG_LIBDIR=\${SYSROOT}/lib64/pkgconfig -export PKG_CONFIG_SYSROOT_DIR=\${SYSROOT} -exec pkg-config "\$@" -EOM -chmod +x $PKG_CONFIG - -# Create a cross file that can be passed to meson -cat > cross_file_android_${arch}_${api}.txt <<- EOM -[host_machine] -system = 'android' -cpu_family = 'arm64' -cpu = 'arm64' -endian = 'little' - -[properties] -c_args = ['-I${prefix_path}/include'] -c_link_args = ['-L${prefix_path}/lib64', - '-fuse-ld=gold'] - -[binaries] -c = '${toolchain_path}/bin/${CC}' -cpp = '${toolchain_path}/bin/${CXX}' -ar = '${toolchain_path}/bin/${AR}' -strip = '${toolchain_path}/bin/${STRIP}' -pkgconfig = '${PKG_CONFIG}' -EOM diff --git a/.gitlab-ci/coverage-docker.sh b/.gitlab-ci/coverage-docker.sh deleted file mode 100755 index b6421be862d439e9f89c1f1dad8b1142f3a74457..0000000000000000000000000000000000000000 --- a/.gitlab-ci/coverage-docker.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -set -e - -# Fixup Windows paths -python3 ./.gitlab-ci/fixup-cov-paths.py _coverage/*.lcov - -for path in _coverage/*.lcov; do - # Remove coverage from generated code in the build directory - lcov --config-file .gitlab-ci/lcovrc -r "${path}" '*/_build/*' -o "$(pwd)/${path}" - # Remove any coverage from system files - lcov --config-file .gitlab-ci/lcovrc -e "${path}" "$(pwd)/*" -o "$(pwd)/${path}" -done - -genhtml \ - --ignore-errors=source \ - --config-file .gitlab-ci/lcovrc \ - _coverage/*.lcov \ - -o _coverage/coverage - -cd _coverage -rm -f *.lcov - -cat >index.html < - - - - -EOL diff --git a/.gitlab-ci/cross_file_mingw64.txt b/.gitlab-ci/cross_file_mingw64.txt deleted file mode 100644 index 1029b6db15014a6c7d2309f8b39528647fc18a52..0000000000000000000000000000000000000000 --- a/.gitlab-ci/cross_file_mingw64.txt +++ /dev/null @@ -1,18 +0,0 @@ -[host_machine] -system = 'windows' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' - -[properties] -c_args = [] -c_link_args = [] - -[binaries] -c = 'x86_64-w64-mingw32-gcc' -cpp = 'x86_64-w64-mingw32-g++' -ar = 'x86_64-w64-mingw32-ar' -objcopy = 'x86_64-w64-mingw32-objcopy' -strip = 'x86_64-w64-mingw32-strip' -pkgconfig = 'x86_64-w64-mingw32-pkg-config' -windres = 'x86_64-w64-mingw32-windres' diff --git a/.gitlab-ci/debian-stable.Dockerfile b/.gitlab-ci/debian-stable.Dockerfile deleted file mode 100644 index faaaae0393b1af4b064676b31ca307100ad60156..0000000000000000000000000000000000000000 --- a/.gitlab-ci/debian-stable.Dockerfile +++ /dev/null @@ -1,73 +0,0 @@ -FROM debian:buster - -RUN apt-get update -qq && apt-get install --no-install-recommends -qq -y \ - bindfs \ - clang \ - clang-tools-7 \ - dbus \ - desktop-file-utils \ - elfutils \ - findutils \ - fuse \ - gcc \ - g++ \ - gettext \ - git \ - libc6-dev \ - gtk-doc-tools \ - itstool \ - lcov \ - libattr1-dev \ - libelf-dev \ - libffi-dev \ - libgamin-dev \ - libmount-dev \ - libpcre2-dev \ - libselinux1-dev \ - libxml2-utils \ - libxslt1-dev \ - libz3-dev \ - locales \ - ninja-build \ - python3 \ - python3-pip \ - python3-setuptools \ - python3-wheel \ - shared-mime-info \ - systemtap-sdt-dev \ - unzip \ - wget \ - xsltproc \ - xz-utils \ - zlib1g-dev \ - && rm -rf /usr/share/doc/* /usr/share/man/* - -# Locale for our build -RUN locale-gen C.UTF-8 && /usr/sbin/update-locale LANG=C.UTF-8 - -# Locales for our tests -RUN locale-gen de_DE.UTF-8 \ - && locale-gen el_GR.UTF-8 \ - && locale-gen en_US.UTF-8 \ - && locale-gen es_ES.UTF-8 \ - && locale-gen fa_IR.UTF-8 \ - && locale-gen fr_FR.UTF-8 \ - && locale-gen hr_HR.UTF-8 \ - && locale-gen ja_JP.UTF-8 \ - && locale-gen lt_LT.UTF-8 \ - && locale-gen pl_PL.UTF-8 \ - && locale-gen ru_RU.UTF-8 \ - && locale-gen tr_TR.UTF-8 - -ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 - -RUN pip3 install meson==0.49.2 - -ARG HOST_USER_ID=5555 -ENV HOST_USER_ID ${HOST_USER_ID} -RUN useradd -u $HOST_USER_ID -ms /bin/bash user - -USER user -WORKDIR /home/user - -ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 diff --git a/.gitlab-ci/fedora.Dockerfile b/.gitlab-ci/fedora.Dockerfile deleted file mode 100644 index 9b01ccf0038542f7b194964544ad9a38e5c0bf8b..0000000000000000000000000000000000000000 --- a/.gitlab-ci/fedora.Dockerfile +++ /dev/null @@ -1,65 +0,0 @@ -FROM fedora:29 - -RUN dnf -y install \ - bindfs \ - clang \ - clang-analyzer \ - dbus-daemon \ - desktop-file-utils \ - elfutils-libelf-devel \ - findutils \ - fuse \ - gamin-devel \ - gcc \ - gcc-c++ \ - gettext \ - git \ - glibc-devel \ - glibc-headers \ - glibc-langpack-de \ - glibc-langpack-el \ - glibc-langpack-el \ - glibc-langpack-en \ - glibc-langpack-es \ - glibc-langpack-es \ - glibc-langpack-fa \ - glibc-langpack-fr \ - glibc-langpack-hr \ - glibc-langpack-ja \ - glibc-langpack-lt \ - glibc-langpack-pl \ - glibc-langpack-ru \ - glibc-langpack-tr \ - gtk-doc \ - itstool \ - lcov \ - libattr-devel \ - libffi-devel \ - libmount-devel \ - libselinux-devel \ - libxslt \ - ncurses-compat-libs \ - ninja-build \ - pcre-devel \ - python3 \ - python3-pip \ - python3-wheel \ - shared-mime-info \ - systemtap-sdt-devel \ - unzip \ - valgrind \ - wget \ - xz \ - zlib-devel \ - && dnf clean all - -RUN pip3 install meson==0.49.2 - -ARG HOST_USER_ID=5555 -ENV HOST_USER_ID ${HOST_USER_ID} -RUN useradd -u $HOST_USER_ID -ms /bin/bash user - -USER user -WORKDIR /home/user - -ENV LANG C.UTF-8 diff --git a/.gitlab-ci/fixup-cov-paths.py b/.gitlab-ci/fixup-cov-paths.py deleted file mode 100644 index d614b60e626bda5fa7d9290c2f2565a995e24cf2..0000000000000000000000000000000000000000 --- a/.gitlab-ci/fixup-cov-paths.py +++ /dev/null @@ -1,29 +0,0 @@ -import sys -import os -import io - - -def main(argv): - # Fix paths in lcov files generated on a Windows host so they match our - # current source layout. - paths = argv[1:] - - for path in paths: - print("cov-fixup:", path) - text = io.open(path, "r", encoding="utf-8").read() - text = text.replace("\\\\", "/") - glib_dir = "/glib/" - end = text.index(glib_dir) - start = text[:end].rindex(":") + 1 - old_root = text[start:end] - assert os.path.basename(os.getcwd()) == "glib" - new_root = os.path.dirname(os.getcwd()) - if old_root != new_root: - print("replacing %r with %r" % (old_root, new_root)) - text = text.replace(old_root, new_root) - with io.open(path, "w", encoding="utf-8") as h: - h.write(text) - - -if __name__ == "__main__": - sys.exit(main(sys.argv)) diff --git a/.gitlab-ci/lcovrc b/.gitlab-ci/lcovrc deleted file mode 100644 index 3901f81e735ed0c1e7bf2ba5c8fff7562aa39204..0000000000000000000000000000000000000000 --- a/.gitlab-ci/lcovrc +++ /dev/null @@ -1,13 +0,0 @@ -# lcov and genhtml configuration -# See http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php - -# Always enable branch coverage -lcov_branch_coverage = 1 - -# Exclude precondition assertions, as we can never reasonably get full branch -# coverage of them, as they should never normally fail. -# See https://github.com/linux-test-project/lcov/issues/44 -lcov_excl_br_line = LCOV_EXCL_BR_LINE|g_return_if_fail|g_return_val_if_fail|g_assert|g_assert_ - -# Similarly for unreachable assertions. -lcov_excl_line = LCOV_EXCL_LINE|g_return_if_reached|g_return_val_if_reached|g_assert_not_reached \ No newline at end of file diff --git a/.gitlab-ci/meson-junit-report.py b/.gitlab-ci/meson-junit-report.py deleted file mode 100755 index 0df07271b5f14e4d5db6b2a51929e268d1aa85e7..0000000000000000000000000000000000000000 --- a/.gitlab-ci/meson-junit-report.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python3 - -# Turns a Meson testlog.json file into a JUnit XML report -# -# Copyright 2019 GNOME Foundation -# -# SPDX-License-Identifier: LGPL-2.1-or-later -# -# Original author: Emmanuele Bassi - -import argparse -import datetime -import json -import os -import sys -import xml.etree.ElementTree as ET - -aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report') -aparser.add_argument('--project-name', metavar='NAME', - help='The project name', - default='unknown') -aparser.add_argument('--job-id', metavar='ID', - help='The job ID for the report', - default='Unknown') -aparser.add_argument('--branch', metavar='NAME', - help='Branch of the project being tested', - default='master') -aparser.add_argument('--output', metavar='FILE', - help='The output file, stdout by default', - type=argparse.FileType('w', encoding='UTF-8'), - default=sys.stdout) -aparser.add_argument('infile', metavar='FILE', - help='The input testlog.json, stdin by default', - type=argparse.FileType('r', encoding='UTF-8'), - default=sys.stdin) - -args = aparser.parse_args() - -outfile = args.output - -testsuites = ET.Element('testsuites') -testsuites.set('id', '{}/{}'.format(args.job_id, args.branch)) -testsuites.set('package', args.project_name) -testsuites.set('timestamp', datetime.datetime.utcnow().isoformat()) - -suites = {} -for line in args.infile: - data = json.loads(line) - (full_suite, unit_name) = data['name'].split(' / ') - (project_name, suite_name) = full_suite.split(':') - - duration = data['duration'] - return_code = data['returncode'] - log = data['stdout'] - log_stderr = data.get('stderr', '') - - unit = { - 'suite': suite_name, - 'name': unit_name, - 'duration': duration, - 'returncode': return_code, - 'stdout': log, - 'stderr': log_stderr, - } - - units = suites.setdefault(suite_name, []) - units.append(unit) - -for name, units in suites.items(): - print('Processing suite {} (units: {})'.format(name, len(units))) - - def if_failed(unit): - if unit['returncode'] != 0: - return True - return False - - def if_succeded(unit): - if unit['returncode'] == 0: - return True - return False - - successes = list(filter(if_succeded, units)) - failures = list(filter(if_failed, units)) - print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures))) - - testsuite = ET.SubElement(testsuites, 'testsuite') - testsuite.set('name', '{}/{}'.format(args.project_name, name)) - testsuite.set('tests', str(len(units))) - testsuite.set('errors', str(len(failures))) - testsuite.set('failures', str(len(failures))) - - for unit in successes: - testcase = ET.SubElement(testsuite, 'testcase') - testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite'])) - testcase.set('name', unit['name']) - testcase.set('time', str(unit['duration'])) - - for unit in failures: - testcase = ET.SubElement(testsuite, 'testcase') - testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite'])) - testcase.set('name', unit['name']) - testcase.set('time', str(unit['duration'])) - - failure = ET.SubElement(testcase, 'failure') - failure.set('classname', '{}/{}'.format(args.project_name, unit['suite'])) - failure.set('name', unit['name']) - failure.set('type', 'error') - failure.text = unit['stdout'] + '\n' + unit['stderr'] - -output = ET.tostring(testsuites, encoding='unicode') -outfile.write(output) diff --git a/.gitlab-ci/mingw.Dockerfile b/.gitlab-ci/mingw.Dockerfile deleted file mode 100644 index 19a061a1c40ff0def29c7f93198cc5c4ec080e6d..0000000000000000000000000000000000000000 --- a/.gitlab-ci/mingw.Dockerfile +++ /dev/null @@ -1,70 +0,0 @@ -FROM fedora:29 - -RUN dnf -y install \ - bindfs \ - clang \ - clang-analyzer \ - desktop-file-utils \ - elfutils-libelf-devel \ - findutils \ - fuse \ - gamin-devel \ - gcc \ - gcc-c++ \ - gettext \ - git \ - glibc-devel \ - glibc-headers \ - glibc-langpack-de \ - glibc-langpack-el \ - glibc-langpack-el \ - glibc-langpack-en \ - glibc-langpack-es \ - glibc-langpack-es \ - glibc-langpack-fa \ - glibc-langpack-fr \ - glibc-langpack-hr \ - glibc-langpack-ja \ - glibc-langpack-lt \ - glibc-langpack-pl \ - glibc-langpack-ru \ - glibc-langpack-tr \ - gtk-doc \ - itstool \ - lcov \ - libattr-devel \ - libffi-devel \ - libmount-devel \ - libselinux-devel \ - libxslt \ - mingw64-gcc \ - mingw64-gcc-c++ \ - mingw64-gettext \ - mingw64-libffi \ - mingw64-zlib \ - ncurses-compat-libs \ - ninja-build \ - pcre-devel \ - python3 \ - python3-pip \ - python3-wheel \ - systemtap-sdt-devel \ - unzip \ - wget \ - xz \ - zlib-devel \ - && dnf clean all - -WORKDIR /opt -COPY cross_file_mingw64.txt /opt - -RUN pip3 install meson==0.49.2 - -ARG HOST_USER_ID=5555 -ENV HOST_USER_ID ${HOST_USER_ID} -RUN useradd -u $HOST_USER_ID -ms /bin/bash user - -USER user -WORKDIR /home/user - -ENV LANG C.UTF-8 diff --git a/.gitlab-ci/run-docker.sh b/.gitlab-ci/run-docker.sh deleted file mode 100755 index 2f2693bc704f182dae27382f729a23dd9aa0c34a..0000000000000000000000000000000000000000 --- a/.gitlab-ci/run-docker.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/bash - -read_arg() { - # $1 = arg name - # $2 = arg value - # $3 = arg parameter - local rematch='^[^=]*=(.*)$' - if [[ $2 =~ $rematch ]]; then - read "$1" <<< "${BASH_REMATCH[1]}" - else - read "$1" <<< "$3" - # There is no way to shift our callers args, so - # return 1 to indicate they should do it instead. - return 1 - fi -} - -set -e - -build=0 -run=0 -push=0 -list=0 -print_help=0 -no_login=0 - -while (($# > 0)); do - case "${1%%=*}" in - build) build=1;; - run) run=1;; - push) push=1;; - list) list=1;; - help) print_help=1;; - --base|-b) read_arg base "$@" || shift;; - --base-version) read_arg base_version "$@" || shift;; - --no-login) no_login=1;; - *) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;; - esac - shift -done - -if [ $print_help == 1 ]; then - echo "$0 - Build and run Docker images" - echo "" - echo "Usage: $0 [options] [basename]" - echo "" - echo "Available commands" - echo "" - echo " build --base= - Build Docker image .Dockerfile" - echo " run --base= - Run Docker image " - echo " push --base= - Push Docker image to the registry" - echo " list - List available images" - echo " help - This help message" - echo "" - exit 0 -fi - -cd "$(dirname "$0")" - -if [ $list == 1 ]; then - echo "Available Docker images:" - for f in *.Dockerfile; do - filename=$( basename -- "$f" ) - basename="${filename%.*}" - - echo -e " \e[1;39m$basename\e[0m" - done - exit 0 -fi - -# All commands after this require --base to be set -if [ -z $base ]; then - echo "Usage: $0 " - exit 1 -fi - -if [ ! -f "$base.Dockerfile" ]; then - echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found" - exit 1 -fi - -if [ -z $base_version ]; then - base_version="latest" -else - base_version="v$base_version" -fi - -TAG="registry.gitlab.gnome.org/gnome/glib/${base}:${base_version}" - -if [ $build == 1 ]; then - echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}" - sudo docker build \ - --build-arg HOST_USER_ID="$UID" \ - --tag "${TAG}" \ - --file "${base}.Dockerfile" . - exit $? -fi - -if [ $push == 1 ]; then - echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}" - - if [ $no_login == 0 ]; then - sudo docker login registry.gitlab.gnome.org - fi - - sudo docker push $TAG - exit $? -fi - -if [ $run == 1 ]; then - echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}" - sudo docker run \ - --rm \ - --volume "$(pwd)/..:/home/user/app" \ - --workdir "/home/user/app" \ - --tty \ - --interactive "${TAG}" \ - bash - exit $? -fi diff --git a/.gitlab-ci/run-tests.sh b/.gitlab-ci/run-tests.sh deleted file mode 100755 index 539726e9a5bbf2e085e6d22bc472fa994fc4fbdd..0000000000000000000000000000000000000000 --- a/.gitlab-ci/run-tests.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -set +e - -case "$1" in - --log-file) - log_file="$2" - shift - shift - ;; - *) - log_file="_build/meson-logs/testlog.json" -esac - -meson test \ - -C _build \ - --timeout-multiplier ${MESON_TEST_TIMEOUT_MULTIPLIER} \ - --no-suite flaky \ - "$@" - -exit_code=$? - -python3 .gitlab-ci/meson-junit-report.py \ - --project-name=glib \ - --job-id "${CI_JOB_NAME}" \ - --output "_build/${CI_JOB_NAME}-report.xml" \ - "${log_file}" - -exit $exit_code diff --git a/.gitlab-ci/test-msvc.bat b/.gitlab-ci/test-msvc.bat deleted file mode 100644 index ea1870eab603448f286ccf46818fac718dea244f..0000000000000000000000000000000000000000 --- a/.gitlab-ci/test-msvc.bat +++ /dev/null @@ -1,24 +0,0 @@ -@echo on -:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the -:: specified build architecture -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 -@echo on - -:: FIXME: make warnings fatal -pip3 install --upgrade --user meson==0.49.2 || goto :error -meson _build || goto :error -ninja -C _build || goto :error - -:: FIXME: dont ignore test errors -meson test -C _build --timeout-multiplier %MESON_TEST_TIMEOUT_MULTIPLIER% --no-suite flaky - -:: FIXME: can we get code coverage support? - - -python "%CD%\.gitlab-ci\meson-junit-report.py" --project-name glib ^ ---job-id "%CI_JOB_NAME%" --output "%CD%/_build/%CI_JOB_NAME%-report.xml" ^ -"%CD%/_build/meson-logs/testlog.json" - -goto :EOF -:error -exit /b 1 diff --git a/.gitlab-ci/test-msys2.sh b/.gitlab-ci/test-msys2.sh deleted file mode 100755 index 34953d545f2d0dfc61ffdfb660b3344d7e286d36..0000000000000000000000000000000000000000 --- a/.gitlab-ci/test-msys2.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash - -set -e - -export PATH="/c/msys64/$MSYSTEM/bin:$PATH" -if [[ "$MSYSTEM" == "MINGW32" ]]; then - export MSYS2_ARCH="i686" -else - export MSYS2_ARCH="x86_64" -fi - -pacman --noconfirm -Suy - -pacman --noconfirm -S --needed \ - base-devel \ - mingw-w64-$MSYS2_ARCH-ccache \ - mingw-w64-$MSYS2_ARCH-gettext \ - mingw-w64-$MSYS2_ARCH-libffi \ - mingw-w64-$MSYS2_ARCH-meson \ - mingw-w64-$MSYS2_ARCH-pcre \ - mingw-w64-$MSYS2_ARCH-python3 \ - mingw-w64-$MSYS2_ARCH-python3-pip \ - mingw-w64-$MSYS2_ARCH-toolchain \ - mingw-w64-$MSYS2_ARCH-zlib \ - mingw-w64-$MSYS2_ARCH-libelf - -curl -O -J -L "https://github.com/linux-test-project/lcov/releases/download/v1.14/lcov-1.14.tar.gz" -echo "14995699187440e0ae4da57fe3a64adc0a3c5cf14feab971f8db38fb7d8f071a lcov-1.14.tar.gz" | sha256sum -c -tar -xzf lcov-1.14.tar.gz -LCOV="$(pwd)/lcov-1.14/bin/lcov" - -mkdir -p _coverage -mkdir -p _ccache -export CCACHE_BASEDIR="$(pwd)" -export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" -pip3 install --upgrade --user meson==0.49.2 -export PATH="$HOME/.local/bin:$PATH" -export CFLAGS="-coverage -ftest-coverage -fprofile-arcs" -DIR="$(pwd)" - -meson --werror --buildtype debug _build -cd _build -ninja - -# FIXME: lcov doesn't support gcc9 yet: -# https://github.com/linux-test-project/lcov/issues/58 -#"${LCOV}" \ -# --quiet \ -# --config-file "${DIR}"/.gitlab-ci/lcovrc \ -# --directory "${DIR}/_build" \ -# --capture \ -# --initial \ -# --output-file "${DIR}/_coverage/${CI_JOB_NAME}-baseline.lcov" - -# FIXME: fix the test suite -meson test --timeout-multiplier ${MESON_TEST_TIMEOUT_MULTIPLIER} --no-suite flaky || true - -python3 "${DIR}"/.gitlab-ci/meson-junit-report.py \ - --project-name glib \ - --job-id "${CI_JOB_NAME}" \ - --output "${DIR}/_build/${CI_JOB_NAME}-report.xml" \ - "${DIR}/_build/meson-logs/testlog.json" - -# FIXME: see above -#"${LCOV}" \ -# --quiet \ -# --config-file "${DIR}"/.gitlab-ci/lcovrc \ -# --directory "${DIR}/_build" \ -# --capture \ -# --output-file "${DIR}/_coverage/${CI_JOB_NAME}.lcov" diff --git a/BUILD.gn b/BUILD.gn old mode 100644 new mode 100755 index ce99e34a58486d486e94aa2f105924656bb1777a..c3c29b11a084e12e630ced9c3ea8d271e054ce56 --- a/BUILD.gn +++ b/BUILD.gn @@ -21,6 +21,7 @@ config("glib_config") { "glib/pcre", "glib", "glib/deprecated", + "//third_party/gettext/gettext-runtime/intl", ] cflags = [ "-DG_LOG_DOMAIN=\"GLib\"", @@ -121,6 +122,7 @@ ohos_source_set("glib_source") { "glib/gthreadpool.c", "glib/gtimer.c", "glib/gtimezone.c", + "glib/gtrace.c", "glib/gtranslit.c", "glib/gtrashstack.c", "glib/gtree.c", @@ -128,7 +130,7 @@ ohos_source_set("glib_source") { "glib/gunicollate.c", "glib/gunidecomp.c", "glib/guniprop.c", - "glib/gurifuncs.c", + "glib/guri.c", "glib/gutf8.c", "glib/gutils.c", "glib/gutilsprivate.h", @@ -165,7 +167,10 @@ ohos_source_set("glib_source") { configs = [ ":glib_config" ] } ohos_shared_library("glib") { - deps = [ ":glib_source" ] + deps = [ + ":glib_source", + "//third_party/gettext:libintl", + ] part_name = "multimedia_media_standard" subsystem_name = "multimedia" } @@ -201,6 +206,7 @@ config("gobject_config") { "gobject", "glib", "//third_party/libffi/include", + "//third_party/gettext/gettext-runtime/intl", ] cflags = [ "-DG_LOG_DOMAIN=\"GObject\"", @@ -240,6 +246,7 @@ ohos_shared_library("gobject") { deps = [ ":glib", ":gobject_source", + "//third_party/gettext:libintl", "//third_party/libffi:ffi", ] part_name = "multimedia_media_standard" @@ -271,6 +278,7 @@ config("gio_config") { "-Wno-int-conversion", "-DGIO_COMPILATION", "-DGIO_MODULE_DIR=\"\"", + "-DLOCALSTATEDIR=\"var\"", "-Wno-implicit-function-declaration", "-Wno-format", "-Wno-conditional-type-mismatch", @@ -286,35 +294,38 @@ config("gio_config") { ohos_source_set("gio_source") { sources = [ + # application_sources "gio/gaction.c", "gio/gactiongroup.c", "gio/gactiongroupexporter.c", "gio/gactionmap.c", - "gio/gappinfo.c", "gio/gapplication.c", "gio/gapplicationcommandline.c", "gio/gapplicationimpl-dbus.c", - - #"gio/gapplication-tool.c", - "gio/gasynchelper.c", - "gio/gasyncinitable.c", - "gio/gasyncresult.c", - "gio/gbufferedinputstream.c", - "gio/gbufferedoutputstream.c", - "gio/gbytesicon.c", - "gio/gcancellable.c", - "gio/gcharsetconverter.c", - "gio/gcontenttype.c", - "gio/gcontextspecificgroup.c", - "gio/gconverter.c", - "gio/gconverterinputstream.c", - "gio/gconverteroutputstream.c", - "gio/gcredentials.c", - "gio/gdatagrambased.c", - "gio/gdatainputstream.c", - "gio/gdataoutputstream.c", - "gio/gdbus-daemon-generated.c", "gio/gdbusactiongroup.c", + "gio/gdbusmenumodel.c", + "gio/gmenu.c", + "gio/gmenuexporter.c", + "gio/gmenumodel.c", + "gio/gnotification.c", + "gio/gnotificationbackend.c", + "gio/gpropertyaction.c", + "gio/gremoteactiongroup.c", + "gio/gsimpleaction.c", + "gio/gsimpleactiongroup.c", + + # settings_sources + "gio/gdelayedsettingsbackend.c", + "gio/gkeyfilesettingsbackend.c", + "gio/gmemorysettingsbackend.c", + "gio/gnullsettingsbackend.c", + "gio/gsettings-mapping.c", + "gio/gsettings.c", + "gio/gsettingsbackend.c", + "gio/gsettingsschema.c", + "gio/gvdb/gvdb-reader.c", + + # gdbus_sources "gio/gdbusaddress.c", "gio/gdbusauth.c", "gio/gdbusauthmechanism.c", @@ -323,12 +334,10 @@ ohos_source_set("gio_source") { "gio/gdbusauthmechanismsha1.c", "gio/gdbusauthobserver.c", "gio/gdbusconnection.c", - "gio/gdbusdaemon.c", "gio/gdbuserror.c", "gio/gdbusinterface.c", "gio/gdbusinterfaceskeleton.c", "gio/gdbusintrospection.c", - "gio/gdbusmenumodel.c", "gio/gdbusmessage.c", "gio/gdbusmethodinvocation.c", "gio/gdbusnameowning.c", @@ -342,12 +351,82 @@ ohos_source_set("gio_source") { "gio/gdbusprivate.c", "gio/gdbusproxy.c", "gio/gdbusserver.c", - - #"gio/gdbus-tool.c", "gio/gdbusutils.c", - "gio/gdelayedsettingsbackend.c", - "gio/gdesktopappinfo.c", + "gio/gtestdbus.c", + + # portal_sources "gio/gdocumentportal.c", + "gio/gmemorymonitorportal.c", + "gio/gnetworkmonitorportal.c", + "gio/gopenuriportal.c", + "gio/gportalnotificationbackend.c", + "gio/gportalsupport.c", + "gio/gproxyresolverportal.c", + "gio/gtrashportal.c", + + # local_sources + "gio/ghttpproxy.c", + "gio/glocalfile.c", + "gio/glocalfileenumerator.c", + "gio/glocalfileinfo.c", + "gio/glocalfileinputstream.c", + "gio/glocalfileiostream.c", + "gio/glocalfilemonitor.c", + "gio/glocalfileoutputstream.c", + "gio/glocalvfs.c", + "gio/gsocks4aproxy.c", + "gio/gsocks4proxy.c", + "gio/gsocks5proxy.c", + "gio/thumbnail-verify.c", + + # unix_sources + HAVE_NETLINK + "gio/gnetworkmonitornetlink.c", + "gio/gnetworkmonitornm.c", + + # unix_sources + "gio/gfdonotificationbackend.c", + "gio/gfiledescriptorbased.c", + "gio/ggtknotificationbackend.c", + "gio/giounix-private.c", + "gio/gunixconnection.c", + "gio/gunixcredentialsmessage.c", + "gio/gunixfdlist.c", + "gio/gunixfdmessage.c", + "gio/gunixinputstream.c", + "gio/gunixmount.c", + "gio/gunixmounts.c", + "gio/gunixoutputstream.c", + "gio/gunixsocketaddress.c", + "gio/gunixvolume.c", + "gio/gunixvolumemonitor.c", + + # appinfo_sources + "gio/gdesktopappinfo.c", + + # contenttype_sources + "gio/gcontenttype.c", + + # gdbus_daemon_sources + "gio/gdbusdaemon.c", + + # gio_sources + "gio/gappinfo.c", + "gio/gasynchelper.c", + "gio/gasyncinitable.c", + "gio/gasyncresult.c", + "gio/gbufferedinputstream.c", + "gio/gbufferedoutputstream.c", + "gio/gbytesicon.c", + "gio/gcancellable.c", + "gio/gcharsetconverter.c", + "gio/gcontextspecificgroup.c", + "gio/gconverter.c", + "gio/gconverterinputstream.c", + "gio/gconverteroutputstream.c", + "gio/gcredentials.c", + "gio/gdatagrambased.c", + "gio/gdatainputstream.c", + "gio/gdataoutputstream.c", "gio/gdrive.c", "gio/gdtlsclientconnection.c", "gio/gdtlsconnection.c", @@ -357,10 +436,8 @@ ohos_source_set("gio_source") { "gio/gdummytlsbackend.c", "gio/gemblem.c", "gio/gemblemedicon.c", - "gio/gfdonotificationbackend.c", "gio/gfile.c", "gio/gfileattribute.c", - "gio/gfiledescriptorbased.c", "gio/gfileenumerator.c", "gio/gfileicon.c", "gio/gfileinfo.c", @@ -371,64 +448,25 @@ ohos_source_set("gio_source") { "gio/gfileoutputstream.c", "gio/gfilterinputstream.c", "gio/gfilteroutputstream.c", - "gio/ggtknotificationbackend.c", - "gio/ghttpproxy.c", "gio/gicon.c", "gio/ginetaddress.c", "gio/ginetaddressmask.c", "gio/ginetsocketaddress.c", "gio/ginitable.c", "gio/ginputstream.c", - "gio/gioenumtypes.c", "gio/gioerror.c", "gio/giomodule-priv.c", - - #"gio/gio-launch-desktop.c", "gio/giomodule.c", - - #"gio/gio-querymodules.c", "gio/gioscheduler.c", "gio/giostream.c", - - #"gio/gio-tool.c", - #"gio/gio-tool-cat.c", - #"gio/gio-tool-copy.c", - #"gio/gio-tool-info.c", - #"gio/gio-tool-list.c", - #"gio/gio-tool-mime.c", - #"gio/gio-tool-mkdir.c", - #"gio/gio-tool-monitor.c", - #"gio/gio-tool-mount.c", - #"gio/gio-tool-move.c", - #"gio/gio-tool-open.c", - #"gio/gio-tool-remove.c", - #"gio/gio-tool-rename.c", - #"gio/gio-tool-save.c", - #"gio/gio-tool-set.c", - #"gio/gio-tool-trash.c", - #"gio/gio-tool-tree.c", - "gio/gkeyfilesettingsbackend.c", - - #"gio/glib-compile-resources.c", - #"gio/glib-compile-schemas.c", "gio/glistmodel.c", "gio/gliststore.c", "gio/gloadableicon.c", - "gio/glocalfile.c", - "gio/glocalfileenumerator.c", - "gio/glocalfileinfo.c", - "gio/glocalfileinputstream.c", - "gio/glocalfileiostream.c", - "gio/glocalfilemonitor.c", - "gio/glocalfileoutputstream.c", - "gio/glocalvfs.c", "gio/gmarshal-internal.c", "gio/gmemoryinputstream.c", + "gio/gmemorymonitor.c", + "gio/gmemorymonitordbus.c", "gio/gmemoryoutputstream.c", - "gio/gmemorysettingsbackend.c", - "gio/gmenu.c", - "gio/gmenuexporter.c", - "gio/gmenumodel.c", "gio/gmount.c", "gio/gmountoperation.c", "gio/gnativesocketaddress.c", @@ -437,45 +475,21 @@ ohos_source_set("gio_source") { "gio/gnetworking.c", "gio/gnetworkmonitor.c", "gio/gnetworkmonitorbase.c", - "gio/gnetworkmonitornetlink.c", - "gio/gnetworkmonitornm.c", - "gio/gnetworkmonitorportal.c", "gio/gnetworkservice.c", - "gio/gnotification.c", - "gio/gnotificationbackend.c", - "gio/gnullsettingsbackend.c", - "gio/gopenuriportal.c", "gio/goutputstream.c", "gio/gpermission.c", "gio/gpollableinputstream.c", "gio/gpollableoutputstream.c", "gio/gpollableutils.c", "gio/gpollfilemonitor.c", - "gio/gportalnotificationbackend.c", - "gio/gportalsupport.c", - "gio/gpropertyaction.c", "gio/gproxy.c", "gio/gproxyaddress.c", "gio/gproxyaddressenumerator.c", "gio/gproxyresolver.c", - "gio/gproxyresolverportal.c", - - #"gio/gregistrysettingsbackend.c", - "gio/gremoteactiongroup.c", "gio/gresolver.c", "gio/gresource.c", "gio/gresourcefile.c", - - #"gio/gresource-tool.c", "gio/gseekable.c", - "gio/gsettings-mapping.c", - "gio/gsettings.c", - "gio/gsettingsbackend.c", - "gio/gsettingsschema.c", - - #"gio/gsettings-tool.c", - "gio/gsimpleaction.c", - "gio/gsimpleactiongroup.c", "gio/gsimpleasyncresult.c", "gio/gsimpleiostream.c", "gio/gsimplepermission.c", @@ -491,18 +505,15 @@ ohos_source_set("gio_source") { "gio/gsocketlistener.c", "gio/gsocketoutputstream.c", "gio/gsocketservice.c", - "gio/gsocks4aproxy.c", - "gio/gsocks4proxy.c", - "gio/gsocks5proxy.c", "gio/gsrvtarget.c", "gio/gsubprocess.c", "gio/gsubprocesslauncher.c", "gio/gtask.c", "gio/gtcpconnection.c", "gio/gtcpwrapperconnection.c", - "gio/gtestdbus.c", "gio/gthemedicon.c", "gio/gthreadedresolver.c", + "gio/gthreadedresolver.h", "gio/gthreadedsocketservice.c", "gio/gtlsbackend.c", "gio/gtlscertificate.c", @@ -513,27 +524,16 @@ ohos_source_set("gio_source") { "gio/gtlsinteraction.c", "gio/gtlspassword.c", "gio/gtlsserverconnection.c", - "gio/gtrashportal.c", "gio/gunionvolumemonitor.c", - "gio/gunixconnection.c", - "gio/gunixcredentialsmessage.c", - "gio/gunixfdlist.c", - "gio/gunixfdmessage.c", - "gio/gunixinputstream.c", - "gio/gunixmount.c", - "gio/gunixmounts.c", - "gio/gunixoutputstream.c", - "gio/gunixsocketaddress.c", - "gio/gunixvolume.c", - "gio/gunixvolumemonitor.c", - "gio/gvdb/gvdb-reader.c", "gio/gvfs.c", "gio/gvolume.c", "gio/gvolumemonitor.c", "gio/gzlibcompressor.c", "gio/gzlibdecompressor.c", - "gio/strinfo.c", - "gio/thumbnail-verify.c", + + # out + "gio/gdbus-daemon-generated.c", + "gio/gioenumtypes.c", "gio/xdp-dbus.c", ] diff --git a/NEWS b/NEWS index 6fb3561473d5a37abbdc2ed714f0546fe4176573..0f0a50775451c836271f649af3aaefd158813cb4 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,960 @@ -Overview of changes in GLib 2.62.5 +Overview of changes in GLib 2.68.1 +================================== + +* Fix a crash in `GKeyFile` when parsing a file which contains translations + using a `GKeyFile` instance which has loaded another file previously (#2361) + +* Pin GIO DLL in memory on Windows (!2016) + +* Bugs fixed: + - #2361 g_key_file_load_from_file segfaults on "Key[*]="like lines + - !1997 Backport !1996 “Include glibconfig.h to get the G_OS_UNIX token” to glib-2-68 + - !2016 GIO W32: Pin gio DLL + - !2021 Backport MR !2016 (GIO W32: Pin gio DLL) into glib-2-68 + - !2022 Few fixes and notes for building on Visual Studio 2012 and earlier + - !2034 Backport MR !2032 (gkeyfile: Drop a redundant check) into glib-2-68 + - !2035 Backport !2026 “Split g_test_log() messages that contain multiple lines” to glib-2-68 + +* Translation updates: + - English (United Kingdom) + + +Overview of changes in GLib 2.68.0 +================================== + +* Bugs fixed: + - !1987 build: Drop gconstructor_as_data_h usage from glib-compile-schemas + - !1989 glib.supp: Generalize some suppressions + - !1992 gbytesicon: Fix error in g_bytes_icon_new() documentation + - !1994 glocalfileoutputstream: Tidy up error handling + - !1995 tests: Fix copy/paste error in queue test + +* Translation updates: + - Czech + - Finnish + - Italian + - Korean + - Lithuanian + - Polish + - Romanian + - Slovenian + - Turkish + + +Overview of changes in GLib 2.67.6 +================================== + +* Fix a security issue when using `g_file_replace()` with + `G_FILE_CREATE_REPLACE_DESTINATION` (#2325) + +* Disallow operations on the empty path with `g_file_new_from_path()` (#2328) + +* Various fixes for GLib when building with clang-cl on Windows (work by + Aleksandr Mezin) (#2341, #2344) + +* Bugs fixed: + - #2325 file-roller symlink attack + - #2327 Teach glib-mkenums about GLIB_AVAILABLE_ENUMERATOR_IN_2_68, and start using it + - #2328 g_file_new_for_path("") yields CWD, which seems wrong + - #2341 glib-genmarshal output is sometimes empty because output file is not closed + - #2344 c_std=c11: gbitlock.c: ‘asm’ undeclared + - !1962 Validate D-Bus machine ID after loading + - !1976 Use the right permissions for directory watching on Win32 + - !1977 gio/tests/{meson.build,pollable.c}: Determine libutil SONAME at build time + - !1980 glib.supp: Add another system thread suppression + +* Translation updates: + - Basque + - Catalan + - Czech + - French + - Galician + - German + - Hungarian + - Indonesian + - Korean + - Latvian + - Portuguese + - Portuguese (Brazil) + - Serbian + - Spanish + - Swedish + - Ukrainian + + +Overview of changes in GLib 2.67.5 +================================== + +* Fix more issues with `glib_typeof` macro from 2.67.3–2.67.4 (work by + Iain Lane, Simon McVittie) (#2331, !1975) + +* Fix regression with some FD mappings passed to `g_subprocess_launcher_spawnv()` + caused by changes for #2097 in GLib 2.67.4 (work by Olivier Fourdan, + Philip Withnall) (#2332) + +* Fix detection of `str[n]casecmp()` when building with `clang-cl` (work by + Aleksandr Mezin) (#2337) + +* Use zlib from subproject if configured with `wrap_mode=forcefallback` (work by + Seungha Yang) (!1959) + +* Bump Visual Studio compilation requirement to VS 2012, and Windows 8 SDK for + GLib 2.67.x onwards (work by Chun-wei Fan) (!1970) + +* Bugs fixed: + - #832 Some tweaks re: GRWLock + - #2331 glib 2.67.3: can no longer be included in extern "C" blocks + - #2332 Glib 2.67.4 causes gnome-shell to exit when spawning Xwayland on demand + - #2333 Missing relation between g_file_info_get_size() and G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in documentation + - #2337 Linking fails when building with clang-cl because of str[n]casecmp + - !1936 tests: Fix leak of dlopened module in pollable test + - !1954 Change SkipAsyncData fields to be gsize (and not gssize) + - !1956 The ETag returned by various GFile functions is nullable + - !1959 meson: Use subproject zlib if "wrap_mode=forcefallback" was specified + - !1961 gkeyfilesettingsbackend: check for errors when creating file monitors + - !1970 README.win32.md: Mention about Window 8+ SDK requirement + - !1971 gio/tests/pollable.c: Fix build on non-Linux UNIX + - !1975 gatomic.h: Make `glib_typeof` API break opt in. + +* Translation updates: + - Basque + - Danish + - English (United Kingdom) + - Galician + - German + - Indonesian + - Lithuanian + - Portuguese + - Portuguese (Brazil) + - Slovenian + + +Overview of changes in GLib 2.67.4 +================================== + +* Add a `g_string_replace()` function (work by Joshua Lee) (#225) + +* Add `G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER` flag to simplify + the common case for writing a D-Bus authentication observer, allowing most + uses of `GDBusAuthObserver` to be dropped (#1804) + +* Add a new `g_spawn_with_pipes_and_fds()` variant which supports renumbering + FDs (#2097) + +* Add new g_memdup2() API to replace g_memdup(), which is vulnerable to a + silent integer truncation and heap overflow problem if not used carefully + (discovered by Kevin Backhouse, work by Philip Withnall) (#2319) + +* Fix various regressions caused by rushed security fixes in 2.66.6 (work by + Simon McVittie and Jan Alexander Steffens) (!1932, !1941, #2323) + +* Fix a silent integer truncation when calling g_byte_array_new_take() for + byte arrays bigger than G_MAXUINT (work by Krzesimir Nowak) (!1942) + +* Fix `g_utf8_strdown()` to fix some issues in Turkish + (work by Kjell Ahlstedt) (!1930) + +* Bugs fixed: + - #225 GString doesn't have a g_string_replace() function + - #587 g_input_stream_skip() out-of-bounds behavior is inconsistent between implementations + - #1804 Add G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flag + - #2097 GSubprocessLauncher with FD assignment can clash with g_spawn_async internal pipe + - #2315 httpproxy: Need overflow protection when reading response during connection establishment + - #2319 CVE-2021-27219 (GHSL-2021-045): integer overflow in g_bytes_new/g_memdup + - #2322 g_test_dbus: double output when piping + - #2323 [GLIB 2.66.6] g_io_channel_set_line_term() stopped working with null terminated strings and length -1 + - !1917 Adding a missing test on integer overflow within g_http_proxy_connect() + - !1918 Fix more warnings + - !1923 Add support for Tilix and Konsole + - !1930 guniprop: Fix g_utf8_strdown() for Turkish locale + - !1932 gtlspassword: Fix inverted assertion + - !1934 gdbus: Reject attempts to set future connection or server flags + - !1938 Fix more warnings + - !1939 ci: Temporarily disable macOS CI job as runner is offline + - !1940 Fix more warnings + - !1941 gkeyfilesettingsbackend: Fix basename handling when group is unset + - !1942 CVE-2021-27218: gbytearray: Do not accept too large byte arrays + - !1947 Revert "Merge branch 'wip/pwithnall/macos-ci-disable' into 'master'" + - !1948 tests: Use a more realistic language code than sv_SV + - !1949 gatomic: Make fallback g_atomic_pointer_get type-safe + - !1951 Add a test for parsing 0 as double + - !1955 tests: Add missing NULL terminator to spawn-singlethread test + +* Translation updates: + - Catalan + - Galician + - Hungarian + - Portuguese + - Romanian + - Slovenian + - Spanish + - Swedish + - Turkish + - Ukrainian + + +Overview of changes in GLib 2.67.3 +================================== + +* Add new `g_memdup2()` API to replace `g_memdup()`, which is vulnerable to a + silent integer truncation and heap overflow problem if not used carefully + (discovered by Kevin Backhouse, work by Philip Withnall) (#2319) + +* Add new `g_dbus_object_path_escape()` and `g_dbus_object_path_unescape()` APIs + to provide one way of escaping arbitrary bytestrings for use in D-Bus object + paths (work by Lars Karlitski and Frederic Martinsons) (#968) + +* Use `bash-completion.pc` (if available) to provide the path to install + completion files into (work by Frederic Martinsons) (#1054) + +* Fix support for public/private trigraphs in `glib-mkenums` (work by Matthias Klumpp) (!1870) + +* Add `glib_debug` configure option to allow disabling debug infrastructure in + builds with debug symbols enabled (work by Ole André Vadla Ravnås) (!1889) + +* Fix a regression where `PATH` would always be searched when using `g_spawn()`, + even when it wasn’t supposed to (work by Simon McVittie and Thomas Haller) (!1902) + +* Override `gio-querymodules` in Meson when used as a submodule (work by Xavier Claessens) (!1909) + +* Bugs fixed: + - #344 gdbus(1) command-line completion issues + - #968 gdbus: add g_dbus_object_path_{un,}escape + - #1054 Use pkg-config to get path for bash-completion file installation + - #1180 GUnixInputStream and GUnixOutputStream don't consider TTYs pollable + - #2011 Add additional unit tests for D-Bus name watching + - #2226 clang++ compilation fails on clusterfuzz + - #2292 Cannot find a common ancestor when running CI style check jobs + - #2299 GObject introspection annotation of g_closure_new_object() is wrong + - #2305 GIO security hardening causing gnome-keyring to regress when session bus is provided by dbus-launch (dbus-x11) + - #2314 gdatetime: math library link issue + - #2319 GHSL-2021-045: integer overflow in g_bytes_new/g_memdup + - !610 Various memory leak cleanups to GSettings tests + - !1804 Add more GIR annotations to gparam.c and gsignal.c + - !1823 Fix more warnings + - !1843 gfile: Add Linux kernel headers compatibility kludge + - !1847 Port to QNX + - !1853 ginetaddress: Handle systems without IPv6 support + - !1859 docs: update g_action_group_activate_action() remote activation semantics + - !1860 glocalfile: Fix an uninitialized variable + - !1865 tests: Add more debug information to gdbus-connection-slow + - !1868 gdesktopappinfo: Fix validation of XDG_CURRENT_DESKTOP + - !1870 mkenums: Support public/private trigraph again + - !1873 Fix possible integer overflow of g_socket_send_message() + - !1876 Fixing g_socket_send_message() documentation to make it clearer + - !1877 Fix more warnings + - !1878 Another fix on g_socket_send_message() + - !1879 Fix more warnings + - !1880 GError documentation tweaks + - !1881 docs: Move ‘Notes’ section from README to NEWS + - !1883 gutils: Document caching of XDG directory variables + - !1884 gthread-win32: Use SetThreadDescription Win32 API for setting thread name + - !1887 ci: Fix msys-mingw32 CI builds due to package rename + - !1888 docs: Add documentation for GLIB_VERSION_CUR_STABLE and PREV_STABLE + - !1889 build: Add glib_debug option + - !1890 gtype: Improve formatting of GType documentation + - !1891 Fix more warnings + - !1893 gwin32appinfo: Fix printf length sub-specifier + - !1894 gsocket: Fix SO_NOSIGPIPE regression on Darwin + - !1898 gtestutils: Add g_test_get_path() API + - !1899 m4macros: replace obsolete macros AC_TRY_RUN and AC_TRY_LINK in glib-2.0.m4 + - !1900 [th/gsignal-cleanup] minor changes to GSignal related code + - !1901 Check if the remote already exists before adding it. + - !1902 spawn: Don't set a search path if we don't want to search PATH + - !1903 m4macros: Increment serial number of glib-2.0.m4 + - !1905 Start to ignore known leaks under AddressSanitizer + - !1906 gdbus-serialization: Don't leak string containing first serialization + - !1908 Fix straightforward memory leaks in tests + - !1909 Meson: override gio-querymodules program + - !1910 gio: Add explicit virtual g-i annotations for undiscovered invoker relationship + - !1911 Fix more warnings + - !1915 Mark g_key_file_get_comment() key parameter as nullable + - !1919 atomic: Fix type check of g_atomic_pointer_compare_and_exchange() + - !1921 guri: Mark g_uri_get_host as nullable + - !1925 gapplication: Fix a memory leak + +* Translation updates: + - Czech + - Friulian + - Galician + - Hungarian + - Portuguese + - Portuguese (Brazil) + - Romanian + - Spanish + - Ukrainian + + +Overview of changes in GLib 2.67.2 +================================== + +* Add `gio launch` command to execute programs (work by Frederic Martinsons) (#54) + +* Fix unused parameter warnings in code generated by `gdbus-codegen` (work by Frederic Martinsons) (#1105) + +* Officially deprecate `to-pixdata` option for `glib-compile-resources`, in favour + of simply embedding more modern image formats in linked-in `GResource` files (#1281) + +* Support querying and running UWP applications on Windows (work by LRN) (#1991) + +* Support `gio trash --restore` and `gio trash --list` commands (work by Frederic Martinsons) (#2098) + +* No longer read environment variables for GIO module locations when running as setuid (#2168) + +* More progress on fixing compiler warnings (work by Emmanuel Fleury) (!1773 and others) + +* `GKeyFile` performance improvements (work by Timm Bäder) (!1829, !1832) + +* Improve UDP socket behaviour on Windows (work by Marco Mastropaolo and Ole André Vadla Ravnås) (!1827, !1844) + +* Add `-Dtests` meson configure option for disabling tests entirely (work by Ole André Vadla Ravnås) (!1850) + +* Bugs fixed: + - #54 Add `gio launch` command to execute .desktop files + - #513 GSignal: Impossible to have return values in signals which are G_SIGNAL_RUN_FIRST only + - #514 GSignal: Only limited usage of accumulator function possible + - #1105 gdbus-codegen: fix some unused parameter warnings + - #1188 Crash in gapplication.c:1014 when reading error message if dbus_register returns false without setting error + - #1281 Update glib-compile-resources and GResource docs to deprecate/remove to-pixdata in stable/master resp. + - #1283 gvfs-trash error message when unable to create trash directory is unhelpful + - #1568 GObject tutorial does not mention floating references + - #1991 W32: Glib cannot run UWP applications + - #2098 gio trash: restore trashed files to their original location + - #2168 giomodule: Loads GIO modules even if setuid, etc. + - #2264 GPtrArray might call qsort() with NULL data + - #2265 2.67.1 regression: assertion failure starting gnome-terminal + - #2275 gio/completion/gio: Some variables are not localized + - #2279 g_source_is_destroyed example uses deprecated GDK API + - !1304 Extended error + - !1773 Fix more warnings + - !1783 gtlsdatabase: remove duplicate precondition check + - !1784 fuzzing: Add more fuzzing tests for various string parsing functions + - !1785 glocalfile: Add an assertion to help static analysis + - !1787 Debuggability improvements in gosxappinfo.m + - !1788 gdate: Validate input as UTF-8 before parsing + - !1791 gdatetime: Disallow NAN as a number of seconds in a GDateTime + - !1794 gio-tool-info: Prevent criticals if mount options are not available + - !1796 gfileutils: Fix typo in docs + - !1797 gdatetime: Improve ISO 8601 parsing to avoid floating point checks + - !1801 glib: Add more missing return value annotations + - !1802 gobject: More missing return value annotations + - !1806 tests: Add some rounding tolerance in timeout test + - !1807 python: Reformat some files to keep style-check-diff happy + - !1808 tests: Be more lenient with timing checks on asyncqueue pops + - !1810 gfileinfo: Add missing preconditions to g_file_info_get_attribute_data() + - !1811 Add more missing nullable annotations + - !1813 gdbus-codegen: Ignore some flake8 warnings + - !1815 Fix more warnings + - !1816 fuzzing: Add more GUriFlags to the URI parsing test + - !1817 fuzzing: Add more parsing flags to the GKeyFile test + - !1818 Fix more warnings + - !1819 Fix more warnings + - !1821 gdate: Limit length of dates which can be parsed as valid + - !1822 Fix more warnings + - !1827 Windows: fix FD_READ condition flag still set on recoverable UDP socket errors. + - !1829 keyfile: Delay calling g_get_language_names() until it's needed + - !1830 gsocket: Fix credentials error-handling on Apple OSes + - !1832 More small GKeyFile performance improvements + - !1834 Update gvdb + - !1837 gdatetime.c: Fix MSVC builds for lack of NAN items + - !1838 Minor improvements to GError documentation + - !1840 Add nullable annotation for g_file_get_uri_scheme + - !1841 gthread: Fix incorrect cast + - !1842 gthread: Port native mutex to Clang + - !1844 gsocket: Improve default UDP behavior on Windows + - !1845 gsocket: Fix use-after-close + - !1848 gwin32: Always use unicode APIs + - !1850 build: Add option for disabling tests + - !1855 build: Fix ssize_t detection on older versions of glibc + - !1856 build: Fix Android system checks + - !1857 gtestutils: Fix g_assert_not_reached() on MSVC + - !1861 More GError tests + - !1863 tests: Ignore -Wformat-nonliteral warning in new GError tests + +* Translation updates: + - Catalan + - Galician + - German + - Lithuanian + - Romanian + - Spanish + - Ukrainian + + +Overview of changes in GLib 2.67.1 +================================== + +* Deprecate `g_time_zone_new()` in favour of `g_time_zone_new_identifier()`, + which makes error checking easier (#553) + +* Remove `volatile` from various public APIs, including `G_DEFINE_*`. You should + adjust your code to not use `volatile` for atomic variables, `GOnce` + variables, or mostly anything else (see + http://isvolatileusefulwiththreads.in/c/). (#600) + +* Support passing file handles to `gdbus` command line tool (work by + Norbert Pocs and Tim Waugh) (#961) + +* Add `g_assert_cmpstrv()` test convenience function (work by Niels De Graef) (#2015) + +* Changes to the behaviour of the `G_URI_FLAGS_SCHEME_NORMALIZE` scheme + normalization flag in `GUri` (work by Carlos Garcia Campos) (#2257, !1716) + +* Add new `--run-prefix` and `--skip-prefix` options to GTest, to allow running + or skipping test suites by prefix (work by Frederic Martinsons) (!1738) + +* Fix thread-safety of `GBinding`; see the updated documentation for + `g_object_bind_property()` for full details — if your code uses `GBinding` + across threads, you should re-check it against the latest documentation, use + `g_binding_unbind()` rather than implicitly dropping the binding with your + last `g_object_unref()` call, and use `g_binding_dup_source()`/`g_binding_dup_target()` + instead of `g_binding_get_source()`/`g_binding_get_target()` + (work by Sebastian Dröge) (!1745) + +* Bugs fixed: + - #553 Improved error-handling when timezone lookup fails + - #600 Remove "volatile" from G_DEFINE_* + - #961 gdbus tool: file handle passing doesn't work + - #994 mark g_assert_* as "noreturn" also on MSVC + - #1560 Can't get data for empty compressed resources + - #1592 Main loop ignores GPollFD sources when there is at least one source ready with priority higher than default one + - #1833 meson: reconsider G_DISABLE_CAST_CHECKS handling + - #1849 Documentation of g_set_object(): can object_ptr be null? + - #1963 Follow-up from "gdbusmessage: Limit recursion of variants in D-Bus messages" + - #2015 Add g_assert_cmpstrv() test utility + - #2046 Add pylint and shellcheck CI checks + - #2074 Big dbus writes with a FD list fail + - #2076 g_type_register_fundamental() and g_type_add_interface_static() should not trigger valgrind leak warnings + - #2150 Add URI parsing tests from GstURI to GUri + - #2221 GLib-GIO:ERROR:../gio/tests/gsocketclient-slow.c:99:on_event: 'connection' should be NULL + - #2223 Documentation of g_strrstr_len is misleading; suggested fix + - #2233 GSocketClient crashes on connection failure + - #2236 Docs: gdbus-codegen example links broken + - #2253 In gspawn.c, use sysconf() system call on Mac OS, instead of default maxfiles limit of 4096 + - #2257 GUri: apply scheme normalization flag consistently + - !1251 Improve support for interface types + - !1385 gobject: allocate parameter list for g_object_new_valist() entirely on stack + - !1629 Add some tracing to GTask + - !1699 Fix signedness warnings + - !1701 gio: Fix some remaining DocBook syntax in a documentation comment + - !1708 gio: Add missing nullable annotations + - !1716 guri: Normalize uri segments if they are encoded and add a flag to do scheme-based normalization + - !1722 gio: Fix various typos of the name ‘D-Bus’ + - !1724 glib/tests/fileutils: Fix expectations when running as root + - !1726 gdbus: Document the intended semantics of handles and fdsTim Waugh + - !1731 Make more use of g_assert_no_errno() + - !1733 gdbusauthmechanismsha1: Don’t create keyring dir when running as setuid + - !1734 glocalfileinfo: Use a single timeout source at a time for hidden file cache + - !1735 gobject: Standardise on the term ‘instantiatable’ + - !1737 gscanner: Avoid undefined behaviour copying between union members + - !1738 Extend the usage of -p option for glib test framework + - !1740 Fix more warnings + - !1745 Make GBinding thread-safe (alternative approach) + - !1746 gkeyfilesettingsbackend: improve error-checking + - !1747 Fix broken link syntax in g_vasprintf docs + - !1748 Fix minor Coverity return value warnings + - !1750 Fix warnings + - !1754 GWin32AppInfo: Use a thread pool for async appinfo tree rebuilds + - !1755 Minor Coverity fixes + - !1756 shellcheck fixes + - !1757 Python formatting improvements + - !1758 Fix warnings + - !1765 Fix more warnings + - !1766 Fix some gdatetime annotations + - !1767 tests: Fix GDateTime tests on FreeBSD + - !1769 gfileicon: Fix unused-but-set variable with G_DISABLE_ASSERT + - !1770 Minor scan-build fixes + - !1771 macos: fix frexpl checks in cross-compilation + - !1776 gio: ‘security_context_t’ is deprecated + - !1780 Minor Coverity fixes + - !1781 gspawn: Handle ENOSYS from close_range() + - !1782 ghostutils: Abandon hostname conversion early if it’s too long + +* Translation updates: + - Czech + - Spanish + - Ukrainian + + +Overview of changes in GLib 2.67.0 +================================== + +* Important and time-critical fix to DST transitions which will happen in Europe + on 2020-10-25 on distributions which use the ‘slim’ tzdata format (which is + now the default in tzdata/tzcode 2020b) (work by Claudi M., LRN) (#2224) + +* Further timezone handling changes to improve performance of `GTimeZone` (work + by António Fernandes, Sebastian Keller) (#2204) + +* Fix deadlock on Windows when `G_SLICE` is set in the environment (diagnosis by + Christoph Reiter) (#2225) + +* Fix UTF-8 validation when escaping URI components (thanks to Marc-André Lureau) (!1680) + +* Security fix for incorrect scope/zone ID parsing in URIs (!1669) + +* Add `g_log_writer_default_set_use_stderr()` API for printing log messages to stderr (work by Simon McVittie) (#2087) + +* Improve connection error reporting when IPv6 is available and disabled (work by Michael Catanzaro, debugging by Konstantin Kharlamov and Milan Crha) (#2211) + +* Fix definition of `G_MSVC_SYMBOL_PREFIX` for ARM (work by Wolfgang Stöggl) (!1187) + +* Add `GStrvBuilder` convenience API for building `NULL`-terminated string arrays (work by Robert Ancell) (!1417) + +* Support appinfo verbs other than ‘open’ on Windows (work by LRN) (!1502) + +* Expose node-based `GTree` APIs (work by Maciej S. Szmigiero) (!1509) + +* Add `G_DBUS_METHOD_INVOCATION_HANDLED`/`_UNHANDLED` convenience constants (work by Simon McVittie) (!1603) + +* Set `IP_BIND_ADDRESS_NO_PORT` on sockets when binding to local addresses (work by Cristian Rodríguez) (!1598) + +* Add Meson option for libelf support (work by Niklas Gürtler) (!1650) + +* Add support for PKCS #11-backed TLS certificates (work by Patrick Griffis) (!1663) + +* Add `g_subprocess_launcher_close()` API to make `GSubprocessLauncher` more usable in bindings (work by Sergio Costas) (!1677) + +* Bugs fixed: + - #1233 GType for GTree + - #2077 Invalid Pointer Arithmetic in g_path_get_basename + - #2087 Respecting G_MESSAGES_DEBUG in a custom log writer should be easy to do + - #2164 GDBus DBUS_COOKIE_SHA1 mechanism may use too old a key + - #2194 gtk3/glib crash on gimp + - #2203 fstatat is available only on macOS 10.10+ + - #2204 Time zone cache is constantly invalidated if TZ is NULL + - #2209 gthreadedresolver: faulty logic in parse_res_txt + - #2210 g_private_replace ordering issue + - #2211 "Network is unreachable" error returned when IPv6 is disabled and network is reachable using IPv4 + - #2215 DST incorrectly ends on wrong dates + - #2224 top bar time is incorrect, timezone map in control center is broken + - #2225 Setting G_SLICE makes Windows programs hang since 2.66 + - !1187 Define G_MSVC_SYMBOL_PREFIX correctly for ARM + - !1417 gstrvbuilder: Add a new object to make NULL-terminated string arrays. + - !1449 gio: Expose g_file_query_info_for_copy() + - !1502 GWin32AppInfo: Support verbs other than "open" + - !1509 GTree: add an ability to iterate over a tree and a node-based API + - !1575 Use C++11 decltype where possible + - !1598 gsocketclient: set IP_BIND_ADDRESS_NO_PORT if binding to local address + - !1603 GDBus: Add G_DBUS_METHOD_INVOCATION_HANDLED, _UNHANDLED + - !1643 Minor Coverity fixes + - !1645 Fix various signedness warnings + - !1647 Fix warnings (keep going) + - !1648 glocalfile: Never require G_LOCAL_FILE_STAT_FIELD_ATIME + - !1650 Make libelf dependency optional via meson feature + - !1652 trash portal: Handle portal failures + - !1654 gio-tool-trash: Prevent recursion to speed up emptying trash + - !1657 glist: Clarify that g_list_free() and friends only free an entire list + - !1658 utils: Limit the scope of the variable `max` + - !1661 Lookup fallback time zones in the cache to improve performance + - !1663 gtlscertificate: Add support for PKCS #11 backed certificates + - !1665 Fix g_module_symbol() under Windows sometimes not succeeding + - !1669 guri: Fix URI scope parsing + - !1670 GSubprocessLauncher: Move cleanup to dispose() + - !1671 gdatetime: Avoid integer overflow creating dates too far in the past + - !1673 CI: Re-enable code coverage reporting for MSYS2 builds + - !1674 Add version macros for 2.68 + - !1675 Make static assertions about standard types + - !1677 gsubprocesslauncher: Allow to close FDs + - !1678 gmessages: Document that using a custom log writer basically disables fatal handling + - !1679 gmain: Fix minor typo in documentation + - !1680 guri: Fix UTF-8 validation when escaping URI components + - !1681 gspawn: Handle error opening /dev/null + - !1686 Various improvements in GSocketClient + - !1687 uri: add missing (not)nullable annotations + - !1688 gspawn: Use close_range() if available to close FDs between fork/exec + - !1691 gmain: Fix possible locking issue in source unref + - !1692 gsignal: Plug g_signal_connect_object leak + - !1695 gfile: Clarify refcount handling for g_file_replace_contents_bytes_async() + - !1696 Fix various minor scan build warnings + - !1706 Add various missing nullable annotations + - !1712 Revert "Use C++11 decltype where possible" + - !1714 gmacros: Use __typeof__ when compiling with Clang + - !1718 gtrace: Add G_GNUC_PRINTF annotation + +* Translation updates: + - Chinese (Taiwan) + - Danish + - Greek, Modern (1453-) + - Hebrew + - Latvian + - Portuguese + - Russian + - Slovak + - Ukrainian + + +Overview of changes in GLib 2.66.0 +================================== + +* Bugs fixed: + - #2200 missing tab in makefile rule + - !1639 guri: Fix user passed to g_uri_split_with_user() not being NULL'd + +* Translation updates: + - Croatian + - Hungarian + - Italian + - Serbian + - Slovak + - Swedish + + +Overview of changes in GLib 2.65.3 +================================== + +* Fixes to the new `statx()` calls — note that since GLib 2.65.2 uses `statx()` + (if available) instead of `stat()`/`fstat()`/`lstat()`/`fstatat()`, syscall + sandboxing for third party applications might need to be updated + +* Bugs fixed: + - #2189 g_file_query_info on ro file system: Numerical result out of range + - #2191 Calling nice(20) can lead to thread related warnings + - #2197 Segfaulting Integer Overflow in g_option_group_add_entries + - !1025 Big o notations + - !1626 gio: Document g_settings_new() missing schema behaviour + - !1627 gthread: Add a sysprof mark for thread creation + - !1628 Replace a bunch of fallthrough comments with an attribute + - !1631 Fix splice behavior on cancellation + - !1632 Fixing signedness warning in glib/gfileutils.c + - !1635 gcancellable: Mark a variable as unused if built with G_DISABLE_ASSERT + +* Translation updates: + - Basque + - Catalan + - Chinese (China) + - Czech + - English (United Kingdom) + - Friulian + - German + - Japanese + - Kazakh + - Korean + - Lithuanian + - Polish + - Portuguese (Brazil) + - Slovenian + + +Overview of changes in GLib 2.65.2 +================================== + +* Support `statx()` and `G_FILE_ATTRIBUTE_TIME_CREATED` (work by Andre Miranda) (#1970) + +* Fix deadlock in `g_subprocess_communicate_async()` (work by Alexander Larsson) (#2182) + +* Add `%f`/microsecond placeholder support to `g_date_time_format()` (work by Johan Bjäreholt) (!1605) + +* Bugs fixed: + - #5 g_new0 performance + - #1970 Make G_FILE_ATTRIBUTE_TIME_CREATED support stx_btime + - #2176 Inconsistent introspection annotations for g_input_stream_read and g_socket_receive + - #2182 g_subprocess_communicate_async() can deadlock when writing + - !1593 CI support for Coverity Scan + - !1605 gdatetime: Add %f format specifier and microsecond precision to g_date_time_format_iso8601 + - !1613 gfile: Document TOCTTOU avoidance using g_file_delete() + - !1615 docs: glib-compile-resources: json-stripblanks + - !1616 gioerror: Map WSAENETRESET on Windows to G_IO_ERROR_CONNECTION_CLOSED + - !1619 Minor Coverity fixes + - !1620 gvariant: Ensure GVS.depth is initialised + - !1622 gdatetime: Widen a variable before multiplication + - !1623 gcancellable: Assert that make_pollfd() call succeeds + - !1624 gdbusaddress: Drop an unnecessary NULL check + - !1625 gdbusmessage: Drop redundant uint ≥ 0 checks + +* Translation updates: + - French + - Galician + - Greek, Modern (1453-) + - Indonesian + - Romanian + - Spanish + - Turkish + - Ukrainian + + +Overview of changes in GLib 2.65.1 +================================== + +* Add `GUri` API for parsing, building and representing URIs according to + [RFC 3986](https://tools.ietf.org/html/rfc3986) (work by Marc-André Lureau) (#110) + +* Fix handling of xattr data with embedded nuls (#422) + +* Add `g_file_set_contents_full()` which gives more control over fsyncs (#1302) + +* Fix cross-compilation on iOS (work by Nirbheek Chauhan) (#1868) + +* Add a `x-gvfs-notrash` option to disable trash on certain mounts (work by Ondrej Holy) (!1549) + +* Support ‘slim’ TZif files generated with `zic -b slim` (work by Paul Eggert) (#2129) + +* Support emitting profiling marks from `GMainContext` to sysprof capture files (!1551) + +* Accept IPv6 zone IDs in `g_hostname_is_ip_address()` (work by Marc-André Lureau) (!1604) + +* Bugs fixed: + - #4 Include a UTF-8 safe escaping function + - #110 Basic URI operations + - #137 display_name should be always available + - #250 GTestCase's setup/teardown functions appear pointless + - #272 allow thread pools to adjust the number of threads to the number of cpu's/cores + - #422 Wrong assumption in libgio GFileInfo on xattr/acl string: it may contain binary data. + - #858 glib2 @2.40.0 issues a "Got weird mach timebase info" error (Macports, PPC) + - #1022 g_object_new Should Mention That it Zeroes Out Private Struct + - #1200 Make g_assert_null/nonnull clang static analyzer friendly + - #1203 Add a variant of g_file_set_contents() which accepts file mode + - #1288 gmacros: Introduce non-public G_CLANG_ANALYZER_NORETURN macro + - #1302 g_file_set_contents() can fill target with NUL bytes if it did not previously exist + - #1670 ThreadSanitizer data races + - #1764 cancellable test: on_mock_operation_ready: assertion failed (iterations_requested > iterations_done): (10 > 10) + - #1868 iOS cross compile impossible due to frexpl check not supporting cross compilation + - #1869 iOS doesn't have Cocoa, which thankfully isn't a requirement of this code that supposedly requires it + - #1982 GSocketAddressEnumerator documentation is inconsistent with existing usage + - #2127 Spurious GIO module initialization on Fedora Silverblue (and other ostree-based systems?) + - #2129 date_time bugs after 2038, or with today's date and 'zic -b slim' TZif files + - #2132 Valgrind reports "still reachable" after g_thread_pool_new/free + - #2136 Valgrind reports "still reachable" after g_option_context_parse + - #2140 calling malloc in fork child is undefined-behaviour + - #2141 g_value_copy is was recently broken + - #2149 Make G_URI_FLAGS_PARSE_STRICT the default + - #2156 Merge _g_uri_parse_authority() into GUri + - #2159 Thread-unsafe initialization in gportalsupport.c + - #2160 More guri regressions + - #2165 More guri breakage + - #2166 g_uri_build() functions should accept a NULL scheme + - !1328 guri: new URI parsing and generating functions + - !1527 Add g_tls_connection_get_channel_binding_data call and enums + - !1534 Various GLocalFile fixes related to the filesystem::remote attribute + - !1546 tree: Fix various ableist language + - !1549 Add support to ignore trash for certain mounts + - !1551 Add initial sysprof support + - !1553 gtestutils: Mark that g_assert_whatever() macros do not normally return + - !1554 GUri build fixes + - !1555 Remove c-format from the string that is not c-formatted + - !1556 fuzzing: Another fix for g_uri_parse() test + - !1557 A few g_uri_parse_params() improvements + - !1559 Fix buffer read overflows in GUri + - !1561 gconvert: Use a pointer array in extract_uris + - !1563 gdesktopappinfo: Fix unnecessarily copied and leaked URI list + - !1564 tests: limit number of threads to something reasonable. + - !1570 Reduce CI bandwidth requirements + - !1572 Add GUriParamsIter + - !1576 gtask: Only override g_task_set_source_tag() for GLib ≥ 2.60 + - !1577 uri: add illegal_characters argument to unescape_bytes + - !1578 tests: Add tests for RFC 8536 v3 parsing of time zones + - !1579 glib: Use g_getenv everywhere instead of getenv + - !1582 appinfo: Add properties + - !1583 gio: Remove broken support for XP + - !1590 Use CI schedules and DAGs + - !1591 gfileutils: Fix O_NOFOLLOW handling on BSD systems + - !1594 GFile: Document that G_FILE_CREATE_REPLACE_DESTINATION can only be used with... + - !1595 uri: add ENCODED_PATH & ENCODED_FRAGMENT flags + - !1599 uri: do not add ipv6 brackets on non-ip host + - !1600 uri: do not encode ':' and ';' from userinfo + - !1601 timezone: Fix an uninitialized use + - !1602 Revert "Merge branch 'appinfo-properties' into 'master'" + - !1604 Make g_hostname_is_ip_address() accept ipv6 zoneid + - !1609 Fix multiple typos in guri.c + - !1611 guri: Always prepend `//` to the host when building a URI + - !1612 guri: Document and check restrictions on path prefixes + +* Translation updates: + - Catalan + - Kazakh + - Lithuanian + - Romanian + - Slovenian + - Spanish + - Ukrainian + + +Overview of changes in GLib 2.65.0 +================================== + +* Fix memory monitor tests to only be installed if installed-tests are enabled, + and to be skipped if GObject-Introspection is too old (!1407) + +* Stability improvements for various unit tests + +* D-Bus credentials support on macOS (#507) + +* MSVC support for the files generated by `glib-compile-resource` and `gdbus-codegen` (#1215, !1452) + +* Year 2038 fixes involving new API in `GBookmarkFile` (#1931) + +* SOCKS5 proxy authentication fixes (#1986, #1988) + +* Support for more than `MAXIMUM_WAIT_OBJECTS` FDs for `g_poll()` on Windows (#2107) + +* Add `g_assert_no_errno()` test macro for testing POSIX-style functions (!1204) + +* Update Unicode Character Database to version 13.0.0 (!1422) + +* Support storing interned strings in `GValue`s efficiently, via `g_value_set_interned_string()` (#2109) + +* Bugs fixed: + - #2 g_filename_from_utf8() should normalize? + - #176 the behaviour of constructors for GLib data types is not specified if memory allocation fails + - #480 /gdbus/connection/signals test intermittently fails: assertion failed (count_name_owner_changed == 2): (1 == 2) + - #507 GDBus credentials don’t work on OS X + - #602 GLib.Thread not usable from GObject-Introspection + - #1154 Missing documentation how to set a value in a GArray + - #1215 MSVC cannot build glib-compile-resource's output resource file + - #1323 meson, autotools: figure out if mem barrier is needed for arm64 host variant aarch64 + - #1398 gdate: Add error handling for GetDateFormatW calls + - #1841 Signal handler disconnection race when finalising GCancellableSource + - #1851 Meson Build Failure on Windows: Undefined Reference to libiconv + - #1911 Memory leak in g_param_spec_flags and/or g_param_spec_enum + - #1931 GBookmarkFile API involves time_t + - #1954 gdbus-server-auth intermittent failure + - #1957 gdbus-connection test failure on FreeBSD + - #1986 Socks5 Proxy: Authentication seems broken + - #1988 Socks5 Proxy: Wrong error returned when using no authentication + - #2038 Bindings: g_tls_connection_set_database() does not allow None as argument + - #2051 GUnixOutputStream can block on close() + - #2057 Call malloc_trim() under memory pressure + - #2067 Glib uses _Static_assert in C++17 mode + - #2081 gdbus error messages contains mixed up body and head signatures + - #2082 AM/PM - specific variation support needed to Hebrew language + - #2083 Memory monitor tests fail if dbusmock isn't installed + - #2092 FreeBSD CI timing out in gdbus-connection filter test + - #2094 Deprecation warnings when compiling with -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_28 -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28 + - #2106 Duplicated if - else if conditions in gtranslit.c + - #2107 g_poll() implementation on Windows stall when more than MAXIMUM_WAIT_OBJECTS FDs have passed + - #2109 GValue: Add support for interned string + - #2124 g_file_info_get_content_type() may return NULL + - #2132 Valgrind reports "still reachable" after g_thread_pool_new/free + - #2134 Valgrind reports "still reachable" after `g_uuid_string_random()`. + - #2135 Valgrind reports "still reachable" after g_key_file_new/free + - #2136 Valgrind reports "still reachable" after g_option_context_parse + - !1204 gtestutils: Add a new g_assert_no_errno() test macro + - !1302 gobject: new g_param_is_valid_property_name() function. + - !1329 Support nanoseconds in stat timestamps on Windows + - !1341 MUI capabilities for GWin32RegistryKey + - !1360 CI: Show execution environment before we start + - !1395 tests: Move memory_monitor_tests under installed_tests_enabled + - !1396 macros: Define G_GNUC_FALLTHROUGH for more compilers + - !1397 tests: Skip MemoryMonitor test if GObject-Introspection is too old + - !1398 gcontenttype: Fix crash in _get_generic_icon_name() + - !1402 ci: Update Android Docker image for aarch64 CPU naming change + - !1405 tests: Disable link-time warning for mem-overflow + - !1406 Replace fallthrough comments with G_GNUC_FALLTHROUGH + - !1408 tests: Don't compare strings by pointer + - !1409 gdummytlsconnection: Add missing overrides for ALPN properties + - !1413 gapplication: Fix a minor typo in the documentation + - !1414 gstrutils: Set locale explicitly for search-utils test + - !1415 meson: Don't use assert in test code + - !1418 ginetaddress, ginetsocketaddress: Add missing (nullable) annotations + - !1422 glib: Update Unicode Character Database to version 13.0.0 + - !1423 gobject: Clarify assertion failure on ref-after-finalize + - !1424 docs: Fix configuration with gtk_doc=true and installed_tests=false + - !1425 gdbusconnection: GDBusSignalCallback can have a NULL sender_name + - !1426 gunidecomp: Update and reformat Unicode version support history + - !1427 gicon: Clarify GVariant refcounting in docs + - !1428 Add missing 'extern' to the dllexport version of GLIB_VAR/GOBJECT_VAR + - !1429 Fix arch detection ifdefs in glib/valgrind.h + - !1430 Use __builtin_trap() on Clang on any platform + - !1431 glib-unix.c: fix heap corruption in g_unix_get_passwd_entry + - !1432 docs: Mention new gio tool options + - !1433 meson: Fix buildtype usage + - !1434 gdbusconnection: Clarify nullability of SignalInstance.sender + - !1436 glib: Update internal copy of valgrind.h from Valgrind 3.15 release + - !1437 gmarkup tests: tab character escape/unescape + - !1439 Don't misdetect stpcpy on windows platforms on clang + - !1440 Silence clang errors about -Wformat-nonliteral due to missing intermediate attributes + - !1441 Meson: Override every dependency glib provides + - !1442 gfile: Fallback to fast-content-type if content-type is not set + - !1443 gio: use TAPTestRunner in the memory monitor tests + - !1444 Meson: Add glib-checks and glib-asserts options + - !1452 Make symbols generated by gdbus-codegen exportable on Visual Studio-style builds + - !1455 gdesktopappinfo: Note that search results are not filtered + - !1456 GCredentials documentation fixes + - !1458 meson: Exclude gosxutils.m when building for iOS + - !1459 meson: Fix the gnulib checks for isnan* functions + - !1460 glib: Sync the local modification to glib/valgrind.h to what was upstreamed + - !1462 gvariant-core: Add a note about memory safety of children + - !1463 gdesktopappinfo: Add several nullable annotation to GAppInfo getters + - !1464 Update Fedora CI + - !1466 CI: Switch to new Windows runners + - !1469 goption: Treat an empty option context parameter string as NULL + - !1475 Improve documentation of g_tls_database_verify_chain() + - !1476 tests: Fix remaining race in gdbus-connection filter test + - !1479 Improve documentation of client connection validation flags + - !1480 CI: Make sure we use meson 0.49.2 in MSYS2 + - !1481 array: fix corrupt state of GPtrArray after g_ptr_array_extend_and_steal() + - !1482 [th/g-ptr-array-variable-cleanups] minor cleanup of variables for GPtrArray + - !1487 glib: annotate static inline functions with G_AVAILABLE-type macros + - !1488 Rebuild Fedora CI image + - !1491 gdatetime: update annotations + - !1492 glib-mkenums: allow optional 'since' tag + - !1493 meson: Remove stray ] in O_DIRECTORY check + - !1496 Fix GLIB_UNAVAILABLE_STATIC_INLINE declaration + - !1498 array: add internal ptr_array_new() helper for creating GPtrArray + - !1503 docs: Add indexes for symbols added in 2.66 + - !1505 gobject: Handle runtime checks as such + - !1506 tests: Speed up the cancellable test + - !1508 tests: Speed up the file test and make it more reliable + - !1512 Various fixes when building for iOS + - !1513 Initialize the visited time of a new GBookmarkFile + - !1515 meson: check for stpcpy using cc.links() + - !1516 gthreadedsocketservice: Mark source_object of run signal as nullable + - !1517 GWin32RegistryKey: Move assertions + - !1518 strfuncs: Use a GPtrArray in strsplit() + - !1522 meson: Fix gnulib printf checks + - !1524 meson: Fix gnulib build where isnan*() is needed + - !1525 Normalize C source files to end with exactly one newline + - !1528 gtlsconnection: Improve documentation of peer-certificate[-errors] + - !1530 tree: Fix various typos and outdated terminology + - !1531 gvariant: Fix documentation for g_variant_get_string() to match reality + - !1532 win32: spelling fix + - !1535 glib.supp improvements + +* Translation updates: + - Bokmål, Norwegian + - Catalan + - Catalan (Valencia) + - Chinese (Taiwan) + - Dutch + - French + - Galician + - German + - Hebrew + - Indonesian + - Italian + - Japanese + - Latvian + - Lithuanian + - Malay + - Romanian + - Serbian + - Slovak + - Slovenian + - Spanish + - Turkish + - Ukrainian + + +Overview of changes in GLib 2.64.0 +================================== + +* Use `posix_spawn()` to speed up launching test D-Bus instances (!1388) + +* Bugs fixed: + - #1783 Document using glib-mkenums with meson + - #2049 Crash in g_array_copy + - !1384 Some minor clang warning fixes + - !1386 docs: Document generated headers caveats for genmarshal + - !1387 ci: Correctly propagate exit status in run-style-check-diff.sh + - !1388 gtestdbus: Use posix_spawn() to spawn dbus-daemon + - !1389 Update GError docs to use G_DEFINE_QUARK + +* Translation updates: + - Czech + - Danish + + +Overview of changes in GLib 2.63.6 ================================== * Fix potential relative read when calling g_printerr(), which could lead to a @@ -10,87 +966,410 @@ Overview of changes in GLib 2.62.5 * Several other Happy Eyeballs fixes for address resolution (#1871, #1872, #1902) -* Fix parsing of full Julian day range from `$TZ` environment variable (#1999) +* Various race fixes in `GDBusConnection` and its unit tests (#1515) + +* Fix a race condition with D-Bus name ownership (#1517) + +* Drop `gio-launch-desktop` helper application in favour of calling `sh` directly (#1633) + +* Fix win32 exception handling with C# exceptions (#2025) -* Several race condition/crash fixes (!1353, !1357) +* Fix thread safety of `GUnixMountMonitor` (#2030) + +* Additional fixes to new thread pool attribute behaviour from GLib 2.63.4 to + check if sched_setattr() is allowed by system policies before depending on it (#2039, !1356) + +* Fix memory leaks and corruption when freeing `GSource`s while freeing a `GMainContext` (!1353) + +* Drop inappropriate installation of object manager example documentation (!1359) * Bugs fixed: + - #938 gdbus call -a doesn't support message bus connections + - #1515 gio/gdbus-threading test sometimes fails in CI + - #1517 g_bus_own_name does not always call name_lost_handler when _REPLACE and _ALLOW_REPLACEMENT are set + - #1633 should not install gio-launch-desktop into PATH - #1919 read from relative path in g_printerr() in 2.58.3 - #1995 Tracker issue for Happy Eyeballs regressions - - #1999 GTimeZone fails to accept full Julian day range when parsing the direct $TZ string format - - !1323 Backport !1314 “gtimezone: fix parsing of Julian day in POSIX TZ format” to glib-2-62 - - !1331 Backport !1330 “W32: Correctly set st_ino when doing private stat()” to glib-2-62 - - !1352 Backport !1351 “glib.supp: update g-threaded-resolver-getaddrinfo-config” to glib-2-62 - - !1361 Backport !1353 GMainContext source reference fixes to glib-2-62 - - !1365 Refactor g_socket_client_connect_async() - - !1370 Backport !1369 “build: Rework path construction to reliably add prefix” to glib-2-62 - - !1371 Backport !1357 “gunixmounts: Make GUnixMountMonitor thread-safe” to glib-2-62 + - #2002 g_io_channel_read_line does not honour the line_term symbols set + - #2025 W32 exception handling misbehaves when C# exceptions are thrown when running inside the Visual Studio debugger + - #2030 Random nautilus test suite failures involving GUnixMountMonitor + - #2039 sched_setattr() still can cause EPERM through natural causes + - #2043 Low memory monitor test failed in CI + - #2044 GApplication docs suggest invalid GVariant type + - !1185 gtimezone: Tidy up UTC timezone creation + - !1281 ci: Update Docker packages + - !1283 gmodule: change _g_module_close to only take a handle. + - !1298 tests: Speed up the GIO actions test + - !1299 gapplication: Fix a minor typo in the documentation + - !1339 gsocketclient: Refactor g_socket_client_connect_async() + - !1353 GMainContext - Fix memory leaks and memory corruption when freeing sources while freeing a context + - !1354 GThreadPool - Add test for !1340 + - !1355 glist: Add docs examples of how to combine with g_steal_pointer() + - !1356 GThread - Check if sched_setattr is allowed by the system policies before depending on it + - !1359 docs: Don’t install object manager example separately + - !1363 Make tests pass if we are euid != 0 with capabilities + - !1366 Fix oss-fuzz coverage link + - !1372 gobject: Fix strict aliasing warnings with g_set_object() + - !1376 gitlab-ci: 64-bit ARM is aarch64, not arm64 + - !1381 ghash: Document the iteration order over a hash table is not defined + - !1382 tests: Bump the refcount timeout in gdbus-threading + - !1383 ci: Enable parallelisation when running installed tests * Translation updates: + - Basque + - English (United Kingdom) + - French + - Galician - German + - Greek, Modern (1453-) - Hungarian - Indonesian - - Italian + - Japanese + - Korean - Lithuanian - - Malay - Polish - Portuguese (Brazil) - Spanish - Swedish + - Turkish + + +Overview of changes in GLib 2.63.5 +================================== + +* Fix behaviour of `g_file_move()` fallback code to not follow symlinks (#986) + +* Rename `--glib-min-version` argument of `gdbus-codegen` to `--glib-min-required` + (this is not an API break as `--glib-min-version` was added earlier in the + 2.63 cycle) (#1993) + +* Add gtk-doc checks to CI and fix a number of documentation issues + (thanks to Xavier Claessens) (!978) + +* Add `G_SIZEOF_MEMBER()` macro (!1333) + +* Add a debug message if `g_setenv()` or `g_unsetenv()` are used after any + threads have been spawned — this will be upgraded to a warning in future (!1337, #715) + +* Skip memory monitor tests if xdg-desktop-portal or dbusmock are not available (!1296, !1338) + +* Change the `libmount` configure option from a boolean to a Meson `feature` (!1344) + +* Do not return `target-uri` from `g_file_peek_path()` when called on trash/recent files (!1346) + +* Drop new TLS certificate API for PKCS #11 backed certificates, as the implementation + is not ready yet (this is not an API break as the API was added earlier in the + 2.63 cycle) (!1347) + +* Bugs fixed: + - #986 g_file_move: remove G_FILE_COPY_NOFOLLOW_SYMLINKS section + - #1551 CI: Add checks for `TODO` in MRs + - #1925 Large number of routes installed into kernel cause high cpu usage + - #1993 Rename gdbus-codegen --glib-min-version argument to --glib-min-required and add --glib-max-allowed + - #2012 spawn_thread_queue not initialised in GThreadPool + - #2020 g_network_monitor_base_add_network() improperly unrefs GInetAddressMask + - !978 Various fixes to make gtkdoc-check pass on glib + - !1018 docs: tag enclose 'all' and 'help' values + - !1170 Avoid C++20 deprecated assignment to volatile + - !1296 tests: Skip GMemoryMonitor tests if the dbusmock template is not available + - !1307 Remove global declaration of GMemoryMonitor + - !1322 gmain: Mark G_SOURCE_FUNC as available in 2.58 + - !1333 Add and use G_SIZEOF_MEMBER() macro + - !1337 genviron: Message if g_setenv()/g_unsetenv() are used after threads spawned + - !1338 tests: Skip GMemoryMonitor tests if xdg-desktop-portal is not available + - !1344 meson: libmount autodectection + - !1345 gio-tool-info: Print unix mount information where available + - !1346 gfile: Do not return target-uri from g_file_peek_path() + - !1347 Revert "gtlscertificate: Add support for PKCS #11 backed certificates" + - !1348 ghash: Clarify that g_hash_table_add() always consumes the key + - !1349 doc: Clarify that _locker_new() does not actually allocate memory + - !1351 glib.supp: update g-threaded-resolver-getaddrinfo-config + +* Translation updates: + - Japanese + - Lithuanian + - Malay + - Portuguese (Brazil) + - Swedish + + +Overview of changes in GLib 2.63.4 +================================== + +* Fix various race conditions on signal emission in GDBus (#604, #978, #1232) + +* Change thread pools so that thread attributes (in particular, priority) are + inherited from the thread which created the `GThreadPool` initially, rather + than from the thread which is pushing a new job into the pool (#1834, #2007) + +* Expand support for running Windows apps with + `g_app_info_launch_default_for_uri()` using rundll32 on Windows (#1932) + +* Support multiple directories in `GSETTINGS_SCHEMA_DIR` environment variable (#1998) + +* Support full Julian day range in `TZ` environment variable (#1999) + +* Apply recursion depth limits to variants in D-Bus messages (!1201) + +* Support adding call flags and timeouts to method calls generated by + `gdbus-codegen` through the new `--glib-min-version` option (!1286) + +* Fully deprecate TLS rehandshakes; they are now ignored due to TLS protocol + changes (!1305) +* Bugs fixed: + - #198 g_fopen and friends: should also state how to close a stream + - #604 GDBus name watching dispatch is buggy/excessively-complicated + - #833 g_object_set: document the need to cast varargs + - #978 SIGSEGV in on_name_lost_or_acquired + - #1232 Insufficient thread safety around GDBusObjectManagerClient + - #1416 Re-add macOS CI + - #1834 Unwanted priority/etc inheritance with GThreadPool and GThread and the POSIX implementation + - #1932 Windows: Gio.AppInfo.launch_default_for_uri seems not to work for local files/folders + - #1983 glib:gio / dbus-appinfo test fails: GLib-GIO:ERROR:../../../../Projects/glib/gio/tests/dbus-appinfo.c:326:on_flatpak_open: 'g_file_equal (files[0], f)' should be TRUE + - #1997 Base64 encoding with "break_lines" claims to wrap at 72 characters but seems to wrap at 76 + - #1998 support multiple directories in GSETTINGS_SCHEMA_DIR + - #1999 GTimeZone fails to accept full Julian day range when parsing the direct $TZ string format + - #2007 Thread scheduler attributes fail under valgrind + - !388 ci: Avoid downloading subprojects for each job + - !1111 gio: test that launch_uris() exports files with the document portal when launching a flatpak + - !1201 gdbusmessage: Limit recursion of variants in D-Bus messages + - !1279 tests: Fix an error message set by foo_set_property() + - !1286 gdbus-codegen: Add a GDBusCallFlags arg to method calls + - !1291 gio-tool-list: Add an option to print display names + - !1294 GMemoryMonitor docs fixes + - !1295 gio: Fix socket test + - !1301 GThread - Inherit parent thread priority by default for new Win32 threads + - !1303 gvariant-core: Don't pass NULL second argument to memcpy + - !1305 Fully deprecate TLS rehandshakes + - !1308 gsocketclient: run timeout source on the task's main context + - !1309 Fix crash in gutils when application is prevented access to passwd file + - !1317 gfdonotificationbackend: remove notifications when bus name vanishes + - !1320 subprojects: Temporarily avoid using wrapdb while it’s down + - !1324 ci: Add some documentation to the style check CI test + - !1325 Check for SYS_sched_getattr before using it unconditionally + - !1330 W32: Correctly set st_ino when doing private stat() + - !1334 gthread: Ensure GThreadSchedulerSettings is always defined + +* Translation updates: + - Catalan + - Galician + - Hungarian + - Indonesian + - Polish + - Portuguese (Brazil) + - Spanish -Overview of changes in GLib 2.62.4 + +Overview of changes in GLib 2.63.3 ================================== -* Apply recursion depth limits to variants in D-Bus messages (!1290) +* Add a `--glib-min-version` argument to `gdbus-codegen` which controls breaks in the API of generated code (#1726) + +* Add `g_clear_list()` API to clear `GList`s to `NULL` (#1943) + +* Add a `GMemoryMonitor` API to be notified of memory pressure situations using the low-memory-monitor project (!1005) + +* Add support for dispose functions for `GSource` implementations (!1175) + +* Tighten up validation of GObject signal and property names, allowing performance improvements (!1224) + +* Fix installation path of GIO modules on MSVC to be the bindir (!1254) + +* Bugs fixed: + - #650 g_signal_lookup gives too many warnings + - #1011 GListStore, easily find if the item is already inserted + - #1130 gdbus-codegen: Add an option to strictly generate markdown in source comments + - #1687 glocalvfs.c uses non-thread-safe getpwnam() + - #1726 Warn when method/signal uses type 'h' but lacks GDBus.C.UnixFD annotation + - #1935 Assert in _kqsub_free seems to be too strict + - #1943 Consider g_clear_list() + - #1947 Documentation clarification for g_uuid_string_random() + - #1953 Documentation for g_type_init() and others missing from online gtk-doc documentation + - #1961 A typo in the comment of `g_settings_schema_get_path`: threfore -> therefore + - !1005 gio: Add GMemoryMonitor to monitor for low-memory + - !1172 gptrarray: Add an example to the g_ptr_array_steal() docs + - !1175 Implement a dispose function for GSource + - !1223 Add additional valgrind suppressions + - !1224 Signal name handling improvements + - !1230 ci: Run installed-tests on Fedora + - !1235 Add sudo to Fedora docker image + - !1239 tests: Run "timeout tests" sequentially + - !1248 ci: Update all Debian CI runners to use v5 of the Dockerfile + - !1249 gio-tool-mount: Allow mounting by the given UUID + - !1252 ci: Fix running all jobs on merge requests + - !1253 gthread: Fix "zero as null pointer" warning + - !1254 giomodule: gio modules are no longer installed in bindir on MSVC + - !1255 ci: Build Docker images rather than OCI images if using podman + - !1256 gdate: Add autoptr support + - !1258 Minor CI fixups + - !1261 gtk-doc: Ensure we have recent enough version + - !1262 tests: Add tests for the gdbus-codegen executable + - !1265 build: don't check for protected visibility + - !1267 Revert "doc: Workaround gtkdoc-scan bug leading to undocumented symbols" + - !1268 ci: Work-around successful installed tests having no logs + - !1269 gvariant: Add guard to g_variant_get() + - !1271 tests: Enable GDBus debug for a number of unreliable tests + - !1274 trash portal: Don't follow symlinks + - !1275 Small doc correction + - !1277 Various gtk-doc improvements + - !1278 Update installed tests CI + - !1280 clang-format-diff: Output diff for multiple files, not just one + - !1282 Revert "Revert "docs: remove GDBusObjectManager example"" + - !1284 Update POTFILES.in 191212 + - !1287 atomic/tests: test g_atomic_pointer_compare_and_exchange() with const pointers + - !1289 gtype: Define auto-cleanup functions for Module class + +* Translation updates: + - Spanish + + +Overview of changes in GLib 2.63.2 +================================== + +* Use `lldb` rather than `gdb` on macOS for debugging (#1004) + +* Switch the atomic builtins from `__sync_fetch_*()` to the slightly more modern + `__atomic_*()` (#1750) + +* Fix calculation of `gsize` width on various platforms (including OpenBSD) (#1777) + +* Fix undefined behaviour causing brokenness in `g_utf8_find_prev_char()` when + compiling with GCC ≥ 8 (#1917) + +* Revert UNIX mode changes in `G_FILE_ATTRIBUTE_ID_UNIX_MODE` which broke OSTree (#1934) + +* Slightly improve performance for signal emissions when no handlers are connected (!1083) + +* Add `g_task_return_value()` and `g_task_propagate_value()` APIs to allow + `GTask` to be used from language bindings more easily (!1216) + +* Fix a file monitoring crash on kqueue-based systems (BSD) (!1221) * Bugs fixed: + - #1004 [PATCH] Make gbacktrace use lldb on Mac OS X + - #1552 CI: Add code style checks + - #1750 Switch from __sync_fetch_*() to __atomic_*() in glib/gatomic.h + - #1777 gsize: improper typedef on (at least) OpenBSD + - #1895 Regression: glib does not compile on centos 6: "objcopy: unrecognized option '--add-symbol'" + - #1917 Test utf8-pointer fails with static build, LTO, optimisations, and new GCC + - #1930 glib/tests/bookmarkfile.c:385:test_modify: assertion failed: (stamp == now) + - #1934 ostree tests broken since bfdc5fc4fc84ef8518d2d1a328c8482cf5a38e98: File '/tmp/test-tmp-libostree_test-basic-user.sh.test-QB4SA0/diff-test2' is not empty - #1938 GDateTime doesn't support leap seconds - - !1240 Backport !1233 “gdatetime: Handle leap seconds in ISO8601 dates” to glib-2-62 - - !1257 Backport !1232 “kqueue: Do not return early from _kqsub_cancel” to glib-2-62 - - !1266 Backport !1265 “build: don't check for protected visibility” to glib-2-62 - - !1276 Backport !1274 “trash portal: Don't follow symlinks” to glib-2-62 - - !1290 Backport !1201 “gdbusmessage: Limit recursion of variants in D-Bus messages” to glib-2-62 + - #1940 atomics test fails on FreeBSD CI since !1123 + - !1039 Improve documentation for footgun function g_tls_client_connection_copy_session_state() + - !1083 Use the GObject hole on 64bit arches for some flags to improve performance + - !1202 CI updates after !1177 + - !1208 gutils: Slightly improve docs formatting for g_get_os_info() + - !1209 Make ld executable configurable + - !1210 gdbus-server-auth test: Include gcredentialsprivate.h + - !1213 gsocket: Improve diagnostics on bind() failure + - !1214 gvariant, gbytes: Avoid memcmp (NULL, ., 0) or memcmp (., NULL, 0) + - !1216 Make GTask more binding-friendly + - !1218 gdb: Fix GHashTable pretty printer off-by-one error + - !1220 gparam: fix memory leak in g_param_value_defaults() + - !1221 Add NOTE_REVOKE to the list of the monitoring events + - !1225 gtlsconnection: clarify handshake() documentation + - !1227 Deprecate old GTlsConnection functionality even harder! + - !1231 Fix build on old libc that does not define _SC_HOST_NAME_MAX + - !1238 gstrfuncs: use gsize type internally for strv functions + - !1242 gfileinfo: Clarify the documentation for G_FILE_ATTRIBUTE_UNIX_MODE + - !1243 docs: Fix "occurred" typos in API documentation + +* Translation updates: + - Spanish -Overview of changes in GLib 2.62.3 +Overview of changes in GLib 2.63.1 ================================== -* Use `poll()` in `g_spawn_sync()` rather than `select()`, which is subject to - FD limits (#954) +* Several usability improvements to command line `gio` tool (!1153) + +* Add `g_array_steal()`, `g_ptr_array_steal()` and `g_byte_array_steal()` APIs (#285) + +* Add `g_get_os_info()` API (!1063, !1160) + +* Add `g_warning_once()` API (!1028) -* Fix undefined behaviour with `g_utf8_find_prev_char()` (#1917) +* Always resolve `localhost` to loopback address in `GResolver` (!616) + +* Add `GMainContextPusher` API (!983) + +* Limit recursion in `g_variant_parse()` (!1173) + +* Fix crash in `g_spawn()` with high FD numbers due to use of `select()` rather + than `poll()` (#954) + +* Allow passing empty `GValue`s to `g_param_value_set_default()` (!1186) + +* Escape header guards generated by `gdbus-codegen` better (#1379) * Bugs fixed: + - #285 [PATCH] add array steal and memdup functions - #954 The g_spawn_sync() function uses select() which has limitations - #1318 rare failure in gdbus-peer test: invalid uninstantiatable type '(null)' in cast to 'GDBusServer' + - #1379 gdbus-codegen generates invalid header guards when build directory contains a + character + - #1622 NULL pointer derefs on g_vasprintf() failure + - #1813 g_option_context_add_main_entries() is missing array annotation for entries parameter + - #1831 No reply on private socket due to auth problem + - #1836 gobject.c uses undefined annotation “(not optional)” + - #1858 docs/reference/gobject/tut_gobject.xml: object properties example uses deprecated API + - #1877 g_cancellable_source_new annotated with 'skip' + - #1896 Use after free when calling g_dbus_connection_flush_sync() in a dedicated thread - #1897 glib 2.62.0 fails test 'test_writev_no_vectors' wih gcc7 - #1903 use-after-free in mimeapps test causes intermittent segfault during testing + - #1906 test_os_info fails on FreeBSD - #1916 objcopy not used from cross-compilation file in GIO tests - - #1917 Test utf8-pointer fails with static build, LTO, optimisations, and new GCC - - !1174 Backport !1164 “use-after-free fix in mimeapps test” to glib-2-62 - - !1184 Backport !1173 “gvariant: Limit recursion in g_variant_parse()” to glib-2-62 - - !1194 Backport !1176, !1183, !1188, !1191 to `glib-2-62` - - !1203 Backport !1192, !1193, !1197 Fixes for gdbus-peer tests to glib-2-62 - - !1207 Backport !1206 “goption: Relax assertion to avoid being broken by kdeinit5” to glib-2-62 - - !1215 [2.62] gdbus-peer: Specifically listen on 127.0.0.1 - - !1219 Backport !1218 “gdb: Fix GHashTable pretty printer off-by-one error” - - !1222 Backport !1221 “Add NOTE_REVOKE to the list of the monitoring events” to glib-2-62 - - !1228 Backport !1199 “gunicode: Fix UB in gutf8.c and utf8-pointer test” to glib-2-62 - - -Overview of changes in GLib 2.62.2 -================================== + - #1923 Recent Versions of GLib Break Dolphin File-Manager's Thumbnailing when Using 'gtk2' Style + - !616 Always resolve localhost to loopback address + - !983 gmain: Add GMainContextPusher convenience API + - !1014 tests: Add a test for g_assert_finalize_object() + - !1028 gmessages: Add g_warning_once() + - !1035 Switching from C gnu89 to C gnu99 standard + - !1063 gutils: Add g_get_os_info() + - !1082 gdatetime: Document RFC 3339 extensions when parsing ISO 8601 + - !1105 syscall flood on every time*() function call + - !1120 Update documentation with FreeBSD build instructions + - !1135 gmain: use atomic operation instead of GMutex to access g_main_context_default() + - !1146 Solaris build fixes + - !1147 gmodule: fix typo in doc comment + - !1148 gio/gfileinfo: fix parameter references + - !1149 gio/gfile: fix parameter reference for value_p + - !1150 gio/gfile: fix parameter references to @contents + - !1151 gio/gfile: fix typo in doc comment + - !1152 gwinhttpvfs: Handle g_get_prgname() returning NULL + - !1153 Several gio-tool bash completion fixes and improvements + - !1155 Strict-aliasing fixes to new atomic built-ins + - !1157 Fix various compiler warnings on Android + - !1160 Add Windows support to g_get_os_info() + - !1161 hash: Remove an assertion from the hot path + - !1163 gcharset: Expand the documentation for g_get_locale_variants() + - !1165 Use uname as a fallback to get OS info + - !1167 Fix some minor leaks in testfilemonitor + - !1168 Fix gdatetime tests on toolbox + - !1171 Revert "gdbus-codegen: emit GUnixFDLists if an arg has type 'h'" + - !1173 gvariant: Limit recursion in g_variant_parse() + - !1177 ci: Add libdbus development files to CI Docker images + - !1179 Improve GPtrArray doc-comments + - !1180 array: Avoid use of memcpy(dest, NULL, 0) + - !1181 gmain: Clarify thread safety of some common GSource functions + - !1182 gio: Fix typo in URL + - !1186 Allow using an empty GValue with g_param_value_set_default() + - !1189 gparamspecs: Fix type class leaks on error handling paths + - !1197 Fix GDBus test failures on non-Linux (in particular FreeBSD) + - !1200 Minor fixes from a scan-build run -* Bugs fixed: - - #1896 Use after free when calling g_dbus_connection_flush_sync() in a dedicated thread - - !1154 Backport !1152 “gwinhttpvfs: Handle g_get_prgname() returning NULL” to glib-2-62 - - !1156 Backport !1146 Solaris fixes to glib-2-62 +* Translation updates: + - Catalan + - Chinese (Taiwan) + - Spanish -Overview of changes in GLib 2.62.1 +Overview of changes in GLib 2.63.0 ================================== +* Add g_fsync() API (#35) + * Fix regression in g_file_copy() when passing `G_FILE_COPY_TARGET_DEFAULT_PERMS` flag; the destination permissions would be private rather than following the process’ umask (!1142) @@ -100,22 +1379,57 @@ Overview of changes in GLib 2.62.1 * Always build the tests if installed-tests are enabled, so that the tests can actually be installed (!1141) +* Rework atomic function implementations to use memory barrier in the correct + place (when compiler intrinsics aren’t providing the atomics), and fix + signedness issues (#1449, #1565) + +* Use the OS’ `fdwalk()` function (if safe) to speed up `g_spawn_*()` on BSD (#1638) + +* Remove the macOS `dyld` `GModule` implementation in favour of `dl` instead (!1093) + +* Bump Python requirement to ≥ 3.5, which we implicitly relied on anyway through + our Meson dependency (!1132) + * Bugs fixed: + - #35 add g_fsync to API - #174 g_file_copy always preserves permissions, even if G_FILE_COPY_ALL_METADATA flag is not set + - #259 docs: fix a misunderstanding in g_type_add_interface_* + - #767 g_signal_lookup fails if class is not referenced + - #1052 g_io_write_chars calls abort when given a null byte as input + - #1449 glib fallback atomic int/ptr get/set have memory barrier in wrong place + - #1565 Signedness of atomic operations + - #1638 g_spawn_*() is extremely slow under certain circumstances + - #1809 Provide API for working with PKCS11 backed certificates + - #1843 TSAN false positive with g_atomic_pointer_get/g_atomic_pointer_set under Clang - #1865 g_variant_get_data_as_bytes fails after serializing a variant - #1875 Segfault and Overflow in __gio_xdg_cache_mime_type_subclass() with Wps-Office installed - #1887 glib 2.62.0 breaks loading dylibs as modules - #1888 2.62: docs build on Windows broken - - !1021 docs: Remove priv pointers from the tutorial example - - !1094 Backport to 2.62: gmodule: use dl implementation on macOS - - !1101 Backport !1092 “Fix doc build on Windows” to glib-2-62 - - !1102 Backport !1080 “tests: Fix skipping mkdir-with-parents-permission test” to glib-2-62 - - !1103 Backport !1085 “xdgmime: Prevent infinite loops from badly-formed MIME registrations” to glib-2-62 - - !1127 Backport !1125 and !1115 GDateTime parsing fixes to glib-2-62 - - !1128 Backport !1043 “gvariant: Handle empty serialisations in get_child_value()” to glib-2-62 - - !1140 [2.62] g_file_info_get_modification_date_time: Calculate in integer domain - - !1141 [2.62] Always build tests if we enabled installed-tests - - !1142 Backport !1134 Fix for file copy permissions to glib-2-62 + - #1897 glib 2.62.0 fails test 'test_writev_no_vectors' wih gcc7 + - !1020 docs: Remove priv pointers from the tutorial example + - !1062 gtype: mark the inline functions in G_DECLARE_*_TYPE() as UNUSED + - !1080 tests: Fix skipping mkdir-with-parents-permission test + - !1088 Various small scan-build fixes + - !1090 giochannel: Clarify type of GSource callback in documentation + - !1093 gmodule: remove macOS dyld implementation + - !1095 Define G_IOV_MAX to 512 on macOS/iOS + - !1099 gmem: clarify that g_malloc always uses the system allocator + - !1109 doc: fix typo in gio/gsettings.c + - !1110 gio: Add missing "gio remove" option to bash completion script + - !1112 Add version macros for GLib 2.64 + - !1115 gdatetime: Fix error handling in g_date_time_new_ordinal() + - !1116 gmarkup: Add a limit on the number of attributes in an element + - !1119 Annotate the return value of various utility functions + - !1124 docs: Fix typo in GConverter{Input,Output}Stream section titles + - !1125 gdatetime: Fix error handling in g_date_time_new_week() + - !1126 fileinfo: Mention that usec mtimes are set + - !1129 gdate: Fix tautological comparison warnings on Android + - !1130 Improve GLIB_DEPRECATED_MACRO_FOR output + - !1131 gio/gfileinfo: fix param reference in doc comment + - !1132 build: Bump Python requirement to ≥ 3.5 + - !1137 gregistrysettings: bump key name length to 2048 + - !1138 Always build tests if we enabled installed-tests + - !1139 g_file_info_get_modification_date_time: Calculate in integer domain * Translation updates: - Danish @@ -2409,6 +3723,10 @@ Translation updates: Overview of changes in GLib 2.48.0 ================================== + * The system copy of PCRE is now used by default to implement GRegex. + Configure with --with-pcre=internal if a system PCRE version + is unavailable or undesired. + * a minor build fix in the name of determinism * a few coverity fixes @@ -2682,6 +4000,21 @@ Overview of changes in GLib 2.47.1 Overview of changes in GLib 2.46.0 ================================== +* GTask no longer imposes a fixed limit on the number of tasks that + can be run_in_thread() simultaneously, since doing this inevitably + results in deadlocks in some use cases. Instead, it now has a base + number of threads that can be used "for free", but will gradually + add more threads to the pool if too much time passes without any + tasks completing. + + The exact behavior may continue to change in the future, and it's + possible that some future version of GLib may not do any + rate-limiting at all. As a result, you should no longer assume that + GTask will rate-limit tasks itself (or, by extension, that calls to + certain async gio methods will automatically be rate-limited for + you). If you have a very large number of tasks to run, and don't + want them to all run at once, you should rate-limit them yourself. + * Disable runtime-deprecation warnings * Fix marshalling of flags on bigendian 64bit architectures @@ -3597,6 +4930,21 @@ Overview of changes from GLib 2.39.91 to GLib 2.39.92 This is a release candidate for 2.40.0. +* g_test_run() no longer runs tests in exactly the order they are + registered; instead, it groups them according to test suites (ie, + path components) like the documentation always claimed it did. In + some cases, this can result in a sub-optimal ordering of tests, + relative to the old behavior. The fix is to change the test paths to + properly group together the tests that should run together. (eg, if + you want to run test_foo_simple(), test_bar_simple(), and + test_foo_using_bar() in that order, they should have test paths like + "/simple/foo", "/simple/bar", "/complex/foo-using-bar", not + "/foo/simple", "/bar/simple", "/foo/using-bar" (which would result + in test_foo_using_bar() running before test_bar_simple()). + + (The behavior actually changed in GLib 2.36, but it was not + documented at the time, since we didn't realize it mattered.) + There are no major changes in this release, but a few serious bugs have been fixed. @@ -4724,6 +6072,28 @@ Overview of changes fron GLib 2.36.0 to 2.37.0 Overview of changes fron GLib 2.35.9 to 2.36.0 ============================================== +* It is no longer necessary to call g_type_init(). If you are + loading GLib as a dynamic module, you should be careful to avoid + unloading it, then subsequently loading it again. This never + really worked before, but it is now explicitly undefined behavior. + Note that if g_type_init() was the only explicit use of a GObject + API and you are using linker flags such as --no-add-needed, then + you may have to artificially use some GObject call to keep the + linker from optimizing away -lgobject. We recommend to use + g_type_ensure (G_TYPE_OBJECT) for this purpose. + +* This release contains an incompatible change to the g_get_home_dir() + function. Previously, this function would effectively ignore the HOME + environment variable and always return the value from /etc/password. + As of this version, the HOME variable is used if it is set and the + value from /etc/passwd is only used as a fallback. + +* The 'flowinfo' and 'scope_id' fields of GInetSocketAddress + (introduced in GLib 2.32) have been fixed to be in host byte order + rather than network byte order. This is an incompatible change, but + the previous behavior was clearly broken, so it seems unlikely that + anyone was using it. + This release contains only small bugfixes and translations updates. - g_file_copy(): fix bug where attributes were not applied properly to @@ -5207,6 +6577,13 @@ The remaining changes should not cause problems. Overview of changes from GLib 2.33.14 to 2.34.0 =============================================== +* GIO now looks for thumbnails in XDG_CACHE_HOME, following a + recent alignment of the thumbnail spec with the basedir spec. + +* The default values for GThreadPools max_unused_threads and + max_idle_time settings have been changed to 2 and 15*1000, + respectively. + * Bug fixes: 654239 g_type_init()'s docs have no statement about how to... 674620 Update GSettings migration guide for intltool updates @@ -5727,6 +7104,49 @@ Overview of changes from GLib 2.32.0 to 2.32.1 Overview of changes from GLib 2.31.22 to 2.32.0 =============================================== +* It is no longer necessary to use g_thread_init() or to link against + libgthread. libglib is now always thread-enabled. Custom thread + system implementations are no longer supported (including errorcheck + mutexes). + +* The thread and synchronisation APIs have been updated. + GMutex and GCond can be statically allocated without explicit + initialisation, as can new types GRWLock and GRecMutex. The + GStatic_______ variants of these types have been deprecated. GPrivate + can also be statically allocated and has a nicer API (deprecating + GStaticPrivate). Finally, g_thread_create() has been replaced with a + substantially simplified g_thread_new(). + +* The g_once_init_enter()/_leave() functions have been replaced with + macros that allow for a pointer to any gsize-sized object, not just a + gsize*. The assertions to ensure that a pointer to a correctly-sized + object is being used will not work with generic pointers (ie: (void*) + and (gpointer) casts) which would have worked with the old version. + +* It is now mandatory to include glib.h instead of individual headers. + +* The -uninstalled variants of the pkg-config files have been dropped. + +* For a long time, gobject-2.0.pc mistakenly declared a public + dependency on gthread-2.0.pc (when the dependency should have been + private). This means that programs got away with calling + g_thread_init() without explicitly listing gthread-2.0.pc among their + dependencies. + + gthread has now been removed as a gobject dependency, which will cause + such programs to break. + + The fix for this problem is either to declare an explicit dependency + on gthread-2.0.pc (if you care about compatibility with older GLib + versions) or to stop calling g_thread_init(). + +* g_debug() output is no longer enabled by default. It can be enabled + on a per-domain basis with the G_MESSAGES_DEBUG environment variable + like + G_MESSAGES_DEBUG=domain1,domain2 + or + G_MESSAGES_DEBUG=all + * Bugs fixed: 671988 Quickly registering / unregistering objects on bus... 672095 glib needs stable sort function @@ -6404,6 +7824,11 @@ list below attempts to summarise, but not every change is listed. Overview of changes from GLib 2.29.18 to 2.29.90 ================================================ +* GObject includes a generic marshaller, g_cclosure_marshal_generic. + To use it, simply specify NULL as the marshaller in g_signal_new(). + The generic marshaller is implemented with libffi, and consequently + GObject depends on libffi now. + * API/ABI changes: - unix signal watches now match the API of all of the other sources - revert the addition of g_date_time_source_new () from last release @@ -6969,6 +8394,10 @@ Overview of Changes from GLib 2.28.0 to 2.29.2 Overview of Changes from GLib 2.27.93 to 2.28.0 =============================================== +* The GApplication API has changed compared to the version that was + included in the 2.25 development snapshots. Existing users will need + adjustments. + * Bugs fixed: 641363 GInitable documentation isn't clear about that finalize... 641395 Add more data about the origin application to the "Lau... @@ -8224,6 +9653,23 @@ Overview of Changes from GLib 2.24.0 to GLib 2.25.0 Overview of Changes from GLib 2.23.6 to GLib 2.24.0 =================================================== +* It is now allowed to call g_thread_init(NULL) multiple times, and + to call glib functions before g_thread_init(NULL) is called + (although the later is mainly a change in docs as this worked before + too). See the GThread reference documentation for the details. + +* GObject now links to GThread and threads are enabled automatically + when g_type_init() is called. + +* GObject no longer allows to call g_object_set() on construct-only properties + while an object is being initialized. If this behavior is needed, setting a + custom constructor that just chains up will re-enable this functionality. + +* GMappedFile on an empty file now returns NULL for the contents instead of + returning an empty string. The documentation specifically states that code + may not rely on nul-termination here so any breakage caused by this change + is a bug in application code. + * Bug fixes: 613601 buglet in dup_close_on_exec_fd 584284 g_data_input_stream_read_until_async behaves confusingly @@ -8585,6 +10031,10 @@ Overview of Changes from GLib 2.22.0 to GLib 2.22.1 Overview of Changes from GLib 2.21.6 to GLib 2.22.0 =================================================== +* Repeated calls to g_simple_async_result_set_op_res_gpointer used + to leak the data. This has been fixed to always call the provided + destroy notify. + * Add gdb python macros to make gobject debugging more pleasant * Bugs fixed: @@ -8944,6 +10394,18 @@ Overview of Changes from GLib 2.20.0 to GLib 2.20.1 Overview of Changes from GLib 2.19.9 to GLib 2.20.0 =================================================== +* The functions for launching applications (e.g. g_app_info_launch() + + friends) now passes a FUSE file:// URI if possible (requires gvfs + with the FUSE daemon to be running and operational). With gvfs 2.26, + FUSE file:// URIs will be mapped back to gio URIs in the GFile + constructors. The intent of this change is to better integrate + POSIX-only applications, see bug #528670 for the rationale. The + only user-visible change is when an application needs to examine an + URI passed to it (e.g. as a positional parameter). Instead of + looking at the given URI, the application will now need to look at + the result of g_file_get_uri() after having constructed a GFile + object with the given URI. + * Base64 support: Avoid integer overflows. CVE-2008-4316 * Bugs fixed: @@ -9323,6 +10785,13 @@ Overview of Changes from GLib 2.18.0 to GLib 2.18.1 Overview of Changes from GLib 2.17.7 to GLib 2.18.0 =================================================== +* The recommended way of using GLib has always been to only include the + toplevel headers glib.h, glib-object.h and gio.h. GLib enforces this by + generating an error when individual headers are directly included. + To help with the transition, the enforcement is not turned on by + default for GLib headers (it is turned on for GObject and GIO). + To turn it on, define the preprocessor symbol G_DISABLE_SINGLE_INCLUDES. + * Win32: - rework the g_poll() implementation to match poll() semantics more closely @@ -9737,6 +11206,10 @@ Overview of Changes from GLib 2.16.0 to GLib 2.16.1 Overview of Changes from GLib 2.15.6 to GLib 2.16.0 =================================================== +* GLib now includes GIO, which adds optional dependencies against libattr + and libselinux for extended attribute and SELinux support. Use + --disable-xattr and --disable-selinux to build without these. + * Fix the definition of G_INLINE_FUNC to work with gcc 4.3.0 * GIO: @@ -10658,6 +12131,36 @@ Overview of Changes from GLib 2.10.0 to GLib 2.10.1 Overview of Changes from GLib 2.9.6 to GLib 2.10.0 ================================================== +* The functions g_snprintf() and g_vsnprintf() have been removed from + the gprintf.h header, since they are already declared in glib.h. This + doesn't break documented use of gprintf.h, but people have been known + to include gprintf.h without including glib.h. + +* The Unicode support has been updated to Unicode 4.1. This adds several + new members to the GUnicodeBreakType enumeration. + +* The support for Solaris threads has been retired. Solaris has provided + POSIX threads for long enough now to have them available on every + Solaris platform. + +* 'make check' has been changed to validate translations by calling + msgfmt with the -c option. As a result, it may fail on systems with + older gettext implementations (GNU gettext < 0.14.1, or Solaris gettext). + 'make check' will also fail on systems where the C compiler does not + support ELF visibility attributes. + +* The GMemChunk API has been deprecated in favour of a new 'slice + allocator'. See the g_slice documentation for more details. + +* A new type, GInitiallyUnowned, has been introduced, which is + intended to serve as a common implementation of the 'floating reference' + concept that is e.g. used by GtkObject. Note that changing the + inheritance hierarchy of a type can cause problems for language + bindings and other code which needs to work closely with the type + system. Therefore, switching to GInitiallyUnowned should be done + carefully. g_object_compat_control() has been added to GLib 2.8.5 + to help with the transition. + * Bugs fixed: 328997 64bit pointer trunction in glib slab-allocator [Pascal Hofstee] @@ -11092,6 +12595,65 @@ Overview of Changes from GLib 2.6.0 to GLib 2.6.1 Overview of Changes from GLib 2.4.x to GLib 2.6.0 ================================================= +* GLib 2.6 introduces the concept of 'GLib filename encoding', which is the + on-disk encoding on Unix, but UTF-8 on Windows. All GLib functions + returning or accepting pathnames have been changed to expect + filenames in this encoding, and the common POSIX functions dealing + with pathnames have been wrapped. These wrappers are declared in the + header which must be included explicitly; it is not + included through . + + On current (NT-based) Windows versions, where the on-disk file names + are Unicode, these wrappers use the wide-character API in the C + library. Thus applications can handle file names containing any + Unicode characters through GLib's own API and its POSIX wrappers, + not just file names restricted to characters in the system codepage. + + To keep binary compatibility with applications compiled against + older versions of GLib, the Windows DLL still provides entry points + with the old semantics using the old names, and applications + compiled against GLib 2.6 will actually use new names for the + functions. This is transparent to the programmer. + + When compiling against GLib 2.6, applications intended to be + portable to Windows must take the UTF-8 file name encoding into + consideration, and use the gstdio wrappers to access files whose + names have been constructed from strings returned from GLib. + +* Likewise, g_get_user_name() and g_get_real_name() have been changed + to return UTF-8 on Windows, while keeping the old semantics for + applications compiled against older versions of GLib. + +* The GLib uses an '_' prefix to indicate private symbols that + must not be used by applications. On some platforms, symbols beginning + with prefixes such as _g will be exported from the library, on others not. + In no case can applications use these private symbols. In addition to that, + GLib+ 2.6 makes several symbols private which were not in any installed + header files and were never intended to be exported. + +* To reduce code size and improve efficiency, GLib, when compiled + with the GNU toolchain, has separate internal and external entry + points for exported functions. The internal names, which begin with + IA__, may be seen when debugging a GLib program. + +* On Windows, GLib no longer opens a console window when printing + warning messages if stdout or stderr are invalid, as they are in + "Windows subsystem" (GUI) applications. Simply redirect stdout or + stderr if you need to see them. + +* The child watch functionality tends to reveal a bug in many + thread implementations (in particular the older LinuxThreads + implementation on Linux) where it's not possible to call waitpid() + for a child created in a different thread. For this reason, for + maximum portability, you should structure your code to fork all + child processes that you want to wait for from the main thread. + +* A problem was recently discovered with g_signal_connect_object(); + it doesn't actually disconnect the signal handler once the object being + connected to dies, just disables it. See the API docs for the function + for further details and the correct workaround that will continue to + work with future versions of GLib. + * Major new APIs - GOption, a commandline option parser - GKeyFile, a parser/editor for the .ini like files diff --git a/OAT.xml b/OAT.xml old mode 100644 new mode 100755 diff --git a/README.OpenSource b/README.OpenSource old mode 100644 new mode 100755 index 7fadb9b339410977c83f097446b06bf81df03f1c..23b7fc1f1d9fc1509a3d6985ef6afb5c7bdd7050 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name": "glib", "License": "LGPL V2.1", "License File": "COPYING", - "Version Number": "2.62.5", + "Version Number": "2.68.1", "Upstream URL": "https://www.gtk.org/", "Description": "GLib is the low-level core library that forms the basis for projects such as GTK and GNOME. It provides data structure handling for C, portability wrappers, and interfaces for such runtime functionality as an event loop, threads, dynamic loading, and an object system." } diff --git a/README.md b/README.md index 6cdd66cf53be11b71bdc1002e6e5444a81fc3d65..9ef3b3d6b057cebe195a78e2156e2d59422a9a72 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ In the bug report please include: As a last resort, you can also provide a pointer to a larger piece of software that can be downloaded. * If the bug was a crash, the exact text that was printed out - when the crash occured. + when the crash occurred. * Further information such as stack traces may be useful, but is not necessary. @@ -47,287 +47,3 @@ Closes: #123 Otherwise, create a new merge request that introduces the change, filing a separate issue is not required. - -## Notes - -### Notes about GLib 2.48 - -* The system copy of PCRE is now used by default to implement GRegex. - Configure with --with-pcre=internal if a system PCRE version - is unavailable or undesired. - -### Notes about GLib 2.46 - -* GTask no longer imposes a fixed limit on the number of tasks that - can be run_in_thread() simultaneously, since doing this inevitably - results in deadlocks in some use cases. Instead, it now has a base - number of threads that can be used "for free", but will gradually - add more threads to the pool if too much time passes without any - tasks completing. - - The exact behavior may continue to change in the future, and it's - possible that some future version of GLib may not do any - rate-limiting at all. As a result, you should no longer assume that - GTask will rate-limit tasks itself (or, by extension, that calls to - certain async gio methods will automatically be rate-limited for - you). If you have a very large number of tasks to run, and don't - want them to all run at once, you should rate-limit them yourself. - -### Notes about GLib 2.40 - -* g_test_run() no longer runs tests in exactly the order they are - registered; instead, it groups them according to test suites (ie, - path components) like the documentation always claimed it did. In - some cases, this can result in a sub-optimal ordering of tests, - relative to the old behavior. The fix is to change the test paths to - properly group together the tests that should run together. (eg, if - you want to run test_foo_simple(), test_bar_simple(), and - test_foo_using_bar() in that order, they should have test paths like - "/simple/foo", "/simple/bar", "/complex/foo-using-bar", not - "/foo/simple", "/bar/simple", "/foo/using-bar" (which would result - in test_foo_using_bar() running before test_bar_simple()). - - (The behavior actually changed in GLib 2.36, but it was not - documented at the time, since we didn't realize it mattered.) - -### Notes about GLib 2.36 - -* It is no longer necessary to call g_type_init(). If you are - loading GLib as a dynamic module, you should be careful to avoid - unloading it, then subsequently loading it again. This never - really worked before, but it is now explicitly undefined behavior. - Note that if g_type_init() was the only explicit use of a GObject - API and you are using linker flags such as --no-add-needed, then - you may have to artificially use some GObject call to keep the - linker from optimizing away -lgobject. We recommend to use - g_type_ensure (G_TYPE_OBJECT) for this purpose. - -* This release contains an incompatible change to the g_get_home_dir() - function. Previously, this function would effectively ignore the HOME - environment variable and always return the value from /etc/password. - As of this version, the HOME variable is used if it is set and the - value from /etc/passwd is only used as a fallback. - -* The 'flowinfo' and 'scope_id' fields of GInetSocketAddress - (introduced in GLib 2.32) have been fixed to be in host byte order - rather than network byte order. This is an incompatible change, but - the previous behavior was clearly broken, so it seems unlikely that - anyone was using it. - -### Notes about GLib 2.34 - -* GIO now looks for thumbnails in XDG_CACHE_HOME, following a - recent alignment of the thumbnail spec with the basedir spec. - -* The default values for GThreadPools max_unused_threads and - max_idle_time settings have been changed to 2 and 15*1000, - respectively. - -### Notes about GLib 2.32 - -* It is no longer necessary to use g_thread_init() or to link against - libgthread. libglib is now always thread-enabled. Custom thread - system implementations are no longer supported (including errorcheck - mutexes). - -* The thread and synchronisation APIs have been updated. - GMutex and GCond can be statically allocated without explicit - initialisation, as can new types GRWLock and GRecMutex. The - GStatic_______ variants of these types have been deprecated. GPrivate - can also be statically allocated and has a nicer API (deprecating - GStaticPrivate). Finally, g_thread_create() has been replaced with a - substantially simplified g_thread_new(). - -* The g_once_init_enter()/_leave() functions have been replaced with - macros that allow for a pointer to any gsize-sized object, not just a - gsize*. The assertions to ensure that a pointer to a correctly-sized - object is being used will not work with generic pointers (ie: (void*) - and (gpointer) casts) which would have worked with the old version. - -* It is now mandatory to include glib.h instead of individual headers. - -* The -uninstalled variants of the pkg-config files have been dropped. - -* For a long time, gobject-2.0.pc mistakenly declared a public - dependency on gthread-2.0.pc (when the dependency should have been - private). This means that programs got away with calling - g_thread_init() without explicitly listing gthread-2.0.pc among their - dependencies. - - gthread has now been removed as a gobject dependency, which will cause - such programs to break. - - The fix for this problem is either to declare an explicit dependency - on gthread-2.0.pc (if you care about compatibility with older GLib - versions) or to stop calling g_thread_init(). - -* g_debug() output is no longer enabled by default. It can be enabled - on a per-domain basis with the G_MESSAGES_DEBUG environment variable - like - G_MESSAGES_DEBUG=domain1,domain2 - or - G_MESSAGES_DEBUG=all - -### Notes about GLib 2.30 - -* GObject includes a generic marshaller, g_cclosure_marshal_generic. - To use it, simply specify NULL as the marshaller in g_signal_new(). - The generic marshaller is implemented with libffi, and consequently - GObject depends on libffi now. - -### Notes about GLib 2.28 - -* The GApplication API has changed compared to the version that was - included in the 2.25 development snapshots. Existing users will need - adjustments. - -### Notes about GLib 2.26 - -* Nothing noteworthy. - -### Notes about GLib 2.24 - -* It is now allowed to call g_thread_init(NULL) multiple times, and - to call glib functions before g_thread_init(NULL) is called - (although the later is mainly a change in docs as this worked before - too). See the GThread reference documentation for the details. - -* GObject now links to GThread and threads are enabled automatically - when g_type_init() is called. - -* GObject no longer allows to call g_object_set() on construct-only properties - while an object is being initialized. If this behavior is needed, setting a - custom constructor that just chains up will re-enable this functionality. - -* GMappedFile on an empty file now returns NULL for the contents instead of - returning an empty string. The documentation specifically states that code - may not rely on nul-termination here so any breakage caused by this change - is a bug in application code. - -### Notes about GLib 2.22 - -* Repeated calls to g_simple_async_result_set_op_res_gpointer used - to leak the data. This has been fixed to always call the provided - destroy notify. - -### Notes about GLib 2.20 - -* The functions for launching applications (e.g. g_app_info_launch() + - friends) now passes a FUSE file:// URI if possible (requires gvfs - with the FUSE daemon to be running and operational). With gvfs 2.26, - FUSE file:// URIs will be mapped back to gio URIs in the GFile - constructors. The intent of this change is to better integrate - POSIX-only applications, see bug #528670 for the rationale. The - only user-visible change is when an application needs to examine an - URI passed to it (e.g. as a positional parameter). Instead of - looking at the given URI, the application will now need to look at - the result of g_file_get_uri() after having constructed a GFile - object with the given URI. - -### Notes about GLib 2.18 - -* The recommended way of using GLib has always been to only include the - toplevel headers glib.h, glib-object.h and gio.h. GLib enforces this by - generating an error when individual headers are directly included. - To help with the transition, the enforcement is not turned on by - default for GLib headers (it is turned on for GObject and GIO). - To turn it on, define the preprocessor symbol G_DISABLE_SINGLE_INCLUDES. - -### Notes about GLib 2.16 - -* GLib now includes GIO, which adds optional dependencies against libattr - and libselinux for extended attribute and SELinux support. Use - --disable-xattr and --disable-selinux to build without these. - -### Notes about GLib 2.10 - -* The functions g_snprintf() and g_vsnprintf() have been removed from - the gprintf.h header, since they are already declared in glib.h. This - doesn't break documented use of gprintf.h, but people have been known - to include gprintf.h without including glib.h. - -* The Unicode support has been updated to Unicode 4.1. This adds several - new members to the GUnicodeBreakType enumeration. - -* The support for Solaris threads has been retired. Solaris has provided - POSIX threads for long enough now to have them available on every - Solaris platform. - -* 'make check' has been changed to validate translations by calling - msgfmt with the -c option. As a result, it may fail on systems with - older gettext implementations (GNU gettext < 0.14.1, or Solaris gettext). - 'make check' will also fail on systems where the C compiler does not - support ELF visibility attributes. - -* The GMemChunk API has been deprecated in favour of a new 'slice - allocator'. See the g_slice documentation for more details. - -* A new type, GInitiallyUnowned, has been introduced, which is - intended to serve as a common implementation of the 'floating reference' - concept that is e.g. used by GtkObject. Note that changing the - inheritance hierarchy of a type can cause problems for language - bindings and other code which needs to work closely with the type - system. Therefore, switching to GInitiallyUnowned should be done - carefully. g_object_compat_control() has been added to GLib 2.8.5 - to help with the transition. - -### Notes about GLib 2.6.0 - -* GLib 2.6 introduces the concept of 'GLib filename encoding', which is the - on-disk encoding on Unix, but UTF-8 on Windows. All GLib functions - returning or accepting pathnames have been changed to expect - filenames in this encoding, and the common POSIX functions dealing - with pathnames have been wrapped. These wrappers are declared in the - header which must be included explicitly; it is not - included through . - - On current (NT-based) Windows versions, where the on-disk file names - are Unicode, these wrappers use the wide-character API in the C - library. Thus applications can handle file names containing any - Unicode characters through GLib's own API and its POSIX wrappers, - not just file names restricted to characters in the system codepage. - - To keep binary compatibility with applications compiled against - older versions of GLib, the Windows DLL still provides entry points - with the old semantics using the old names, and applications - compiled against GLib 2.6 will actually use new names for the - functions. This is transparent to the programmer. - - When compiling against GLib 2.6, applications intended to be - portable to Windows must take the UTF-8 file name encoding into - consideration, and use the gstdio wrappers to access files whose - names have been constructed from strings returned from GLib. - -* Likewise, g_get_user_name() and g_get_real_name() have been changed - to return UTF-8 on Windows, while keeping the old semantics for - applications compiled against older versions of GLib. - -* The GLib uses an '_' prefix to indicate private symbols that - must not be used by applications. On some platforms, symbols beginning - with prefixes such as _g will be exported from the library, on others not. - In no case can applications use these private symbols. In addition to that, - GLib+ 2.6 makes several symbols private which were not in any installed - header files and were never intended to be exported. - -* To reduce code size and improve efficiency, GLib, when compiled - with the GNU toolchain, has separate internal and external entry - points for exported functions. The internal names, which begin with - IA__, may be seen when debugging a GLib program. - -* On Windows, GLib no longer opens a console window when printing - warning messages if stdout or stderr are invalid, as they are in - "Windows subsystem" (GUI) applications. Simply redirect stdout or - stderr if you need to see them. - -* The child watch functionality tends to reveal a bug in many - thread implementations (in particular the older LinuxThreads - implementation on Linux) where it's not possible to call waitpid() - for a child created in a different thread. For this reason, for - maximum portability, you should structure your code to fork all - child processes that you want to wait for from the main thread. - -* A problem was recently discovered with g_signal_connect_object(); - it doesn't actually disconnect the signal handler once the object being - connected to dies, just disables it. See the API docs for the function - for further details and the correct workaround that will continue to - work with future versions of GLib. diff --git a/README.win32.md b/README.win32.md index 2925d3ddf15064648bf0550281c3fe3554127c2d..e67552270654aadad5450c3621391c0193d89a9e 100644 --- a/README.win32.md +++ b/README.win32.md @@ -161,6 +161,57 @@ To overcome this problem, please set your system's locale setting for non-Unicod English (United States), reboot, and restart the build, and the code should build normally. +### Support for pre-2012 Visual Studio + +This release of GLib requires at least the Windows 8.0 SDK in order to be built +successfully using Visual Studio, which means that building with Visual Studio +2008 or 2010 is possible only with a special setup and must be done in the +command line with Ninja. Please see +https://devblogs.microsoft.com/cppblog/using-the-windows-software-development-kit-sdk-for-windows-8-consumer-preview-with-visual-studio-2010/ +for references; basically, assuming that your Windows 8.0 SDK is installed in +`C:\Program Files (x86)\Windows Kits\8.0` (`$(WIN8SDKDIR)` in short), you need +to ensure the following before invoking Meson to configure the build: + +- Your `%INCLUDE%` must not include the Windows 7.0/7.1 SDK include directories, + and `$(WIN8SDKDIR)\include\um`, `$(WIN8SDKDIR)\include\um\share` and + `$(WIN8SDKDIR)\include\winrt` (in this order) must be before your stock + Visual Studio 2008/2010 header directories. If you have the DirectX SDK installed, + you should remove its include directory from your `%INCLUDE%` as well. +- You must replace the Windows 7.0/7.1 SDK library directory in `%LIB%` with the + Windows 8.0 SDK library directory, i.e. `$(WIN8SDKDIR)\lib\win8\um\[x86|x64]`. + If you have the DirectX SDK installed, you should remove its library directory + from your `%INCLUDE%` as well. +- You must replace the Windows 7.0/7.1 SDK tools directory from your `%PATH%` with + the Windows 8.0 SDK tools directory, i.e. `$(WIN8SDKDIR)\bin\[x86|x64]`. + If you have the DirectX SDK installed, you should remove its utility directory + from your `%PATH%` as well. + +The Windows 8.0 SDK headers may contain an `roapi.h` that cannot be used under plain +C, so to remedy that, change the following lines (around lines 55-57): + +``` +// RegisterActivationFactory/RevokeActivationFactory registration cookie +typedef struct {} *RO_REGISTRATION_COOKIE; +// RegisterActivationFactory/DllGetActivationFactory callback +``` + +to + +``` +// RegisterActivationFactory/RevokeActivationFactory registration cookie +#ifdef __cplusplus +typedef struct {} *RO_REGISTRATION_COOKIE; +#else +typedef struct _RO_REGISTRATION_COOKIE *RO_REGISTRATION_COOKIE; /* make this header includable in C files */ +#endif +// RegisterActivationFactory/DllGetActivationFactory callback +``` + +This follows what is done in the Windows 8.1 SDK, which contains an `roapi.h` +that is usable under plain C. Please note that you might need to copy that file +into a location that is in your `%INCLUDE%` which precedes the include path for the +Windows 8.0 SDK headers, if you do not have administrative privileges. + ### Visual Studio 2008 hacks - You need to run the following lines from your build directory, to embed the @@ -168,8 +219,8 @@ normally. are installed to `$(PREFIX)`, after a successful build/installation: ```cmd -> for /r %f in (*.dll.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f $(PREFIX)\bin\%~nf;2 -> for /r %f in (*.exe.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f $(PREFIX)\bin\%~nf;1 +> for /r %f in (*.dll.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f (PREFIX)\bin\%~nf;2 +> for /r %f in (*.exe.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f (PREFIX)\bin\%~nf;1 ``` @@ -179,4 +230,4 @@ normally. the build flags of the sources that hang on compilation by changing its `"/O2"` flag to `"/O1"` in `build.ninja`, and retry the build, where things should continue to build normally. At the time of writing, this is needed for compiling `glib/gtestutils.c`, `gio/gsettings.c`, - `gio/gsettingsschema.c` and `gio/tests/gsubprocess-testprog.c` + `gio/gsettingsschema.c`, `glib/tests/fileutils.c` and `gio/tests/gsubprocess-testprog.c` diff --git a/bundle.json b/bundle.json old mode 100644 new mode 100755 index 2b92fcf39cccea72c47c4e8bd0dcf7783b8f17f6..c97fdae24784f5cdc3ea1575ec2442e0580b4848 --- a/bundle.json +++ b/bundle.json @@ -1,7 +1,7 @@ { "name": "@ohos/glib", "description": "GLib is the low-level core library that forms the basis for projects such as GTK and GNOME. It provides data structure handling for C, portability wrappers, and interfaces for such runtime functionality as an event loop, threads, dynamic loading, and an object system.", - "version": "3.1", + "version": "2.68.1", "license": "LGPL V2.1", "publishAs": "code-segment", "segment": { diff --git a/check-abis.sh b/check-abis.sh old mode 100755 new mode 100644 index a18103bf89214c7ee17ca2c3fd464b7f3d26c9f8..5340f317d6df605a81054addcb1e0084c3f6a54d --- a/check-abis.sh +++ b/check-abis.sh @@ -1,11 +1,11 @@ #!/bin/sh -e list_leaked_symbols () { - nm -D "$1" | grep ' T ' | cut -f 3 -d ' ' | egrep -v "$2" + nm -D "$1" | grep ' T ' | cut -f 3 -d ' ' | grep -E -v "$2" } check_symbols () { - if [ "`list_leaked_symbols "$1" "$2" | wc -l`" -ne 0 ]; then + if [ "$(list_leaked_symbols "$1" "$2" | wc -l)" -ne 0 ]; then echo File "$1" possibly leaking symbols: list_leaked_symbols "$1" "$2" exit 1 diff --git a/clang-format-diff.py b/clang-format-diff.py new file mode 100644 index 0000000000000000000000000000000000000000..4eb1910626077e156b180dd76abca10e4614f93a --- /dev/null +++ b/clang-format-diff.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +# +# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== # +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ===---------------------------------------------------------------------=== # + +""" +This script reads input from a unified diff and reformats all the changed +lines. This is useful to reformat all the lines touched by a specific patch. +Example usage for git/svn users: + + git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i + svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i + +""" +from __future__ import absolute_import, division, print_function + +import argparse +import difflib +import re +import subprocess +import sys + +if sys.version_info.major >= 3: + from io import StringIO +else: + from io import BytesIO as StringIO + + +def main(): + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "-i", + action="store_true", + default=False, + help="apply edits to files instead of displaying a " "diff", + ) + parser.add_argument( + "-p", + metavar="NUM", + default=0, + help="strip the smallest prefix containing P slashes", + ) + parser.add_argument( + "-regex", + metavar="PATTERN", + default=None, + help="custom pattern selecting file paths to reformat " + "(case sensitive, overrides -iregex)", + ) + parser.add_argument( + "-iregex", + metavar="PATTERN", + default=r".*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc" + r"|js|ts|proto|protodevel|java|cs)", + help="custom pattern selecting file paths to reformat " + "(case insensitive, overridden by -regex)", + ) + parser.add_argument( + "-sort-includes", + action="store_true", + default=False, + help="let clang-format sort include blocks", + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="be more verbose, ineffective without -i", + ) + parser.add_argument( + "-style", + help="formatting style to apply (LLVM, Google, " "Chromium, Mozilla, WebKit)", + ) + parser.add_argument( + "-binary", + default="clang-format", + help="location of binary to use for clang-format", + ) + args = parser.parse_args() + + # Extract changed lines for each file. + filename = None + lines_by_file = {} + for line in sys.stdin: + match = re.search(r"^\+\+\+\ (.*?/){%s}(\S*)" % args.p, line) + if match: + filename = match.group(2) + if filename is None: + continue + + if args.regex is not None: + if not re.match("^%s$" % args.regex, filename): + continue + else: + if not re.match("^%s$" % args.iregex, filename, re.IGNORECASE): + continue + + match = re.search(r"^@@.*\+(\d+)(,(\d+))?", line) + if match: + start_line = int(match.group(1)) + line_count = 1 + if match.group(3): + line_count = int(match.group(3)) + if line_count == 0: + continue + end_line = start_line + line_count - 1 + lines_by_file.setdefault(filename, []).extend( + ["-lines", str(start_line) + ":" + str(end_line)] + ) + + # Reformat files containing changes in place. + # We need to count amount of bytes generated in the output of + # clang-format-diff. If clang-format-diff doesn't generate any bytes it + # means there is nothing to format. + format_line_counter = 0 + for filename, lines in lines_by_file.items(): + if args.i and args.verbose: + print("Formatting {}".format(filename)) + command = [args.binary, filename] + if args.i: + command.append("-i") + if args.sort_includes: + command.append("-sort-includes") + command.extend(lines) + if args.style: + command.extend(["-style", args.style]) + p = subprocess.Popen( + command, + stdout=subprocess.PIPE, + stderr=None, + stdin=subprocess.PIPE, + universal_newlines=True, + ) + stdout, _ = p.communicate() + if p.returncode != 0: + sys.exit(p.returncode) + + if not args.i: + with open(filename) as f: + code = f.readlines() + formatted_code = StringIO(stdout).readlines() + diff = difflib.unified_diff( + code, + formatted_code, + filename, + filename, + "(before formatting)", + "(after formatting)", + ) + diff_string = "".join(diff) + if diff_string: + format_line_counter += sys.stdout.write(diff_string) + + if format_line_counter > 0: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/config.h b/config.h index 918e3d386c9e91926a2784f330abd9feffe4758b..ee7bb6bd29f4a806035f35d3c44844fee8949560 100644 --- a/config.h +++ b/config.h @@ -19,24 +19,28 @@ #define ALIGNOF_UNSIGNED_LONG 4 #endif +#define ENABLE_NLS 1 + #define EXEEXT #define GETTEXT_PACKAGE "glib20" -#define GLIB_BINARY_AGE 6205 +#define GLIB_BINARY_AGE 6801 -#define GLIB_INTERFACE_AGE 0 +#define GLIB_INTERFACE_AGE 1 #define GLIB_LOCALE_DIR "/usr/local/share/locale" #define GLIB_MAJOR_VERSION 2 -#define GLIB_MICRO_VERSION 5 +#define GLIB_MICRO_VERSION 1 -#define GLIB_MINOR_VERSION 62 +#define GLIB_MINOR_VERSION 68 #define G_VA_COPY va_copy +#define G_VA_COPY_AS_ARRAY 1 + #define HAVE_ALLOCA_H 1 #define HAVE_BIND_TEXTDOMAIN_CODESET @@ -57,6 +61,8 @@ #define HAVE_ENDSERVENT 1 +#define HAVE_EPOLL_CREATE 1 + #define HAVE_EVENTFD 1 #define HAVE_FALLOCATE 1 @@ -67,6 +73,8 @@ #define HAVE_FLOAT_H 1 +#define HAVE_FSTAB_H 1 + #define HAVE_FSYNC 1 #define HAVE_FUTEX 1 @@ -103,6 +111,8 @@ #define HAVE_INTTYPES_H_WITH_UINTMAX 1 +#define HAVE_IPV6 + #define HAVE_IP_MREQN 1 #define HAVE_LANGINFO_CODESET 1 @@ -113,6 +123,8 @@ #define HAVE_LC_MESSAGES 1 +#undef HAVE_LIBMOUNT + #define HAVE_LIMITS_H 1 #define HAVE_LINK 1 @@ -137,6 +149,8 @@ #define HAVE_MEMORY_H 1 +#define HAVE_MKOSTEMP 1 + #define HAVE_MMAP 1 #define HAVE_MNTENT_H 1 @@ -159,7 +173,7 @@ #define HAVE_PRLIMIT 1 -#undef HAVE_PROC_SELF_CMDLINE +#define HAVE_PROC_SELF_CMDLINE #define HAVE_PTHREAD_ATTR_SETINHERITSCHED 1 @@ -181,6 +195,10 @@ #define HAVE_RES_INIT 1 +#define HAVE_RES_NCLOSE 1 + +#define HAVE_RES_NINIT 1 + #define HAVE_RTLD_GLOBAL 1 #define HAVE_RTLD_LAZY 1 @@ -191,6 +209,8 @@ #define HAVE_SCHED_H 1 +#undef HAVE_SELINUX + #define HAVE_SENDMMSG 1 #define HAVE_SETENV 1 @@ -211,6 +231,8 @@ #define HAVE_STATVFS 1 +#define HAVE_STDATOMIC_H 1 + #define HAVE_STDINT_H 1 #define HAVE_STDINT_H_WITH_UINTMAX 1 @@ -257,6 +279,8 @@ #define HAVE_SYMLINK 1 +#undef HAVE_SYSPROF + #define HAVE_SYS_AUXV_H 1 #define HAVE_SYS_INOTIFY_H 1 @@ -277,6 +301,8 @@ #define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_SYSCTL_H 1 + #define HAVE_SYS_TIMES_H 1 #define HAVE_SYS_TIME_H 1 @@ -295,6 +321,8 @@ #define HAVE_TIMEGM 1 +#define HAVE_UINT128_T 1 + #define HAVE_UNISTD_H 1 #undef HAVE_UNIX98_PRINTF @@ -303,6 +331,10 @@ #define HAVE_UTIMES 1 +#define HAVE_VALLOC 1 + +#define HAVE_VALUES_H 1 + #define HAVE_VASPRINTF 1 #define HAVE_VSNPRINTF 1 @@ -323,31 +355,17 @@ #define MAJOR_IN_SYSMACROS 1 -#define NEED_PRINTF_DIRECTIVE_A 1 - -#define NEED_PRINTF_DIRECTIVE_F 1 - -#define NEED_PRINTF_DOUBLE 1 - -#define NEED_PRINTF_ENOMEM 1 - -#define NEED_PRINTF_FLAG_ZERO 1 - -#define NEED_PRINTF_INFINITE_DOUBLE 1 - -#define NEED_PRINTF_LONG_DOUBLE 1 - #define PACKAGE_BUGREPORT "https://gitlab.gnome.org/GNOME/glib/issues/new" #define PACKAGE_NAME "glib" -#define PACKAGE_STRING "glib 2.63.6" +#define PACKAGE_STRING "glib 2.68.1" #define PACKAGE_TARNAME "glib" #define PACKAGE_URL "" -#define PACKAGE_VERSION "2.63.6" +#define PACKAGE_VERSION "2.68.1" #define SIZEOF_CHAR 1 @@ -396,108 +414,7 @@ #define _GNU_SOURCE 1 -#define gl_extern_inline -/* Please see the Gnulib manual for how to use these macros. - - Suppress extern inline with HP-UX cc, as it appears to be broken; see - . - - Suppress extern inline with Sun C in standards-conformance mode, as it - mishandles inline functions that call each other. E.g., for 'inline void f - (void) { } inline void g (void) { f (); }', c99 incorrectly complains - 'reference to static identifier "f" in extern inline function'. - This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16. - - Suppress extern inline (with or without __attribute__ ((__gnu_inline__))) - on configurations that mistakenly use 'static inline' to implement - functions or macros in standard C headers like . For example, - if isdigit is mistakenly implemented via a static inline function, - a program containing an extern inline function that calls isdigit - may not work since the C standard prohibits extern inline functions - from calling static functions. This bug is known to occur on: - - OS X 10.8 and earlier; see: - https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html - - DragonFly; see - http://muscles.dragonflybsd.org/bulk/bleeding-edge-potential/latest-per-pkg/ah-tty-0.3.12.log - - FreeBSD; see: - https://lists.gnu.org/r/bug-gnulib/2014-07/msg00104.html - - OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and - for clang but remains for g++; see . - Assume DragonFly and FreeBSD will be similar. */ -#if (((defined __APPLE__ && defined __MACH__) \ - || defined __DragonFly__ || defined __FreeBSD__) \ - && (defined __header_inline \ - ? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \ - && ! defined __clang__) \ - : ((! defined _DONT_USE_CTYPE_INLINE_ \ - && (defined __GNUC__ || defined __cplusplus)) \ - || (defined _FORTIFY_SOURCE && 0 < _FORTIFY_SOURCE \ - && defined __GNUC__ && ! defined __cplusplus)))) -# define _GL_EXTERN_INLINE_STDHEADER_BUG -#endif -#if ((__GNUC__ \ - ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \ - : (199901L <= __STDC_VERSION__ \ - && !defined __HP_cc \ - && !defined __PGI \ - && !(defined __SUNPRO_C && __STDC__))) \ - && !defined _GL_EXTERN_INLINE_STDHEADER_BUG) -# define _GL_INLINE inline -# define _GL_EXTERN_INLINE extern inline -# define _GL_EXTERN_INLINE_IN_USE -#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \ - && !defined _GL_EXTERN_INLINE_STDHEADER_BUG) -# if defined __GNUC_GNU_INLINE__ && __GNUC_GNU_INLINE__ - /* __gnu_inline__ suppresses a GCC 4.2 diagnostic. */ -# define _GL_INLINE extern inline __attribute__ ((__gnu_inline__)) __attribute__ ((always_inline)) -# else -# define _GL_INLINE extern inline -# endif -# define _GL_EXTERN_INLINE extern -# define _GL_EXTERN_INLINE_IN_USE -#else -# define _GL_INLINE static _GL_UNUSED -# define _GL_EXTERN_INLINE static _GL_UNUSED -#endif - -/* In GCC 4.6 (inclusive) to 5.1 (exclusive), - suppress bogus "no previous prototype for 'FOO'" - and "no previous declaration for 'FOO'" diagnostics, - when FOO is an inline function in the header; see - and - . */ -#if __GNUC__ == 4 && 6 <= __GNUC_MINOR__ -# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ -# define _GL_INLINE_HEADER_CONST_PRAGMA -# else -# define _GL_INLINE_HEADER_CONST_PRAGMA \ - _Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") -# endif -# define _GL_INLINE_HEADER_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \ - _GL_INLINE_HEADER_CONST_PRAGMA -# define _GL_INLINE_HEADER_END \ - _Pragma ("GCC diagnostic pop") -#else -# define _GL_INLINE_HEADER_BEGIN -# define _GL_INLINE_HEADER_END -#endif - +#define gl_extern_inline #define gl_unused -/* Define as a marker that can be attached to declarations that might not - be used. This helps to reduce warnings, such as from - GCC -Wunused-parameter. */ -#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) -# define _GL_UNUSED __attribute__ ((__unused__)) -#else -# define _GL_UNUSED -#endif - diff --git a/docs/debugging.txt b/docs/debugging.txt index 8bd6e312457ec7e40da3627c757a8472ae7763bb..2cc600aa9b6251fbb269a868d52691b5f0985ed1 100644 --- a/docs/debugging.txt +++ b/docs/debugging.txt @@ -1,6 +1,6 @@ -Traps (G_BREAKPOINT) and traces for the debuging -================================================ +Traps (G_BREAKPOINT) and traces for the debugging +================================================= Some code portions contain trap variables that can be set during debugging time if G_ENABLE_DEBUG has been defined upon compilation diff --git a/docs/macros.txt b/docs/macros.txt index c462de513028e4829b5f786a658a914376185333..ec449f17f585b0645142ddb62bd8f06089e6b76f 100644 --- a/docs/macros.txt +++ b/docs/macros.txt @@ -5,9 +5,14 @@ GLib's configure options and corresponding macros none --buildtype={debug,debugoptimized} [debugoptimized is the default] -DG_ENABLE_DEBUG -g - -Available to define yourself: - -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS +-Dglib_debug=disabled + Omits G_ENABLE_DEBUG when implied by --buildtype/-Ddebug +-Dglib_debug=enabled + Defines G_ENABLE_DEBUG regardless of --buildtype/-Ddebug +-Dglib_asserts=false + -DG_DISABLE_ASSERT +-Dglib_checks=false + -DG_DISABLE_CHECKS Besides these, there are some local feature specific options, but my main focus here is to concentrate on macros that affect overall GLib behaviour diff --git a/docs/reference/gio/concat-files-helper.py b/docs/reference/gio/concat-files-helper.py index 94d64c34589fa067c4f2f3b0256d894d42ae307c..d434f9e1ec8c9d1a77c952faac8a702dedd1048e 100644 --- a/docs/reference/gio/concat-files-helper.py +++ b/docs/reference/gio/concat-files-helper.py @@ -18,13 +18,18 @@ # # Author: Xavier Claessens +import os import sys if len(sys.argv) < 3: - print('Usage: {} ...'.format(os.path.basename(sys.argv[0]))) - sys.exit(1) + print( + "Usage: {} ...".format( + os.path.basename(sys.argv[0]) + ) + ) + sys.exit(1) -with open(sys.argv[1], 'w') as outfile: +with open(sys.argv[1], "w") as outfile: for fname in sys.argv[2:]: with open(fname) as infile: for line in infile: diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml index fdd367bc58e986fda61fc45621be67aaae9845cb..960b5ffa0894b41cf374ff6b43c48cf24d8fbd63 100644 --- a/docs/reference/gio/gdbus-codegen.xml +++ b/docs/reference/gio/gdbus-codegen.xml @@ -41,6 +41,9 @@ + DECORATOR + HEADER + DEFINE OUTFILE @@ -50,6 +53,8 @@ VALUE + VERSION + VERSION FILE FILE @@ -85,7 +90,7 @@ When generating C code, a #GInterface-derived type is generated for each D-Bus interface. Additionally, for every generated type, - FooBar, two concrete instantiable types, + FooBar, two concrete instantiatable types, FooBarProxy and FooBarSkeleton, implementing said interface are also generated. The former is derived from #GDBusProxy and intended for use on the client side @@ -370,6 +375,52 @@ + + DECORATOR + + + If a DECORATOR is passed in with this option, all the + generated function prototypes in the generated header will be marked with + DECORATOR. This can be used, for instance, to export + symbols from code generated with gdbus-codegen. + This option is added in GLib-2.66 + + + + + + HEADER + + + If a HEADER is passed in with this option, the + generated header will put a #include HEADER before the rest of the + items, except for the inclusion guards or #pragma once + (if is used). This is used if using another header file is + needed for the decorator passed in via to be defined. + This option is added in GLib-2.66. + + + This option can only be used if is used. + + + + + + DEFINE + + + If a DEFINE is passed in with this option, the + generated source will add a #define DEFINE before the rest of the + items. This is used if a particular macro is needed to ensure the decorator + passed in via uses the correct definition when the + generated source is being compiled. This option is added in GLib-2.66. + + + This option can only be used if is used. + + + + OUTFILE @@ -420,6 +471,66 @@ gdbus-codegen --c-namespace MyApp \ + + VERSION + + + Specifies the minimum version of GLib which the code generated by + gdbus-codegen can depend on. This may be used to + make backwards-incompatible changes in the output or behaviour of + gdbus-codegen in future, which users may opt in to + by increasing the value they pass for . + If this option is not passed, the output from gdbus-codegen + is guaranteed to be compatible with all versions of GLib from 2.30 + upwards, as that is when gdbus-codegen was first + released. + + + Note that some version parameters introduce incompatible changes: all callers + of the generated code might need to be updated, and if the generated code is part of + a library's API or ABI, then increasing the version parameter can result in an API + or ABI break. + + + The version number must be of the form + MAJOR.MINOR.MICRO, + where all parts are integers. MINOR and + MICRO are optional. The version number may not be smaller + than 2.30. + + + If the version number is 2.64 or greater, the generated code will + have the following features: (1) If a method has h (file + descriptor) parameter(s), a GUnixFDList parameter will exist in the + generated code for it (whereas previously the annotation + org.gtk.GDBus.C.UnixFD was required), and (2) Method call functions will + have two additional arguments to allow the user to specify GDBusCallFlags + and a timeout value, as is possible when using g_dbus_proxy_call(). + + + + + + VERSION + + + Specifies the maximum version of GLib which the code generated by + gdbus-codegen can depend on. This may be used to + ensure that code generated by gdbus-codegen is + compilable with specific older versions of GLib that your software has + to support. + + + The version number must be of the form + MAJOR.MINOR.MICRO, + where all parts are integers. MINOR and + MICRO are optional. The version number must + be greater than or equal to that passed to . + It defaults to the version of GLib which provides this gdbus-codegen. + + + + @@ -660,7 +771,7 @@ gdbus-codegen --generate-c-code myapp-generated \ myapp-generated.[ch] are generated. The files provide an abstract #GTypeInterface-derived type called - MyAppFrobber as well as two instantiable types with + MyAppFrobber as well as two instantiatable types with the same name but suffixed with Proxy and Skeleton. The generated file, roughly, contains the following facilities: @@ -841,7 +952,7 @@ my_app_frobber_proxy_new_sync (GDBusConnection *connection, the net.Corp.MyApp.Frobber.HelloWorld() D-Bus method, connect to the ::notification GObject signal to receive - the net.Corp.MyApp.Frobber::Notication + the net.Corp.MyApp.Frobber::Notification D-Bus signal and get/set the net.Corp.MyApp.Frobber:Verbose D-Bus Property using either the GObject property diff --git a/docs/reference/gio/gdbus-object-manager-example/.gitignore b/docs/reference/gio/gdbus-object-manager-example/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..cc8a11df2b45c31b732a064777baa4063c76840e --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/.gitignore @@ -0,0 +1 @@ +gdbus-object-manager-example-overrides.txt diff --git a/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-docs.xml b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-docs.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd4c30736e62d2c007b22843c430071035120c37 --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-docs.xml @@ -0,0 +1,19 @@ + + +]> + + + GDBus ObjctManager Example + + Interfaces + + + + + + + + + diff --git a/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-sections.tx b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-sections.tx new file mode 100644 index 0000000000000000000000000000000000000000..1e3b8b81479c0aba32faf1d03c12b6eb773df590 --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/gdbus-object-manager-example-sections.tx @@ -0,0 +1,161 @@ +
+ExampleAnimal +ExampleAnimal +ExampleAnimal +ExampleAnimalIface +example_animal_interface_info +example_animal_override_properties +example_animal_call_poke +example_animal_call_poke_finish +example_animal_call_poke_sync +example_animal_complete_poke +example_animal_emit_jumped +example_animal_get_mood +example_animal_get_foo +example_animal_get_bar +example_animal_dup_mood +example_animal_dup_foo +example_animal_dup_bar +example_animal_set_mood +example_animal_set_foo +example_animal_set_bar +ExampleAnimalProxy +ExampleAnimalProxyClass +example_animal_proxy_new +example_animal_proxy_new_finish +example_animal_proxy_new_sync +example_animal_proxy_new_for_bus +example_animal_proxy_new_for_bus_finish +example_animal_proxy_new_for_bus_sync +ExampleAnimalSkeleton +ExampleAnimalSkeletonClass +example_animal_skeleton_new + +example_animal_get_type +example_animal_proxy_get_type +example_animal_skeleton_get_type +ExampleAnimalSkeletonPrivate +ExampleAnimalProxyPrivate +EXAMPLE_TYPE_ANIMAL +EXAMPLE_TYPE_ANIMAL_PROXY +EXAMPLE_TYPE_ANIMAL_SKELETON +EXAMPLE_ANIMAL +EXAMPLE_ANIMAL_GET_IFACE +EXAMPLE_ANIMAL_PROXY +EXAMPLE_ANIMAL_PROXY_CLASS +EXAMPLE_ANIMAL_PROXY_GET_CLASS +EXAMPLE_ANIMAL_SKELETON +EXAMPLE_ANIMAL_SKELETON_CLASS +EXAMPLE_ANIMAL_SKELETON_GET_CLASS +EXAMPLE_IS_ANIMAL +EXAMPLE_IS_ANIMAL_PROXY +EXAMPLE_IS_ANIMAL_PROXY_CLASS +EXAMPLE_IS_ANIMAL_SKELETON +EXAMPLE_IS_ANIMAL_SKELETON_CLASS +
+ +
+ExampleCat +ExampleCat +ExampleCat +ExampleCatIface +example_cat_interface_info +example_cat_override_properties +ExampleCatProxy +ExampleCatProxyClass +example_cat_proxy_new +example_cat_proxy_new_finish +example_cat_proxy_new_sync +example_cat_proxy_new_for_bus +example_cat_proxy_new_for_bus_finish +example_cat_proxy_new_for_bus_sync +ExampleCatSkeleton +ExampleCatSkeletonClass +example_cat_skeleton_new + +example_cat_get_type +example_cat_proxy_get_type +example_cat_skeleton_get_type +ExampleCatProxyPrivate +ExampleCatSkeletonPrivate +EXAMPLE_TYPE_CAT +EXAMPLE_TYPE_CAT_PROXY +EXAMPLE_TYPE_CAT_SKELETON +EXAMPLE_CAT +EXAMPLE_CAT_GET_IFACE +EXAMPLE_CAT_PROXY +EXAMPLE_CAT_PROXY_CLASS +EXAMPLE_CAT_PROXY_GET_CLASS +EXAMPLE_CAT_SKELETON +EXAMPLE_CAT_SKELETON_CLASS +EXAMPLE_CAT_SKELETON_GET_CLASS +EXAMPLE_IS_CAT +EXAMPLE_IS_CAT_PROXY +EXAMPLE_IS_CAT_PROXY_CLASS +EXAMPLE_IS_CAT_SKELETON +EXAMPLE_IS_CAT_SKELETON_CLASS +
+ +
+ExampleObject +ExampleObject +ExampleObject +ExampleObjectIface +example_object_get_animal +example_object_get_cat +example_object_peek_animal +example_object_peek_cat +ExampleObjectProxy +ExampleObjectProxyClass +example_object_proxy_new +ExampleObjectSkeleton +ExampleObjectSkeletonClass +example_object_skeleton_new +example_object_skeleton_set_animal +example_object_skeleton_set_cat + +example_object_get_type +example_object_proxy_get_type +example_object_skeleton_get_type +ExampleObjectProxyPrivate +ExampleObjectSkeletonPrivate +EXAMPLE_IS_OBJECT +EXAMPLE_IS_OBJECT_PROXY +EXAMPLE_IS_OBJECT_PROXY_CLASS +EXAMPLE_IS_OBJECT_SKELETON +EXAMPLE_IS_OBJECT_SKELETON_CLASS +EXAMPLE_OBJECT +EXAMPLE_OBJECT_GET_IFACE +EXAMPLE_OBJECT_PROXY +EXAMPLE_OBJECT_PROXY_CLASS +EXAMPLE_OBJECT_PROXY_GET_CLASS +EXAMPLE_OBJECT_SKELETON +EXAMPLE_OBJECT_SKELETON_CLASS +EXAMPLE_OBJECT_SKELETON_GET_CLASS +EXAMPLE_TYPE_OBJECT +EXAMPLE_TYPE_OBJECT_PROXY +EXAMPLE_TYPE_OBJECT_SKELETON +
+ +
+ExampleObjectManagerClient +ExampleObjectManagerClient +ExampleObjectManagerClient +ExampleObjectManagerClientClass +example_object_manager_client_get_proxy_type +example_object_manager_client_new +example_object_manager_client_new_finish +example_object_manager_client_new_sync +example_object_manager_client_new_for_bus +example_object_manager_client_new_for_bus_finish +example_object_manager_client_new_for_bus_sync + +example_object_manager_client_get_type +EXAMPLE_IS_OBJECT_MANAGER_CLIENT +EXAMPLE_IS_OBJECT_MANAGER_CLIENT_CLASS +EXAMPLE_OBJECT_MANAGER_CLIENT +EXAMPLE_OBJECT_MANAGER_CLIENT_CLASS +EXAMPLE_OBJECT_MANAGER_CLIENT_GET_CLASS +EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT +ExampleObjectManagerClientPrivate +
diff --git a/docs/reference/gio/gdbus-object-manager-example/meson.build b/docs/reference/gio/gdbus-object-manager-example/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..13cae5b48e2d90b492ca2b9dc81ecd663dd40683 --- /dev/null +++ b/docs/reference/gio/gdbus-object-manager-example/meson.build @@ -0,0 +1,11 @@ +gdbus_object_manager_example_doc = gnome.gtkdoc('gdbus-object-manager-example', + main_xml : 'gdbus-object-manager-example-docs.xml', + namespace : 'example', + dependencies : [libgdbus_example_objectmanager_dep], + src_dir : 'gio/tests/gdbus-object-manager-example', + scan_args : gtkdoc_common_scan_args + [ + '--rebuild-types', + ], + install : false, +) + diff --git a/docs/reference/gio/gdbus.xml b/docs/reference/gio/gdbus.xml index 0e6c14db1d61a812c41b4cbe6f33a83ddb08cf7f..77fdfebed2d8e3a2f93ce5b84b9a05bc32cad5d4 100644 --- a/docs/reference/gio/gdbus.xml +++ b/docs/reference/gio/gdbus.xml @@ -321,6 +321,18 @@ $ gdbus call --session \ 5000 (uint32 12,) + + Call a method with file handle argument: + + +$ gdbus call --session \ + --dest org.example.foo \ + --object-path /org/example/foo \ + --method SendFDs \ + 1 \ + 10 \ + 10<file.foo + Monitoring all objects on a service: diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index 0ce0e2d4229ed3fac2006ec9cbb26b4aae1f7475..9cd3d0e39f28e446269a070a8ac2f765a1191cc0 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -133,7 +133,7 @@ - High-level network functionallity + High-level network functionality @@ -232,6 +232,7 @@ + @@ -372,6 +373,22 @@ Index of new symbols in 2.60 + + Index of new symbols in 2.62 + + + + Index of new symbols in 2.64 + + + + Index of new symbols in 2.66 + + + + Index of new symbols in 2.68 + + diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index bb483b0ce49e096a69b418117214179a41d98fd4..945c26adeaad6d566039bb2cbb8b931e4b1fb19a 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -199,6 +199,7 @@ g_file_replace_contents g_file_replace_contents_async g_file_replace_contents_bytes_async g_file_replace_contents_finish +g_file_build_attribute_list_for_copy g_file_copy_attributes g_file_create_readwrite g_file_create_readwrite_async @@ -1572,6 +1573,7 @@ g_unix_mount_point_guess_symbolic_icon g_unix_mount_point_guess_name g_unix_mount_point_guess_can_eject g_unix_mount_points_get +g_unix_mount_point_at g_unix_mounts_get g_unix_mount_at g_unix_mount_for @@ -2462,7 +2464,7 @@ g_charset_converter_get_type
gconverterinputstream -GConverterInputstream +GConverterInputStream GConverterInputStream g_converter_input_stream_new g_converter_input_stream_get_converter @@ -2481,7 +2483,7 @@ g_converter_input_stream_get_type
gconverteroutputstream -GConverterOutputstream +GConverterOutputStream GConverterOutputStream g_converter_output_stream_new g_converter_output_stream_get_converter @@ -2802,6 +2804,9 @@ g_dbus_is_member_name g_dbus_is_interface_name g_dbus_gvalue_to_gvariant g_dbus_gvariant_to_gvalue +g_dbus_escape_object_path_bytestring +g_dbus_escape_object_path +g_dbus_unescape_object_path
@@ -3025,6 +3030,8 @@ g_dbus_method_invocation_return_gerror g_dbus_method_invocation_return_dbus_error g_dbus_method_invocation_take_error g_dbus_method_invocation_return_value_with_unix_fd_list +G_DBUS_METHOD_INVOCATION_HANDLED +G_DBUS_METHOD_INVOCATION_UNHANDLED G_DBUS_METHOD_INVOCATION G_IS_DBUS_METHOD_INVOCATION @@ -3651,15 +3658,20 @@ g_pollable_return_get_type gtls G_TLS_ERROR GTlsError +G_TLS_CHANNEL_BINDING_ERROR +GTlsChannelBindingError GTlsAuthenticationMode GTlsCertificateFlags G_TYPE_TLS_AUTHENTICATION_MODE G_TYPE_TLS_CERTIFICATE_FLAGS +G_TYPE_TLS_CHANNEL_BINDING_ERROR G_TYPE_TLS_ERROR g_tls_authentication_mode_get_type g_tls_certificate_flags_get_type +g_tls_channel_binding_error_get_type +g_tls_channel_binding_error_quark g_tls_error_get_type
@@ -3697,6 +3709,7 @@ GTlsCertificate g_tls_certificate_new_from_pem g_tls_certificate_new_from_file g_tls_certificate_new_from_files +g_tls_certificate_new_from_pkcs11_uris g_tls_certificate_list_new_from_file g_tls_certificate_get_issuer g_tls_certificate_verify @@ -3718,10 +3731,12 @@ g_tls_certificate_get_type gtlsconnection GTlsConnection GTlsConnection +GTlsChannelBindingType g_tls_connection_set_certificate g_tls_connection_get_certificate g_tls_connection_get_peer_certificate g_tls_connection_get_peer_certificate_errors +g_tls_connection_get_channel_binding_data g_tls_connection_set_require_close_notify g_tls_connection_get_require_close_notify GTlsRehandshakeMode @@ -3749,9 +3764,11 @@ G_IS_TLS_CONNECTION_CLASS G_TLS_CONNECTION G_TLS_CONNECTION_CLASS G_TLS_CONNECTION_GET_CLASS +G_TYPE_TLS_CHANNEL_BINDING_TYPE G_TYPE_TLS_CONNECTION G_TYPE_TLS_REHANDSHAKE_MODE +g_tls_channel_binding_type_get_type g_tls_connection_get_type g_tls_rehandshake_mode_get_type
@@ -3916,6 +3933,7 @@ g_dtls_connection_set_certificate g_dtls_connection_get_certificate g_dtls_connection_get_peer_certificate g_dtls_connection_get_peer_certificate_errors +g_dtls_connection_get_channel_binding_data g_dtls_connection_set_require_close_notify g_dtls_connection_get_require_close_notify g_dtls_connection_set_rehandshake_mode @@ -4169,6 +4187,24 @@ G_DBUS_OBJECT_MANAGER_SERVER_GET_CLASS GDBusObjectManagerServerPrivate +
+gmemorymonitor +GMemoryMonitor +GMemoryMonitor +GMemoryMonitorInterface +GMemoryMonitorWarningLevel +G_MEMORY_MONITOR_EXTENSION_POINT_NAME +g_memory_monitor_dup_default + +g_memory_monitor_get_type +G_TYPE_MEMORY_MONITOR +G_MEMORY_MONITOR +G_IS_MEMORY_MONITOR +G_MEMORY_MONITOR_GET_INTERFACE +G_TYPE_MEMORY_MONITOR_WARNING_LEVEL +g_memory_monitor_warning_level_get_type +
+
gnetworkmonitor GNetworkMonitor @@ -4458,6 +4494,7 @@ g_task_get_name g_task_return_boolean g_task_return_int g_task_return_pointer +g_task_return_value g_task_return_error g_task_return_new_error g_task_return_error_if_cancelled @@ -4465,6 +4502,7 @@ g_task_return_error_if_cancelled g_task_propagate_boolean g_task_propagate_int g_task_propagate_pointer +g_task_propagate_value g_task_had_error g_task_get_completed @@ -4495,7 +4533,6 @@ CMSG_LEN CMSG_SPACE GLIB_ALIGN_TO_SIZEOF T_SRV -ws2funcs
@@ -4583,6 +4620,7 @@ g_subprocess_launcher_take_stdout_fd g_subprocess_launcher_set_stderr_file_path g_subprocess_launcher_take_stderr_fd g_subprocess_launcher_take_fd +g_subprocess_launcher_close g_subprocess_launcher_set_child_setup G_IS_SUBPROCESS_LAUNCHER @@ -4654,6 +4692,8 @@ g_list_store_remove g_list_store_remove_all g_list_store_splice g_list_store_sort +g_list_store_find +g_list_store_find_with_equal_func G_TYPE_LIST_STORE diff --git a/docs/reference/gio/gio.xml b/docs/reference/gio/gio.xml index bd0c66e8ec44bf4788e84cc486c7405457ad68f1..532bf9064f7d72c630d84a7d32af156c7bcfa4eb 100644 --- a/docs/reference/gio/gio.xml +++ b/docs/reference/gio/gio.xml @@ -53,6 +53,12 @@ OPTION LOCATION + + gio + launch + DESKTOP-FILE + FILE-ARG + gio list @@ -226,6 +232,10 @@ , Never follow symbolic links. + + + Use the default permissions of the current process for the destination file, rather than copying the permissions of the source file. + @@ -269,6 +279,19 @@ + + + launch + DESKTOP-FILE + FILE-ARG + + + Launch a desktop file from any location given. + The launch command extends the behavior of the open command by allowing + any desktop file to be launched, not only those registered as file handlers. + + + list @@ -303,6 +326,10 @@ , Don’t follow symbolic links. + + , + Print display names. + , Print full URIs. @@ -421,8 +448,8 @@ Mount as mountable. - , - Mount volume with device file. + , + Mount volume with device file, or other identifier. , @@ -432,6 +459,10 @@ , Eject the location. + + , + Stop drive with device file. + , Unmount all mounts with the given scheme. @@ -490,6 +521,31 @@ to DESTINATION. If more than one source is specified, the destination must be a directory. The move command is similar to the traditional mv utility. + + Options + + + , + Don’t copy into DESTINATION even if it is a directory. + + + , + Show progress. + + + , + Prompt for confirmation before overwriting files. + + + , + Create backups of existing destination files. + + + , + Don’t use copy and delete fallback. + + + @@ -641,17 +697,18 @@ LOCATION - Sends files or directories to the ‘Trashcan’. This can be a - different folder depending on where the file is located, and not - all file systems support this concept. In the common case that the - file lives inside a user’s home directory, the trash folder is + Sends files or directories to the ‘Trashcan’ or restore them from + ‘Trashcan’. This can be a different folder depending on where the file + is located, and not all file systems support this concept. In the common + case that the file lives inside a user’s home directory, the trash folder is $XDG_DATA_HOME/Trash. Note that moving files to the trash does not free up space on the file system until the ‘Trashcan’ is emptied. If you are interested in deleting a file irreversibly, see the remove command. Inspecting and emptying the ‘Trashcan’ is normally supported by graphical file managers such as Nautilus, but you can also see the - trash with the command: gio list trash://. + trash with the command: gio trash --list or + gio list trash://. Options @@ -663,6 +720,16 @@ Empty the trash. + + + List files in the trash with their original locations + + + + Restore a file from trash to its original location. A URI beginning + with trash:// is expected here. If the original + directory doesn't exist, it will be recreated. + diff --git a/docs/reference/gio/glib-compile-resources.xml b/docs/reference/gio/glib-compile-resources.xml index 5421f3d91bf917c7b27be8d237b26b8ceef756ea..a85f6003c396788ae077873b9baf088d1759dfe0 100644 --- a/docs/reference/gio/glib-compile-resources.xml +++ b/docs/reference/gio/glib-compile-resources.xml @@ -219,6 +219,9 @@ searched for in the PATH. GDK_PIXBUF_PIXDATA +Deprecated since gdk-pixbuf 2.32, as GResource supports embedding +modern image formats without conversion. + The full path to the gdk-pixbuf-pixdata executable. This is used to preprocess resources with the to-pixdata preprocessing option. If this environment variable is not set, gdk-pixbuf-pixdata diff --git a/docs/reference/gio/meson.build b/docs/reference/gio/meson.build index f8805a57529b8535f67463f3573edec1f7d9c983..4d036481976d8a9f5440472d8ca499b81dbb26dc 100644 --- a/docs/reference/gio/meson.build +++ b/docs/reference/gio/meson.build @@ -1,4 +1,5 @@ if get_option('gtk_doc') + subdir('gdbus-object-manager-example') subdir('xml') ignore_headers = [ @@ -50,6 +51,8 @@ if get_option('gtk_doc') 'glocalfilemonitor.h', 'glocalfileoutputstream.h', 'glocalvfs.h', + 'gmemorymonitordbus.h', + 'gmemorymonitorportal.h', 'gmountprivate.h', 'gnativevolumemonitor.h', 'gnetworkingprivate.h', @@ -82,8 +85,15 @@ if get_option('gtk_doc') 'gunixvolume.h', 'gunixvolumemonitor.h', 'gwin32networkmonitor.h', + 'gwin32api-application-activation-manager.h', + 'gwin32api-iterator.h', + 'gwin32api-misc.h', + 'gwin32api-package.h', + 'gwin32api-storage.h', 'gwin32appinfo.h', + 'gwin32file-sync-stream.h', 'gwin32mount.h', + 'gwin32packageparser.h', 'gwin32resolver.h', 'gwin32volumemonitor.h', 'thumbnail-verify.h', @@ -130,8 +140,6 @@ if get_option('gtk_doc') 'xdp-dbus.c', ] - # FIXME: ExampleAnimal docs aren't built - docpath = join_paths(glib_datadir, 'gtk-doc', 'html') version_conf = configuration_data() version_conf.set('VERSION', meson.project_version()) @@ -159,6 +167,28 @@ if get_option('gtk_doc') copy : true, ) + content_files = [ + 'overview.xml', + 'migrating-posix.xml', + 'migrating-gnome-vfs.xml', + 'migrating-gconf.xml', + 'migrating-gdbus.xml', + 'gio-querymodules.xml', + 'glib-compile-schemas.xml', + 'glib-compile-resources.xml', + 'gapplication.xml', + 'gsettings.xml', + 'gresource.xml', + 'gdbus.xml', + 'gdbus-codegen.xml', + ] + + content_files += [ + gdbus_example_objectmanager_xml, + gdbus_example_objectmanager_sources, + gdbus_object_manager_example_doc + ] + gnome.gtkdoc('gio', main_xml : 'gio-docs.xml', namespace : 'g', @@ -172,21 +202,7 @@ if get_option('gtk_doc') mkdb_args : [ '--ignore-files=' + ' '.join(ignore_sources), ], - content_files : [ - 'overview.xml', - 'migrating-posix.xml', - 'migrating-gnome-vfs.xml', - 'migrating-gconf.xml', - 'migrating-gdbus.xml', - 'gio-querymodules.xml', - 'glib-compile-schemas.xml', - 'glib-compile-resources.xml', - 'gapplication.xml', - 'gsettings.xml', - 'gresource.xml', - 'gdbus.xml', - 'gdbus-codegen.xml', - ], + content_files : content_files, expand_content_files : [ 'overview.xml', 'migrating-posix.xml', @@ -205,7 +221,8 @@ if get_option('gtk_doc') '--extra-dir=' + join_paths('gio', '..', 'glib', 'html'), '--extra-dir=' + join_paths('gio', '..', 'gobject', 'html'), ], - install: true + install: true, + check: true, ) endif diff --git a/docs/reference/gio/migrating-gconf.xml b/docs/reference/gio/migrating-gconf.xml index 12176a6d7d4231a1f456bfa8e8d07f0b132e1e29..d9fd064247d44361f7391bd39a45e4b6994aac37 100644 --- a/docs/reference/gio/migrating-gconf.xml +++ b/docs/reference/gio/migrating-gconf.xml @@ -161,7 +161,7 @@ have a GConf schema. GConf comes with a commandline tool gsettings-schema-convert that can help with the task of converting a GConf schema into an equivalent GSettings schema. The tool is not - perfect and may need assistence in some cases. + perfect and may need assistance in some cases. An example for using gsettings-schema-convert Running gsettings-schema-convert --gconf --xml --schema-id "org.gnome.font-rendering" --output org.gnome.font-rendering.gschema.xml destop_gnome_font_rendering.schemas on the following desktop_gnome_font_rendering.schemas file: diff --git a/docs/reference/gio/migrating-gdbus.xml b/docs/reference/gio/migrating-gdbus.xml index 7595aaa02250aae97cadbd7f3b4a514f98eb0fab..dc4ee75d9a139f6e40f45271400972f9163ea306 100644 --- a/docs/reference/gio/migrating-gdbus.xml +++ b/docs/reference/gio/migrating-gdbus.xml @@ -241,6 +241,9 @@ on_name_acquired (GDBusConnection *connection,
+
+ Generating code and docs +
Using gdbus-codegen @@ -251,7 +254,7 @@ on_name_acquired (GDBusConnection *connection, linkend="gdbus-codegen">gdbus-codegen is used and like its counterpart, it also takes D-Bus Introspection XML as input: - Example D-Bus Introspection XMLFIXME: MISSING XINCLUDE CONTENT + Example D-Bus Introspection XMLFIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager.xml If this XML is processed like this generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal and generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat - with Docbook XML are generated. + with Docbook XML are generated. For an example of what the docs look + like see the Animal D-Bus interface documentation. + and + the Cat D-Bus interface documentation. While the contents of generated-code.h and @@ -276,9 +284,27 @@ gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \ linkend="gdbus-codegen">gdbus-codegen manual page, brief examples of how this generated code can be used can be found in - and . + and . Additionally, since + the generated code has 100% gtk-doc coverage, see + #ExampleAnimal, #ExampleCat, #ExampleObject and + #ExampleObjectManagerClient pages for documentation. + Server-side application using generated codeFIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager-server.c + + Client-side application using generated codeFIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager-client.c + +
+ + + FIXME: MISSING XINCLUDE CONTENT: objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml + FIXME: MISSING XINCLUDE CONTENT: objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Cat.xml + FIXME: MISSING XINCLUDE CONTENT: ExampleAnimal.xml + FIXME: MISSING XINCLUDE CONTENT: ExampleCat.xml + FIXME: MISSING XINCLUDE CONTENT: ExampleObject.xml + FIXME: MISSING XINCLUDE CONTENT: ExampleObjectManagerClient.xml +
diff --git a/docs/reference/gio/overview.xml b/docs/reference/gio/overview.xml index 960cd2fc13982855ebab45f3fa6b00d7ba830715..816afb9d3786d9aa6d13fda3d57a8ab62dc2fab4 100644 --- a/docs/reference/gio/overview.xml +++ b/docs/reference/gio/overview.xml @@ -281,7 +281,7 @@ be careful. GIO has extension points whose implementations get loaded from modules (executable code in shared objects), which could allow an attacker to sneak his own code into your application by tricking it into loading the code as a module. However, GIO will never load modules -from your home directory except when explictly asked to do so via an +from your home directory except when explicitly asked to do so via an environment variable. @@ -370,7 +370,7 @@ Gvfs is also heavily distributed and relies on a session bus to be present. The #GVfs implementation for local files that is included in GIO has the name "local", the implementation in the gvfs module has the name "gvfs". Most commonly, system software will set this to "local" - to avoid having `GFile` APIs perform unnecessary DBus calls. + to avoid having `GFile` APIs perform unnecessary D-Bus calls. The special value help can be used to print a list of available implementations to standard output. @@ -436,6 +436,9 @@ Gvfs is also heavily distributed and relies on a session bus to be present. modules from this alternate directory instead of the directory built into GIO. This is useful when running tests, for example. + + This environment variable is ignored when running in a setuid program. + @@ -446,6 +449,9 @@ Gvfs is also heavily distributed and relies on a session bus to be present. paths separated by a colon, GIO will attempt to load additional modules from within the path. + + This environment variable is ignored when running in a setuid program. + @@ -466,10 +472,9 @@ Gvfs is also heavily distributed and relies on a session bus to be present. <envar>GSETTINGS_SCHEMA_DIR</envar> - This variable can be set to the name of a directory that is - considered in addition to the glib-2.0/schemas - subdirectories of the XDG system data dirs when looking - for compiled schemas for #GSettings. + This variable can be set to the names of directories to consider when looking for compiled schemas for #GSettings, + in addition to the glib-2.0/schemas + subdirectories of the XDG system data dirs. To specify multiple directories, use G_SEARCHPATH_SEPARATOR_S as a separator. diff --git a/docs/reference/glib/building.xml b/docs/reference/glib/building.xml index 79567f6f7b0a6c114f07e99bf5dc23b975f078f3..9ff2fbfe771f532b39a95deba8694e503b539f35 100644 --- a/docs/reference/glib/building.xml +++ b/docs/reference/glib/building.xml @@ -26,6 +26,12 @@ ninja -C _build ninja -C _build install + + On FreeBSD: + + env CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib -Wl,--disable-new-dtags" meson -Dxattr=false -Dinstalled_tests=true -Diconv=external -Db_lundef=false _build + ninja -C _build + @@ -119,6 +125,16 @@ operating systems as well. + + + Python 3.5 or newer is required. Your system Python must + conform to PEP 394 + + For FreeBSD, this means that the + lang/python3 port must be installed. + + The libintl library from the G_ENABLE_DEBUG will be defined and GLib will be built with additional debug code enabled. + + If the build type is plain, GLib will not enable any + optimization or debug options by default, and will leave it entirely to + the user to choose their options. To build with the options recommended + by GLib developers, choose release. + diff --git a/docs/reference/glib/changes.xml b/docs/reference/glib/changes.xml index 24d6bcdb2152731a71dbd36dba39e8412dbe3739..9b4aa74ce5d896c93b80d1f6edc3286cfb7f8d19 100644 --- a/docs/reference/glib/changes.xml +++ b/docs/reference/glib/changes.xml @@ -12,7 +12,7 @@ Changes to GLib -Incompatible changes made between successing versions of GLib +Incompatible changes made between successive versions of GLib diff --git a/docs/reference/glib/cross.xml b/docs/reference/glib/cross.xml index 977421faa16129867b732241b59679013f32f840..c90b30b3690c0a1bb6a7c1b10788031bfe3355db 100644 --- a/docs/reference/glib/cross.xml +++ b/docs/reference/glib/cross.xml @@ -59,6 +59,7 @@ c_link_args = [] c = 'x86_64-w64-mingw32-gcc' cpp = 'x86_64-w64-mingw32-g++' ar = 'x86_64-w64-mingw32-ar' +ld = 'x86_64-w64-mingw32-ld' objcopy = 'x86_64-w64-mingw32-objcopy' strip = 'x86_64-w64-mingw32-strip' pkgconfig = 'x86_64-w64-mingw32-pkg-config' diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml index fa43eaff718ac3b40a3458f524cc093acd72dd96..e464fb792e0cfb77324440b70e49e9d8adc6f9e8 100644 --- a/docs/reference/glib/glib-docs.xml +++ b/docs/reference/glib/glib-docs.xml @@ -81,7 +81,7 @@ - + @@ -276,6 +276,18 @@ Index of new symbols in 2.62 + + Index of new symbols in 2.64 + + + + Index of new symbols in 2.66 + + + + Index of new symbols in 2.68 + + diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 6e00302e192f44a728df12442323ce3a389a56c0..460a299bf4147192a7a1163a726a4ac2a10a2375 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -135,6 +135,11 @@ GLIB_VERSION_2_56 GLIB_VERSION_2_58 GLIB_VERSION_2_60 GLIB_VERSION_2_62 +GLIB_VERSION_2_64 +GLIB_VERSION_2_66 +GLIB_VERSION_2_68 +GLIB_VERSION_CUR_STABLE +GLIB_VERSION_PREV_STABLE GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_MAX_ALLOWED GLIB_DISABLE_DEPRECATION_WARNINGS @@ -160,6 +165,9 @@ GLIB_AVAILABLE_ENUMERATOR_IN_2_56 GLIB_AVAILABLE_ENUMERATOR_IN_2_58 GLIB_AVAILABLE_ENUMERATOR_IN_2_60 GLIB_AVAILABLE_ENUMERATOR_IN_2_62 +GLIB_AVAILABLE_ENUMERATOR_IN_2_64 +GLIB_AVAILABLE_ENUMERATOR_IN_2_66 +GLIB_AVAILABLE_ENUMERATOR_IN_2_68 GLIB_AVAILABLE_IN_ALL GLIB_AVAILABLE_IN_2_26 GLIB_AVAILABLE_IN_2_28 @@ -180,6 +188,9 @@ GLIB_AVAILABLE_IN_2_56 GLIB_AVAILABLE_IN_2_58 GLIB_AVAILABLE_IN_2_60 GLIB_AVAILABLE_IN_2_62 +GLIB_AVAILABLE_IN_2_64 +GLIB_AVAILABLE_IN_2_66 +GLIB_AVAILABLE_IN_2_68 GLIB_AVAILABLE_MACRO_IN_2_26 GLIB_AVAILABLE_MACRO_IN_2_28 GLIB_AVAILABLE_MACRO_IN_2_30 @@ -199,6 +210,15 @@ GLIB_AVAILABLE_MACRO_IN_2_56 GLIB_AVAILABLE_MACRO_IN_2_58 GLIB_AVAILABLE_MACRO_IN_2_60 GLIB_AVAILABLE_MACRO_IN_2_62 +GLIB_AVAILABLE_MACRO_IN_2_64 +GLIB_AVAILABLE_MACRO_IN_2_66 +GLIB_AVAILABLE_MACRO_IN_2_68 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_44 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_60 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_64 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_66 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_68 GLIB_AVAILABLE_TYPE_IN_2_26 GLIB_AVAILABLE_TYPE_IN_2_28 GLIB_AVAILABLE_TYPE_IN_2_30 @@ -218,6 +238,9 @@ GLIB_AVAILABLE_TYPE_IN_2_56 GLIB_AVAILABLE_TYPE_IN_2_58 GLIB_AVAILABLE_TYPE_IN_2_60 GLIB_AVAILABLE_TYPE_IN_2_62 +GLIB_AVAILABLE_TYPE_IN_2_64 +GLIB_AVAILABLE_TYPE_IN_2_66 +GLIB_AVAILABLE_TYPE_IN_2_68 GLIB_DEPRECATED_ENUMERATOR GLIB_DEPRECATED_ENUMERATOR_FOR GLIB_DEPRECATED_ENUMERATOR_IN_2_26 @@ -258,6 +281,12 @@ GLIB_DEPRECATED_ENUMERATOR_IN_2_60 GLIB_DEPRECATED_ENUMERATOR_IN_2_60_FOR GLIB_DEPRECATED_ENUMERATOR_IN_2_62 GLIB_DEPRECATED_ENUMERATOR_IN_2_62_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_64 +GLIB_DEPRECATED_ENUMERATOR_IN_2_64_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_66 +GLIB_DEPRECATED_ENUMERATOR_IN_2_66_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_68 +GLIB_DEPRECATED_ENUMERATOR_IN_2_68_FOR GLIB_DEPRECATED_IN_2_26 GLIB_DEPRECATED_IN_2_26_FOR GLIB_DEPRECATED_IN_2_28 @@ -296,6 +325,12 @@ GLIB_DEPRECATED_IN_2_60 GLIB_DEPRECATED_IN_2_60_FOR GLIB_DEPRECATED_IN_2_62 GLIB_DEPRECATED_IN_2_62_FOR +GLIB_DEPRECATED_IN_2_64 +GLIB_DEPRECATED_IN_2_64_FOR +GLIB_DEPRECATED_IN_2_66 +GLIB_DEPRECATED_IN_2_66_FOR +GLIB_DEPRECATED_IN_2_68 +GLIB_DEPRECATED_IN_2_68_FOR GLIB_DEPRECATED_MACRO GLIB_DEPRECATED_MACRO_FOR GLIB_DEPRECATED_MACRO_IN_2_26 @@ -336,6 +371,12 @@ GLIB_DEPRECATED_MACRO_IN_2_60 GLIB_DEPRECATED_MACRO_IN_2_60_FOR GLIB_DEPRECATED_MACRO_IN_2_62 GLIB_DEPRECATED_MACRO_IN_2_62_FOR +GLIB_DEPRECATED_MACRO_IN_2_64 +GLIB_DEPRECATED_MACRO_IN_2_64_FOR +GLIB_DEPRECATED_MACRO_IN_2_66 +GLIB_DEPRECATED_MACRO_IN_2_66_FOR +GLIB_DEPRECATED_MACRO_IN_2_68 +GLIB_DEPRECATED_MACRO_IN_2_68_FOR GLIB_DEPRECATED_TYPE GLIB_DEPRECATED_TYPE_FOR GLIB_DEPRECATED_TYPE_IN_2_26 @@ -376,6 +417,12 @@ GLIB_DEPRECATED_TYPE_IN_2_60 GLIB_DEPRECATED_TYPE_IN_2_60_FOR GLIB_DEPRECATED_TYPE_IN_2_62 GLIB_DEPRECATED_TYPE_IN_2_62_FOR +GLIB_DEPRECATED_TYPE_IN_2_64 +GLIB_DEPRECATED_TYPE_IN_2_64_FOR +GLIB_DEPRECATED_TYPE_IN_2_66 +GLIB_DEPRECATED_TYPE_IN_2_66_FOR +GLIB_DEPRECATED_TYPE_IN_2_68 +GLIB_DEPRECATED_TYPE_IN_2_68_FOR GLIB_VERSION_CUR_STABLE GLIB_VERSION_PREV_STABLE @@ -411,6 +458,7 @@ CLAMP G_APPROX_VALUE +G_SIZEOF_MEMBER G_STRUCT_MEMBER G_STRUCT_MEMBER_P G_STRUCT_OFFSET @@ -423,6 +471,8 @@ G_ALIGNOF G_CONST_RETURN +G_NORETURN +G_NORETURN_FUNCPTR G_N_ELEMENTS @@ -679,11 +729,13 @@ GLIB_DEPRECATED_FOR GLIB_UNAVAILABLE GLIB_UNAVAILABLE_ENUMERATOR GLIB_UNAVAILABLE_MACRO +GLIB_UNAVAILABLE_STATIC_INLINE GLIB_UNAVAILABLE_TYPE G_ANALYZER_ANALYZING G_ANALYZER_NORETURN g_autoptr_cleanup_generic_gfree -g_has_typeof +glib_typeof +glib_typeof_2_68 g_macro__has_attribute g_macro__has_builtin g_macro__has_feature @@ -705,6 +757,13 @@ g_propagate_error g_clear_error g_prefix_error g_propagate_prefixed_error + +GErrorInitFunc +GErrorCopyFunc +GErrorClearFunc +G_DEFINE_EXTENDED_ERROR +g_error_domain_register_static +g_error_domain_register
@@ -768,6 +827,11 @@ g_main_set_poll_func g_main_context_invoke g_main_context_invoke_full + +GMainContextPusher +g_main_context_pusher_new +g_main_context_pusher_free + g_main_context_get_thread_default g_main_context_ref_thread_default @@ -805,11 +869,13 @@ G_POLLFD_FORMAT GSource GSourceDummyMarshal GSourceFuncs +GSourceDisposeFunc GSourceCallbackFuncs g_source_new g_source_ref g_source_unref g_source_set_funcs +g_source_set_dispose_function g_source_attach g_source_destroy g_source_is_destroyed @@ -1399,6 +1465,7 @@ g_log g_logv g_message g_warning +g_warning_once g_critical g_error g_info @@ -1430,6 +1497,8 @@ g_log_writer_format_fields g_log_writer_journald g_log_writer_standard_streams g_log_writer_default +g_log_writer_default_set_use_stderr +g_log_writer_default_would_drop g_log_structured_standard @@ -1458,6 +1527,7 @@ GSpawnFlags GSpawnChildSetupFunc g_spawn_async_with_fds g_spawn_async_with_pipes +g_spawn_async_with_pipes_and_fds g_spawn_async g_spawn_sync G_SPAWN_EXIT_ERROR @@ -1573,7 +1643,9 @@ G_FILE_ERROR GFileTest g_file_error_from_errno g_file_get_contents +GFileSetContentsFlags g_file_set_contents +g_file_set_contents_full g_file_test g_mkstemp g_mkstemp_full @@ -1614,6 +1686,7 @@ g_remove g_rmdir g_fopen g_freopen +g_fsync g_chmod g_access g_creat @@ -1747,9 +1820,15 @@ g_strjoinv GStrv +GStrvBuilder g_strv_length g_strv_contains g_strv_equal +g_strv_builder_new +g_strv_builder_ref +g_strv_builder_unref +g_strv_builder_add +g_strv_builder_end g_strerror @@ -1874,6 +1953,7 @@ g_time_zone_unref g_time_zone_ref g_time_zone_new +g_time_zone_new_identifier g_time_zone_new_local g_time_zone_new_utc g_time_zone_new_offset @@ -2073,6 +2153,20 @@ g_get_user_special_dir g_get_system_data_dirs g_get_system_config_dirs g_reload_user_special_dirs_cache +g_get_os_info + + +G_OS_INFO_KEY_NAME +G_OS_INFO_KEY_PRETTY_NAME +G_OS_INFO_KEY_VERSION +G_OS_INFO_KEY_VERSION_CODENAME +G_OS_INFO_KEY_VERSION_ID +G_OS_INFO_KEY_ID +G_OS_INFO_KEY_HOME_URL +G_OS_INFO_KEY_DOCUMENTATION_URL +G_OS_INFO_KEY_SUPPORT_URL +G_OS_INFO_KEY_BUG_REPORT_URL +G_OS_INFO_KEY_PRIVACY_POLICY_URL g_get_host_name @@ -2314,11 +2408,15 @@ g_bookmark_file_get_mime_type g_bookmark_file_get_is_private g_bookmark_file_get_icon g_bookmark_file_get_added +g_bookmark_file_get_added_date_time g_bookmark_file_get_modified +g_bookmark_file_get_modified_date_time g_bookmark_file_get_visited +g_bookmark_file_get_visited_date_time g_bookmark_file_get_groups g_bookmark_file_get_applications g_bookmark_file_get_app_info +g_bookmark_file_get_application_info g_bookmark_file_set_title @@ -2327,10 +2425,14 @@ g_bookmark_file_set_mime_type g_bookmark_file_set_is_private g_bookmark_file_set_icon g_bookmark_file_set_added +g_bookmark_file_set_added_date_time g_bookmark_file_set_groups g_bookmark_file_set_modified +g_bookmark_file_set_modified_date_time g_bookmark_file_set_visited +g_bookmark_file_set_visited_date_time g_bookmark_file_set_app_info +g_bookmark_file_set_application_info g_bookmark_file_add_group g_bookmark_file_add_application g_bookmark_file_remove_group @@ -2422,6 +2524,9 @@ g_unix_fd_add g_unix_fd_add_full g_unix_fd_source_new + +g_unix_get_passwd_entry + g_unix_error_quark
@@ -2470,6 +2575,7 @@ g_list_delete_link g_list_remove_all g_list_free g_list_free_full +g_clear_list g_list_alloc @@ -2526,6 +2632,7 @@ g_slist_free g_slist_free_full g_slist_free_1 g_slist_free1 +g_clear_slist g_slist_length @@ -2755,6 +2862,7 @@ g_string_insert_unichar g_string_insert_len g_string_overwrite g_string_overwrite_len +g_string_replace g_string_erase g_string_truncate g_string_set_size @@ -2792,6 +2900,7 @@ g_string_chunk_free arrays GArray g_array_new +g_array_steal g_array_sized_new g_array_copy g_array_ref @@ -2820,6 +2929,7 @@ g_array_free arrays_pointer GPtrArray g_ptr_array_new +g_ptr_array_steal g_ptr_array_sized_new g_ptr_array_new_with_free_func g_ptr_array_copy @@ -2855,6 +2965,7 @@ g_ptr_array_find_with_equal_func GByteArray g_byte_array_new +g_byte_array_steal g_byte_array_new_take g_byte_array_sized_new g_byte_array_ref @@ -2895,21 +3006,36 @@ g_bytes_get_type Balanced Binary Trees trees-binary GTree +GTreeNode g_tree_new g_tree_ref g_tree_unref g_tree_new_with_data g_tree_new_full +g_tree_node_first +g_tree_node_last +g_tree_node_previous +g_tree_node_next +g_tree_insert_node g_tree_insert +g_tree_replace_node g_tree_replace +g_tree_node_key +g_tree_node_value g_tree_nnodes g_tree_height +g_tree_lookup_node g_tree_lookup g_tree_lookup_extended +g_tree_foreach_node g_tree_foreach g_tree_traverse GTraverseFunc +GTraverseNodeFunc +g_tree_search_node g_tree_search +g_tree_lower_bound +g_tree_upper_bound g_tree_remove g_tree_steal g_tree_destroy @@ -3264,19 +3390,67 @@ g_base64_decode_inplace
URI Functions -gurifuncs +guri +GUri +g_uri_ref +g_uri_unref + +GUriFlags +g_uri_split +g_uri_split_with_user +g_uri_split_network +g_uri_is_valid +g_uri_join +g_uri_join_with_user +g_uri_parse +g_uri_parse_relative +g_uri_resolve_relative +g_uri_build +g_uri_build_with_user +g_uri_peek_scheme +g_uri_parse_scheme + +GUriHideFlags +g_uri_to_string +g_uri_to_string_partial + +g_uri_get_scheme +g_uri_get_userinfo +g_uri_get_user +g_uri_get_password +g_uri_get_auth_params +g_uri_get_host +g_uri_get_port +g_uri_get_path +g_uri_get_query +g_uri_get_fragment +g_uri_get_flags + +GUriParamsIter +GUriParamsFlags +g_uri_params_iter_init +g_uri_params_iter_next +g_uri_parse_params + G_URI_RESERVED_CHARS_ALLOWED_IN_PATH G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO G_URI_RESERVED_CHARS_GENERIC_DELIMITERS G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS -g_uri_parse_scheme g_uri_escape_string g_uri_unescape_string +g_uri_escape_bytes +g_uri_unescape_bytes g_uri_unescape_segment + g_uri_list_extract_uris g_filename_from_uri g_filename_to_uri + +G_URI_ERROR +GUriError + +g_uri_error_quark
@@ -3338,6 +3512,7 @@ GTestDataFunc g_test_add_data_func g_test_add_data_func_full g_test_add +g_test_get_path GTestFileType g_test_build_filename @@ -3389,6 +3564,7 @@ g_assert g_assert_not_reached g_assert_cmpstr +g_assert_cmpstrv g_assert_cmpint g_assert_cmpuint g_assert_cmphex @@ -3402,6 +3578,7 @@ g_assert_true g_assert_false g_assert_null g_assert_nonnull +g_assert_no_errno g_test_set_nonfatal_assertions GTestCase diff --git a/docs/reference/glib/gvariant-text.xml b/docs/reference/glib/gvariant-text.xml index 7a61c19daa43ddd78b17e1c9553864e920a72e28..55d476e39f4e32d330c35b8ea8987e963b1a5492 100644 --- a/docs/reference/glib/gvariant-text.xml +++ b/docs/reference/glib/gvariant-text.xml @@ -288,7 +288,7 @@ Unicode escapes of the form \uxxxx and \Uxxxxxxxx are supported, in - hexidecimal. The usual control sequence escapes \a, \b, + hexadecimal. The usual control sequence escapes \a, \b, \f, \n, \r, \t and \v are supported. Additionally, a \ before a newline character causes the newline to be ignored. Finally, any other character following \ is copied literally @@ -296,7 +296,7 @@ additions you should only use this feature when necessary for escaping backslashes or quotes. - The usual octal and hexidecimal escapes \0nnn and \xnn are not + The usual octal and hexadecimal escapes \0nnn and \xnn are not supported here. Those escapes are used to encode byte values and GVariant strings are Unicode. @@ -309,10 +309,10 @@ Numbers are given by default as decimal values. Octal and hex values can be given in the usual way (by prefixing with 0 or 0x). Note that GVariant considers bytes to be - unsigned integers and will print them as a two digit hexidecimal number by default. + unsigned integers and will print them as a two digit hexadecimal number by default. - Floating point numbers can also be given in the usual ways, including scientific and hexidecimal notations. + Floating point numbers can also be given in the usual ways, including scientific and hexadecimal notations. For lack of additional information, integers will be parsed as int32 values by default. If the number has a @@ -575,7 +575,7 @@ Bytestrings support the full range of escapes that you would expect (ie: those supported by g_strcompress(). This includes the normal control - sequence escapes (as mentioned in the section on strings) as well as octal and hexidecimal escapes of the + sequence escapes (as mentioned in the section on strings) as well as octal and hexadecimal escapes of the forms \0nnn and \xnn. diff --git a/docs/reference/glib/gvariant-varargs.xml b/docs/reference/glib/gvariant-varargs.xml index b60ab2a341fe609fa1ab250488fcddbe47085c7b..cd9002ca5e2842ec1a8bf95425d9b985053ea6a4 100644 --- a/docs/reference/glib/gvariant-varargs.xml +++ b/docs/reference/glib/gvariant-varargs.xml @@ -532,8 +532,8 @@ value4 = g_variant_new ("x", G_GINT64_CONSTANT (998877665544332211)); gchar *) and makes a copy of it. NULL is not a valid string; use maybe types to encode that. If the 'o' or - 'g' characters are used, care must be taken to ensure that the passed string is a valid DBus - object path or DBus type signature, respectively. + 'g' characters are used, care must be taken to ensure that the passed string is a valid D-Bus + object path or D-Bus type signature, respectively. Upon encounting 's', 'o' or 'g', g_variant_get() returns (by reference) a non-NULL pointer. When any of these format strings are prefixed with an 'm', the type of arguments that are collected does not change in any way, but - NULL becomes a permissable value, to indicate the Nothing case. + NULL becomes a permissible value, to indicate the Nothing case. Note that the "special exception" introduced in the array section for constructing empty arrays is ignored diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build index bba7649f0802174124fd4eec2ded2c40bfafa477..43c2738551a944fbaf8172cb1fdbf69895598572 100644 --- a/docs/reference/glib/meson.build +++ b/docs/reference/glib/meson.build @@ -22,6 +22,7 @@ if get_option('gtk_doc') 'gprintfint.h', 'gmirroringtable.h', 'gscripttable.h', + 'gtrace-private.h', 'glib-mirroring-tab', 'gnulib', 'pcre', @@ -88,7 +89,8 @@ if get_option('gtk_doc') fixxref_args: [ '--html-dir=' + docpath, ], - install: true) + install: true, + check: true) endif if get_option('man') diff --git a/docs/reference/glib/regex-syntax.xml b/docs/reference/glib/regex-syntax.xml index 4cff1796bc2df3cc005cda0bb6d02a7a32c8ca16..5dd92917abdc9707021dec79c1abb8cb43e4e15c 100644 --- a/docs/reference/glib/regex-syntax.xml +++ b/docs/reference/glib/regex-syntax.xml @@ -2313,7 +2313,7 @@ refer to them instead of the whole pattern. In a larger pattern, keeping track of parenthesis numbers can be tricky. It may be more convenient to use named parentheses instead. The Perl syntax for this is (?&name); GRegex also supports the(?P>name) -syntac. We could rewrite the above example as follows: +syntax. We could rewrite the above example as follows: diff --git a/docs/reference/glib/running.xml b/docs/reference/glib/running.xml index 86765c8687780c82e2517a95f494954a784d0a74..aaafddf1dd5769afe7beba0422a7e5f24e8e0e3f 100644 --- a/docs/reference/glib/running.xml +++ b/docs/reference/glib/running.xml @@ -156,8 +156,8 @@ How to run and debug your GLib application - The special value all can be used to turn on all debug options. - The special value help can be used to print all available options. + The special value all can be used to turn on all debug options. + The special value help can be used to print all available options. @@ -207,8 +207,8 @@ How to run and debug your GLib application - The special value all can be used to turn on all options. - The special value help can be used to print all available options. + The special value all can be used to turn on all options. + The special value help can be used to print all available options. @@ -311,7 +311,7 @@ How to run and debug your GLib application Vectored Exception Handling on Windows (see G_DEBUGGER), allowing GLib to catch more exceptions. Set this variable to a comma-separated list of - hexademical exception codes that should additionally be caught. + hexadecimal exception codes that should additionally be caught. By default GLib will only catch Access Violation, Stack Overflow and diff --git a/docs/reference/gobject/glib-genmarshal.xml b/docs/reference/gobject/glib-genmarshal.xml index bf72ba7fef4357c27b5af525fd17c9ee6db2d940..2b3e86fdc6a5746a9a3f2b08f9fb3ff40a53fde6 100644 --- a/docs/reference/gobject/glib-genmarshal.xml +++ b/docs/reference/gobject/glib-genmarshal.xml @@ -411,7 +411,66 @@ debugging information. This option is mutually exclusive with the -Using glib-genmarshal with Autotools +Using <command>glib-genmarshal</command> with Meson + +Meson supports generating closure marshallers using glib-genmarshal +out of the box in its "gnome" module. + + + +In your meson.build file you will typically call the +gnome.genmarshal() method with the source list of marshallers +to generate: + + +gnome = import('gnome') +marshal_files = gnome.genmarshal('marshal', + sources: 'marshal.list', + internal: true, +) + + +The marshal_files variable will contain an array of two elements +in the following order: + + + a build target for the source file + a build target for the header file + + +You should use the returned objects to provide a dependency on every other +build target that references the source or header file; for instance, if you +are using the source to build a library: + + +mainlib = library('project', + sources: project_sources + marshal_files, + ... +) + + +Additionally, if you are including the generated header file inside a build +target that depends on the library you just built, you must ensure that the +internal dependency includes the generated header as a required source file: + + +mainlib_dep = declare_dependency(sources: marshal_files[1], link_with: mainlib) + + +You should not include the generated source file as well, otherwise it will +be built separately for every target that depends on it, causing build +failures. To know more about why all this is required, please refer to the + +corresponding Meson FAQ entry. + + +For more information on how to use the method, see the +Meson +documentation for gnome.genmarshal(). + + + +Using <command>glib-genmarshal</command> with Autotools In order to use glib-genmarshal in your project when using Autotools as the build system, you will first need to modify your diff --git a/docs/reference/gobject/glib-mkenums.xml b/docs/reference/gobject/glib-mkenums.xml index 4c864165739839f3a34315a3ccbf223e47a54e3a..ce250a3ff50726b2481c72facbd25bddaca626c9 100644 --- a/docs/reference/gobject/glib-mkenums.xml +++ b/docs/reference/gobject/glib-mkenums.xml @@ -153,15 +153,16 @@ The same as @type@ with all letters uppercased (e.g. @filename@ -The name of the input file currently being processed (e.g. foo.h). +The full path of the input file currently being processed (e.g. /build/environment/project/src/foo.h). @basename@ -The base name of the input file currently being processed (e.g. foo.h). Typically -you want to use @basename@ in place of @filename@ in your templates, to improve the reproducibility of the build. (Since: 2.22) +The base name of the input file currently being processed (e.g. foo.h). +Typically you want to use @basename@ in place of @filename@ +in your templates, to improve the reproducibility of the build. (Since: 2.22) @@ -171,25 +172,62 @@ you want to use @basename@ in place of @filename@/*< and end with the trigraph sequence >*/. -Per enum definition, the options skip and flags can be specified, to -indicate this enum definition to be skipped, or for it to be treated as -a flags definition, or to specify the common prefix to be stripped from -all values to generate value nicknames, respectively. The underscore_name -option can be used to specify the word separation used in the *_get_type() -function. For instance, /*< underscore_name=gnome_vfs_uri_hide_options >*/. - - -Per value definition, the options skip and nick are supported. -The former causes the value to be skipped, and the latter can be used to -specify the otherwise auto-generated nickname. -Examples: + +The following options can be specified per enum definition: + + +skip + +Indicates this enum definition should be skipped. + + + +flags + +Indicates this enum should be treated as a flags definition. + + + +underscore_name + +Specifies the word separation used in the *_get_type() +function. For instance, /*< underscore_name=gnome_vfs_uri_hide_options >*/. + + + +since + +Specifies the version tag that will be used to substitute the @enumsince@ +keyword in the template, useful when documenting methods generated from the enums +(e.g. Since: @enumsince@). (Since: 2.66) + + + + +The following options can be specified per value definition: + + +skip + +Indicates the value should be skipped. + + + +nick + +Specifies the otherwise auto-generated nickname. + + + + +Examples: typedef enum /*< skip >*/ { PREFIX_FOO } PrefixThisEnumWillBeSkipped; -typedef enum /*< flags,prefix=PREFIX >*/ +typedef enum /*< flags,prefix=PREFIX,since=1.0 >*/ { PREFIX_THE_ZEROTH_VALUE, /*< skip >*/ PREFIX_THE_FIRST_VALUE, @@ -389,52 +427,15 @@ limit. For example, Windows has a limit of 8191 characters. -Using glib-mkenums with Autotools +Using templates -In order to use glib-mkenums in your project when using -Autotools as the build system, you will first need to modify your -configure.ac file to ensure you find the appropriate -command using pkg-config, similarly as to how you discover -the compiler and linker flags for GLib. +Instead of passing the various sections of the generated file to the command +line of glib-mkenums, it's strongly recommended to use a +template file, especially for generating C sources. - -PKG_PROG_PKG_CONFIG([0.28]) -PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums]) - -In your Makefile.am file you will typically use rules -like these: - - -# A list of headers to inspect -project_headers = \ - project-foo.h \ - project-bar.h \ - project-baz.h - -enum-types.h: $(project_headers) enum-types.h.in - $(AM_V_GEN)$(GLIB_MKENUMS) \ - --template=enum-types.h.in \ - --output=$@ \ - $(project_headers) - -enum-types.c: $(project_headers) enum-types.c.in enum-types.h - $(AM_V_GEN)$(GLIB_MKENUMS) \ - --template=enum-types.c.in \ - --output=$@ \ - $(project_headers) - -BUILT_SOURCES += enum-types.h enum-types.c -CLEANFILES += enum-types.h enum-types.c -EXTRA_DIST += enum-types.h.in enum-types.c.in - - -In the example above, we have a variable called project_headers -where we reference all header files we want to inspect for generating enumeration -GTypes. In the enum-types.h rule we use glib-mkenums -with a template called enum-types.h.in in order to generate the -header file; a header template file will typically look like this: +A C header template file will typically look like this: /*** BEGIN file-header ***/ @@ -448,7 +449,7 @@ G_BEGIN_DECLS /*** BEGIN file-production ***/ -/* enumerations from "@filename@" */ +/* enumerations from "@basename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ @@ -460,10 +461,9 @@ GType @enum_name@_get_type (void) G_GNUC_CONST; G_END_DECLS /*** END file-tail ***/ + -The enum-types.c rule is similar to the rule for the -header file, but will use a different enum-types.c.in template -file, similar to this: +A C source template file will typically look like this: /*** BEGIN file-header ***/ @@ -473,16 +473,16 @@ file, similar to this: /*** END file-header ***/ /*** BEGIN file-production ***/ -/* enumerations from "@filename@" */ +/* enumerations from "@basename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) { - static volatile gsize g_@type@_type_id__volatile; + static gsize static_g_@type@_type_id; - if (g_once_init_enter (&g_define_type_id__volatile)) + if (g_once_init_enter (&static_g_@type@_type_id)) { static const G@Type@Value values[] = { /*** END value-header ***/ @@ -498,13 +498,148 @@ GType GType g_@type@_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - g_once_init_leave (&g_@type@_type_id__volatile, g_@type@_type_id); + g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id); } - return g_@type@_type_id__volatile; + return static_g_@type@_type_id; } /*** END value-tail ***/ + + +Template files are easier to modify and update, and can be used +to generate various types of outputs using the same command line +or tools during the build. + + + +Using glib-mkenums with Meson + +Meson supports generating enumeration types using glib-mkenums +out of the box in its "gnome" module. + + + +In your meson.build file you will typically call the +gnome.mkenums_simple() method to generate idiomatic enumeration +types from a list of headers to inspect: + + +project_headers = [ + 'project-foo.h', + 'project-bar.h', + 'project-baz.h', +] + +gnome = import('gnome') +enum_files = gnome.mkenums_simple('enum-types', + sources: project_headers, +) + + + +The enum_files variable will contain an array of two elements +in the following order: + + + a build target for the source file + a build target for the header file + + +You should use the returned objects to provide a dependency on every other +build target that references the source or header file; for instance, if you +are using the source to build a library: + + +mainlib = library('project', + sources: project_sources + enum_files, + ... +) + + +Additionally, if you are including the generated header file inside a build +target that depends on the library you just built, you must ensure that the +internal dependency includes the generated header as a required source file: + + +mainlib_dep = declare_dependency(sources: enum_files[1], link_with: mainlib) + + +You should not include the generated source file as well, otherwise it will +be built separately for every target that depends on it, causing build +failures. To know more about why all this is required, please refer to the + +corresponding Meson FAQ entry. + + + +If you are generating C header and source files that require special +templates, you can use gnome.mkenums() to provide those +headers, for instance: + + +enum_files = gnome.mkenums('enum-types', + sources: project_headers, + h_template: 'enum-types.h.in', + c_template: 'enum-types.c.in', + install_header: true, +) + + +For more information, see the Meson +documentation for gnome.mkenums(). + + + +Using glib-mkenums with Autotools + +In order to use glib-mkenums in your project when using +Autotools as the build system, you will first need to modify your +configure.ac file to ensure you find the appropriate +command using pkg-config, similarly as to how you discover +the compiler and linker flags for GLib. + + +PKG_PROG_PKG_CONFIG([0.28]) + +PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums]) + + +In your Makefile.am file you will typically use rules +like these: + + +# A list of headers to inspect +project_headers = \ + project-foo.h \ + project-bar.h \ + project-baz.h + +enum-types.h: $(project_headers) enum-types.h.in + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template=enum-types.h.in \ + --output=$@ \ + $(project_headers) + +enum-types.c: $(project_headers) enum-types.c.in enum-types.h + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template=enum-types.c.in \ + --output=$@ \ + $(project_headers) + +# Build the enum types files before every other target +BUILT_SOURCES += enum-types.h enum-types.c +CLEANFILES += enum-types.h enum-types.c +EXTRA_DIST += enum-types.h.in enum-types.c.in + + +In the example above, we have a variable called project_headers +where we reference all header files we want to inspect for generating enumeration +GTypes. In the enum-types.h rule we use glib-mkenums +with a template called enum-types.h.in in order to generate the +header file; similarly, in the enum-types.c rule we use a +template called enum-types.c.in. + See also diff --git a/docs/reference/gobject/gobject-docs.xml b/docs/reference/gobject/gobject-docs.xml index 14c8eb4e1cadc502f97a8a4211ed07f8f9cddc1b..ddbc9f274bb2a7709ef1fa3ca453f7036613f91a 100644 --- a/docs/reference/gobject/gobject-docs.xml +++ b/docs/reference/gobject/gobject-docs.xml @@ -200,6 +200,14 @@ Index of new symbols in 2.62 + + Index of new symbols in 2.66 + + + + Index of new symbols in 2.68 + + diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index bed38e4c58356307080bfd2e43212f03226faa26..54fbccaf839405a73c4e4328b52e494f0689ed6e 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -65,6 +65,7 @@ g_type_default_interface_unref g_type_children g_type_interfaces g_type_interface_prerequisites +g_type_interface_instantiatable_prerequisite g_type_set_qdata g_type_get_qdata g_type_query @@ -408,6 +409,8 @@ G_TYPE_SOURCE G_TYPE_POLLFD G_TYPE_THREAD G_TYPE_OPTION_GROUP +G_TYPE_URI +G_TYPE_TREE G_TYPE_IS_BOXED @@ -441,6 +444,8 @@ g_mapped_file_get_type g_markup_parse_context_get_type g_thread_get_type g_option_group_get_type +g_uri_get_type +g_tree_get_type
@@ -521,6 +526,7 @@ g_param_value_defaults g_param_value_validate g_param_value_convert g_param_values_cmp +g_param_spec_is_valid_name g_param_spec_get_name g_param_spec_get_name_quark g_param_spec_get_nick @@ -683,6 +689,8 @@ G_IS_PARAM_SPEC_STRING G_PARAM_SPEC_STRING G_VALUE_HOLDS_STRING G_TYPE_PARAM_STRING +G_VALUE_IS_INTERNED_STRING +G_VALUE_INTERNED_STRING GParamSpecString gchararray g_param_spec_string @@ -692,6 +700,7 @@ g_value_take_string g_value_set_string_take_ownership g_value_get_string g_value_dup_string +g_value_set_interned_string G_IS_PARAM_SPEC_PARAM @@ -859,6 +868,7 @@ g_signal_override_class_handler g_signal_chain_from_overridden_handler g_signal_add_emission_hook g_signal_remove_emission_hook +g_signal_is_valid_name g_signal_parse_name g_signal_get_invocation_hint g_signal_type_cclosure_new @@ -968,8 +978,10 @@ g_io_condition_get_type GBinding GBindingFlags g_binding_get_source +g_binding_dup_source g_binding_get_source_property g_binding_get_target +g_binding_dup_target g_binding_get_target_property g_binding_get_flags g_binding_unbind diff --git a/docs/reference/gobject/meson.build b/docs/reference/gobject/meson.build index 096c9036f0d2745ea45c534961a8119fed6be777..a9a6543549501b5255eb507b7facf93103ec73d7 100644 --- a/docs/reference/gobject/meson.build +++ b/docs/reference/gobject/meson.build @@ -50,7 +50,8 @@ if get_option('gtk_doc') '--html-dir=' + docpath, '--extra-dir=' + join_paths('gobject', '..', 'glib', 'html'), ], - install: true + install: true, + check: true, ) endif diff --git a/docs/reference/gobject/tut_gobject.xml b/docs/reference/gobject/tut_gobject.xml index 947f488d1c08fc2646cd861affe011736a381b9a..0423a38a30881a7211e19548e618ec5dfe5eda34 100644 --- a/docs/reference/gobject/tut_gobject.xml +++ b/docs/reference/gobject/tut_gobject.xml @@ -12,7 +12,7 @@ - GObject is a fundamental classed instantiable type. It implements: + GObject is a fundamental classed instantiatable type. It implements: Memory management with reference counting Construction/Destruction of instances @@ -65,6 +65,8 @@ struct _ViewerFile GObject parent_instance; /* instance members */ + gchar *filename; + guint zoom_level; }; /* will create viewer_file_get_type and set viewer_file_parent_class */ @@ -80,12 +82,25 @@ viewer_file_constructed (GObject *obj) G_OBJECT_CLASS (viewer_file_parent_class)->constructed (obj); } +static void +viewer_file_finalize (GObject *obj) +{ + ViewerFile *self = VIEWER_FILE (obj); + + g_free (self->filename); + + /* Always chain up to the parent finalize function to complete object + * destruction. */ + G_OBJECT_CLASS (viewer_file_parent_class)->finalize (obj); +} + static void viewer_file_class_init (ViewerFileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = viewer_file_constructed; + object_class->finalize = viewer_file_finalize; } static void @@ -265,7 +280,7 @@ ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL); The reference count is initialized to one by g_object_new which means that the caller - is currently the sole owner of the newly-created reference. + is currently the sole owner of the newly-created reference. (If the object is derived from GInitiallyUnowned, this reference count is floating.) When the reference count reaches zero, that is, when g_object_unref is called by the last client holding a reference to the object, the dispose and the @@ -278,8 +293,8 @@ ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL); one of the g_type_register_* functions), the object's instance memory will be freed or returned to the object pool for this type. Once the object has been freed, if it was the last instance of the type, the type's class - will be destroyed as described in and - . + will be destroyed as described in and + . @@ -465,12 +480,12 @@ ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL); /* Implementation */ /************************************************/ -enum +typedef enum { PROP_FILENAME = 1, PROP_ZOOM_LEVEL, N_PROPERTIES -}; +} ViewerFileProperty; static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; @@ -482,7 +497,7 @@ viewer_file_set_property (GObject *object, { ViewerFile *self = VIEWER_FILE (object); - switch (property_id) + switch ((ViewerFileProperty) property_id) { case PROP_FILENAME: g_free (self->filename); @@ -510,7 +525,7 @@ viewer_file_get_property (GObject *object, { ViewerFile *self = VIEWER_FILE (object); - switch (property_id) + switch ((ViewerFileProperty) property_id) { case PROP_FILENAME: g_value_set_string (value, self->filename); diff --git a/docs/reference/gobject/tut_gtype.xml b/docs/reference/gobject/tut_gtype.xml index a1c6005a074c568906004d26228ac9fb85a04c05..ee042889d257018cbb2b62f47a0eb8ebb1432b1c 100644 --- a/docs/reference/gobject/tut_gtype.xml +++ b/docs/reference/gobject/tut_gtype.xml @@ -108,7 +108,7 @@ GType g_type_register_fundamental (GType type_id, The major common point between all GLib types (fundamental and - non-fundamental, classed and non-classed, instantiable and non-instantiable) is that + non-fundamental, classed and non-classed, instantiatable and non-instantiatable) is that they can all be manipulated through a single API to copy/assign them. @@ -300,11 +300,11 @@ GType viewer_file_get_type (void) - - Non-instantiable non-classed fundamental types + + Non-instantiatable non-classed fundamental types - A lot of types are not instantiable by the type system and do not have + A lot of types are not instantiatable by the type system and do not have a class. Most of these types are fundamental trivial types such as gchar, and are already registered by GLib. @@ -344,7 +344,7 @@ GType viewer_file_get_type (void) - Having non-instantiable types might seem a bit useless: what good is a type + Having non-instantiatable types might seem a bit useless: what good is a type if you cannot instantiate an instance of that type ? Most of these types are used in conjunction with GValues: a GValue is initialized with an integer or a string and it is passed around by using the registered @@ -354,8 +354,8 @@ GType viewer_file_get_type (void) - - Instantiable classed types: objects + + Instantiatable classed types: objects This section covers the theory behind objects. See @@ -364,10 +364,10 @@ GType viewer_file_get_type (void) - Types which are registered with a class and are declared instantiable are + Types which are registered with a class and are declared instantiatable are what most closely resembles an object. Although GObjects (detailed in ) - are the most well known type of instantiable + are the most well known type of instantiatable classed types, other kinds of similar objects used as the base of an inheritance hierarchy have been externally developed and they are all built on the fundamental features described below. @@ -498,7 +498,7 @@ B *b; - + Initialization and Destruction @@ -599,7 +599,7 @@ B *b; interface initialization, see - + @@ -610,7 +610,7 @@ B *b; Last call to g_type_free_instance for target type interface destruction, see - + @@ -633,8 +633,8 @@ B *b; - - Non-instantiable classed types: interfaces + + Non-instantiatable classed types: interfaces This section covers the theory behind interfaces. See @@ -648,7 +648,7 @@ B *b; Imagine the play, pause and stop buttons on hi-fi equipment — those can be seen as a playback interface. Once you know what they do, you can control your CD player, MP3 player or anything that uses these symbols. - To declare an interface you have to register a non-instantiable + To declare an interface you have to register a non-instantiatable classed type which derives from GTypeInterface. The following piece of code declares such an interface. @@ -792,14 +792,14 @@ struct _GInterfaceInfo - + Interface Initialization - When an instantiable classed type which implements an interface + When an instantiatable classed type which implements an interface (either directly or by inheriting an implementation from a superclass) is created for the first time, its class structure is initialized - following the process described in . + following the process described in . After that, the interface implementations associated with the type are initialized. @@ -852,7 +852,7 @@ viewer_editable_default_init (ViewerEditableInterface *iface) GType viewer_editable_get_type (void) { - static volatile gsize type_id = 0; + static gsize type_id = 0; if (g_once_init_enter (&type_id)) { const GTypeInfo info = { sizeof (ViewerEditableInterface), @@ -937,11 +937,11 @@ viewer_editable_default_init (ViewerEditableInterface *iface) - + Interface Destruction - When the last instance of an instantiable type which registered + When the last instance of an instantiatable type which registered an interface implementation is destroyed, the interface's implementations associated to the type are destroyed. @@ -955,7 +955,7 @@ viewer_editable_default_init (ViewerEditableInterface *iface) Again, it is important to understand, as in - , + , that both interface_finalize and base_finalize are invoked exactly once for the destruction of each implementation of an interface. Thus, if you were to use one of these functions, you would need to use a static integer variable diff --git a/docs/reference/gobject/tut_howto.xml b/docs/reference/gobject/tut_howto.xml index bfb8d95c5857cbeb8004af5e0cfa0d5eb9665cc1..b61a328b6e74e096eaa21ea45a50a6fe01ba7d4e 100644 --- a/docs/reference/gobject/tut_howto.xml +++ b/docs/reference/gobject/tut_howto.xml @@ -854,7 +854,7 @@ b_method_to_call (B *obj, gint some_param) The theory behind how GObject interfaces work is given in - ; this section covers how to + ; this section covers how to define and implement an interface. diff --git a/docs/reference/meson.build b/docs/reference/meson.build index 8da9665f4e7f3c35bffe21b2869e255348310948..3f09be555bcffd0ba7cbd0a64eac278e3b04d871 100644 --- a/docs/reference/meson.build +++ b/docs/reference/meson.build @@ -7,7 +7,7 @@ stable_2_series_versions = [ '26', '28', '30', '32', '34', '36', '38', '40', '42', '44', '46', '48', '50', '52', '54', '56', '58', - '60', '62', + '60', '62', '64', '66', '68', ] ignore_decorators = [ @@ -19,9 +19,26 @@ ignore_decorators = [ foreach version : stable_2_series_versions ignore_decorators += [ + # Note that gtkdoc is going to use those in regex, and the longest match + # must come first. That's why '_FOR()' variant comes first. + # gtkdoc special-case '()' and replace it by a regex matching a symbol name. 'GLIB_AVAILABLE_IN_2_' + version, + 'GLIB_DEPRECATED_IN_2_' + version + '_FOR()', 'GLIB_DEPRECATED_IN_2_' + version, - 'GLIB_DEPRECATED_IN_2_' + version + '_FOR', + + 'GLIB_AVAILABLE_STATIC_INLINE_IN_2_' + version, + + 'GLIB_AVAILABLE_ENUMERATOR_IN_2_' + version, + 'GLIB_DEPRECATED_ENUMERATOR_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_ENUMERATOR_IN_2_' + version, + + 'GLIB_AVAILABLE_MACRO_IN_2_' + version, + 'GLIB_DEPRECATED_MACRO_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_MACRO_IN_2_' + version, + + 'GLIB_AVAILABLE_TYPE_IN_2_' + version, + 'GLIB_DEPRECATED_TYPE_IN_2_' + version + '_FOR()', + 'GLIB_DEPRECATED_TYPE_IN_2_' + version, ] endforeach @@ -29,6 +46,17 @@ gtkdoc_common_scan_args = [ '--ignore-decorators=' + '|'.join(ignore_decorators), ] +if get_option('gtk_doc') + if not meson.version().version_compare('>=0.52.0') + error('Building documentation requires Meson >= 0.52.0.') + endif + # Check we have the minimum gtk-doc version required. Older versions won't + # generate correct documentation. + dependency('gtk-doc', version : '>=1.32.1', + fallback : ['gtk-doc', 'dummy_dep'], + default_options : ['tests=false']) +endif + subdir('gio') subdir('glib') -subdir('gobject') \ No newline at end of file +subdir('gobject') diff --git a/fuzzing/README.md b/fuzzing/README.md index dcacef6377efa259ddee55c919c8df3e10a1a867..16f5a05bc2eaaaea838af9a4e562200679604610 100644 --- a/fuzzing/README.md +++ b/fuzzing/README.md @@ -1,6 +1,6 @@ Fuzz targets used by [oss-fuzz](https://github.com/google/oss-fuzz/). -Useful links: [Dashboard](https://oss-fuzz.com/) _(requires access)_, [Build logs](https://oss-fuzz-build-logs.storage.googleapis.com/index.html), [Coverage](https://oss-fuzz.com/v2/coverage-report/job/libfuzzer_asan_glib/latest) +Useful links: [Dashboard](https://oss-fuzz.com/) _(requires access)_, [Build logs](https://oss-fuzz-build-logs.storage.googleapis.com/index.html), [Coverage](https://oss-fuzz.com/coverage-report/job/libfuzzer_asan_glib/latest) ## How to add new targets diff --git a/fuzzing/driver.c b/fuzzing/driver.c index 99e965ba6f22c1e41b9536ffb397648f2e280228..f6d2396db0127352a9d361872c3830a261a82e9e 100644 --- a/fuzzing/driver.c +++ b/fuzzing/driver.c @@ -10,6 +10,7 @@ int main (int argc, char **argv) { FILE *f; + long tell_result; size_t n_read, len; unsigned char *buf; @@ -19,7 +20,9 @@ main (int argc, char **argv) f = fopen (argv[1], "r"); assert (f); fseek (f, 0, SEEK_END); - len = ftell (f); + tell_result = ftell (f); + assert (tell_result >= 0); + len = (size_t) tell_result; fseek (f, 0, SEEK_SET); buf = (unsigned char*) malloc (len); n_read = fread (buf, 1, len, f); diff --git a/fuzzing/fuzz_date_parse.c b/fuzzing/fuzz_date_parse.c new file mode 100644 index 0000000000000000000000000000000000000000..0a7b62eecdf06df3213542b8e2903b542351459e --- /dev/null +++ b/fuzzing/fuzz_date_parse.c @@ -0,0 +1,19 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GDate *date = g_date_new (); + + fuzz_set_logging_func (); + + /* ignore @size (g_date_set_parse() doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + g_date_set_parse (date, (const gchar *) nul_terminated_data); + g_free (nul_terminated_data); + + g_date_free (date); + + return 0; +} diff --git a/fuzzing/fuzz_date_time_new_from_iso8601.c b/fuzzing/fuzz_date_time_new_from_iso8601.c new file mode 100644 index 0000000000000000000000000000000000000000..be53a13192bb4a5c0e4674db49ac8167adb1d15b --- /dev/null +++ b/fuzzing/fuzz_date_time_new_from_iso8601.c @@ -0,0 +1,25 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GDateTime *dt = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (the function doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + dt = g_date_time_new_from_iso8601 ((const gchar *) nul_terminated_data, NULL); + g_free (nul_terminated_data); + + if (dt != NULL) + { + gchar *text = g_date_time_format_iso8601 (dt); + g_free (text); + } + + g_clear_pointer (&dt, g_date_time_unref); + + return 0; +} diff --git a/fuzzing/fuzz_dbus_message.c b/fuzzing/fuzz_dbus_message.c index bccb2ba3e37f29868075bd670a9cb95180ab6073..1030d8df04db2ba8545634932a708c48a5e7fc79 100644 --- a/fuzzing/fuzz_dbus_message.c +++ b/fuzzing/fuzz_dbus_message.c @@ -1,6 +1,6 @@ #include "fuzz.h" -const static GDBusCapabilityFlags flags = G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING; +static const GDBusCapabilityFlags flags = G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING; int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) diff --git a/fuzzing/fuzz_inet_address_mask_new_from_string.c b/fuzzing/fuzz_inet_address_mask_new_from_string.c new file mode 100644 index 0000000000000000000000000000000000000000..9ac62eda4edd38df9466cf36a8c3a6789133501c --- /dev/null +++ b/fuzzing/fuzz_inet_address_mask_new_from_string.c @@ -0,0 +1,25 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GInetAddressMask *mask = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (the function doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + mask = g_inet_address_mask_new_from_string ((const gchar *) nul_terminated_data, NULL); + g_free (nul_terminated_data); + + if (mask != NULL) + { + gchar *text = g_inet_address_mask_to_string (mask); + g_free (text); + } + + g_clear_object (&mask); + + return 0; +} diff --git a/fuzzing/fuzz_inet_address_new_from_string.c b/fuzzing/fuzz_inet_address_new_from_string.c new file mode 100644 index 0000000000000000000000000000000000000000..af24592ac5f199595276ed08bb59c0bbb7dad50a --- /dev/null +++ b/fuzzing/fuzz_inet_address_new_from_string.c @@ -0,0 +1,25 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GInetAddress *addr = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (the function doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + addr = g_inet_address_new_from_string ((const gchar *) nul_terminated_data); + g_free (nul_terminated_data); + + if (addr != NULL) + { + gchar *text = g_inet_address_to_string (addr); + g_free (text); + } + + g_clear_object (&addr); + + return 0; +} diff --git a/fuzzing/fuzz_inet_socket_address_new_from_string.c b/fuzzing/fuzz_inet_socket_address_new_from_string.c new file mode 100644 index 0000000000000000000000000000000000000000..11dd16508861cbf92e7496cce7ae93fbccfaef4b --- /dev/null +++ b/fuzzing/fuzz_inet_socket_address_new_from_string.c @@ -0,0 +1,25 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GSocketAddress *addr = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (the function doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + addr = g_inet_socket_address_new_from_string ((const gchar *) nul_terminated_data, 1); + g_free (nul_terminated_data); + + if (addr != NULL) + { + gchar *text = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr)); + g_free (text); + } + + g_clear_object (&addr); + + return 0; +} diff --git a/fuzzing/fuzz_key.c b/fuzzing/fuzz_key.c index 8d0edc5fa06c0b6b8235add5776355adb2ef20d5..9f1f9187e6005c499926bc836b5ad3a86017039e 100644 --- a/fuzzing/fuzz_key.c +++ b/fuzzing/fuzz_key.c @@ -1,16 +1,27 @@ #include "fuzz.h" -int -LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +static void +test_parse (const gchar *data, + size_t size, + GKeyFileFlags flags) { GKeyFile *key = NULL; - fuzz_set_logging_func (); - key = g_key_file_new (); g_key_file_load_from_data (key, (const gchar*) data, size, G_KEY_FILE_NONE, NULL); g_key_file_free (key); +} + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + fuzz_set_logging_func (); + + test_parse ((const gchar *) data, size, G_KEY_FILE_NONE); + test_parse ((const gchar *) data, size, G_KEY_FILE_KEEP_COMMENTS); + test_parse ((const gchar *) data, size, G_KEY_FILE_KEEP_TRANSLATIONS); + return 0; } diff --git a/fuzzing/fuzz_network_address_parse.c b/fuzzing/fuzz_network_address_parse.c new file mode 100644 index 0000000000000000000000000000000000000000..bda05c2f6638de3ebb908df35d5ea6eda4c73840 --- /dev/null +++ b/fuzzing/fuzz_network_address_parse.c @@ -0,0 +1,25 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GSocketConnectable *connectable = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (g_network_address_parse() doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + connectable = g_network_address_parse ((const gchar *) nul_terminated_data, 1, NULL); + g_free (nul_terminated_data); + + if (connectable != NULL) + { + gchar *text = g_socket_connectable_to_string (connectable); + g_free (text); + } + + g_clear_object (&connectable); + + return 0; +} diff --git a/fuzzing/fuzz_network_address_parse_uri.c b/fuzzing/fuzz_network_address_parse_uri.c new file mode 100644 index 0000000000000000000000000000000000000000..ea51133632537c614daeb33bc1c1898be748638e --- /dev/null +++ b/fuzzing/fuzz_network_address_parse_uri.c @@ -0,0 +1,25 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + GSocketConnectable *connectable = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (g_network_address_parse_uri() doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + connectable = g_network_address_parse_uri ((const gchar *) nul_terminated_data, 1, NULL); + g_free (nul_terminated_data); + + if (connectable != NULL) + { + gchar *text = g_socket_connectable_to_string (connectable); + g_free (text); + } + + g_clear_object (&connectable); + + return 0; +} diff --git a/fuzzing/fuzz_uri_escape.c b/fuzzing/fuzz_uri_escape.c new file mode 100644 index 0000000000000000000000000000000000000000..6a3d197507e8477bc81834d23d7410dfba00b3dc --- /dev/null +++ b/fuzzing/fuzz_uri_escape.c @@ -0,0 +1,65 @@ +#include "fuzz.h" + +static void +test_bytes (const guint8 *data, + gsize size) +{ + GError *error = NULL; + GBytes *unescaped_bytes = NULL; + gchar *escaped_string = NULL; + + if (size > G_MAXSSIZE) + return; + + unescaped_bytes = g_uri_unescape_bytes ((const gchar *) data, (gssize) size, NULL, &error); + if (unescaped_bytes == NULL) + { + g_assert_nonnull (error); + g_clear_error (&error); + return; + } + + escaped_string = g_uri_escape_bytes (g_bytes_get_data (unescaped_bytes, NULL), + g_bytes_get_size (unescaped_bytes), + NULL); + g_bytes_unref (unescaped_bytes); + + if (escaped_string == NULL) + return; + + g_free (escaped_string); +} + +static void +test_string (const guint8 *data, + gsize size) +{ + gchar *unescaped_string = NULL; + gchar *escaped_string = NULL; + + unescaped_string = g_uri_unescape_segment ((const gchar *) data, (const gchar *) data + size, NULL); + if (unescaped_string == NULL) + return; + + escaped_string = g_uri_escape_string (unescaped_string, NULL, TRUE); + g_free (unescaped_string); + + if (escaped_string == NULL) + return; + + g_free (escaped_string); +} + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + fuzz_set_logging_func (); + + /* Bytes form */ + test_bytes (data, size); + + /* String form (doesn’t do %-decoding) */ + test_string (data, size); + + return 0; +} diff --git a/fuzzing/fuzz_uri_parse.c b/fuzzing/fuzz_uri_parse.c new file mode 100644 index 0000000000000000000000000000000000000000..03c581ecbd547b6f30343853d9e88248856b2df8 --- /dev/null +++ b/fuzzing/fuzz_uri_parse.c @@ -0,0 +1,44 @@ +#include "fuzz.h" + +static void +test_with_flags (const gchar *data, + GUriFlags flags) +{ + GUri *uri = NULL; + gchar *uri_string = NULL; + + uri = g_uri_parse (data, flags, NULL); + + if (uri == NULL) + return; + + uri_string = g_uri_to_string (uri); + g_uri_unref (uri); + + if (uri_string == NULL) + return; + + g_free (uri_string); +} + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (g_uri_parse() doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_NONE); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_PARSE_RELAXED); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_NON_DNS); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_HAS_AUTH_PARAMS); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_HAS_PASSWORD); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_ENCODED_QUERY); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_ENCODED_PATH); + test_with_flags ((const gchar *) nul_terminated_data, G_URI_FLAGS_SCHEME_NORMALIZE); + g_free (nul_terminated_data); + + return 0; +} diff --git a/fuzzing/fuzz_uri_parse_params.c b/fuzzing/fuzz_uri_parse_params.c new file mode 100644 index 0000000000000000000000000000000000000000..ddae5708a113a499390db17889e13a1811c851be --- /dev/null +++ b/fuzzing/fuzz_uri_parse_params.c @@ -0,0 +1,28 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + GError *error = NULL; + GHashTable *parsed_params = NULL; + + fuzz_set_logging_func (); + + if (size > G_MAXSSIZE) + return 0; + + parsed_params = g_uri_parse_params ((const gchar *) data, (gssize) size, + "&", G_URI_PARAMS_NONE, &error); + if (parsed_params == NULL) + { + g_assert (error); + g_clear_error (&error); + return 0; + } + + + g_assert_no_error (error); + g_hash_table_unref (parsed_params); + + return 0; +} diff --git a/fuzzing/meson.build b/fuzzing/meson.build index 7fdd8c909b141b7db589d4593d205fd76a3332e6..a403212005a4f304242d1cfa81fbba90ec31a2b7 100644 --- a/fuzzing/meson.build +++ b/fuzzing/meson.build @@ -1,7 +1,17 @@ fuzz_targets = [ 'fuzz_bookmark', + 'fuzz_date_parse', + 'fuzz_date_time_new_from_iso8601', 'fuzz_dbus_message', + 'fuzz_inet_address_mask_new_from_string', + 'fuzz_inet_address_new_from_string', + 'fuzz_inet_socket_address_new_from_string', 'fuzz_key', + 'fuzz_network_address_parse', + 'fuzz_network_address_parse_uri', + 'fuzz_uri_escape', + 'fuzz_uri_parse', + 'fuzz_uri_parse_params', 'fuzz_variant_binary', 'fuzz_variant_text', ] diff --git a/gio/completion/gio b/gio/completion/gio index c1db98561d081738b3653b8bb9e920a9d9a87454..c650475b9401e42c34bdb141a60980bb9ac4baad 100644 --- a/gio/completion/gio +++ b/gio/completion/gio @@ -22,7 +22,8 @@ # Check whether the suggestions have common prefix (i.e. suggestions won't be # shown and prefix will be completed first) -__has_common_prefix() { +__gio_has_common_prefix() { + local i for (( i = 1; i < ${#COMPREPLY[@]}; i++ )); do if [[ "${COMPREPLY[i-1]:${#cur}:1}" != "${COMPREPLY[i]:${#cur}:1}" ]]; then return 1 # False @@ -43,28 +44,29 @@ __gio_location() { if [[ $cur =~ "/"$ ]]; then dir="$cur" elif [[ $cur =~ "/" ]]; then - dir="$(dirname "$cur")/" + # Subtract basename because dirname cmd doesn't work well with schemes + dir=${cur%$(basename "$cur")} fi - # List daemon mounts, just if dir is not specified, or looks like scheme - local mounts=() - if [[ $dir == "" ]] || [[ $dir =~ ":"$ && ! $dir =~ "/" ]]; then - while IFS=$'\n' read mount; do - # Do not care about local mounts - [[ "$mount" =~ ^"file:" ]] && continue + # List volumes and mounts + local mounts=( ) + local mount + while IFS=$'\n' read mount; do + # Do not care about local mounts + [[ "$mount" =~ ^"file:" ]] && continue - # Use only matching mounts - [[ "$mount" =~ ^"$cur" && "$mount" != "$cur" ]] && mounts+=("$mount") - done < <(gio mount -l | sed -n -r 's/^ *Mount\([0-9]+\): .* -> (.*)$/\1/p') - fi + # Use only matching mounts + [[ "$mount" =~ ^"$cur" && "$mount" != "$cur" ]] && mounts+=("$mount") + done < <(gio mount -li | sed -n -r 's/^ *(default_location|activation_root)=(.*)$/\2/p' | sort -u) # Workaround to unescape dir name (e.g. "\ " -> " ") - declare -a tmp="( ${dir} )" - unescaped_dir="${tmp[0]}" + local -a tmp="( ${dir} )" + local unescaped_dir="${tmp[0]}" # List files local files=() local names=() + local name size type while IFS=$'\t' read name size type; do # Escape name properly local escaped_name="$(printf "%q" "$name")" @@ -76,7 +78,7 @@ __gio_location() { escaped_name="$escaped_name " fi - path="$dir$escaped_name" + local path="$dir$escaped_name" # Use only matching paths if [[ "$path" =~ ^"$cur" ]]; then @@ -88,10 +90,10 @@ __gio_location() { COMPREPLY=("${files[@]}" "${mounts[@]}") # Workaround to show suggestions as basenames only - if ! __has_common_prefix; then + if ! __gio_has_common_prefix; then COMPREPLY=("${mounts[@]} ${names[@]}") - # Workaround to prevent overwritting suggestions, it adds empty + # Workaround to prevent overwriting suggestions, it adds empty # suggestion, otherwise names with colons will be corrupted COMPREPLY+=(" ") @@ -106,7 +108,7 @@ __gio_location() { __gio() { # Complete subcommands if (( ${COMP_CWORD} == 1 )); then - COMPREPLY=($(compgen -W "help version cat copy info list mime mkdir monitor mount move open rename save set trash tree" -- "${COMP_WORDS[1]}")) + COMPREPLY=($(compgen -W "help version cat copy info launch list mime mkdir monitor mount move open rename remove save set trash tree" -- "${COMP_WORDS[1]}")) compopt +o nospace return 0 fi diff --git a/gio/data-to-c.py b/gio/data-to-c.py old mode 100755 new mode 100644 index f226220eda1437266eb9bc89246af0953cf22093..d8854b4174a45ccf6c6f1d1d2863ff52f87094cd --- a/gio/data-to-c.py +++ b/gio/data-to-c.py @@ -3,14 +3,14 @@ import sys if len(sys.argv) < 4: - print('Usage: {0} ') + print("Usage: {0} ") -with open(sys.argv[1], 'rb') as f: - in_data = f.read().decode('utf-8', 'backslashreplace') -b = [r'\x{:02x}'.format(ord(c)) for c in in_data] +with open(sys.argv[1], "rb") as f: + in_data = f.read().decode("utf-8", "backslashreplace") +b = [r"\x{:02x}".format(ord(c)) for c in in_data] -out_data = "const char {0}[] = \"".format(sys.argv[2]) -out_data += "".join(b) + "\";" +out_data = 'const char {0}[] = "'.format(sys.argv[2]) +out_data += "".join(b) + '";' -with open(sys.argv[3], 'w') as f: +with open(sys.argv[3], "w") as f: f.write(out_data) diff --git a/gio/gaction.c b/gio/gaction.c index c3748a902f109290493ca58f370bacc065998892..645eb26ed7323991dce25960758df4ae5966d081 100644 --- a/gio/gaction.c +++ b/gio/gaction.c @@ -224,7 +224,7 @@ g_action_change_state (GAction *action, * The return value (if non-%NULL) should be freed with * g_variant_unref() when it is no longer required. * - * Returns: (transfer full): the current state of the action + * Returns: (nullable) (transfer full): the current state of the action * * Since: 2.28 **/ diff --git a/gio/gactiongroup.c b/gio/gactiongroup.c index 2345ce3b971882b722e296bb940f244d5601a3cc..ecd3af1c33e51b909889d1fac8d1c701d29b2b1a 100644 --- a/gio/gactiongroup.c +++ b/gio/gactiongroup.c @@ -529,7 +529,7 @@ g_action_group_get_action_enabled (GActionGroup *action_group, * The return value (if non-%NULL) should be freed with * g_variant_unref() when it is no longer required. * - * Returns: (nullable): the current state of the action + * Returns: (nullable) (transfer full): the current state of the action * * Since: 2.28 **/ @@ -589,6 +589,33 @@ g_action_group_change_action_state (GActionGroup *action_group, * parameters then @parameter must be %NULL. See * g_action_group_get_action_parameter_type(). * + * If the #GActionGroup implementation supports asynchronous remote + * activation over D-Bus, this call may return before the relevant + * D-Bus traffic has been sent, or any replies have been received. In + * order to block on such asynchronous activation calls, + * g_dbus_connection_flush() should be called prior to the code, which + * depends on the result of the action activation. Without flushing + * the D-Bus connection, there is no guarantee that the action would + * have been activated. + * + * The following code which runs in a remote app instance, shows an + * example of a "quit" action being activated on the primary app + * instance over D-Bus. Here g_dbus_connection_flush() is called + * before `exit()`. Without g_dbus_connection_flush(), the "quit" action + * may fail to be activated on the primary instance. + * + * |[ + * // call "quit" action on primary instance + * g_action_group_activate_action (G_ACTION_GROUP (app), "quit", NULL); + * + * // make sure the action is activated now + * g_dbus_connection_flush (...); + * + * g_debug ("application has been terminated. exiting."); + * + * exit (0); + * ]| + * * Since: 2.28 **/ void diff --git a/gio/gactiongroupexporter.c b/gio/gactiongroupexporter.c index 17111ffb88fa7d9299645df175981b0af4f67e5e..8453723f54e663cdfefd0ca5da5ba71350584003 100644 --- a/gio/gactiongroupexporter.c +++ b/gio/gactiongroupexporter.c @@ -538,7 +538,7 @@ g_dbus_connection_export_action_group (GDBusConnection *connection, GError **error) { const GDBusInterfaceVTable vtable = { - org_gtk_Actions_method_call + org_gtk_Actions_method_call, NULL, NULL, { 0 } }; GActionGroupExporter *exporter; guint id; diff --git a/gio/gactionmap.c b/gio/gactionmap.c index bfcda8df32ec7c8a8a65a35671000da10890814b..077e3cfa601d049a129f6806730ea5d6c4ae4363 100644 --- a/gio/gactionmap.c +++ b/gio/gactionmap.c @@ -76,7 +76,7 @@ g_action_map_default_init (GActionMapInterface *iface) * * If no such action exists, returns %NULL. * - * Returns: (transfer none): a #GAction, or %NULL + * Returns: (nullable) (transfer none): a #GAction, or %NULL * * Since: 2.32 */ diff --git a/gio/gappinfo.c b/gio/gappinfo.c index 1dafc78fe1f81f86a983ea864dfa79f8a128302a..eff18da83181ae53787ace3a50eeb8ee1fdea6d3 100644 --- a/gio/gappinfo.c +++ b/gio/gappinfo.c @@ -138,7 +138,7 @@ g_app_info_dup (GAppInfo *appinfo) * * Checks if two #GAppInfos are equal. * - * Note that the check may not compare each individual + * Note that the check *may not* compare each individual * field, and only does an identity check. In case detecting changes in the * contents is needed, program code must additionally compare relevant fields. * @@ -173,7 +173,7 @@ g_app_info_equal (GAppInfo *appinfo1, * Note that the returned ID may be %NULL, depending on how * the @appinfo has been constructed. * - * Returns: a string containing the application's ID. + * Returns: (nullable): a string containing the application's ID. **/ const char * g_app_info_get_id (GAppInfo *appinfo) @@ -240,7 +240,7 @@ g_app_info_get_display_name (GAppInfo *appinfo) * * Gets a human-readable description of an installed application. * - * Returns: a string containing a description of the + * Returns: (nullable): a string containing a description of the * application @appinfo, or %NULL if none. **/ const char * @@ -256,7 +256,7 @@ g_app_info_get_description (GAppInfo *appinfo) } /** - * g_app_info_get_executable: + * g_app_info_get_executable: (virtual get_executable) * @appinfo: a #GAppInfo * * Gets the executable's name for the installed application. @@ -278,13 +278,13 @@ g_app_info_get_executable (GAppInfo *appinfo) /** - * g_app_info_get_commandline: + * g_app_info_get_commandline: (virtual get_commandline) * @appinfo: a #GAppInfo * * Gets the commandline with which the application will be * started. * - * Returns: (type filename): a string containing the @appinfo's commandline, + * Returns: (nullable) (type filename): a string containing the @appinfo's commandline, * or %NULL if this information is not available * * Since: 2.20 @@ -518,7 +518,7 @@ g_app_info_get_supported_types (GAppInfo *appinfo) * * Gets the icon for the application. * - * Returns: (transfer none): the default #GIcon for @appinfo or %NULL + * Returns: (nullable) (transfer none): the default #GIcon for @appinfo or %NULL * if there is no default icon. **/ GIcon * @@ -1279,7 +1279,7 @@ g_app_launch_context_get_environment (GAppLaunchContext *context) * applications are started on the same display as the launching * application, by setting the `DISPLAY` environment variable. * - * Returns: a display string for the display. + * Returns: (nullable): a display string for the display. */ char * g_app_launch_context_get_display (GAppLaunchContext *context, @@ -1309,9 +1309,9 @@ g_app_launch_context_get_display (GAppLaunchContext *context, * `DESKTOP_STARTUP_ID` for the launched operation, if supported. * * Startup notification IDs are defined in the - * [FreeDesktop.Org Startup Notifications standard](http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt"). + * [FreeDesktop.Org Startup Notifications standard](http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt). * - * Returns: a startup notification ID for the application, or %NULL if + * Returns: (nullable): a startup notification ID for the application, or %NULL if * not supported. **/ char * diff --git a/gio/gapplication-tool.c b/gio/gapplication-tool.c index 68a7424197050ffefea33f0bcacff77cd75e995e..7ad06229976f1d6f04602154714a1998e541cd53 100644 --- a/gio/gapplication-tool.c +++ b/gio/gapplication-tool.c @@ -47,10 +47,12 @@ static const struct help_topic topics[] = { N_("[COMMAND]") }, { "version", N_("Print version"), - N_("Print version information and exit") + N_("Print version information and exit"), + NULL }, { "list-apps", N_("List applications"), - N_("List the installed D-Bus activatable applications (by .desktop files)") + N_("List the installed D-Bus activatable applications (by .desktop files)"), + NULL }, { "launch", N_("Launch an application"), N_("Launch the application (with optional files to open)"), @@ -85,7 +87,7 @@ app_help (gboolean requested, if (command) { - gint i; + gsize i; for (i = 0; i < G_N_ELEMENTS (topics); i++) if (g_str_equal (topics[i].command, command)) @@ -102,8 +104,8 @@ app_help (gboolean requested, if (topic) { - gint maxwidth; - gint i; + guint maxwidth; + gsize i; g_string_append_printf (string, "\n %s %s %s\n\n", "gapplication", topic->command, topic->synopsis ? _(topic->synopsis) : ""); @@ -127,8 +129,8 @@ app_help (gboolean requested, } else { - gint maxwidth; - gint i; + guint maxwidth; + gsize i; g_string_append_printf (string, "\n %s %s %s\n\n", "gapplication", _("COMMAND"), _("[ARGS…]")); g_string_append_printf (string, _("Commands:\n")); diff --git a/gio/gapplication.c b/gio/gapplication.c index 02ab2b046ecb0045d9aa741031b5c9dd74f3ddf9..3720146af96f17d19286e14d383cbfd21052cd02 100644 --- a/gio/gapplication.c +++ b/gio/gapplication.c @@ -70,7 +70,7 @@ * arguments are passed through platform communication to the already * running program. The already running instance of the program is * called the "primary instance"; for non-unique applications this is - * the always the current instance. On Linux, the D-Bus session bus + * always the current instance. On Linux, the D-Bus session bus * is used for communication. * * The use of #GApplication differs from some other commonly-used @@ -129,7 +129,7 @@ * initialization for all of these in a single place. * * Regardless of which of these entry points is used to start the - * application, GApplication passes some "platform data from the + * application, GApplication passes some ‘platform data’ from the * launching instance to the primary instance, in the form of a * #GVariant dictionary mapping strings to variants. To use platform * data, override the @before_emit or @after_emit virtual functions @@ -542,7 +542,7 @@ g_application_parse_command_line (GApplication *application, { GOptionEntry entries[] = { { "gapplication-service", '\0', 0, G_OPTION_ARG_NONE, &become_service, - N_("Enter GApplication service mode (use from D-Bus service files)") }, + N_("Enter GApplication service mode (use from D-Bus service files)"), NULL }, { NULL } }; @@ -554,7 +554,7 @@ g_application_parse_command_line (GApplication *application, { GOptionEntry entries[] = { { "gapplication-app-id", '\0', 0, G_OPTION_ARG_STRING, &app_id, - N_("Override the application’s ID") }, + N_("Override the application’s ID"), NULL }, { NULL } }; @@ -566,7 +566,7 @@ g_application_parse_command_line (GApplication *application, { GOptionEntry entries[] = { { "gapplication-replace", '\0', 0, G_OPTION_ARG_NONE, &replace, - N_("Replace the running instance") }, + N_("Replace the running instance"), NULL }, { NULL } }; @@ -701,14 +701,14 @@ add_packed_option (GApplication *application, * * It is important to use the proper GVariant format when retrieving * the options with g_variant_dict_lookup(): - * - for %G_OPTION_ARG_NONE, use b - * - for %G_OPTION_ARG_STRING, use &s - * - for %G_OPTION_ARG_INT, use i - * - for %G_OPTION_ARG_INT64, use x - * - for %G_OPTION_ARG_DOUBLE, use d - * - for %G_OPTION_ARG_FILENAME, use ^ay - * - for %G_OPTION_ARG_STRING_ARRAY, use &as - * - for %G_OPTION_ARG_FILENAME_ARRAY, use ^aay + * - for %G_OPTION_ARG_NONE, use `b` + * - for %G_OPTION_ARG_STRING, use `&s` + * - for %G_OPTION_ARG_INT, use `i` + * - for %G_OPTION_ARG_INT64, use `x` + * - for %G_OPTION_ARG_DOUBLE, use `d` + * - for %G_OPTION_ARG_FILENAME, use `^&ay` + * - for %G_OPTION_ARG_STRING_ARRAY, use `^a&s` + * - for %G_OPTION_ARG_FILENAME_ARRAY, use `^a&ay` * * Since: 2.40 */ @@ -1091,6 +1091,7 @@ g_application_real_local_command_line (GApplication *application, if (!options) { g_printerr ("%s\n", error->message); + g_error_free (error); *exit_status = 1; return TRUE; } @@ -1793,7 +1794,7 @@ g_application_new (const gchar *application_id, * * Gets the unique identifier for @application. * - * Returns: the identifier for @application, owned by @application + * Returns: (nullable): the identifier for @application, owned by @application * * Since: 2.28 **/ @@ -2084,7 +2085,7 @@ g_application_get_is_remote (GApplication *application) * This function must not be called before the application has been * registered. See g_application_get_is_registered(). * - * Returns: (transfer none): a #GDBusConnection, or %NULL + * Returns: (nullable) (transfer none): a #GDBusConnection, or %NULL * * Since: 2.34 **/ @@ -2116,7 +2117,7 @@ g_application_get_dbus_connection (GApplication *application) * This function must not be called before the application has been * registered. See g_application_get_is_registered(). * - * Returns: the object path, or %NULL + * Returns: (nullable): the object path, or %NULL * * Since: 2.34 **/ @@ -2743,7 +2744,7 @@ static GApplication *default_app; * * If there is no default application then %NULL is returned. * - * Returns: (transfer none): the default application for this process, or %NULL + * Returns: (nullable) (transfer none): the default application for this process, or %NULL * * Since: 2.32 **/ @@ -2870,7 +2871,7 @@ g_application_unmark_busy (GApplication *application) * Gets the application's current busy state, as set through * g_application_mark_busy() or g_application_bind_busy_property(). * - * Returns: %TRUE if @application is currenty marked as busy + * Returns: %TRUE if @application is currently marked as busy * * Since: 2.44 */ diff --git a/gio/gapplicationcommandline.c b/gio/gapplicationcommandline.c index d6c5c45fa670eaaf09a9b5434d066af50dfcd1b2..7d3f0e6652d9ce6de27d10de4826b9d7953457cf 100644 --- a/gio/gapplicationcommandline.c +++ b/gio/gapplicationcommandline.c @@ -523,13 +523,13 @@ g_application_command_line_get_options_dict (GApplicationCommandLine *cmdline) * The #GInputStream can be used to read data passed to the standard * input of the invoking process. * This doesn't work on all platforms. Presently, it is only available - * on UNIX when using a DBus daemon capable of passing file descriptors. + * on UNIX when using a D-Bus daemon capable of passing file descriptors. * If stdin is not available then %NULL will be returned. In the * future, support may be expanded to other platforms. * * You must only call this function once per commandline invocation. * - * Returns: (transfer full): a #GInputStream for stdin + * Returns: (nullable) (transfer full): a #GInputStream for stdin * * Since: 2.34 **/ @@ -610,7 +610,7 @@ g_application_command_line_get_environ (GApplicationCommandLine *cmdline) * The return value should not be modified or freed and is valid for as * long as @cmdline exists. * - * Returns: the value of the variable, or %NULL if unset or unsent + * Returns: (nullable): the value of the variable, or %NULL if unset or unsent * * Since: 2.28 **/ diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c index fd9d0468dc128fd53df1774d5fd239d5a20dc1dc..5604b9260fa90db00d1d27d1c95bfe1a289d94be 100644 --- a/gio/gapplicationimpl-dbus.c +++ b/gio/gapplicationimpl-dbus.c @@ -43,7 +43,7 @@ #include "gunixfdlist.h" #endif -/* DBus Interface definition {{{1 */ +/* D-Bus Interface definition {{{1 */ /* For documentation of these interfaces, see * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI @@ -361,16 +361,18 @@ g_application_impl_attempt_primary (GApplicationImpl *impl, GCancellable *cancellable, GError **error) { - const static GDBusInterfaceVTable vtable = { + static const GDBusInterfaceVTable vtable = { g_application_impl_method_call, g_application_impl_get_property, - NULL /* set_property */ + NULL, /* set_property */ + { 0 } }; GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app); GBusNameOwnerFlags name_owner_flags; GApplicationFlags app_flags; GVariant *reply; guint32 rval; + GError *local_error = NULL; if (org_gtk_Application == NULL) { @@ -430,8 +432,14 @@ g_application_impl_attempt_primary (GApplicationImpl *impl, if (!app_class->dbus_register (impl->app, impl->session_bus, impl->object_path, - error)) - return FALSE; + &local_error)) + { + g_return_val_if_fail (local_error != NULL, FALSE); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + g_return_val_if_fail (local_error == NULL, FALSE); if (impl->bus_name == NULL) { @@ -640,7 +648,7 @@ g_application_impl_register (GApplication *application, /* We are non-primary. Try to get the primary's list of actions. * This also serves as a mechanism to ensure that the primary exists - * (ie: DBus service files installed correctly, etc). + * (ie: D-Bus service files installed correctly, etc). */ actions = g_dbus_action_group_get (impl->session_bus, impl->bus_name, impl->object_path); if (!g_dbus_action_group_sync (actions, cancellable, error)) @@ -768,8 +776,8 @@ g_application_impl_command_line (GApplicationImpl *impl, const gchar * const *arguments, GVariant *platform_data) { - const static GDBusInterfaceVTable vtable = { - g_application_impl_cmdline_method_call + static const GDBusInterfaceVTable vtable = { + g_application_impl_cmdline_method_call, NULL, NULL, { 0 } }; const gchar *object_path = "/org/gtk/Application/CommandLine"; GMainContext *context; diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c index 41bbb2ad588f8ce3e6cc43f80d29df022cd7e21c..8b18835847fb2f3f48b860fccdd87c774ec64760 100644 --- a/gio/gasynchelper.c +++ b/gio/gasynchelper.c @@ -67,7 +67,7 @@ loop: * current thread and since we're doing only sync operations, * this is safe.... */ /* CancelIoEx is only Vista+. Since we have only one overlap - * operaton on this thread, we can just use: */ + * operation on this thread, we can just use: */ result = CancelIo (hfile); g_warn_if_fail (result); } diff --git a/gio/gasyncinitable.c b/gio/gasyncinitable.c index 8936f98b24bcb9d0c80cefd9f6a8d51c30f1a07a..6af65068840e4aaddc3b2f1110972107b54799b8 100644 --- a/gio/gasyncinitable.c +++ b/gio/gasyncinitable.c @@ -87,6 +87,7 @@ * GTask *task; * * task = g_task_new (initable, cancellable, callback, user_data); + * g_task_set_name (task, G_STRFUNC); * * switch (self->priv->state) * { diff --git a/gio/gbufferedinputstream.c b/gio/gbufferedinputstream.c index f5090d064c2706f18c73ccfc95b3c9700a3e5230..d9f150d33cf089d9ca91e7cb307d4e50452e3e8c 100644 --- a/gio/gbufferedinputstream.c +++ b/gio/gbufferedinputstream.c @@ -661,10 +661,10 @@ g_buffered_input_stream_real_fill (GBufferedInputStream *stream, in_buffer = priv->end - priv->pos; /* Never fill more than can fit in the buffer */ - count = MIN (count, priv->len - in_buffer); + count = MIN ((gsize) count, priv->len - in_buffer); /* If requested length does not fit at end, compact */ - if (priv->len - priv->end < count) + if (priv->len - priv->end < (gsize) count) compact_buffer (stream); base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; @@ -896,7 +896,8 @@ g_buffered_input_stream_seek (GSeekable *seekable, if (type == G_SEEK_CUR) { - if (offset <= priv->end - priv->pos && offset >= -priv->pos) + if (offset <= (goffset) (priv->end - priv->pos) && + offset >= (goffset) -priv->pos) { priv->pos += offset; return TRUE; @@ -1072,10 +1073,10 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, in_buffer = priv->end - priv->pos; /* Never fill more than can fit in the buffer */ - count = MIN (count, priv->len - in_buffer); + count = MIN ((gsize) count, priv->len - in_buffer); /* If requested length does not fit at end, compact */ - if (priv->len - priv->end < count) + if (priv->len - priv->end < (gsize) count) compact_buffer (stream); task = g_task_new (stream, cancellable, callback, user_data); @@ -1103,8 +1104,8 @@ g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, typedef struct { - gssize bytes_skipped; - gssize count; + gsize bytes_skipped; + gsize count; } SkipAsyncData; static void @@ -1185,6 +1186,7 @@ skip_fill_buffer_callback (GObject *source_object, priv->pos += data->count; } + g_assert (data->bytes_skipped <= G_MAXSSIZE); g_task_return_int (task, data->bytes_skipped); } @@ -1242,9 +1244,12 @@ g_buffered_input_stream_skip_async (GInputStream *stream, if (count > priv->len) { /* Large request, shortcut buffer */ - base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + /* If 'count > G_MAXSSIZE then 'g_input_stream_skip_async()' + * will return an error anyway before calling this. + * Assert that this is never called for too big `count` for clarity. */ + g_assert ((gssize) count >= 0); g_input_stream_skip_async (base_stream, count, io_priority, cancellable, diff --git a/gio/gbufferedoutputstream.c b/gio/gbufferedoutputstream.c index 98bda501d26419c7cb3af160a73598312057dac3..969bbae0bd6ed43071c89492c8262defecf053f3 100644 --- a/gio/gbufferedoutputstream.c +++ b/gio/gbufferedoutputstream.c @@ -208,7 +208,7 @@ g_buffered_output_stream_set_buffer_size (GBufferedOutputStream *stream, if (priv->buffer) { - size = MAX (size, priv->pos); + size = (priv->pos > 0) ? MAX (size, (gsize) priv->pos) : size; buffer = g_malloc (size); memcpy (buffer, priv->buffer, priv->pos); diff --git a/gio/gbytesicon.c b/gio/gbytesicon.c index ca78be1be76f7875aa50b5bd00d415173a131d91..4103b60bce8ae6c1fe569fae0cdda5193ba7f975 100644 --- a/gio/gbytesicon.c +++ b/gio/gbytesicon.c @@ -146,8 +146,11 @@ g_bytes_icon_init (GBytesIcon *bytes) * * Creates a new icon for a bytes. * + * This cannot fail, but loading and interpreting the bytes may fail later on + * (for example, if g_loadable_icon_load() is called) if the image is invalid. + * * Returns: (transfer full) (type GBytesIcon): a #GIcon for the given - * @bytes, or %NULL on error. + * @bytes. * * Since: 2.38 **/ @@ -165,7 +168,7 @@ g_bytes_icon_new (GBytes *bytes) * * Gets the #GBytes associated with the given @icon. * - * Returns: (transfer none): a #GBytes, or %NULL. + * Returns: (transfer none): a #GBytes. * * Since: 2.38 **/ diff --git a/gio/gcancellable.c b/gio/gcancellable.c index 0cfa91c0b4a0f1afcc8171ac43dfa32372ffb3eb..a084282ec97f6823bb5b8592bcba63b254fd8ec5 100644 --- a/gio/gcancellable.c +++ b/gio/gcancellable.c @@ -348,6 +348,9 @@ int g_cancellable_get_fd (GCancellable *cancellable) { GPollFD pollfd; +#ifndef G_OS_WIN32 + gboolean retval G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */; +#endif if (cancellable == NULL) return -1; @@ -355,7 +358,8 @@ g_cancellable_get_fd (GCancellable *cancellable) #ifdef G_OS_WIN32 pollfd.fd = -1; #else - g_cancellable_make_pollfd (cancellable, &pollfd); + retval = g_cancellable_make_pollfd (cancellable, &pollfd); + g_assert (retval); #endif return pollfd.fd; @@ -642,28 +646,47 @@ typedef struct { GSource source; GCancellable *cancellable; - guint cancelled_handler; + gulong cancelled_handler; + /* Protected by cancellable_mutex: */ + gboolean resurrected_during_cancellation; } GCancellableSource; /* - * We can't guarantee that the source still has references, so we are - * relying on the fact that g_source_set_ready_time() no longer makes - * assertions about the reference count - the source might be in the - * window between last-unref and finalize, during which its refcount - * is officially 0. However, we *can* guarantee that it's OK to - * dereference it in a limited way, because we know we haven't yet reached - * cancellable_source_finalize() - if we had, then we would have waited - * for signal emission to finish, then disconnected the signal handler - * under the lock. - * See https://bugzilla.gnome.org/show_bug.cgi?id=791754 + * The reference count of the GSource might be 0 at this point but it is not + * finalized yet and its dispose function did not run yet, or otherwise we + * would have disconnected the signal handler already and due to the signal + * emission lock it would be impossible to call the signal handler at that + * point. That is: at this point we either have a fully valid GSource, or + * it's not disposed or finalized yet and we can still resurrect it as needed. + * + * As such we first ensure that we have a strong reference to the GSource in + * here before calling any other GSource API. */ static void cancellable_source_cancelled (GCancellable *cancellable, gpointer user_data) { GSource *source = user_data; + GCancellableSource *cancellable_source = (GCancellableSource *) source; + + g_mutex_lock (&cancellable_mutex); + + /* Drop the reference added in cancellable_source_dispose(); see the comment there. + * The reference must be dropped after unlocking @cancellable_mutex since + * it could be the final reference, and the dispose function takes + * @cancellable_mutex. */ + if (cancellable_source->resurrected_during_cancellation) + { + cancellable_source->resurrected_during_cancellation = FALSE; + g_mutex_unlock (&cancellable_mutex); + g_source_unref (source); + return; + } + g_source_ref (source); + g_mutex_unlock (&cancellable_mutex); g_source_set_ready_time (source, 0); + g_source_unref (source); } static gboolean @@ -679,16 +702,41 @@ cancellable_source_dispatch (GSource *source, } static void -cancellable_source_finalize (GSource *source) +cancellable_source_dispose (GSource *source) { GCancellableSource *cancellable_source = (GCancellableSource *)source; + g_mutex_lock (&cancellable_mutex); + if (cancellable_source->cancellable) { - g_cancellable_disconnect (cancellable_source->cancellable, - cancellable_source->cancelled_handler); - g_object_unref (cancellable_source->cancellable); + if (cancellable_source->cancellable->priv->cancelled_running) + { + /* There can be a race here: if thread A has called + * g_cancellable_cancel() and has got as far as committing to call + * cancellable_source_cancelled(), then thread B drops the final + * ref on the GCancellableSource before g_source_ref() is called in + * cancellable_source_cancelled(), then cancellable_source_dispose() + * will run through and the GCancellableSource will be finalised + * before cancellable_source_cancelled() gets to g_source_ref(). It + * will then be left in a state where it’s committed to using a + * dangling GCancellableSource pointer. + * + * Eliminate that race by resurrecting the #GSource temporarily, and + * then dropping that reference in cancellable_source_cancelled(), + * which should be guaranteed to fire because we’re inside a + * @cancelled_running block. + */ + g_source_ref (source); + cancellable_source->resurrected_during_cancellation = TRUE; + } + + g_clear_signal_handler (&cancellable_source->cancelled_handler, + cancellable_source->cancellable); + g_clear_object (&cancellable_source->cancellable); } + + g_mutex_unlock (&cancellable_mutex); } static gboolean @@ -720,12 +768,13 @@ static GSourceFuncs cancellable_source_funcs = NULL, NULL, cancellable_source_dispatch, - cancellable_source_finalize, + NULL, (GSourceFunc)cancellable_source_closure_callback, + NULL, }; /** - * g_cancellable_source_new: (skip) + * g_cancellable_source_new: * @cancellable: (nullable): a #GCancellable, or %NULL * * Creates a source that triggers if @cancellable is cancelled and @@ -750,6 +799,7 @@ g_cancellable_source_new (GCancellable *cancellable) source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource)); g_source_set_name (source, "GCancellable"); + g_source_set_dispose_function (source, cancellable_source_dispose); cancellable_source = (GCancellableSource *)source; if (cancellable) diff --git a/gio/gconstructor_as_data.h b/gio/gconstructor_as_data.h index 8289d023a7c5fee699426c2ff93f5213ddc98382..35dc3951c99b70efe70cb0c95a7651d69f32f8a1 100644 --- a/gio/gconstructor_as_data.h +++ b/gio/gconstructor_as_data.h @@ -1 +1 @@ -const char gconstructor_code[] = "\x2f\x2a\x0a\x20\x20\x49\x66\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x69\x73\x20\x74\x72\x75\x65\x20\x74\x68\x65\x6e\x20\x74\x68\x65\x20\x63\x6f\x6d\x70\x69\x6c\x65\x72\x20\x73\x75\x70\x70\x6f\x72\x74\x20\x2a\x62\x6f\x74\x68\x2a\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x20\x61\x6e\x64\x0a\x20\x20\x64\x65\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x2c\x20\x69\x6e\x20\x61\x20\x73\x61\x6e\x65\x20\x77\x61\x79\x2c\x20\x69\x6e\x63\x6c\x75\x64\x69\x6e\x67\x20\x65\x2e\x67\x2e\x20\x6f\x6e\x20\x6c\x69\x62\x72\x61\x72\x79\x20\x75\x6e\x6c\x6f\x61\x64\x2e\x20\x49\x66\x20\x6e\x6f\x74\x20\x79\x6f\x75\x27\x72\x65\x20\x6f\x6e\x0a\x20\x20\x79\x6f\x75\x72\x20\x6f\x77\x6e\x2e\x0a\x0a\x20\x20\x53\x6f\x6d\x65\x20\x63\x6f\x6d\x70\x69\x6c\x65\x72\x73\x20\x6e\x65\x65\x64\x20\x23\x70\x72\x61\x67\x6d\x61\x20\x74\x6f\x20\x68\x61\x6e\x64\x6c\x65\x20\x74\x68\x69\x73\x2c\x20\x77\x68\x69\x63\x68\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x77\x6f\x72\x6b\x20\x77\x69\x74\x68\x20\x6d\x61\x63\x72\x6f\x73\x2c\x0a\x20\x20\x73\x6f\x20\x74\x68\x65\x20\x77\x61\x79\x20\x79\x6f\x75\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x75\x73\x65\x20\x74\x68\x69\x73\x20\x69\x73\x20\x28\x66\x6f\x72\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x29\x3a\x0a\x0a\x20\x20\x23\x69\x66\x64\x65\x66\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x0a\x20\x20\x23\x70\x72\x61\x67\x6d\x61\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x6d\x79\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x0a\x20\x20\x23\x65\x6e\x64\x69\x66\x0a\x20\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x6d\x79\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x6d\x79\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x0a\x20\x20\x20\x2e\x2e\x2e\x0a\x20\x20\x7d\x0a\x0a\x2a\x2f\x0a\x0a\x23\x69\x66\x6e\x64\x65\x66\x20\x5f\x5f\x47\x54\x4b\x5f\x44\x4f\x43\x5f\x49\x47\x4e\x4f\x52\x45\x5f\x5f\x0a\x0a\x23\x69\x66\x20\x20\x5f\x5f\x47\x4e\x55\x43\x5f\x5f\x20\x3e\x20\x32\x20\x7c\x7c\x20\x28\x5f\x5f\x47\x4e\x55\x43\x5f\x5f\x20\x3d\x3d\x20\x32\x20\x26\x26\x20\x5f\x5f\x47\x4e\x55\x43\x5f\x4d\x49\x4e\x4f\x52\x5f\x5f\x20\x3e\x3d\x20\x37\x29\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x29\x20\x5f\x66\x75\x6e\x63\x20\x28\x76\x6f\x69\x64\x29\x3b\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x64\x65\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x29\x20\x5f\x66\x75\x6e\x63\x20\x28\x76\x6f\x69\x64\x29\x3b\x0a\x0a\x23\x65\x6c\x69\x66\x20\x64\x65\x66\x69\x6e\x65\x64\x20\x28\x5f\x4d\x53\x43\x5f\x56\x45\x52\x29\x20\x26\x26\x20\x28\x5f\x4d\x53\x43\x5f\x56\x45\x52\x20\x3e\x3d\x20\x31\x35\x30\x30\x29\x0a\x2f\x2a\x20\x56\x69\x73\x75\x61\x6c\x20\x73\x74\x75\x64\x69\x6f\x20\x32\x30\x30\x38\x20\x61\x6e\x64\x20\x6c\x61\x74\x65\x72\x20\x68\x61\x73\x20\x5f\x50\x72\x61\x67\x6d\x61\x20\x2a\x2f\x0a\x0a\x23\x69\x6e\x63\x6c\x75\x64\x65\x20\x3c\x73\x74\x64\x6c\x69\x62\x2e\x68\x3e\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x2f\x2a\x20\x57\x65\x20\x64\x6f\x20\x73\x6f\x6d\x65\x20\x77\x65\x69\x72\x64\x20\x74\x68\x69\x6e\x67\x73\x20\x74\x6f\x20\x61\x76\x6f\x69\x64\x20\x74\x68\x65\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x20\x62\x65\x69\x6e\x67\x20\x6f\x70\x74\x69\x6d\x69\x7a\x65\x64\x0a\x20\x2a\x20\x61\x77\x61\x79\x20\x6f\x6e\x20\x56\x53\x32\x30\x31\x35\x20\x69\x66\x20\x57\x68\x6f\x6c\x65\x50\x72\x6f\x67\x72\x61\x6d\x4f\x70\x74\x69\x6d\x69\x7a\x61\x74\x69\x6f\x6e\x20\x69\x73\x20\x65\x6e\x61\x62\x6c\x65\x64\x2e\x20\x46\x69\x72\x73\x74\x20\x77\x65\x0a\x20\x2a\x20\x6d\x61\x6b\x65\x20\x61\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x74\x6f\x20\x74\x68\x65\x20\x61\x72\x72\x61\x79\x20\x66\x72\x6f\x6d\x20\x74\x68\x65\x20\x77\x72\x61\x70\x70\x65\x72\x20\x74\x6f\x20\x6d\x61\x6b\x65\x20\x73\x75\x72\x65\x20\x69\x74\x73\x0a\x20\x2a\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x73\x2e\x20\x54\x68\x65\x6e\x20\x77\x65\x20\x75\x73\x65\x20\x61\x20\x70\x72\x61\x67\x6d\x61\x20\x74\x6f\x20\x6d\x61\x6b\x65\x20\x73\x75\x72\x65\x20\x74\x68\x65\x20\x77\x72\x61\x70\x70\x65\x72\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x0a\x20\x2a\x20\x73\x79\x6d\x62\x6f\x6c\x20\x69\x73\x20\x61\x6c\x77\x61\x79\x73\x20\x69\x6e\x63\x6c\x75\x64\x65\x64\x20\x61\x74\x20\x74\x68\x65\x20\x6c\x69\x6e\x6b\x20\x73\x74\x61\x67\x65\x2e\x20\x41\x6c\x73\x6f\x2c\x20\x74\x68\x65\x20\x73\x79\x6d\x62\x6f\x6c\x73\x0a\x20\x2a\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x62\x65\x20\x65\x78\x74\x65\x72\x6e\x20\x28\x62\x75\x74\x20\x6e\x6f\x74\x20\x64\x6c\x6c\x65\x78\x70\x6f\x72\x74\x29\x2c\x20\x65\x76\x65\x6e\x20\x74\x68\x6f\x75\x67\x68\x20\x74\x68\x65\x79\x20\x61\x72\x65\x20\x6e\x6f\x74\x0a\x20\x2a\x20\x72\x65\x61\x6c\x6c\x79\x20\x75\x73\x65\x64\x20\x66\x72\x6f\x6d\x20\x61\x6e\x6f\x74\x68\x65\x72\x20\x6f\x62\x6a\x65\x63\x74\x20\x66\x69\x6c\x65\x2e\x0a\x20\x2a\x2f\x0a\x0a\x2f\x2a\x20\x57\x65\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x61\x63\x63\x6f\x75\x6e\x74\x20\x66\x6f\x72\x20\x64\x69\x66\x66\x65\x72\x65\x6e\x63\x65\x73\x20\x62\x65\x74\x77\x65\x65\x6e\x20\x74\x68\x65\x20\x6d\x61\x6e\x67\x6c\x69\x6e\x67\x20\x6f\x66\x20\x73\x79\x6d\x62\x6f\x6c\x73\x0a\x20\x2a\x20\x66\x6f\x72\x20\x57\x69\x6e\x33\x32\x20\x28\x78\x38\x36\x29\x20\x61\x6e\x64\x20\x78\x36\x34\x20\x70\x72\x6f\x67\x72\x61\x6d\x73\x2c\x20\x61\x73\x20\x73\x79\x6d\x62\x6f\x6c\x73\x20\x6f\x6e\x20\x57\x69\x6e\x33\x32\x20\x61\x72\x65\x20\x70\x72\x65\x66\x69\x78\x65\x64\x0a\x20\x2a\x20\x77\x69\x74\x68\x20\x61\x6e\x20\x75\x6e\x64\x65\x72\x73\x63\x6f\x72\x65\x20\x62\x75\x74\x20\x73\x79\x6d\x62\x6f\x6c\x73\x20\x6f\x6e\x20\x78\x36\x34\x20\x61\x72\x65\x20\x6e\x6f\x74\x2e\x0a\x20\x2a\x2f\x0a\x23\x69\x66\x64\x65\x66\x20\x5f\x57\x49\x4e\x36\x34\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x20\x22\x22\x0a\x23\x65\x6c\x73\x65\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x20\x22\x5f\x22\x0a\x23\x65\x6e\x64\x69\x66\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x47\x5f\x4d\x53\x56\x43\x5f\x43\x54\x4f\x52\x20\x28\x5f\x66\x75\x6e\x63\x2c\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x47\x5f\x4d\x53\x56\x43\x5f\x44\x54\x4f\x52\x20\x28\x5f\x66\x75\x6e\x63\x2c\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x29\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x2c\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x65\x78\x74\x65\x72\x6e\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5c\x0a\x20\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x5f\x66\x75\x6e\x63\x28\x29\x3b\x20\x67\x5f\x73\x6c\x69\x73\x74\x5f\x66\x69\x6e\x64\x20\x28\x4e\x55\x4c\x4c\x2c\x20\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x63\x6f\x6d\x6d\x65\x6e\x74\x28\x6c\x69\x6e\x6b\x65\x72\x2c\x22\x2f\x69\x6e\x63\x6c\x75\x64\x65\x3a\x22\x20\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x20\x23\x20\x5f\x66\x75\x6e\x63\x20\x22\x5f\x77\x72\x61\x70\x70\x65\x72\x22\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x3b\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x44\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x2c\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x65\x78\x74\x65\x72\x6e\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5c\x0a\x20\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x61\x74\x65\x78\x69\x74\x20\x28\x5f\x66\x75\x6e\x63\x29\x3b\x20\x67\x5f\x73\x6c\x69\x73\x74\x5f\x66\x69\x6e\x64\x20\x28\x4e\x55\x4c\x4c\x2c\x20\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x63\x6f\x6d\x6d\x65\x6e\x74\x28\x6c\x69\x6e\x6b\x65\x72\x2c\x22\x2f\x69\x6e\x63\x6c\x75\x64\x65\x3a\x22\x20\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x20\x23\x20\x5f\x66\x75\x6e\x63\x20\x22\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x22\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x3b\x0a\x0a\x23\x65\x6c\x69\x66\x20\x64\x65\x66\x69\x6e\x65\x64\x20\x28\x5f\x4d\x53\x43\x5f\x56\x45\x52\x29\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x2f\x2a\x20\x50\x72\x65\x20\x56\x69\x73\x75\x61\x6c\x20\x73\x74\x75\x64\x69\x6f\x20\x32\x30\x30\x38\x20\x6d\x75\x73\x74\x20\x75\x73\x65\x20\x23\x70\x72\x61\x67\x6d\x61\x20\x73\x65\x63\x74\x69\x6f\x6e\x20\x2a\x2f\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x5f\x66\x75\x6e\x63\x28\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x28\x2a\x70\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x3b\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x61\x74\x65\x78\x69\x74\x20\x28\x5f\x66\x75\x6e\x63\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x3b\x0a\x0a\x23\x65\x6c\x69\x66\x20\x64\x65\x66\x69\x6e\x65\x64\x28\x5f\x5f\x53\x55\x4e\x50\x52\x4f\x5f\x43\x29\x0a\x0a\x2f\x2a\x20\x54\x68\x69\x73\x20\x69\x73\x20\x6e\x6f\x74\x20\x74\x65\x73\x74\x65\x64\x2c\x20\x62\x75\x74\x20\x69\x20\x62\x65\x6c\x69\x65\x76\x65\x20\x69\x74\x20\x73\x68\x6f\x75\x6c\x64\x20\x77\x6f\x72\x6b\x2c\x20\x62\x61\x73\x65\x64\x20\x6f\x6e\x3a\x0a\x20\x2a\x20\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x70\x65\x6e\x73\x6f\x75\x72\x63\x65\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x73\x6f\x75\x72\x63\x65\x2f\x4f\x70\x65\x6e\x53\x53\x4c\x30\x39\x38\x2f\x4f\x70\x65\x6e\x53\x53\x4c\x30\x39\x38\x2d\x33\x35\x2f\x73\x72\x63\x2f\x66\x69\x70\x73\x2f\x66\x69\x70\x73\x5f\x70\x72\x65\x6d\x61\x69\x6e\x2e\x63\x0a\x20\x2a\x2f\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x69\x6e\x69\x74\x28\x5f\x66\x75\x6e\x63\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x66\x69\x6e\x69\x28\x5f\x66\x75\x6e\x63\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x0a\x0a\x23\x65\x6c\x73\x65\x0a\x0a\x2f\x2a\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x20\x6e\x6f\x74\x20\x73\x75\x70\x70\x6f\x72\x74\x65\x64\x20\x66\x6f\x72\x20\x74\x68\x69\x73\x20\x63\x6f\x6d\x70\x69\x6c\x65\x72\x20\x2a\x2f\x0a\x0a\x23\x65\x6e\x64\x69\x66\x0a\x0a\x23\x65\x6e\x64\x69\x66\x20\x2f\x2a\x20\x5f\x5f\x47\x54\x4b\x5f\x44\x4f\x43\x5f\x49\x47\x4e\x4f\x52\x45\x5f\x5f\x20\x2a\x2f\x0a"; \ No newline at end of file +const char gconstructor_code[] = "\x2f\x2a\x0a\x20\x20\x49\x66\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x69\x73\x20\x74\x72\x75\x65\x20\x74\x68\x65\x6e\x20\x74\x68\x65\x20\x63\x6f\x6d\x70\x69\x6c\x65\x72\x20\x73\x75\x70\x70\x6f\x72\x74\x20\x2a\x62\x6f\x74\x68\x2a\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x20\x61\x6e\x64\x0a\x20\x20\x64\x65\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x2c\x20\x69\x6e\x20\x61\x20\x75\x73\x61\x62\x6c\x65\x20\x77\x61\x79\x2c\x20\x69\x6e\x63\x6c\x75\x64\x69\x6e\x67\x20\x65\x2e\x67\x2e\x20\x6f\x6e\x20\x6c\x69\x62\x72\x61\x72\x79\x20\x75\x6e\x6c\x6f\x61\x64\x2e\x20\x49\x66\x20\x6e\x6f\x74\x20\x79\x6f\x75\x27\x72\x65\x20\x6f\x6e\x0a\x20\x20\x79\x6f\x75\x72\x20\x6f\x77\x6e\x2e\x0a\x0a\x20\x20\x53\x6f\x6d\x65\x20\x63\x6f\x6d\x70\x69\x6c\x65\x72\x73\x20\x6e\x65\x65\x64\x20\x23\x70\x72\x61\x67\x6d\x61\x20\x74\x6f\x20\x68\x61\x6e\x64\x6c\x65\x20\x74\x68\x69\x73\x2c\x20\x77\x68\x69\x63\x68\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x77\x6f\x72\x6b\x20\x77\x69\x74\x68\x20\x6d\x61\x63\x72\x6f\x73\x2c\x0a\x20\x20\x73\x6f\x20\x74\x68\x65\x20\x77\x61\x79\x20\x79\x6f\x75\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x75\x73\x65\x20\x74\x68\x69\x73\x20\x69\x73\x20\x28\x66\x6f\x72\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x29\x3a\x0a\x0a\x20\x20\x23\x69\x66\x64\x65\x66\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x0a\x20\x20\x23\x70\x72\x61\x67\x6d\x61\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x6d\x79\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x0a\x20\x20\x23\x65\x6e\x64\x69\x66\x0a\x20\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x6d\x79\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x6d\x79\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x0a\x20\x20\x20\x2e\x2e\x2e\x0a\x20\x20\x7d\x0a\x0a\x2a\x2f\x0a\x0a\x23\x69\x66\x6e\x64\x65\x66\x20\x5f\x5f\x47\x54\x4b\x5f\x44\x4f\x43\x5f\x49\x47\x4e\x4f\x52\x45\x5f\x5f\x0a\x0a\x23\x69\x66\x20\x20\x5f\x5f\x47\x4e\x55\x43\x5f\x5f\x20\x3e\x20\x32\x20\x7c\x7c\x20\x28\x5f\x5f\x47\x4e\x55\x43\x5f\x5f\x20\x3d\x3d\x20\x32\x20\x26\x26\x20\x5f\x5f\x47\x4e\x55\x43\x5f\x4d\x49\x4e\x4f\x52\x5f\x5f\x20\x3e\x3d\x20\x37\x29\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x29\x20\x5f\x66\x75\x6e\x63\x20\x28\x76\x6f\x69\x64\x29\x3b\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x64\x65\x73\x74\x72\x75\x63\x74\x6f\x72\x29\x29\x20\x5f\x66\x75\x6e\x63\x20\x28\x76\x6f\x69\x64\x29\x3b\x0a\x0a\x23\x65\x6c\x69\x66\x20\x64\x65\x66\x69\x6e\x65\x64\x20\x28\x5f\x4d\x53\x43\x5f\x56\x45\x52\x29\x20\x26\x26\x20\x28\x5f\x4d\x53\x43\x5f\x56\x45\x52\x20\x3e\x3d\x20\x31\x35\x30\x30\x29\x0a\x2f\x2a\x20\x56\x69\x73\x75\x61\x6c\x20\x73\x74\x75\x64\x69\x6f\x20\x32\x30\x30\x38\x20\x61\x6e\x64\x20\x6c\x61\x74\x65\x72\x20\x68\x61\x73\x20\x5f\x50\x72\x61\x67\x6d\x61\x20\x2a\x2f\x0a\x0a\x23\x69\x6e\x63\x6c\x75\x64\x65\x20\x3c\x73\x74\x64\x6c\x69\x62\x2e\x68\x3e\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x2f\x2a\x20\x57\x65\x20\x64\x6f\x20\x73\x6f\x6d\x65\x20\x77\x65\x69\x72\x64\x20\x74\x68\x69\x6e\x67\x73\x20\x74\x6f\x20\x61\x76\x6f\x69\x64\x20\x74\x68\x65\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x20\x62\x65\x69\x6e\x67\x20\x6f\x70\x74\x69\x6d\x69\x7a\x65\x64\x0a\x20\x2a\x20\x61\x77\x61\x79\x20\x6f\x6e\x20\x56\x53\x32\x30\x31\x35\x20\x69\x66\x20\x57\x68\x6f\x6c\x65\x50\x72\x6f\x67\x72\x61\x6d\x4f\x70\x74\x69\x6d\x69\x7a\x61\x74\x69\x6f\x6e\x20\x69\x73\x20\x65\x6e\x61\x62\x6c\x65\x64\x2e\x20\x46\x69\x72\x73\x74\x20\x77\x65\x0a\x20\x2a\x20\x6d\x61\x6b\x65\x20\x61\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x74\x6f\x20\x74\x68\x65\x20\x61\x72\x72\x61\x79\x20\x66\x72\x6f\x6d\x20\x74\x68\x65\x20\x77\x72\x61\x70\x70\x65\x72\x20\x74\x6f\x20\x6d\x61\x6b\x65\x20\x73\x75\x72\x65\x20\x69\x74\x73\x0a\x20\x2a\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x73\x2e\x20\x54\x68\x65\x6e\x20\x77\x65\x20\x75\x73\x65\x20\x61\x20\x70\x72\x61\x67\x6d\x61\x20\x74\x6f\x20\x6d\x61\x6b\x65\x20\x73\x75\x72\x65\x20\x74\x68\x65\x20\x77\x72\x61\x70\x70\x65\x72\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x0a\x20\x2a\x20\x73\x79\x6d\x62\x6f\x6c\x20\x69\x73\x20\x61\x6c\x77\x61\x79\x73\x20\x69\x6e\x63\x6c\x75\x64\x65\x64\x20\x61\x74\x20\x74\x68\x65\x20\x6c\x69\x6e\x6b\x20\x73\x74\x61\x67\x65\x2e\x20\x41\x6c\x73\x6f\x2c\x20\x74\x68\x65\x20\x73\x79\x6d\x62\x6f\x6c\x73\x0a\x20\x2a\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x62\x65\x20\x65\x78\x74\x65\x72\x6e\x20\x28\x62\x75\x74\x20\x6e\x6f\x74\x20\x64\x6c\x6c\x65\x78\x70\x6f\x72\x74\x29\x2c\x20\x65\x76\x65\x6e\x20\x74\x68\x6f\x75\x67\x68\x20\x74\x68\x65\x79\x20\x61\x72\x65\x20\x6e\x6f\x74\x0a\x20\x2a\x20\x72\x65\x61\x6c\x6c\x79\x20\x75\x73\x65\x64\x20\x66\x72\x6f\x6d\x20\x61\x6e\x6f\x74\x68\x65\x72\x20\x6f\x62\x6a\x65\x63\x74\x20\x66\x69\x6c\x65\x2e\x0a\x20\x2a\x2f\x0a\x0a\x2f\x2a\x20\x57\x65\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x61\x63\x63\x6f\x75\x6e\x74\x20\x66\x6f\x72\x20\x64\x69\x66\x66\x65\x72\x65\x6e\x63\x65\x73\x20\x62\x65\x74\x77\x65\x65\x6e\x20\x74\x68\x65\x20\x6d\x61\x6e\x67\x6c\x69\x6e\x67\x20\x6f\x66\x20\x73\x79\x6d\x62\x6f\x6c\x73\x0a\x20\x2a\x20\x66\x6f\x72\x20\x78\x38\x36\x20\x61\x6e\x64\x20\x78\x36\x34\x2f\x41\x52\x4d\x2f\x41\x52\x4d\x36\x34\x20\x70\x72\x6f\x67\x72\x61\x6d\x73\x2c\x20\x61\x73\x20\x73\x79\x6d\x62\x6f\x6c\x73\x20\x6f\x6e\x20\x78\x38\x36\x20\x61\x72\x65\x20\x70\x72\x65\x66\x69\x78\x65\x64\x0a\x20\x2a\x20\x77\x69\x74\x68\x20\x61\x6e\x20\x75\x6e\x64\x65\x72\x73\x63\x6f\x72\x65\x20\x62\x75\x74\x20\x73\x79\x6d\x62\x6f\x6c\x73\x20\x6f\x6e\x20\x78\x36\x34\x2f\x41\x52\x4d\x2f\x41\x52\x4d\x36\x34\x20\x61\x72\x65\x20\x6e\x6f\x74\x2e\x0a\x20\x2a\x2f\x0a\x23\x69\x66\x64\x65\x66\x20\x5f\x4d\x5f\x49\x58\x38\x36\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x20\x22\x5f\x22\x0a\x23\x65\x6c\x73\x65\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x20\x22\x22\x0a\x23\x65\x6e\x64\x69\x66\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x47\x5f\x4d\x53\x56\x43\x5f\x43\x54\x4f\x52\x20\x28\x5f\x66\x75\x6e\x63\x2c\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x47\x5f\x4d\x53\x56\x43\x5f\x44\x54\x4f\x52\x20\x28\x5f\x66\x75\x6e\x63\x2c\x20\x47\x5f\x4d\x53\x56\x43\x5f\x53\x59\x4d\x42\x4f\x4c\x5f\x50\x52\x45\x46\x49\x58\x29\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x2c\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x65\x78\x74\x65\x72\x6e\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5c\x0a\x20\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x5f\x66\x75\x6e\x63\x28\x29\x3b\x20\x67\x5f\x73\x6c\x69\x73\x74\x5f\x66\x69\x6e\x64\x20\x28\x4e\x55\x4c\x4c\x2c\x20\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x63\x6f\x6d\x6d\x65\x6e\x74\x28\x6c\x69\x6e\x6b\x65\x72\x2c\x22\x2f\x69\x6e\x63\x6c\x75\x64\x65\x3a\x22\x20\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x20\x23\x20\x5f\x66\x75\x6e\x63\x20\x22\x5f\x77\x72\x61\x70\x70\x65\x72\x22\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x3b\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x4d\x53\x56\x43\x5f\x44\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x2c\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x65\x78\x74\x65\x72\x6e\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5c\x0a\x20\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x61\x74\x65\x78\x69\x74\x20\x28\x5f\x66\x75\x6e\x63\x29\x3b\x20\x67\x5f\x73\x6c\x69\x73\x74\x5f\x66\x69\x6e\x64\x20\x28\x4e\x55\x4c\x4c\x2c\x20\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x63\x6f\x6d\x6d\x65\x6e\x74\x28\x6c\x69\x6e\x6b\x65\x72\x2c\x22\x2f\x69\x6e\x63\x6c\x75\x64\x65\x3a\x22\x20\x5f\x73\x79\x6d\x5f\x70\x72\x65\x66\x69\x78\x20\x23\x20\x5f\x66\x75\x6e\x63\x20\x22\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x22\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x70\x72\x61\x67\x6d\x61\x28\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x29\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x3b\x0a\x0a\x23\x65\x6c\x69\x66\x20\x64\x65\x66\x69\x6e\x65\x64\x20\x28\x5f\x4d\x53\x43\x5f\x56\x45\x52\x29\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x2f\x2a\x20\x50\x72\x65\x20\x56\x69\x73\x75\x61\x6c\x20\x73\x74\x75\x64\x69\x6f\x20\x32\x30\x30\x38\x20\x6d\x75\x73\x74\x20\x75\x73\x65\x20\x23\x70\x72\x61\x67\x6d\x61\x20\x73\x65\x63\x74\x69\x6f\x6e\x20\x2a\x2f\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x5f\x66\x75\x6e\x63\x28\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x28\x2a\x70\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x77\x72\x61\x70\x70\x65\x72\x3b\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x65\x63\x74\x69\x6f\x6e\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x2c\x72\x65\x61\x64\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x28\x76\x6f\x69\x64\x29\x20\x7b\x20\x61\x74\x65\x78\x69\x74\x20\x28\x5f\x66\x75\x6e\x63\x29\x3b\x20\x72\x65\x74\x75\x72\x6e\x20\x30\x3b\x20\x7d\x20\x5c\x0a\x20\x20\x5f\x5f\x64\x65\x63\x6c\x73\x70\x65\x63\x28\x61\x6c\x6c\x6f\x63\x61\x74\x65\x28\x22\x2e\x43\x52\x54\x24\x58\x43\x55\x22\x29\x29\x20\x73\x74\x61\x74\x69\x63\x20\x69\x6e\x74\x20\x28\x2a\x20\x5f\x61\x72\x72\x61\x79\x20\x23\x23\x20\x5f\x66\x75\x6e\x63\x29\x28\x76\x6f\x69\x64\x29\x20\x3d\x20\x5f\x66\x75\x6e\x63\x20\x23\x23\x20\x5f\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x3b\x0a\x0a\x23\x65\x6c\x69\x66\x20\x64\x65\x66\x69\x6e\x65\x64\x28\x5f\x5f\x53\x55\x4e\x50\x52\x4f\x5f\x43\x29\x0a\x0a\x2f\x2a\x20\x54\x68\x69\x73\x20\x69\x73\x20\x6e\x6f\x74\x20\x74\x65\x73\x74\x65\x64\x2c\x20\x62\x75\x74\x20\x69\x20\x62\x65\x6c\x69\x65\x76\x65\x20\x69\x74\x20\x73\x68\x6f\x75\x6c\x64\x20\x77\x6f\x72\x6b\x2c\x20\x62\x61\x73\x65\x64\x20\x6f\x6e\x3a\x0a\x20\x2a\x20\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x70\x65\x6e\x73\x6f\x75\x72\x63\x65\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x73\x6f\x75\x72\x63\x65\x2f\x4f\x70\x65\x6e\x53\x53\x4c\x30\x39\x38\x2f\x4f\x70\x65\x6e\x53\x53\x4c\x30\x39\x38\x2d\x33\x35\x2f\x73\x72\x63\x2f\x66\x69\x70\x73\x2f\x66\x69\x70\x73\x5f\x70\x72\x65\x6d\x61\x69\x6e\x2e\x63\x0a\x20\x2a\x2f\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x48\x41\x53\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x53\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x4e\x45\x45\x44\x53\x5f\x50\x52\x41\x47\x4d\x41\x20\x31\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x69\x6e\x69\x74\x28\x5f\x66\x75\x6e\x63\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x43\x4f\x4e\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x0a\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x5f\x50\x52\x41\x47\x4d\x41\x5f\x41\x52\x47\x53\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x66\x69\x6e\x69\x28\x5f\x66\x75\x6e\x63\x29\x0a\x23\x64\x65\x66\x69\x6e\x65\x20\x47\x5f\x44\x45\x46\x49\x4e\x45\x5f\x44\x45\x53\x54\x52\x55\x43\x54\x4f\x52\x28\x5f\x66\x75\x6e\x63\x29\x20\x5c\x0a\x20\x20\x73\x74\x61\x74\x69\x63\x20\x76\x6f\x69\x64\x20\x5f\x66\x75\x6e\x63\x28\x76\x6f\x69\x64\x29\x3b\x0a\x0a\x23\x65\x6c\x73\x65\x0a\x0a\x2f\x2a\x20\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x73\x20\x6e\x6f\x74\x20\x73\x75\x70\x70\x6f\x72\x74\x65\x64\x20\x66\x6f\x72\x20\x74\x68\x69\x73\x20\x63\x6f\x6d\x70\x69\x6c\x65\x72\x20\x2a\x2f\x0a\x0a\x23\x65\x6e\x64\x69\x66\x0a\x0a\x23\x65\x6e\x64\x69\x66\x20\x2f\x2a\x20\x5f\x5f\x47\x54\x4b\x5f\x44\x4f\x43\x5f\x49\x47\x4e\x4f\x52\x45\x5f\x5f\x20\x2a\x2f\x0a"; \ No newline at end of file diff --git a/gio/gcontenttype.c b/gio/gcontenttype.c index 04d278db3232021dfde2f7ac0da62c9c9659192d..83075fcb66cc9c1bdf0329216887b547890fd9e3 100644 --- a/gio/gcontenttype.c +++ b/gio/gcontenttype.c @@ -405,7 +405,9 @@ load_comment_for_mime_helper (const char *dir, GMarkupParser parser = { mime_info_start_element, mime_info_end_element, - mime_info_text + mime_info_text, + NULL, + NULL }; filename = g_build_filename (dir, basename, NULL); @@ -614,6 +616,8 @@ g_content_type_get_generic_icon_name (const gchar *type) const gchar *xdg_icon_name; gchar *icon_name; + g_return_val_if_fail (type != NULL, NULL); + G_LOCK (gio_xdgmime); xdg_icon_name = xdg_mime_get_generic_icon (type); G_UNLOCK (gio_xdgmime); diff --git a/gio/gcontextspecificgroup.c b/gio/gcontextspecificgroup.c index ffd1307e437824e7049ef0002dd9fc3f4d4d4511..acad72767d21f67c3177439166cc0c53db729182 100644 --- a/gio/gcontextspecificgroup.c +++ b/gio/gcontextspecificgroup.c @@ -73,7 +73,8 @@ g_context_specific_source_new (const gchar *name, NULL, NULL, g_context_specific_source_dispatch, - g_context_specific_source_finalize + g_context_specific_source_finalize, + NULL, NULL }; GContextSpecificSource *css; GSource *source; diff --git a/gio/gconverteroutputstream.c b/gio/gconverteroutputstream.c index bb3d94a03bd297b47e729b0ef4eafb058d7fe87a..c1fa29ee8d2a9cda8b63eb95ec7921d0e5b4165f 100644 --- a/gio/gconverteroutputstream.c +++ b/gio/gconverteroutputstream.c @@ -595,7 +595,7 @@ g_converter_output_stream_flush (GOutputStream *stream, if (!is_closing && res == G_CONVERTER_FLUSHED) { - /* Should not have retured FLUSHED with input left */ + /* Should not have returned FLUSHED with input left */ g_assert (buffer_data_size (&priv->output_buffer) == 0); flushed = TRUE; } diff --git a/gio/gcredentials.c b/gio/gcredentials.c index ff9b7e0b884d3607503e0eb4b8cb204aed97ca05..ebbc2cc5bce23e693af49978f9541079d042445d 100644 --- a/gio/gcredentials.c +++ b/gio/gcredentials.c @@ -51,22 +51,26 @@ * #GUnixCredentialsMessage, g_unix_connection_send_credentials() and * g_unix_connection_receive_credentials() for details. * - * On Linux, the native credential type is a struct ucred - see the + * On Linux, the native credential type is a `struct ucred` - see the * unix(7) man page for details. This corresponds to * %G_CREDENTIALS_TYPE_LINUX_UCRED. * + * On Apple operating systems (including iOS, tvOS, and macOS), + * the native credential type is a `struct xucred`. + * This corresponds to %G_CREDENTIALS_TYPE_APPLE_XUCRED. + * * On FreeBSD, Debian GNU/kFreeBSD, and GNU/Hurd, the native - * credential type is a struct cmsgcred. This corresponds + * credential type is a `struct cmsgcred`. This corresponds * to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED. * - * On NetBSD, the native credential type is a struct unpcbid. + * On NetBSD, the native credential type is a `struct unpcbid`. * This corresponds to %G_CREDENTIALS_TYPE_NETBSD_UNPCBID. * - * On OpenBSD, the native credential type is a struct sockpeercred. + * On OpenBSD, the native credential type is a `struct sockpeercred`. * This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED. * * On Solaris (including OpenSolaris and its derivatives), the native - * credential type is a ucred_t. This corresponds to + * credential type is a `ucred_t`. This corresponds to * %G_CREDENTIALS_TYPE_SOLARIS_UCRED. */ @@ -85,6 +89,8 @@ struct _GCredentials #if G_CREDENTIALS_USE_LINUX_UCRED struct ucred native; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + struct xucred native; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED struct cmsgcred native; #elif G_CREDENTIALS_USE_NETBSD_UNPCBID @@ -148,6 +154,22 @@ g_credentials_init (GCredentials *credentials) credentials->native.pid = getpid (); credentials->native.uid = geteuid (); credentials->native.gid = getegid (); +#elif G_CREDENTIALS_USE_APPLE_XUCRED + gsize i; + + credentials->native.cr_version = XUCRED_VERSION; + credentials->native.cr_uid = geteuid (); + credentials->native.cr_ngroups = 1; + credentials->native.cr_groups[0] = getegid (); + + /* FIXME: In principle this could use getgroups() to fill in the rest + * of cr_groups, but then we'd have to handle the case where a process + * can have more than NGROUPS groups, if that's even possible. A macOS + * user would have to develop and test this. + * + * For now we fill it with -1 (meaning "no data"). */ + for (i = 1; i < NGROUPS; i++) + credentials->native.cr_groups[i] = -1; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED memset (&credentials->native, 0, sizeof (struct cmsgcred)); credentials->native.cmcred_pid = getpid (); @@ -174,7 +196,7 @@ g_credentials_init (GCredentials *credentials) * Creates a new #GCredentials object with credentials matching the * the current process. * - * Returns: A #GCredentials. Free with g_object_unref(). + * Returns: (transfer full): A #GCredentials. Free with g_object_unref(). * * Since: 2.26 */ @@ -194,7 +216,7 @@ g_credentials_new (void) * that can be used in logging and debug messages. The format of the * returned string may change in future GLib release. * - * Returns: A string that should be freed with g_free(). + * Returns: (transfer full): A string that should be freed with g_free(). * * Since: 2.26 */ @@ -202,44 +224,56 @@ gchar * g_credentials_to_string (GCredentials *credentials) { GString *ret; +#if G_CREDENTIALS_USE_APPLE_XUCRED + glib_typeof (credentials->native.cr_ngroups) i; +#endif g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL); ret = g_string_new ("GCredentials:"); #if G_CREDENTIALS_USE_LINUX_UCRED g_string_append (ret, "linux-ucred:"); - if (credentials->native.pid != -1) + if (credentials->native.pid != (pid_t) -1) g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid); - if (credentials->native.uid != -1) + if (credentials->native.uid != (uid_t) -1) g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid); - if (credentials->native.gid != -1) + if (credentials->native.gid != (gid_t) -1) g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid); if (ret->str[ret->len - 1] == ',') ret->str[ret->len - 1] = '\0'; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + g_string_append (ret, "apple-xucred:"); + g_string_append_printf (ret, "version=%u,", credentials->native.cr_version); + if (credentials->native.cr_uid != (uid_t) -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cr_uid); + for (i = 0; i < credentials->native.cr_ngroups; i++) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cr_groups[i]); + if (ret->str[ret->len - 1] == ',') + ret->str[ret->len - 1] = '\0'; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED g_string_append (ret, "freebsd-cmsgcred:"); - if (credentials->native.cmcred_pid != -1) + if (credentials->native.cmcred_pid != (pid_t) -1) g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid); - if (credentials->native.cmcred_euid != -1) + if (credentials->native.cmcred_euid != (uid_t) -1) g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_euid); - if (credentials->native.cmcred_gid != -1) + if (credentials->native.cmcred_gid != (gid_t) -1) g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_gid); #elif G_CREDENTIALS_USE_NETBSD_UNPCBID g_string_append (ret, "netbsd-unpcbid:"); - if (credentials->native.unp_pid != -1) + if (credentials->native.unp_pid != (pid_t) -1) g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_pid); - if (credentials->native.unp_euid != -1) + if (credentials->native.unp_euid != (uid_t) -1) g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_euid); - if (credentials->native.unp_egid != -1) + if (credentials->native.unp_egid != (gid_t) -1) g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_egid); ret->str[ret->len - 1] = '\0'; #elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED g_string_append (ret, "openbsd-sockpeercred:"); - if (credentials->native.pid != -1) + if (credentials->native.pid != (pid_t) -1) g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid); - if (credentials->native.uid != -1) + if (credentials->native.uid != (uid_t) -1) g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid); - if (credentials->native.gid != -1) + if (credentials->native.gid != (gid_t) -1) g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid); if (ret->str[ret->len - 1] == ',') ret->str[ret->len - 1] = '\0'; @@ -247,11 +281,11 @@ g_credentials_to_string (GCredentials *credentials) g_string_append (ret, "solaris-ucred:"); { id_t id; - if ((id = ucred_getpid (credentials->native)) != -1) + if ((id = ucred_getpid (credentials->native)) != (id_t) -1) g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) id); - if ((id = ucred_geteuid (credentials->native)) != -1) + if ((id = ucred_geteuid (credentials->native)) != (id_t) -1) g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) id); - if ((id = ucred_getegid (credentials->native)) != -1) + if ((id = ucred_getegid (credentials->native)) != (id_t) -1) g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) id); if (ret->str[ret->len - 1] == ',') ret->str[ret->len - 1] = '\0'; @@ -280,13 +314,13 @@ linux_ucred_check_valid (struct ucred *native, GError **error) { if (native->pid == 0 - || native->uid == -1 - || native->gid == -1) + || native->uid == (uid_t) -1 + || native->gid == (gid_t) -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "GCredentials contains invalid data"); + _("GCredentials contains invalid data")); return FALSE; } @@ -326,6 +360,10 @@ g_credentials_is_same_user (GCredentials *credentials, if (linux_ucred_check_valid (&credentials->native, NULL) && credentials->native.uid == other_credentials->native.uid) ret = TRUE; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + if (credentials->native.cr_version == other_credentials->native.cr_version && + credentials->native.cr_uid == other_credentials->native.cr_uid) + ret = TRUE; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid) ret = TRUE; @@ -397,10 +435,10 @@ credentials_native_type_check (GCredentialsType requested_type, * logged) to use this method if there is no #GCredentials support for * the OS or if @native_type isn't supported by the OS. * - * Returns: The pointer to native credentials or %NULL if the - * operation there is no #GCredentials support for the OS or if - * @native_type isn't supported by the OS. Do not free the returned - * data, it is owned by @credentials. + * Returns: (transfer none) (nullable): The pointer to native credentials or + * %NULL if there is no #GCredentials support for the OS or if @native_type + * isn't supported by the OS. Do not free the returned data, it is owned + * by @credentials. * * Since: 2.26 */ @@ -469,7 +507,7 @@ g_credentials_set_native (GCredentials *credentials, * OS or if the native credentials type does not contain information * about the UNIX user. * - * Returns: The UNIX user identifier or -1 if @error is set. + * Returns: The UNIX user identifier or `-1` if @error is set. * * Since: 2.26 */ @@ -487,6 +525,21 @@ g_credentials_get_unix_user (GCredentials *credentials, ret = credentials->native.uid; else ret = -1; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + if (credentials->native.cr_version == XUCRED_VERSION) + { + ret = credentials->native.cr_uid; + } + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + /* No point in translating the part in parentheses... */ + "%s (struct xucred cr_version %u != %u)", + _("There is no GCredentials support for your platform"), + credentials->native.cr_version, + XUCRED_VERSION); + ret = -1; + } #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED ret = credentials->native.cmcred_euid; #elif G_CREDENTIALS_USE_NETBSD_UNPCBID @@ -516,9 +569,10 @@ g_credentials_get_unix_user (GCredentials *credentials, * * This operation can fail if #GCredentials is not supported on the * OS or if the native credentials type does not contain information - * about the UNIX process ID. + * about the UNIX process ID (for example this is the case for + * %G_CREDENTIALS_TYPE_APPLE_XUCRED). * - * Returns: The UNIX process ID, or -1 if @error is set. + * Returns: The UNIX process ID, or `-1` if @error is set. * * Since: 2.36 */ @@ -545,6 +599,7 @@ g_credentials_get_unix_pid (GCredentials *credentials, #elif G_CREDENTIALS_USE_SOLARIS_UCRED ret = ucred_getpid (credentials->native); #else + /* this case includes G_CREDENTIALS_USE_APPLE_XUCRED */ ret = -1; g_set_error_literal (error, G_IO_ERROR, @@ -578,16 +633,18 @@ g_credentials_set_unix_user (GCredentials *credentials, uid_t uid, GError **error) { - gboolean ret; + gboolean ret = FALSE; g_return_val_if_fail (G_IS_CREDENTIALS (credentials), FALSE); - g_return_val_if_fail (uid != -1, FALSE); + g_return_val_if_fail (uid != (uid_t) -1, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - ret = FALSE; #if G_CREDENTIALS_USE_LINUX_UCRED credentials->native.uid = uid; ret = TRUE; +#elif G_CREDENTIALS_USE_APPLE_XUCRED + credentials->native.cr_uid = uid; + ret = TRUE; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED credentials->native.cmcred_euid = uid; ret = TRUE; diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h index e9ec09b9f6a05659db9b4bdf55da891c32823c94..13d3bf327ab9c2a2228d5faff6f378a60ee4edf2 100644 --- a/gio/gcredentialsprivate.h +++ b/gio/gcredentialsprivate.h @@ -39,6 +39,7 @@ #undef G_CREDENTIALS_USE_NETBSD_UNPCBID #undef G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED #undef G_CREDENTIALS_USE_SOLARIS_UCRED +#undef G_CREDENTIALS_USE_APPLE_XUCRED /* * G_CREDENTIALS_NATIVE_TYPE: @@ -93,6 +94,13 @@ */ #undef G_CREDENTIALS_PREFER_MESSAGE_PASSING +/* + * G_CREDENTIALS_HAS_PID: + * + * Defined to 1 if the %G_CREDENTIALS_NATIVE_TYPE contains the process ID. + */ +#undef G_CREDENTIALS_HAS_PID + #ifdef __linux__ #define G_CREDENTIALS_SUPPORTED 1 #define G_CREDENTIALS_USE_LINUX_UCRED 1 @@ -101,6 +109,7 @@ #define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 #define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 #define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 #elif defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) /* Debian GNU/kFreeBSD */ || \ @@ -118,6 +127,7 @@ * SCM_CREDS, and if we implement getpeereid() in future, we should * do the same. */ #define G_CREDENTIALS_PREFER_MESSAGE_PASSING 1 +#define G_CREDENTIALS_HAS_PID 1 #elif defined(__NetBSD__) #define G_CREDENTIALS_SUPPORTED 1 @@ -126,6 +136,7 @@ #define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct unpcbid)) /* #undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED */ #define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 #elif defined(__OpenBSD__) #define G_CREDENTIALS_SUPPORTED 1 @@ -134,6 +145,7 @@ #define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct sockpeercred)) #define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 #define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 #elif defined(__sun__) || defined(__illumos__) || defined (__OpenSolaris_kernel__) #include @@ -143,6 +155,18 @@ #define G_CREDENTIALS_NATIVE_SIZE (ucred_size ()) #define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 #define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 1 + +#elif defined(__APPLE__) +#include +#define G_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_USE_APPLE_XUCRED 1 +#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_APPLE_XUCRED +#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct xucred)) +#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED +#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1 +#define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +#define G_CREDENTIALS_HAS_PID 0 #endif diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c index 7de2cb0a8a18d1ee75f7489e2dd03983573df92c..edbead10337640b209d15af31717ba2f27de7b38 100644 --- a/gio/gdatainputstream.c +++ b/gio/gdatainputstream.c @@ -310,7 +310,7 @@ read_data (GDataInputStream *stream, res = g_input_stream_read (G_INPUT_STREAM (stream), buffer, size, NULL, NULL); - g_warn_if_fail (res == size); + g_warn_if_fail (res >= 0 && (gsize) res == size); return TRUE; } @@ -631,7 +631,7 @@ scan_for_newline (GDataInputStream *stream, GDataInputStreamPrivate *priv; const char *buffer; gsize start, end, peeked; - int i; + gsize i; gssize found_pos; int newline_len; gsize available, checked; @@ -861,7 +861,7 @@ scan_for_chars (GDataInputStream *stream, GBufferedInputStream *bstream; const char *buffer; gsize start, end, peeked; - int i; + gsize i; gsize available, checked; const char *stop_char; const char *stop_end; diff --git a/gio/gdbus-2.0/codegen/__init__.py b/gio/gdbus-2.0/codegen/__init__.py index f876f04afc68aa7ec48b0260c3c981d00526455a..ed324d7cfa6043845809c469798cd1051bf3be27 100644 --- a/gio/gdbus-2.0/codegen/__init__.py +++ b/gio/gdbus-2.0/codegen/__init__.py @@ -21,7 +21,9 @@ import os -builddir = os.environ.get('UNINSTALLED_GLIB_BUILDDIR') +builddir = os.environ.get("UNINSTALLED_GLIB_BUILDDIR") if builddir is not None: - __path__.append(os.path.abspath(os.path.join(builddir, 'gio', 'gdbus-2.0', 'codegen'))) + __path__.append( + os.path.abspath(os.path.join(builddir, "gio", "gdbus-2.0", "codegen")) + ) diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py index aa1280f5923b07d51263d6df180e791f268513de..9d28cb77d16f50c8dd460370d6d9f04185b7617f 100644 --- a/gio/gdbus-2.0/codegen/codegen.py +++ b/gio/gdbus-2.0/codegen/codegen.py @@ -21,129 +21,180 @@ # # Author: David Zeuthen -import sys - from . import config from . import utils from . import dbustypes from .utils import print_error -LICENSE_STR = '''/* - * Generated by gdbus-codegen {!s} from {!s}. DO NOT EDIT. +LICENSE_STR = """/* + * This file is generated by gdbus-codegen, do not modify it. * * The license of this code is the same as for the D-Bus interface description - * it was derived from. - */\n''' + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */\n""" + + +# Disable line length warnings as wrapping the C code templates would be hard +# flake8: noqa: E501 + def generate_namespace(namespace): ns = namespace if len(namespace) > 0: if utils.is_ugly_case(namespace): - ns = namespace.replace('_', '') - ns_upper = namespace.upper() + '_' - ns_lower = namespace.lower() + '_' + ns = namespace.replace("_", "") + ns_upper = namespace.upper() + "_" + ns_lower = namespace.lower() + "_" else: - ns_upper = utils.camel_case_to_uscore(namespace).upper() + '_' - ns_lower = utils.camel_case_to_uscore(namespace).lower() + '_' + ns_upper = utils.camel_case_to_uscore(namespace).upper() + "_" + ns_lower = utils.camel_case_to_uscore(namespace).lower() + "_" else: - ns_upper = '' - ns_lower = '' + ns_upper = "" + ns_lower = "" return (ns, ns_upper, ns_lower) + +def generate_header_guard(header_name): + # There might be more characters that are safe to use than these, but lets + # stay conservative. + safe_valid_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + return "".join( + map(lambda c: c if c in safe_valid_chars else "_", header_name.upper()) + ) + + class HeaderCodeGenerator: - def __init__(self, ifaces, namespace, generate_objmanager, - generate_autocleanup, header_name, input_files_basenames, - use_pragma, outfile): + def __init__( + self, + ifaces, + namespace, + generate_objmanager, + generate_autocleanup, + header_name, + input_files_basenames, + use_pragma, + glib_min_required, + symbol_decorator, + symbol_decorator_header, + outfile, + ): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.generate_objmanager = generate_objmanager self.generate_autocleanup = generate_autocleanup - self.header_guard = header_name.upper().replace('.', '_').replace('-', '_').replace('/', '_').replace(':', '_') + self.header_guard = generate_header_guard(header_name) self.input_files_basenames = input_files_basenames self.use_pragma = use_pragma + self.glib_min_required = glib_min_required + self.symbol_decorator = symbol_decorator + self.symbol_decorator_header = symbol_decorator_header self.outfile = outfile # ---------------------------------------------------------------------------------------------------- def generate_header_preamble(self): - basenames = ', '.join(self.input_files_basenames) + basenames = ", ".join(self.input_files_basenames) self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) - self.outfile.write('\n') + self.outfile.write("\n") if self.use_pragma: - self.outfile.write('#pragma once\n') + self.outfile.write("#pragma once\n") else: - self.outfile.write('#ifndef __{!s}__\n'.format(self.header_guard)) - self.outfile.write('#define __{!s}__\n'.format(self.header_guard)) + self.outfile.write("#ifndef __{!s}__\n".format(self.header_guard)) + self.outfile.write("#define __{!s}__\n".format(self.header_guard)) + + if self.symbol_decorator_header is not None: + self.outfile.write("\n") + self.outfile.write('#include "%s"\n' % self.symbol_decorator_header) - self.outfile.write('\n') - self.outfile.write('#include \n') - self.outfile.write('\n') - self.outfile.write('G_BEGIN_DECLS\n') - self.outfile.write('\n') + self.outfile.write("\n") + self.outfile.write("#include \n") + self.outfile.write("\n") + self.outfile.write("G_BEGIN_DECLS\n") + self.outfile.write("\n") # ---------------------------------------------------------------------------------------------------- def declare_types(self): for i in self.ifaces: - self.outfile.write('\n') - self.outfile.write('/* ------------------------------------------------------------------------ */\n') - self.outfile.write('/* Declarations for %s */\n'%i.name) - self.outfile.write('\n') + self.outfile.write("\n") + self.outfile.write( + "/* ------------------------------------------------------------------------ */\n" + ) + self.outfile.write("/* Declarations for %s */\n" % i.name) + self.outfile.write("\n") # First the GInterface - self.outfile.write('#define %sTYPE_%s (%s_get_type ())\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#define %s%s(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s, %s))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %sIS_%s(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) - self.outfile.write('#define %s%s_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_%s, %sIface))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('\n') - self.outfile.write('struct _%s;\n'%(i.camel_name)) - self.outfile.write('typedef struct _%s %s;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('typedef struct _%sIface %sIface;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('\n') - self.outfile.write('struct _%sIface\n'%(i.camel_name)) - self.outfile.write('{\n') - self.outfile.write(' GTypeInterface parent_iface;\n') + self.outfile.write( + "#define %sTYPE_%s (%s_get_type ())\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write( + "#define %s%s(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s, %s))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %sIS_%s(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper) + ) + self.outfile.write( + "#define %s%s_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_%s, %sIface))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write("\n") + self.outfile.write("struct _%s;\n" % (i.camel_name)) + self.outfile.write( + "typedef struct _%s %s;\n" % (i.camel_name, i.camel_name) + ) + self.outfile.write( + "typedef struct _%sIface %sIface;\n" % (i.camel_name, i.camel_name) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sIface\n" % (i.camel_name)) + self.outfile.write("{\n") + self.outfile.write(" GTypeInterface parent_iface;\n") function_pointers = {} # vfuncs for methods if len(i.methods) > 0: - self.outfile.write('\n') + self.outfile.write("\n") for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True - key = (m.since, '_method_%s'%m.name_lower) - value = ' gboolean (*handle_%s) (\n'%(m.name_lower) - value += ' %s *object,\n'%(i.camel_name) - value += ' GDBusMethodInvocation *invocation'%() - if unix_fd: - value += ',\n GUnixFDList *fd_list' + key = (m.since, "_method_%s" % m.name_lower) + value = " gboolean (*handle_%s) (\n" % (m.name_lower) + value += " %s *object,\n" % (i.camel_name) + value += " GDBusMethodInvocation *invocation" + if m.unix_fd: + value += ",\n GUnixFDList *fd_list" for a in m.in_args: - value += ',\n %sarg_%s'%(a.ctype_in, a.name) - value += ');\n\n' + value += ",\n %sarg_%s" % (a.ctype_in, a.name) + value += ");\n\n" function_pointers[key] = value # vfuncs for signals if len(i.signals) > 0: - self.outfile.write('\n') + self.outfile.write("\n") for s in i.signals: - key = (s.since, '_signal_%s'%s.name_lower) - value = ' void (*%s) (\n'%(s.name_lower) - value += ' %s *object'%(i.camel_name) + key = (s.since, "_signal_%s" % s.name_lower) + value = " void (*%s) (\n" % (s.name_lower) + value += " %s *object" % (i.camel_name) for a in s.args: - value += ',\n %sarg_%s'%(a.ctype_in, a.name) - value += ');\n\n' + value += ",\n %sarg_%s" % (a.ctype_in, a.name) + value += ");\n\n" function_pointers[key] = value # vfuncs for properties if len(i.properties) > 0: - self.outfile.write('\n') + self.outfile.write("\n") for p in i.properties: - key = (p.since, '_prop_get_%s'%p.name_lower) - value = ' %s (*get_%s) (%s *object);\n\n'%(p.arg.ctype_in, p.name_lower, i.camel_name) + key = (p.since, "_prop_get_%s" % p.name_lower) + value = " %s (*get_%s) (%s *object);\n\n" % ( + p.arg.ctype_in, + p.name_lower, + i.camel_name, + ) function_pointers[key] = value # Sort according to @since tag, then name.. this ensures @@ -156,458 +207,799 @@ class HeaderCodeGenerator: # See https://bugzilla.gnome.org/show_bug.cgi?id=647577#c5 # for discussion for key in sorted(function_pointers.keys(), key=utils.version_cmp_key): - self.outfile.write('%s'%function_pointers[key]) - - self.outfile.write('};\n') - self.outfile.write('\n') - if self.generate_autocleanup == 'all': - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, g_object_unref)\n' % (i.camel_name)) - self.outfile.write('#endif\n') - self.outfile.write('\n') - self.outfile.write('GType %s_get_type (void) G_GNUC_CONST;\n'%(i.name_lower)) - self.outfile.write('\n') - self.outfile.write('GDBusInterfaceInfo *%s_interface_info (void);\n'%(i.name_lower)) - self.outfile.write('guint %s_override_properties (GObjectClass *klass, guint property_id_begin);\n'%(i.name_lower)) - self.outfile.write('\n') + self.outfile.write("%s" % function_pointers[key]) + + self.outfile.write("};\n") + self.outfile.write("\n") + if self.generate_autocleanup == "all": + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, g_object_unref)\n" + % (i.camel_name) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %s_get_type (void) G_GNUC_CONST;\n" % (i.name_lower) + ) + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GDBusInterfaceInfo *%s_interface_info (void);\n" % (i.name_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "guint %s_override_properties (GObjectClass *klass, guint property_id_begin);\n" + % (i.name_lower) + ) + self.outfile.write("\n") # Then method call completion functions if len(i.methods) > 0: - self.outfile.write('\n') - self.outfile.write('/* D-Bus method call completion functions: */\n') + self.outfile.write("\n") + self.outfile.write("/* D-Bus method call completion functions: */\n") for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if m.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %s_complete_%s (\n' - ' %s *object,\n' - ' GDBusMethodInvocation *invocation'%(i.name_lower, m.name_lower, i.camel_name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList *fd_list') + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %s_complete_%s (\n" + " %s *object,\n" + " GDBusMethodInvocation *invocation" + % (i.name_lower, m.name_lower, i.camel_name) + ) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList *fd_list") for a in m.out_args: - self.outfile.write(',\n %s%s'%(a.ctype_in, a.name)) - self.outfile.write(');\n') - self.outfile.write('\n') - self.outfile.write('\n') + self.outfile.write(",\n %s%s" % (a.ctype_in, a.name)) + self.outfile.write(");\n") + self.outfile.write("\n") + self.outfile.write("\n") # Then signal emission functions if len(i.signals) > 0: - self.outfile.write('\n') - self.outfile.write('/* D-Bus signal emissions functions: */\n') + self.outfile.write("\n") + self.outfile.write("/* D-Bus signal emissions functions: */\n") for s in i.signals: + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if s.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %s_emit_%s (\n' - ' %s *object'%(i.name_lower, s.name_lower, i.camel_name)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %s_emit_%s (\n" + " %s *object" % (i.name_lower, s.name_lower, i.camel_name) + ) for a in s.args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - self.outfile.write(');\n') - self.outfile.write('\n') - self.outfile.write('\n') + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + self.outfile.write(");\n") + self.outfile.write("\n") + self.outfile.write("\n") # Then method call declarations if len(i.methods) > 0: - self.outfile.write('\n') - self.outfile.write('/* D-Bus method calls: */\n') + self.outfile.write("\n") + self.outfile.write("/* D-Bus method calls: */\n") for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True # async begin + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if m.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %s_call_%s (\n' - ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %s_call_%s (\n" + " %s *proxy" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.in_args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList *fd_list') - self.outfile.write(',\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data);\n') - self.outfile.write('\n') + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + if self.glib_min_required >= (2, 64): + self.outfile.write( + ",\n GDBusCallFlags call_flags" + ",\n gint timeout_msec" + ) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList *fd_list") + self.outfile.write( + ",\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data);\n" + ) + self.outfile.write("\n") # async finish + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if m.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('gboolean %s_call_%s_finish (\n' - ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "gboolean %s_call_%s_finish (\n" + " %s *proxy" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.out_args: - self.outfile.write(',\n %sout_%s'%(a.ctype_out, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList **out_fd_list') - self.outfile.write(',\n' - ' GAsyncResult *res,\n' - ' GError **error);\n') - self.outfile.write('\n') + self.outfile.write(",\n %sout_%s" % (a.ctype_out, a.name)) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList **out_fd_list") + self.outfile.write( + ",\n" " GAsyncResult *res,\n" " GError **error);\n" + ) + self.outfile.write("\n") # sync + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if m.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('gboolean %s_call_%s_sync (\n' - ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "gboolean %s_call_%s_sync (\n" + " %s *proxy" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.in_args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList *fd_list') + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + if self.glib_min_required >= (2, 64): + self.outfile.write( + ",\n GDBusCallFlags call_flags" + ",\n gint timeout_msec" + ) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList *fd_list") for a in m.out_args: - self.outfile.write(',\n %sout_%s'%(a.ctype_out, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList **out_fd_list') - self.outfile.write(',\n' - ' GCancellable *cancellable,\n' - ' GError **error);\n') - self.outfile.write('\n') - self.outfile.write('\n') + self.outfile.write(",\n %sout_%s" % (a.ctype_out, a.name)) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList **out_fd_list") + self.outfile.write( + ",\n" + " GCancellable *cancellable,\n" + " GError **error);\n" + ) + self.outfile.write("\n") + self.outfile.write("\n") # Then the property accessor declarations if len(i.properties) > 0: - self.outfile.write('\n') - self.outfile.write('/* D-Bus property accessors: */\n') + self.outfile.write("\n") + self.outfile.write("/* D-Bus property accessors: */\n") for p in i.properties: # getter + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if p.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s%s_get_%s (%s *object);\n'%(p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)) - if p.arg.free_func != None: + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s%s_get_%s (%s *object);\n" + % (p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name) + ) + if p.arg.free_func is not None: + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if p.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s%s_dup_%s (%s *object);\n'%(p.arg.ctype_in_dup, i.name_lower, p.name_lower, i.camel_name)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s%s_dup_%s (%s *object);\n" + % ( + p.arg.ctype_in_dup, + i.name_lower, + p.name_lower, + i.camel_name, + ) + ) # setter + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if p.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %s_set_%s (%s *object, %svalue);\n'%(i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in, )) - self.outfile.write('\n') + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %s_set_%s (%s *object, %svalue);\n" + % (i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in) + ) + self.outfile.write("\n") # Then the proxy - self.outfile.write('\n') - self.outfile.write('/* ---- */\n') - self.outfile.write('\n') - self.outfile.write('#define %sTYPE_%s_PROXY (%s_proxy_get_type ())\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#define %s%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_PROXY, %sProxy))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %s%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_PROXY, %sProxyClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %s%s_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_PROXY, %sProxyClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %sIS_%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_PROXY))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) - self.outfile.write('#define %sIS_%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_PROXY))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) - self.outfile.write('\n') - self.outfile.write('typedef struct _%sProxy %sProxy;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('typedef struct _%sProxyClass %sProxyClass;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('typedef struct _%sProxyPrivate %sProxyPrivate;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('\n') - self.outfile.write('struct _%sProxy\n'%(i.camel_name)) - self.outfile.write('{\n') - self.outfile.write(' /*< private >*/\n') - self.outfile.write(' GDBusProxy parent_instance;\n') - self.outfile.write(' %sProxyPrivate *priv;\n'%(i.camel_name)) - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('struct _%sProxyClass\n'%(i.camel_name)) - self.outfile.write('{\n') - self.outfile.write(' GDBusProxyClass parent_class;\n') - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('GType %s_proxy_get_type (void) G_GNUC_CONST;\n'%(i.name_lower)) - self.outfile.write('\n') - if self.generate_autocleanup in ('objects', 'all'): - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sProxy, g_object_unref)\n' % (i.camel_name)) - self.outfile.write('#endif\n') - self.outfile.write('\n') + self.outfile.write("\n") + self.outfile.write("/* ---- */\n") + self.outfile.write("\n") + self.outfile.write( + "#define %sTYPE_%s_PROXY (%s_proxy_get_type ())\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write( + "#define %s%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_PROXY, %sProxy))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %s%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_PROXY, %sProxyClass))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %s%s_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_PROXY, %sProxyClass))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %sIS_%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_PROXY))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper) + ) + self.outfile.write( + "#define %sIS_%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_PROXY))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper) + ) + self.outfile.write("\n") + self.outfile.write( + "typedef struct _%sProxy %sProxy;\n" % (i.camel_name, i.camel_name) + ) + self.outfile.write( + "typedef struct _%sProxyClass %sProxyClass;\n" + % (i.camel_name, i.camel_name) + ) + self.outfile.write( + "typedef struct _%sProxyPrivate %sProxyPrivate;\n" + % (i.camel_name, i.camel_name) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sProxy\n" % (i.camel_name)) + self.outfile.write("{\n") + self.outfile.write(" /*< private >*/\n") + self.outfile.write(" GDBusProxy parent_instance;\n") + self.outfile.write(" %sProxyPrivate *priv;\n" % (i.camel_name)) + self.outfile.write("};\n") + self.outfile.write("\n") + self.outfile.write("struct _%sProxyClass\n" % (i.camel_name)) + self.outfile.write("{\n") + self.outfile.write(" GDBusProxyClass parent_class;\n") + self.outfile.write("};\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %s_proxy_get_type (void) G_GNUC_CONST;\n" % (i.name_lower) + ) + self.outfile.write("\n") + if self.generate_autocleanup in ("objects", "all"): + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sProxy, g_object_unref)\n" + % (i.camel_name) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %s_proxy_new (\n' - ' GDBusConnection *connection,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data);\n' - %(i.name_lower)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %s_proxy_new (\n" + " GDBusConnection *connection,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data);\n" % (i.name_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%s_proxy_new_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error);\n' - %(i.camel_name, i.name_lower)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%s_proxy_new_finish (\n" + " GAsyncResult *res,\n" + " GError **error);\n" % (i.camel_name, i.name_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%s_proxy_new_sync (\n' - ' GDBusConnection *connection,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error);\n' - %(i.camel_name, i.name_lower)) - self.outfile.write('\n') + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%s_proxy_new_sync (\n" + " GDBusConnection *connection,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error);\n" % (i.camel_name, i.name_lower) + ) + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %s_proxy_new_for_bus (\n' - ' GBusType bus_type,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data);\n' - %(i.name_lower)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %s_proxy_new_for_bus (\n" + " GBusType bus_type,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data);\n" % (i.name_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%s_proxy_new_for_bus_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error);\n' - %(i.camel_name, i.name_lower)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%s_proxy_new_for_bus_finish (\n" + " GAsyncResult *res,\n" + " GError **error);\n" % (i.camel_name, i.name_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%s_proxy_new_for_bus_sync (\n' - ' GBusType bus_type,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error);\n' - %(i.camel_name, i.name_lower)) - self.outfile.write('\n') + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%s_proxy_new_for_bus_sync (\n" + " GBusType bus_type,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error);\n" % (i.camel_name, i.name_lower) + ) + self.outfile.write("\n") # Then the skeleton - self.outfile.write('\n') - self.outfile.write('/* ---- */\n') - self.outfile.write('\n') - self.outfile.write('#define %sTYPE_%s_SKELETON (%s_skeleton_get_type ())\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#define %s%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_SKELETON, %sSkeleton))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %s%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_SKELETON, %sSkeletonClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %s%s_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_SKELETON, %sSkeletonClass))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write('#define %sIS_%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_SKELETON))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) - self.outfile.write('#define %sIS_%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_SKELETON))\n'%(i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) - self.outfile.write('\n') - self.outfile.write('typedef struct _%sSkeleton %sSkeleton;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('typedef struct _%sSkeletonClass %sSkeletonClass;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('typedef struct _%sSkeletonPrivate %sSkeletonPrivate;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('\n') - self.outfile.write('struct _%sSkeleton\n'%(i.camel_name)) - self.outfile.write('{\n') - self.outfile.write(' /*< private >*/\n') - self.outfile.write(' GDBusInterfaceSkeleton parent_instance;\n') - self.outfile.write(' %sSkeletonPrivate *priv;\n'%(i.camel_name)) - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('struct _%sSkeletonClass\n'%(i.camel_name)) - self.outfile.write('{\n') - self.outfile.write(' GDBusInterfaceSkeletonClass parent_class;\n') - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('GType %s_skeleton_get_type (void) G_GNUC_CONST;\n'%(i.name_lower)) - self.outfile.write('\n') - if self.generate_autocleanup in ('objects', 'all'): - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sSkeleton, g_object_unref)\n' % (i.camel_name)) - self.outfile.write('#endif\n') - self.outfile.write('\n') + self.outfile.write("\n") + self.outfile.write("/* ---- */\n") + self.outfile.write("\n") + self.outfile.write( + "#define %sTYPE_%s_SKELETON (%s_skeleton_get_type ())\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write( + "#define %s%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_SKELETON, %sSkeleton))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %s%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_SKELETON, %sSkeletonClass))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %s%s_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_SKELETON, %sSkeletonClass))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name) + ) + self.outfile.write( + "#define %sIS_%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_SKELETON))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper) + ) + self.outfile.write( + "#define %sIS_%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_SKELETON))\n" + % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper) + ) + self.outfile.write("\n") + self.outfile.write( + "typedef struct _%sSkeleton %sSkeleton;\n" + % (i.camel_name, i.camel_name) + ) + self.outfile.write( + "typedef struct _%sSkeletonClass %sSkeletonClass;\n" + % (i.camel_name, i.camel_name) + ) + self.outfile.write( + "typedef struct _%sSkeletonPrivate %sSkeletonPrivate;\n" + % (i.camel_name, i.camel_name) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sSkeleton\n" % (i.camel_name)) + self.outfile.write("{\n") + self.outfile.write(" /*< private >*/\n") + self.outfile.write(" GDBusInterfaceSkeleton parent_instance;\n") + self.outfile.write(" %sSkeletonPrivate *priv;\n" % (i.camel_name)) + self.outfile.write("};\n") + self.outfile.write("\n") + self.outfile.write("struct _%sSkeletonClass\n" % (i.camel_name)) + self.outfile.write("{\n") + self.outfile.write(" GDBusInterfaceSkeletonClass parent_class;\n") + self.outfile.write("};\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %s_skeleton_get_type (void) G_GNUC_CONST;\n" % (i.name_lower) + ) + self.outfile.write("\n") + if self.generate_autocleanup in ("objects", "all"): + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sSkeleton, g_object_unref)\n" + % (i.camel_name) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%s_skeleton_new (void);\n'%(i.camel_name, i.name_lower)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%s_skeleton_new (void);\n" % (i.camel_name, i.name_lower) + ) - self.outfile.write('\n') + self.outfile.write("\n") # Finally, the Object, ObjectProxy, ObjectSkeleton and ObjectManagerClient if self.generate_objmanager: - self.outfile.write('\n') - self.outfile.write('/* ---- */\n') - self.outfile.write('\n') - self.outfile.write('#define %sTYPE_OBJECT (%sobject_get_type ())\n'%(self.ns_upper, self.ns_lower)) - self.outfile.write('#define %sOBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT, %sObject))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sIS_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('#define %sOBJECT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_OBJECT, %sObject))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('\n') - self.outfile.write('struct _%sObject;\n'%(self.namespace)) - self.outfile.write('typedef struct _%sObject %sObject;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectIface %sObjectIface;\n'%(self.namespace, self.namespace)) - self.outfile.write('\n') - self.outfile.write('struct _%sObjectIface\n'%(self.namespace)) - self.outfile.write('{\n' - ' GTypeInterface parent_iface;\n' - '};\n' - '\n') - self.outfile.write('GType %sobject_get_type (void) G_GNUC_CONST;\n' - '\n' - %(self.ns_lower)) - if self.generate_autocleanup == 'all': - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObject, g_object_unref)\n' % (self.namespace)) - self.outfile.write('#endif\n') - self.outfile.write('\n') + self.outfile.write("\n") + self.outfile.write("/* ---- */\n") + self.outfile.write("\n") + self.outfile.write( + "#define %sTYPE_OBJECT (%sobject_get_type ())\n" + % (self.ns_upper, self.ns_lower) + ) + self.outfile.write( + "#define %sOBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT, %sObject))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sIS_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write( + "#define %sOBJECT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_OBJECT, %sObject))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sObject;\n" % (self.namespace)) + self.outfile.write( + "typedef struct _%sObject %sObject;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectIface %sObjectIface;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sObjectIface\n" % (self.namespace)) + self.outfile.write("{\n" " GTypeInterface parent_iface;\n" "};\n" "\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %sobject_get_type (void) G_GNUC_CONST;\n" "\n" % (self.ns_lower) + ) + if self.generate_autocleanup == "all": + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObject, g_object_unref)\n" + % (self.namespace) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") for i in self.ifaces: + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%sobject_get_%s (%sObject *object);\n' - %(i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%sobject_get_%s (%sObject *object);\n" + % ( + i.camel_name, + self.ns_lower, + i.name_upper.lower(), + self.namespace, + ) + ) for i in self.ifaces: + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('%s *%sobject_peek_%s (%sObject *object);\n' - %(i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)) - self.outfile.write('\n') - self.outfile.write('#define %sTYPE_OBJECT_PROXY (%sobject_proxy_get_type ())\n'%(self.ns_upper, self.ns_lower)) - self.outfile.write('#define %sOBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_PROXY, %sObjectProxy))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sOBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sOBJECT_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sIS_OBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_PROXY))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('#define %sIS_OBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_PROXY))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('\n') - self.outfile.write('typedef struct _%sObjectProxy %sObjectProxy;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectProxyClass %sObjectProxyClass;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectProxyPrivate %sObjectProxyPrivate;\n'%(self.namespace, self.namespace)) - self.outfile.write('\n') - self.outfile.write('struct _%sObjectProxy\n'%(self.namespace)) - self.outfile.write('{\n') - self.outfile.write(' /*< private >*/\n') - self.outfile.write(' GDBusObjectProxy parent_instance;\n') - self.outfile.write(' %sObjectProxyPrivate *priv;\n'%(self.namespace)) - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('struct _%sObjectProxyClass\n'%(self.namespace)) - self.outfile.write('{\n') - self.outfile.write(' GDBusObjectProxyClass parent_class;\n') - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('GType %sobject_proxy_get_type (void) G_GNUC_CONST;\n'%(self.ns_lower)) - self.outfile.write('\n') - if self.generate_autocleanup in ('objects', 'all'): - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectProxy, g_object_unref)\n' % (self.namespace)) - self.outfile.write('#endif\n') - self.outfile.write('\n') - self.outfile.write('%sObjectProxy *%sobject_proxy_new (GDBusConnection *connection, const gchar *object_path);\n'%(self.namespace, self.ns_lower)) - self.outfile.write('\n') - self.outfile.write('#define %sTYPE_OBJECT_SKELETON (%sobject_skeleton_get_type ())\n'%(self.ns_upper, self.ns_lower)) - self.outfile.write('#define %sOBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeleton))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sOBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sOBJECT_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sIS_OBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_SKELETON))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('#define %sIS_OBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_SKELETON))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('\n') - self.outfile.write('typedef struct _%sObjectSkeleton %sObjectSkeleton;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectSkeletonClass %sObjectSkeletonClass;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectSkeletonPrivate %sObjectSkeletonPrivate;\n'%(self.namespace, self.namespace)) - self.outfile.write('\n') - self.outfile.write('struct _%sObjectSkeleton\n'%(self.namespace)) - self.outfile.write('{\n') - self.outfile.write(' /*< private >*/\n') - self.outfile.write(' GDBusObjectSkeleton parent_instance;\n') - self.outfile.write(' %sObjectSkeletonPrivate *priv;\n'%(self.namespace)) - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('struct _%sObjectSkeletonClass\n'%(self.namespace)) - self.outfile.write('{\n') - self.outfile.write(' GDBusObjectSkeletonClass parent_class;\n') - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('GType %sobject_skeleton_get_type (void) G_GNUC_CONST;\n'%(self.ns_lower)) - self.outfile.write('\n') - if self.generate_autocleanup in ('objects', 'all'): - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectSkeleton, g_object_unref)\n' % (self.namespace)) - self.outfile.write('#endif\n') - self.outfile.write('\n') - self.outfile.write('%sObjectSkeleton *%sobject_skeleton_new (const gchar *object_path);\n' - %(self.namespace, self.ns_lower)) + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "%s *%sobject_peek_%s (%sObject *object);\n" + % ( + i.camel_name, + self.ns_lower, + i.name_upper.lower(), + self.namespace, + ) + ) + self.outfile.write("\n") + self.outfile.write( + "#define %sTYPE_OBJECT_PROXY (%sobject_proxy_get_type ())\n" + % (self.ns_upper, self.ns_lower) + ) + self.outfile.write( + "#define %sOBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_PROXY, %sObjectProxy))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sOBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sOBJECT_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sIS_OBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_PROXY))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write( + "#define %sIS_OBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_PROXY))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write("\n") + self.outfile.write( + "typedef struct _%sObjectProxy %sObjectProxy;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectProxyClass %sObjectProxyClass;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectProxyPrivate %sObjectProxyPrivate;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sObjectProxy\n" % (self.namespace)) + self.outfile.write("{\n") + self.outfile.write(" /*< private >*/\n") + self.outfile.write(" GDBusObjectProxy parent_instance;\n") + self.outfile.write(" %sObjectProxyPrivate *priv;\n" % (self.namespace)) + self.outfile.write("};\n") + self.outfile.write("\n") + self.outfile.write("struct _%sObjectProxyClass\n" % (self.namespace)) + self.outfile.write("{\n") + self.outfile.write(" GDBusObjectProxyClass parent_class;\n") + self.outfile.write("};\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %sobject_proxy_get_type (void) G_GNUC_CONST;\n" % (self.ns_lower) + ) + self.outfile.write("\n") + if self.generate_autocleanup in ("objects", "all"): + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectProxy, g_object_unref)\n" + % (self.namespace) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "%sObjectProxy *%sobject_proxy_new (GDBusConnection *connection, const gchar *object_path);\n" + % (self.namespace, self.ns_lower) + ) + self.outfile.write("\n") + self.outfile.write( + "#define %sTYPE_OBJECT_SKELETON (%sobject_skeleton_get_type ())\n" + % (self.ns_upper, self.ns_lower) + ) + self.outfile.write( + "#define %sOBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeleton))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sOBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sOBJECT_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sIS_OBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_SKELETON))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write( + "#define %sIS_OBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_SKELETON))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write("\n") + self.outfile.write( + "typedef struct _%sObjectSkeleton %sObjectSkeleton;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectSkeletonClass %sObjectSkeletonClass;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectSkeletonPrivate %sObjectSkeletonPrivate;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sObjectSkeleton\n" % (self.namespace)) + self.outfile.write("{\n") + self.outfile.write(" /*< private >*/\n") + self.outfile.write(" GDBusObjectSkeleton parent_instance;\n") + self.outfile.write(" %sObjectSkeletonPrivate *priv;\n" % (self.namespace)) + self.outfile.write("};\n") + self.outfile.write("\n") + self.outfile.write("struct _%sObjectSkeletonClass\n" % (self.namespace)) + self.outfile.write("{\n") + self.outfile.write(" GDBusObjectSkeletonClass parent_class;\n") + self.outfile.write("};\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %sobject_skeleton_get_type (void) G_GNUC_CONST;\n" + % (self.ns_lower) + ) + self.outfile.write("\n") + if self.generate_autocleanup in ("objects", "all"): + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectSkeleton, g_object_unref)\n" + % (self.namespace) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "%sObjectSkeleton *%sobject_skeleton_new (const gchar *object_path);\n" + % (self.namespace, self.ns_lower) + ) for i in self.ifaces: + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) if i.deprecated: - self.outfile.write('G_GNUC_DEPRECATED ') - self.outfile.write('void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_);\n' - %(self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name)) - self.outfile.write('\n') - - self.outfile.write('/* ---- */\n') - self.outfile.write('\n') - self.outfile.write('#define %sTYPE_OBJECT_MANAGER_CLIENT (%sobject_manager_client_get_type ())\n'%(self.ns_upper, self.ns_lower)) - self.outfile.write('#define %sOBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClient))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sOBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sOBJECT_MANAGER_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n'%(self.ns_upper, self.ns_upper, self.namespace)) - self.outfile.write('#define %sIS_OBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_MANAGER_CLIENT))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('#define %sIS_OBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_MANAGER_CLIENT))\n'%(self.ns_upper, self.ns_upper)) - self.outfile.write('\n') - self.outfile.write('typedef struct _%sObjectManagerClient %sObjectManagerClient;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectManagerClientClass %sObjectManagerClientClass;\n'%(self.namespace, self.namespace)) - self.outfile.write('typedef struct _%sObjectManagerClientPrivate %sObjectManagerClientPrivate;\n'%(self.namespace, self.namespace)) - self.outfile.write('\n') - self.outfile.write('struct _%sObjectManagerClient\n'%(self.namespace)) - self.outfile.write('{\n') - self.outfile.write(' /*< private >*/\n') - self.outfile.write(' GDBusObjectManagerClient parent_instance;\n') - self.outfile.write(' %sObjectManagerClientPrivate *priv;\n'%(self.namespace)) - self.outfile.write('};\n') - self.outfile.write('\n') - self.outfile.write('struct _%sObjectManagerClientClass\n'%(self.namespace)) - self.outfile.write('{\n') - self.outfile.write(' GDBusObjectManagerClientClass parent_class;\n') - self.outfile.write('};\n') - self.outfile.write('\n') - if self.generate_autocleanup in ('objects', 'all'): - self.outfile.write('#if GLIB_CHECK_VERSION(2, 44, 0)\n') - self.outfile.write('G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectManagerClient, g_object_unref)\n' % (self.namespace)) - self.outfile.write('#endif\n') - self.outfile.write('\n') - self.outfile.write('GType %sobject_manager_client_get_type (void) G_GNUC_CONST;\n'%(self.ns_lower)) - self.outfile.write('\n') - self.outfile.write('GType %sobject_manager_client_get_proxy_type (GDBusObjectManagerClient *manager, const gchar *object_path, const gchar *interface_name, gpointer user_data);\n'%(self.ns_lower)) - self.outfile.write('\n') - self.outfile.write('void %sobject_manager_client_new (\n' - ' GDBusConnection *connection,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data);\n' - %(self.ns_lower)) - self.outfile.write('GDBusObjectManager *%sobject_manager_client_new_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error);\n' - %(self.ns_lower)) - self.outfile.write('GDBusObjectManager *%sobject_manager_client_new_sync (\n' - ' GDBusConnection *connection,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error);\n' - %(self.ns_lower)) - self.outfile.write('\n') - self.outfile.write('void %sobject_manager_client_new_for_bus (\n' - ' GBusType bus_type,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data);\n' - %(self.ns_lower)) - self.outfile.write('GDBusObjectManager *%sobject_manager_client_new_for_bus_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error);\n' - %(self.ns_lower)) - self.outfile.write('GDBusObjectManager *%sobject_manager_client_new_for_bus_sync (\n' - ' GBusType bus_type,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error);\n' - %(self.ns_lower)) - self.outfile.write('\n') + self.outfile.write("G_GNUC_DEPRECATED ") + self.outfile.write( + "void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_);\n" + % ( + self.ns_lower, + i.name_upper.lower(), + self.namespace, + i.camel_name, + ) + ) + self.outfile.write("\n") + + self.outfile.write("/* ---- */\n") + self.outfile.write("\n") + self.outfile.write( + "#define %sTYPE_OBJECT_MANAGER_CLIENT (%sobject_manager_client_get_type ())\n" + % (self.ns_upper, self.ns_lower) + ) + self.outfile.write( + "#define %sOBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClient))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sOBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sOBJECT_MANAGER_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n" + % (self.ns_upper, self.ns_upper, self.namespace) + ) + self.outfile.write( + "#define %sIS_OBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_MANAGER_CLIENT))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write( + "#define %sIS_OBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_MANAGER_CLIENT))\n" + % (self.ns_upper, self.ns_upper) + ) + self.outfile.write("\n") + self.outfile.write( + "typedef struct _%sObjectManagerClient %sObjectManagerClient;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectManagerClientClass %sObjectManagerClientClass;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "typedef struct _%sObjectManagerClientPrivate %sObjectManagerClientPrivate;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write("\n") + self.outfile.write("struct _%sObjectManagerClient\n" % (self.namespace)) + self.outfile.write("{\n") + self.outfile.write(" /*< private >*/\n") + self.outfile.write(" GDBusObjectManagerClient parent_instance;\n") + self.outfile.write( + " %sObjectManagerClientPrivate *priv;\n" % (self.namespace) + ) + self.outfile.write("};\n") + self.outfile.write("\n") + self.outfile.write( + "struct _%sObjectManagerClientClass\n" % (self.namespace) + ) + self.outfile.write("{\n") + self.outfile.write(" GDBusObjectManagerClientClass parent_class;\n") + self.outfile.write("};\n") + self.outfile.write("\n") + if self.generate_autocleanup in ("objects", "all"): + self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n") + self.outfile.write( + "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectManagerClient, g_object_unref)\n" + % (self.namespace) + ) + self.outfile.write("#endif\n") + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %sobject_manager_client_get_type (void) G_GNUC_CONST;\n" + % (self.ns_lower) + ) + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GType %sobject_manager_client_get_proxy_type (GDBusObjectManagerClient *manager, const gchar *object_path, const gchar *interface_name, gpointer user_data);\n" + % (self.ns_lower) + ) + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "void %sobject_manager_client_new (\n" + " GDBusConnection *connection,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data);\n" % (self.ns_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GDBusObjectManager *%sobject_manager_client_new_finish (\n" + " GAsyncResult *res,\n" + " GError **error);\n" % (self.ns_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GDBusObjectManager *%sobject_manager_client_new_sync (\n" + " GDBusConnection *connection,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error);\n" % (self.ns_lower) + ) + self.outfile.write("\n") + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "void %sobject_manager_client_new_for_bus (\n" + " GBusType bus_type,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data);\n" % (self.ns_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GDBusObjectManager *%sobject_manager_client_new_for_bus_finish (\n" + " GAsyncResult *res,\n" + " GError **error);\n" % (self.ns_lower) + ) + if self.symbol_decorator is not None: + self.outfile.write("%s\n" % self.symbol_decorator) + self.outfile.write( + "GDBusObjectManager *%sobject_manager_client_new_for_bus_sync (\n" + " GBusType bus_type,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error);\n" % (self.ns_lower) + ) + self.outfile.write("\n") # ---------------------------------------------------------------------------------------------------- def generate_header_postamble(self): - self.outfile.write('\n') - self.outfile.write('G_END_DECLS\n') + self.outfile.write("\n") + self.outfile.write("G_END_DECLS\n") if not self.use_pragma: - self.outfile.write('\n') - self.outfile.write('#endif /* __{!s}__ */\n'.format(self.header_guard)) + self.outfile.write("\n") + self.outfile.write("#endif /* __{!s}__ */\n".format(self.header_guard)) # ---------------------------------------------------------------------------------------------------- @@ -616,51 +1008,76 @@ class HeaderCodeGenerator: self.declare_types() self.generate_header_postamble() + # ---------------------------------------------------------------------------------------------------- + class InterfaceInfoHeaderCodeGenerator: - def __init__(self, ifaces, namespace, header_name, input_files_basenames, use_pragma, outfile): + def __init__( + self, + ifaces, + namespace, + header_name, + input_files_basenames, + use_pragma, + glib_min_required, + symbol_decorator, + symbol_decorator_header, + outfile, + ): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) - self.header_guard = header_name.upper().replace('.', '_').replace('-', '_').replace('/', '_').replace(':', '_') + self.header_guard = generate_header_guard(header_name) self.input_files_basenames = input_files_basenames self.use_pragma = use_pragma + self.glib_min_required = glib_min_required + self.symbol_decorator = symbol_decorator + if self.symbol_decorator is None: + self.symbol_decorator = "" + self.symbol_decorator_header = symbol_decorator_header self.outfile = outfile # ---------------------------------------------------------------------------------------------------- def generate_header_preamble(self): - basenames = ', '.join(self.input_files_basenames) + basenames = ", ".join(self.input_files_basenames) self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) - self.outfile.write('\n') + self.outfile.write("\n") if self.use_pragma: - self.outfile.write('#pragma once\n') + self.outfile.write("#pragma once\n") else: - self.outfile.write('#ifndef __{!s}__\n'.format(self.header_guard)) - self.outfile.write('#define __{!s}__\n'.format(self.header_guard)) + self.outfile.write("#ifndef __{!s}__\n".format(self.header_guard)) + self.outfile.write("#define __{!s}__\n".format(self.header_guard)) + + if self.symbol_decorator_header is not None: + self.outfile.write("\n") + self.outfile.write('#include "%s"\n' % self.symbol_decorator_header) - self.outfile.write('\n') - self.outfile.write('#include \n') - self.outfile.write('\n') - self.outfile.write('G_BEGIN_DECLS\n') - self.outfile.write('\n') + self.outfile.write("\n") + self.outfile.write("#include \n") + self.outfile.write("\n") + self.outfile.write("G_BEGIN_DECLS\n") + self.outfile.write("\n") # ---------------------------------------------------------------------------------------------------- def declare_infos(self): for i in self.ifaces: - self.outfile.write('extern const GDBusInterfaceInfo %s_interface;\n' % i.name_lower) + self.outfile.write( + "extern %s const GDBusInterfaceInfo %s_interface;\n" + % (self.symbol_decorator, i.name_lower) + ) # ---------------------------------------------------------------------------------------------------- def generate_header_postamble(self): - self.outfile.write('\n') - self.outfile.write('G_END_DECLS\n') + self.outfile.write("\n") + self.outfile.write("G_END_DECLS\n") if not self.use_pragma: - self.outfile.write('\n') - self.outfile.write('#endif /* __{!s}__ */\n'.format(self.header_guard)) + self.outfile.write("\n") + self.outfile.write("#endif /* __{!s}__ */\n".format(self.header_guard)) # ---------------------------------------------------------------------------------------------------- @@ -669,42 +1086,63 @@ class InterfaceInfoHeaderCodeGenerator: self.declare_infos() self.generate_header_postamble() + # ---------------------------------------------------------------------------------------------------- + class InterfaceInfoBodyCodeGenerator: - def __init__(self, ifaces, namespace, header_name, input_files_basenames, outfile): + def __init__( + self, + ifaces, + namespace, + header_name, + input_files_basenames, + glib_min_required, + symbol_decoration_define, + outfile, + ): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.header_name = header_name self.input_files_basenames = input_files_basenames + self.glib_min_required = glib_min_required + self.symbol_decoration_define = symbol_decoration_define self.outfile = outfile # ---------------------------------------------------------------------------------------------------- def generate_body_preamble(self): - basenames = ', '.join(self.input_files_basenames) + basenames = ", ".join(self.input_files_basenames) self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) - self.outfile.write('\n') - self.outfile.write('#ifdef HAVE_CONFIG_H\n' - '# include "config.h"\n' - '#endif\n' - '\n' - '#include "%s"\n' - '\n' - '#include \n' - % (self.header_name)) - self.outfile.write('\n') + + if self.symbol_decoration_define is not None: + self.outfile.write("\n") + self.outfile.write("#define %s\n" % self.symbol_decoration_define) + + self.outfile.write("\n") + self.outfile.write( + "#ifdef HAVE_CONFIG_H\n" + '# include "config.h"\n' + "#endif\n" + "\n" + '#include "%s"\n' + "\n" + "#include \n" % (self.header_name) + ) + self.outfile.write("\n") # ---------------------------------------------------------------------------------------------------- def generate_array(self, array_name_lower, element_type, elements): - self.outfile.write('const %s * const %s[] =\n' % (element_type, array_name_lower)) - self.outfile.write('{\n') + self.outfile.write( + "const %s * const %s[] =\n" % (element_type, array_name_lower) + ) + self.outfile.write("{\n") for (_, name) in elements: - self.outfile.write(' &%s,\n' % name) - self.outfile.write(' NULL,\n') - self.outfile.write('};\n') - self.outfile.write('\n') + self.outfile.write(" &%s,\n" % name) + self.outfile.write(" NULL,\n") + self.outfile.write("};\n") + self.outfile.write("\n") def define_annotations(self, array_name_lower, annotations): if len(annotations) == 0: @@ -714,28 +1152,37 @@ class InterfaceInfoBodyCodeGenerator: for a in annotations: # Skip internal annotations. - if a.key.startswith('org.gtk.GDBus'): + if a.key.startswith("org.gtk.GDBus"): continue - self.define_annotations('%s__%s_annotations' % (array_name_lower, a.key_lower), a.annotations) + self.define_annotations( + "%s__%s_annotations" % (array_name_lower, a.key_lower), a.annotations + ) - self.outfile.write('const GDBusAnnotationInfo %s__%s_annotation =\n' % (array_name_lower, a.key_lower)) - self.outfile.write('{\n') - self.outfile.write(' -1, /* ref count */\n') + self.outfile.write( + "const GDBusAnnotationInfo %s__%s_annotation =\n" + % (array_name_lower, a.key_lower) + ) + self.outfile.write("{\n") + self.outfile.write(" -1, /* ref count */\n") self.outfile.write(' (gchar *) "%s",\n' % a.key) self.outfile.write(' (gchar *) "%s",\n' % a.value) if len(a.annotations) > 0: - self.outfile.write(' (GDBusAnnotationInfo **) %s__%s_annotations,\n' % (array_name_lower, a.key_lower)) + self.outfile.write( + " (GDBusAnnotationInfo **) %s__%s_annotations,\n" + % (array_name_lower, a.key_lower) + ) else: - self.outfile.write(' NULL, /* no annotations */\n') - self.outfile.write('};\n') - self.outfile.write('\n') + self.outfile.write(" NULL, /* no annotations */\n") + self.outfile.write("};\n") + self.outfile.write("\n") - key = (a.since, '%s__%s_annotation' % (array_name_lower, a.key_lower)) + key = (a.since, "%s__%s_annotation" % (array_name_lower, a.key_lower)) annotation_pointers.append(key) - self.generate_array(array_name_lower, 'GDBusAnnotationInfo', - annotation_pointers) + self.generate_array( + array_name_lower, "GDBusAnnotationInfo", annotation_pointers + ) def define_args(self, array_name_lower, args): if len(args) == 0: @@ -744,93 +1191,154 @@ class InterfaceInfoBodyCodeGenerator: arg_pointers = [] for a in args: - self.define_annotations('%s__%s_arg_annotations' % (array_name_lower, a.name), a.annotations) - - self.outfile.write('const GDBusArgInfo %s__%s_arg =\n' % (array_name_lower, a.name)) - self.outfile.write('{\n') - self.outfile.write(' -1, /* ref count */\n') + self.define_annotations( + "%s__%s_arg_annotations" % (array_name_lower, a.name), a.annotations + ) + + self.outfile.write( + "const GDBusArgInfo %s__%s_arg =\n" % (array_name_lower, a.name) + ) + self.outfile.write("{\n") + self.outfile.write(" -1, /* ref count */\n") self.outfile.write(' (gchar *) "%s",\n' % a.name) self.outfile.write(' (gchar *) "%s",\n' % a.signature) if len(a.annotations) > 0: - self.outfile.write(' (GDBusAnnotationInfo **) %s__%s_arg_annotations,\n' % (array_name_lower, a.name)) + self.outfile.write( + " (GDBusAnnotationInfo **) %s__%s_arg_annotations,\n" + % (array_name_lower, a.name) + ) else: - self.outfile.write(' NULL, /* no annotations */\n') - self.outfile.write('};\n') - self.outfile.write('\n') + self.outfile.write(" NULL, /* no annotations */\n") + self.outfile.write("};\n") + self.outfile.write("\n") - key = (a.since, '%s__%s_arg' % (array_name_lower, a.name)) + key = (a.since, "%s__%s_arg" % (array_name_lower, a.name)) arg_pointers.append(key) - self.generate_array(array_name_lower, 'GDBusArgInfo', arg_pointers) + self.generate_array(array_name_lower, "GDBusArgInfo", arg_pointers) def define_infos(self): for i in self.ifaces: - self.outfile.write('/* ------------------------------------------------------------------------ */\n') - self.outfile.write('/* Definitions for %s */\n' % i.name) - self.outfile.write('\n') + self.outfile.write( + "/* ------------------------------------------------------------------------ */\n" + ) + self.outfile.write("/* Definitions for %s */\n" % i.name) + self.outfile.write("\n") # GDBusMethodInfos. if len(i.methods) > 0: method_pointers = [] for m in i.methods: - self.define_args('%s_interface__%s_method_in_args' % (i.name_lower, m.name_lower), m.in_args) - self.define_args('%s_interface__%s_method_out_args' % (i.name_lower, m.name_lower), m.out_args) - self.define_annotations('%s_interface__%s_method_annotations' % (i.name_lower, m.name_lower), m.annotations) - - self.outfile.write('const GDBusMethodInfo %s_interface__%s_method =\n' % (i.name_lower, m.name_lower)) - self.outfile.write('{\n') - self.outfile.write(' -1, /* ref count */\n') + self.define_args( + "%s_interface__%s_method_in_args" + % (i.name_lower, m.name_lower), + m.in_args, + ) + self.define_args( + "%s_interface__%s_method_out_args" + % (i.name_lower, m.name_lower), + m.out_args, + ) + self.define_annotations( + "%s_interface__%s_method_annotations" + % (i.name_lower, m.name_lower), + m.annotations, + ) + + self.outfile.write( + "const GDBusMethodInfo %s_interface__%s_method =\n" + % (i.name_lower, m.name_lower) + ) + self.outfile.write("{\n") + self.outfile.write(" -1, /* ref count */\n") self.outfile.write(' (gchar *) "%s",\n' % m.name) if len(m.in_args) > 0: - self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_method_in_args,\n' % (i.name_lower, m.name_lower)) + self.outfile.write( + " (GDBusArgInfo **) %s_interface__%s_method_in_args,\n" + % (i.name_lower, m.name_lower) + ) else: - self.outfile.write(' NULL, /* no in args */\n') + self.outfile.write(" NULL, /* no in args */\n") if len(m.out_args) > 0: - self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_method_out_args,\n' % (i.name_lower, m.name_lower)) + self.outfile.write( + " (GDBusArgInfo **) %s_interface__%s_method_out_args,\n" + % (i.name_lower, m.name_lower) + ) else: - self.outfile.write(' NULL, /* no out args */\n') + self.outfile.write(" NULL, /* no out args */\n") if len(m.annotations) > 0: - self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_method_annotations,\n' % (i.name_lower, m.name_lower)) + self.outfile.write( + " (GDBusAnnotationInfo **) %s_interface__%s_method_annotations,\n" + % (i.name_lower, m.name_lower) + ) else: - self.outfile.write(' NULL, /* no annotations */\n') - self.outfile.write('};\n') - self.outfile.write('\n') - - key = (m.since, '%s_interface__%s_method' % (i.name_lower, m.name_lower)) + self.outfile.write(" NULL, /* no annotations */\n") + self.outfile.write("};\n") + self.outfile.write("\n") + + key = ( + m.since, + "%s_interface__%s_method" % (i.name_lower, m.name_lower), + ) method_pointers.append(key) - self.generate_array('%s_interface_methods' % i.name_lower, - 'GDBusMethodInfo', method_pointers) + self.generate_array( + "%s_interface_methods" % i.name_lower, + "GDBusMethodInfo", + method_pointers, + ) # GDBusSignalInfos. if len(i.signals) > 0: signal_pointers = [] for s in i.signals: - self.define_args('%s_interface__%s_signal_args' % (i.name_lower, s.name_lower), s.args) - self.define_annotations('%s_interface__%s_signal_annotations' % (i.name_lower, s.name_lower), s.annotations) - - self.outfile.write('const GDBusSignalInfo %s_interface__%s_signal =\n' % (i.name_lower, s.name_lower)) - self.outfile.write('{\n') - self.outfile.write(' -1, /* ref count */\n') + self.define_args( + "%s_interface__%s_signal_args" % (i.name_lower, s.name_lower), + s.args, + ) + self.define_annotations( + "%s_interface__%s_signal_annotations" + % (i.name_lower, s.name_lower), + s.annotations, + ) + + self.outfile.write( + "const GDBusSignalInfo %s_interface__%s_signal =\n" + % (i.name_lower, s.name_lower) + ) + self.outfile.write("{\n") + self.outfile.write(" -1, /* ref count */\n") self.outfile.write(' (gchar *) "%s",\n' % s.name) if len(s.args) > 0: - self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_signal_args,\n' % (i.name_lower, s.name_lower)) + self.outfile.write( + " (GDBusArgInfo **) %s_interface__%s_signal_args,\n" + % (i.name_lower, s.name_lower) + ) else: - self.outfile.write(' NULL, /* no args */\n') + self.outfile.write(" NULL, /* no args */\n") if len(s.annotations) > 0: - self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_signal_annotations,\n' % (i.name_lower, s.name_lower)) + self.outfile.write( + " (GDBusAnnotationInfo **) %s_interface__%s_signal_annotations,\n" + % (i.name_lower, s.name_lower) + ) else: - self.outfile.write(' NULL, /* no annotations */\n') - self.outfile.write('};\n') - self.outfile.write('\n') - - key = (s.since, '%s_interface__%s_signal' % (i.name_lower, s.name_lower)) + self.outfile.write(" NULL, /* no annotations */\n") + self.outfile.write("};\n") + self.outfile.write("\n") + + key = ( + s.since, + "%s_interface__%s_signal" % (i.name_lower, s.name_lower), + ) signal_pointers.append(key) - self.generate_array('%s_interface_signals' % i.name_lower, - 'GDBusSignalInfo', signal_pointers) + self.generate_array( + "%s_interface_signals" % i.name_lower, + "GDBusSignalInfo", + signal_pointers, + ) # GDBusPropertyInfos. if len(i.properties) > 0: @@ -838,61 +1346,89 @@ class InterfaceInfoBodyCodeGenerator: for p in i.properties: if p.readable and p.writable: - flags = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' + flags = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE" elif p.readable: - flags = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE' + flags = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE" elif p.writable: - flags = 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' + flags = "G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE" else: - flags = 'G_DBUS_PROPERTY_INFO_FLAGS_NONE' - - self.define_annotations('%s_interface__%s_property_annotations' % (i.name_lower, p.name_lower), p.annotations) - - self.outfile.write('const GDBusPropertyInfo %s_interface__%s_property =\n' % (i.name_lower, p.name_lower)) - self.outfile.write('{\n') - self.outfile.write(' -1, /* ref count */\n') + flags = "G_DBUS_PROPERTY_INFO_FLAGS_NONE" + + self.define_annotations( + "%s_interface__%s_property_annotations" + % (i.name_lower, p.name_lower), + p.annotations, + ) + + self.outfile.write( + "const GDBusPropertyInfo %s_interface__%s_property =\n" + % (i.name_lower, p.name_lower) + ) + self.outfile.write("{\n") + self.outfile.write(" -1, /* ref count */\n") self.outfile.write(' (gchar *) "%s",\n' % p.name) self.outfile.write(' (gchar *) "%s",\n' % p.signature) - self.outfile.write(' %s,\n' % flags) + self.outfile.write(" %s,\n" % flags) if len(p.annotations) > 0: - self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_property_annotations,\n' % (i.name_lower, p.name_lower)) + self.outfile.write( + " (GDBusAnnotationInfo **) %s_interface__%s_property_annotations,\n" + % (i.name_lower, p.name_lower) + ) else: - self.outfile.write(' NULL, /* no annotations */\n') - self.outfile.write('};\n') - self.outfile.write('\n') - - key = (p.since, '%s_interface__%s_property' % (i.name_lower, p.name_lower)) + self.outfile.write(" NULL, /* no annotations */\n") + self.outfile.write("};\n") + self.outfile.write("\n") + + key = ( + p.since, + "%s_interface__%s_property" % (i.name_lower, p.name_lower), + ) property_pointers.append(key) - self.generate_array('%s_interface_properties' % i.name_lower, - 'GDBusPropertyInfo', property_pointers) + self.generate_array( + "%s_interface_properties" % i.name_lower, + "GDBusPropertyInfo", + property_pointers, + ) # Finally the GDBusInterfaceInfo. - self.define_annotations('%s_interface_annotations' % i.name_lower, - i.annotations) - - self.outfile.write('const GDBusInterfaceInfo %s_interface =\n' % i.name_lower) - self.outfile.write('{\n') - self.outfile.write(' -1, /* ref count */\n') + self.define_annotations( + "%s_interface_annotations" % i.name_lower, i.annotations + ) + + self.outfile.write( + "const GDBusInterfaceInfo %s_interface =\n" % i.name_lower + ) + self.outfile.write("{\n") + self.outfile.write(" -1, /* ref count */\n") self.outfile.write(' (gchar *) "%s",\n' % i.name) if len(i.methods) > 0: - self.outfile.write(' (GDBusMethodInfo **) %s_interface_methods,\n' % i.name_lower) + self.outfile.write( + " (GDBusMethodInfo **) %s_interface_methods,\n" % i.name_lower + ) else: - self.outfile.write(' NULL, /* no methods */\n') + self.outfile.write(" NULL, /* no methods */\n") if len(i.signals) > 0: - self.outfile.write(' (GDBusSignalInfo **) %s_interface_signals,\n' % i.name_lower) + self.outfile.write( + " (GDBusSignalInfo **) %s_interface_signals,\n" % i.name_lower + ) else: - self.outfile.write(' NULL, /* no signals */\n') + self.outfile.write(" NULL, /* no signals */\n") if len(i.properties) > 0: - self.outfile.write(' (GDBusPropertyInfo **) %s_interface_properties,\n' % i.name_lower) + self.outfile.write( + " (GDBusPropertyInfo **) %s_interface_properties,\n" % i.name_lower + ) else: - self.outfile.write( 'NULL, /* no properties */\n') + self.outfile.write("NULL, /* no properties */\n") if len(i.annotations) > 0: - self.outfile.write(' (GDBusAnnotationInfo **) %s_interface_annotations,\n' % i.name_lower) + self.outfile.write( + " (GDBusAnnotationInfo **) %s_interface_annotations,\n" + % i.name_lower + ) else: - self.outfile.write(' NULL, /* no annotations */\n') - self.outfile.write('};\n') - self.outfile.write('\n') + self.outfile.write(" NULL, /* no annotations */\n") + self.outfile.write("};\n") + self.outfile.write("\n") # ---------------------------------------------------------------------------------------------------- @@ -900,182 +1436,217 @@ class InterfaceInfoBodyCodeGenerator: self.generate_body_preamble() self.define_infos() + # ---------------------------------------------------------------------------------------------------- + class CodeGenerator: - def __init__(self, ifaces, namespace, generate_objmanager, header_name, - input_files_basenames, docbook_gen, outfile): + def __init__( + self, + ifaces, + namespace, + generate_objmanager, + header_name, + input_files_basenames, + docbook_gen, + glib_min_required, + symbol_decoration_define, + outfile, + ): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.generate_objmanager = generate_objmanager self.header_name = header_name self.input_files_basenames = input_files_basenames self.docbook_gen = docbook_gen + self.glib_min_required = glib_min_required + self.symbol_decoration_define = symbol_decoration_define self.outfile = outfile # ---------------------------------------------------------------------------------------------------- def generate_body_preamble(self): - basenames = ', '.join(self.input_files_basenames) + basenames = ", ".join(self.input_files_basenames) self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) - self.outfile.write('\n') - self.outfile.write('#ifdef HAVE_CONFIG_H\n' - '# include "config.h"\n' - '#endif\n' - '\n' - '#include "%s"\n' - '\n' - '#include \n' - %(self.header_name)) - - self.outfile.write('#ifdef G_OS_UNIX\n' - '# include \n' - '#endif\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusArgInfo parent_struct;\n' - ' gboolean use_gvariant;\n' - '} _ExtendedGDBusArgInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusMethodInfo parent_struct;\n' - ' const gchar *signal_name;\n' - ' gboolean pass_fdlist;\n' - '} _ExtendedGDBusMethodInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusSignalInfo parent_struct;\n' - ' const gchar *signal_name;\n' - '} _ExtendedGDBusSignalInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusPropertyInfo parent_struct;\n' - ' const gchar *hyphen_name;\n' - ' guint use_gvariant : 1;\n' - ' guint emits_changed_signal : 1;\n' - '} _ExtendedGDBusPropertyInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' GDBusInterfaceInfo parent_struct;\n' - ' const gchar *hyphen_name;\n' - '} _ExtendedGDBusInterfaceInfo;\n' - '\n') - - self.outfile.write('typedef struct\n' - '{\n' - ' const _ExtendedGDBusPropertyInfo *info;\n' - ' guint prop_id;\n' - ' GValue orig_value; /* the value before the change */\n' - '} ChangedProperty;\n' - '\n' - 'static void\n' - '_changed_property_free (ChangedProperty *data)\n' - '{\n' - ' g_value_unset (&data->orig_value);\n' - ' g_free (data);\n' - '}\n' - '\n') - - self.outfile.write('static gboolean\n' - '_g_strv_equal0 (gchar **a, gchar **b)\n' - '{\n' - ' gboolean ret = FALSE;\n' - ' guint n;\n' - ' if (a == NULL && b == NULL)\n' - ' {\n' - ' ret = TRUE;\n' - ' goto out;\n' - ' }\n' - ' if (a == NULL || b == NULL)\n' - ' goto out;\n' - ' if (g_strv_length (a) != g_strv_length (b))\n' - ' goto out;\n' - ' for (n = 0; a[n] != NULL; n++)\n' - ' if (g_strcmp0 (a[n], b[n]) != 0)\n' - ' goto out;\n' - ' ret = TRUE;\n' - 'out:\n' - ' return ret;\n' - '}\n' - '\n') - - self.outfile.write('static gboolean\n' - '_g_variant_equal0 (GVariant *a, GVariant *b)\n' - '{\n' - ' gboolean ret = FALSE;\n' - ' if (a == NULL && b == NULL)\n' - ' {\n' - ' ret = TRUE;\n' - ' goto out;\n' - ' }\n' - ' if (a == NULL || b == NULL)\n' - ' goto out;\n' - ' ret = g_variant_equal (a, b);\n' - 'out:\n' - ' return ret;\n' - '}\n' - '\n') + if self.symbol_decoration_define is not None: + self.outfile.write("\n") + self.outfile.write("#define %s\n" % self.symbol_decoration_define) + self.outfile.write("\n") + self.outfile.write( + "#ifdef HAVE_CONFIG_H\n" + '# include "config.h"\n' + "#endif\n" + "\n" + '#include "%s"\n' + "\n" + "#include \n" % (self.header_name) + ) + + self.outfile.write( + "#ifdef G_OS_UNIX\n" "# include \n" "#endif\n" "\n" + ) + + self.outfile.write( + "typedef struct\n" + "{\n" + " GDBusArgInfo parent_struct;\n" + " gboolean use_gvariant;\n" + "} _ExtendedGDBusArgInfo;\n" + "\n" + ) + + self.outfile.write( + "typedef struct\n" + "{\n" + " GDBusMethodInfo parent_struct;\n" + " const gchar *signal_name;\n" + " gboolean pass_fdlist;\n" + "} _ExtendedGDBusMethodInfo;\n" + "\n" + ) + + self.outfile.write( + "typedef struct\n" + "{\n" + " GDBusSignalInfo parent_struct;\n" + " const gchar *signal_name;\n" + "} _ExtendedGDBusSignalInfo;\n" + "\n" + ) + + self.outfile.write( + "typedef struct\n" + "{\n" + " GDBusPropertyInfo parent_struct;\n" + " const gchar *hyphen_name;\n" + " guint use_gvariant : 1;\n" + " guint emits_changed_signal : 1;\n" + "} _ExtendedGDBusPropertyInfo;\n" + "\n" + ) + + self.outfile.write( + "typedef struct\n" + "{\n" + " GDBusInterfaceInfo parent_struct;\n" + " const gchar *hyphen_name;\n" + "} _ExtendedGDBusInterfaceInfo;\n" + "\n" + ) + + self.outfile.write( + "typedef struct\n" + "{\n" + " const _ExtendedGDBusPropertyInfo *info;\n" + " guint prop_id;\n" + " GValue orig_value; /* the value before the change */\n" + "} ChangedProperty;\n" + "\n" + "static void\n" + "_changed_property_free (ChangedProperty *data)\n" + "{\n" + " g_value_unset (&data->orig_value);\n" + " g_free (data);\n" + "}\n" + "\n" + ) + + self.outfile.write( + "static gboolean\n" + "_g_strv_equal0 (gchar **a, gchar **b)\n" + "{\n" + " gboolean ret = FALSE;\n" + " guint n;\n" + " if (a == NULL && b == NULL)\n" + " {\n" + " ret = TRUE;\n" + " goto out;\n" + " }\n" + " if (a == NULL || b == NULL)\n" + " goto out;\n" + " if (g_strv_length (a) != g_strv_length (b))\n" + " goto out;\n" + " for (n = 0; a[n] != NULL; n++)\n" + " if (g_strcmp0 (a[n], b[n]) != 0)\n" + " goto out;\n" + " ret = TRUE;\n" + "out:\n" + " return ret;\n" + "}\n" + "\n" + ) + + self.outfile.write( + "static gboolean\n" + "_g_variant_equal0 (GVariant *a, GVariant *b)\n" + "{\n" + " gboolean ret = FALSE;\n" + " if (a == NULL && b == NULL)\n" + " {\n" + " ret = TRUE;\n" + " goto out;\n" + " }\n" + " if (a == NULL || b == NULL)\n" + " goto out;\n" + " ret = g_variant_equal (a, b);\n" + "out:\n" + " return ret;\n" + "}\n" + "\n" + ) # simplified - only supports the types we use - self.outfile.write('G_GNUC_UNUSED static gboolean\n' - '_g_value_equal (const GValue *a, const GValue *b)\n' - '{\n' - ' gboolean ret = FALSE;\n' - ' g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n' - ' switch (G_VALUE_TYPE (a))\n' - ' {\n' - ' case G_TYPE_BOOLEAN:\n' - ' ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n' - ' break;\n' - ' case G_TYPE_UCHAR:\n' - ' ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n' - ' break;\n' - ' case G_TYPE_INT:\n' - ' ret = (g_value_get_int (a) == g_value_get_int (b));\n' - ' break;\n' - ' case G_TYPE_UINT:\n' - ' ret = (g_value_get_uint (a) == g_value_get_uint (b));\n' - ' break;\n' - ' case G_TYPE_INT64:\n' - ' ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n' - ' break;\n' - ' case G_TYPE_UINT64:\n' - ' ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n' - ' break;\n' - ' case G_TYPE_DOUBLE:\n' - ' {\n' - ' /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n' - ' gdouble da = g_value_get_double (a);\n' - ' gdouble db = g_value_get_double (b);\n' - ' ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n' - ' }\n' - ' break;\n' - ' case G_TYPE_STRING:\n' - ' ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n' - ' break;\n' - ' case G_TYPE_VARIANT:\n' - ' ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n' - ' break;\n' - ' default:\n' - ' if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n' - ' ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n' - ' else\n' - ' g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));\n' - ' break;\n' - ' }\n' - ' return ret;\n' - '}\n' - '\n') + self.outfile.write( + "G_GNUC_UNUSED static gboolean\n" + "_g_value_equal (const GValue *a, const GValue *b)\n" + "{\n" + " gboolean ret = FALSE;\n" + " g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n" + " switch (G_VALUE_TYPE (a))\n" + " {\n" + " case G_TYPE_BOOLEAN:\n" + " ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n" + " break;\n" + " case G_TYPE_UCHAR:\n" + " ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n" + " break;\n" + " case G_TYPE_INT:\n" + " ret = (g_value_get_int (a) == g_value_get_int (b));\n" + " break;\n" + " case G_TYPE_UINT:\n" + " ret = (g_value_get_uint (a) == g_value_get_uint (b));\n" + " break;\n" + " case G_TYPE_INT64:\n" + " ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n" + " break;\n" + " case G_TYPE_UINT64:\n" + " ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n" + " break;\n" + " case G_TYPE_DOUBLE:\n" + " {\n" + " /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n" + " gdouble da = g_value_get_double (a);\n" + " gdouble db = g_value_get_double (b);\n" + " ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n" + " }\n" + " break;\n" + " case G_TYPE_STRING:\n" + " ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n" + " break;\n" + " case G_TYPE_VARIANT:\n" + " ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n" + " break;\n" + " default:\n" + " if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n" + " ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n" + " else\n" + ' g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));\n' + " break;\n" + " }\n" + " return ret;\n" + "}\n" + "\n" + ) def generate_annotations(self, prefix, annotations): if annotations is None: @@ -1083,463 +1654,668 @@ class CodeGenerator: n = 0 for a in annotations: - #self.generate_annotations('%s_%d'%(prefix, n), a.get_annotations()) + # self.generate_annotations('%s_%d'%(prefix, n), a.get_annotations()) # skip internal annotations - if a.key.startswith('org.gtk.GDBus'): + if a.key.startswith("org.gtk.GDBus"): continue - self.outfile.write('static const GDBusAnnotationInfo %s_%d =\n' - '{\n' - ' -1,\n' - ' (gchar *) "%s",\n' - ' (gchar *) "%s",\n'%(prefix, n, a.key, a.value)) + self.outfile.write( + "static const GDBusAnnotationInfo %s_%d =\n" + "{\n" + " -1,\n" + ' (gchar *) "%s",\n' + ' (gchar *) "%s",\n' % (prefix, n, a.key, a.value) + ) if len(a.annotations) == 0: - self.outfile.write(' NULL\n') + self.outfile.write(" NULL\n") else: - self.outfile.write(' (GDBusAnnotationInfo **) &%s_%d_pointers\n'%(prefix, n)) - self.outfile.write('};\n' - '\n') + self.outfile.write( + " (GDBusAnnotationInfo **) &%s_%d_pointers\n" % (prefix, n) + ) + self.outfile.write("};\n" "\n") n += 1 if n > 0: - self.outfile.write('static const GDBusAnnotationInfo * const %s_pointers[] =\n' - '{\n'%(prefix)) - m = 0; + self.outfile.write( + "static const GDBusAnnotationInfo * const %s_pointers[] =\n" + "{\n" % (prefix) + ) + m = 0 for a in annotations: - if a.key.startswith('org.gtk.GDBus'): + if a.key.startswith("org.gtk.GDBus"): continue - self.outfile.write(' &%s_%d,\n'%(prefix, m)) + self.outfile.write(" &%s_%d,\n" % (prefix, m)) m += 1 - self.outfile.write(' NULL\n' - '};\n' - '\n') + self.outfile.write(" NULL\n" "};\n" "\n") return n def generate_args(self, prefix, args): for a in args: - num_anno = self.generate_annotations('%s_arg_%s_annotation_info'%(prefix, a.name), a.annotations) - - self.outfile.write('static const _ExtendedGDBusArgInfo %s_%s =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n' - ' (gchar *) "%s",\n'%(prefix, a.name, a.name, a.signature)) + num_anno = self.generate_annotations( + "%s_arg_%s_annotation_info" % (prefix, a.name), a.annotations + ) + + self.outfile.write( + "static const _ExtendedGDBusArgInfo %s_%s =\n" + "{\n" + " {\n" + " -1,\n" + ' (gchar *) "%s",\n' + ' (gchar *) "%s",\n' % (prefix, a.name, a.name, a.signature) + ) if num_anno == 0: - self.outfile.write(' NULL\n') + self.outfile.write(" NULL\n") else: - self.outfile.write(' (GDBusAnnotationInfo **) &%s_arg_%s_annotation_info_pointers\n'%(prefix, a.name)) - self.outfile.write(' },\n') - if not utils.lookup_annotation(a.annotations, 'org.gtk.GDBus.C.ForceGVariant'): - self.outfile.write(' FALSE\n') + self.outfile.write( + " (GDBusAnnotationInfo **) &%s_arg_%s_annotation_info_pointers\n" + % (prefix, a.name) + ) + self.outfile.write(" },\n") + if not utils.lookup_annotation( + a.annotations, "org.gtk.GDBus.C.ForceGVariant" + ): + self.outfile.write(" FALSE\n") else: - self.outfile.write(' TRUE\n') - self.outfile.write('};\n' - '\n') + self.outfile.write(" TRUE\n") + self.outfile.write("};\n" "\n") if len(args) > 0: - self.outfile.write('static const GDBusArgInfo * const %s_pointers[] =\n' - '{\n'%(prefix)) + self.outfile.write( + "static const GDBusArgInfo * const %s_pointers[] =\n" "{\n" % (prefix) + ) for a in args: - self.outfile.write(' &%s_%s.parent_struct,\n'%(prefix, a.name)) - self.outfile.write(' NULL\n' - '};\n' - '\n') + self.outfile.write(" &%s_%s.parent_struct,\n" % (prefix, a.name)) + self.outfile.write(" NULL\n" "};\n" "\n") def generate_introspection_for_interface(self, i): - self.outfile.write('/* ---- Introspection data for %s ---- */\n' - '\n'%(i.name)) + self.outfile.write( + "/* ---- Introspection data for %s ---- */\n" "\n" % (i.name) + ) - if len(i.methods) > 0: - for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True - self.generate_args('_%s_method_info_%s_IN_ARG'%(i.name_lower, m.name_lower), m.in_args) - self.generate_args('_%s_method_info_%s_OUT_ARG'%(i.name_lower, m.name_lower), m.out_args) - - num_anno = self.generate_annotations('_%s_method_%s_annotation_info'%(i.name_lower, m.name_lower), m.annotations) - - self.outfile.write('static const _ExtendedGDBusMethodInfo _%s_method_info_%s =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n'%(i.name_lower, m.name_lower, m.name)) - if len(m.in_args) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusArgInfo **) &_%s_method_info_%s_IN_ARG_pointers,\n'%(i.name_lower, m.name_lower)) - if len(m.out_args) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusArgInfo **) &_%s_method_info_%s_OUT_ARG_pointers,\n'%(i.name_lower, m.name_lower)) - if num_anno == 0: - self.outfile.write(' NULL\n') - else: - self.outfile.write(' (GDBusAnnotationInfo **) &_%s_method_%s_annotation_info_pointers\n'%(i.name_lower, m.name_lower)) - self.outfile.write(' },\n' - ' "handle-%s",\n' - ' %s\n' - %(m.name_hyphen, 'TRUE' if unix_fd else 'FALSE')) - self.outfile.write('};\n' - '\n') - - self.outfile.write('static const GDBusMethodInfo * const _%s_method_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for m in i.methods: - self.outfile.write(' &_%s_method_info_%s.parent_struct,\n'%(i.name_lower, m.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') + if len(i.methods) > 0: + for m in i.methods: + self.generate_args( + "_%s_method_info_%s_IN_ARG" % (i.name_lower, m.name_lower), + m.in_args, + ) + self.generate_args( + "_%s_method_info_%s_OUT_ARG" % (i.name_lower, m.name_lower), + m.out_args, + ) + + num_anno = self.generate_annotations( + "_%s_method_%s_annotation_info" % (i.name_lower, m.name_lower), + m.annotations, + ) + + self.outfile.write( + "static const _ExtendedGDBusMethodInfo _%s_method_info_%s =\n" + "{\n" + " {\n" + " -1,\n" + ' (gchar *) "%s",\n' % (i.name_lower, m.name_lower, m.name) + ) + if len(m.in_args) == 0: + self.outfile.write(" NULL,\n") + else: + self.outfile.write( + " (GDBusArgInfo **) &_%s_method_info_%s_IN_ARG_pointers,\n" + % (i.name_lower, m.name_lower) + ) + if len(m.out_args) == 0: + self.outfile.write(" NULL,\n") + else: + self.outfile.write( + " (GDBusArgInfo **) &_%s_method_info_%s_OUT_ARG_pointers,\n" + % (i.name_lower, m.name_lower) + ) + if num_anno == 0: + self.outfile.write(" NULL\n") + else: + self.outfile.write( + " (GDBusAnnotationInfo **) &_%s_method_%s_annotation_info_pointers\n" + % (i.name_lower, m.name_lower) + ) + self.outfile.write( + " },\n" + ' "handle-%s",\n' + " %s\n" % (m.name_hyphen, "TRUE" if m.unix_fd else "FALSE") + ) + self.outfile.write("};\n" "\n") + + self.outfile.write( + "static const GDBusMethodInfo * const _%s_method_info_pointers[] =\n" + "{\n" % (i.name_lower) + ) + for m in i.methods: + self.outfile.write( + " &_%s_method_info_%s.parent_struct,\n" + % (i.name_lower, m.name_lower) + ) + self.outfile.write(" NULL\n" "};\n" "\n") - # --- + # --- - if len(i.signals) > 0: - for s in i.signals: - self.generate_args('_%s_signal_info_%s_ARG'%(i.name_lower, s.name_lower), s.args) - - num_anno = self.generate_annotations('_%s_signal_%s_annotation_info'%(i.name_lower, s.name_lower), s.annotations) - self.outfile.write('static const _ExtendedGDBusSignalInfo _%s_signal_info_%s =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n'%(i.name_lower, s.name_lower, s.name)) - if len(s.args) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusArgInfo **) &_%s_signal_info_%s_ARG_pointers,\n'%(i.name_lower, s.name_lower)) - if num_anno == 0: - self.outfile.write(' NULL\n') - else: - self.outfile.write(' (GDBusAnnotationInfo **) &_%s_signal_%s_annotation_info_pointers\n'%(i.name_lower, s.name_lower)) - self.outfile.write(' },\n' - ' "%s"\n' - %(s.name_hyphen)) - self.outfile.write('};\n' - '\n') - - self.outfile.write('static const GDBusSignalInfo * const _%s_signal_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for s in i.signals: - self.outfile.write(' &_%s_signal_info_%s.parent_struct,\n'%(i.name_lower, s.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') + if len(i.signals) > 0: + for s in i.signals: + self.generate_args( + "_%s_signal_info_%s_ARG" % (i.name_lower, s.name_lower), s.args + ) + + num_anno = self.generate_annotations( + "_%s_signal_%s_annotation_info" % (i.name_lower, s.name_lower), + s.annotations, + ) + self.outfile.write( + "static const _ExtendedGDBusSignalInfo _%s_signal_info_%s =\n" + "{\n" + " {\n" + " -1,\n" + ' (gchar *) "%s",\n' % (i.name_lower, s.name_lower, s.name) + ) + if len(s.args) == 0: + self.outfile.write(" NULL,\n") + else: + self.outfile.write( + " (GDBusArgInfo **) &_%s_signal_info_%s_ARG_pointers,\n" + % (i.name_lower, s.name_lower) + ) + if num_anno == 0: + self.outfile.write(" NULL\n") + else: + self.outfile.write( + " (GDBusAnnotationInfo **) &_%s_signal_%s_annotation_info_pointers\n" + % (i.name_lower, s.name_lower) + ) + self.outfile.write(" },\n" ' "%s"\n' % (s.name_hyphen)) + self.outfile.write("};\n" "\n") + + self.outfile.write( + "static const GDBusSignalInfo * const _%s_signal_info_pointers[] =\n" + "{\n" % (i.name_lower) + ) + for s in i.signals: + self.outfile.write( + " &_%s_signal_info_%s.parent_struct,\n" + % (i.name_lower, s.name_lower) + ) + self.outfile.write(" NULL\n" "};\n" "\n") - # --- + # --- - if len(i.properties) > 0: - for p in i.properties: - if p.readable and p.writable: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' - elif p.readable: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE' - elif p.writable: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' - else: - access = 'G_DBUS_PROPERTY_INFO_FLAGS_NONE' - num_anno = self.generate_annotations('_%s_property_%s_annotation_info'%(i.name_lower, p.name_lower), p.annotations) - self.outfile.write('static const _ExtendedGDBusPropertyInfo _%s_property_info_%s =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n' - ' (gchar *) "%s",\n' - ' %s,\n'%(i.name_lower, p.name_lower, p.name, p.arg.signature, access)) - if num_anno == 0: - self.outfile.write(' NULL\n') - else: - self.outfile.write(' (GDBusAnnotationInfo **) &_%s_property_%s_annotation_info_pointers\n'%(i.name_lower, p.name_lower)) - self.outfile.write(' },\n' - ' "%s",\n' - %(p.name_hyphen)) - if not utils.lookup_annotation(p.annotations, 'org.gtk.GDBus.C.ForceGVariant'): - self.outfile.write(' FALSE,\n') - else: - self.outfile.write(' TRUE,\n') - if p.emits_changed_signal: - self.outfile.write(' TRUE\n') - else: - self.outfile.write(' FALSE\n') - self.outfile.write('};\n' - '\n') + if len(i.properties) > 0: + for p in i.properties: + if p.readable and p.writable: + access = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE" + elif p.readable: + access = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE" + elif p.writable: + access = "G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE" + else: + access = "G_DBUS_PROPERTY_INFO_FLAGS_NONE" + num_anno = self.generate_annotations( + "_%s_property_%s_annotation_info" % (i.name_lower, p.name_lower), + p.annotations, + ) + self.outfile.write( + "static const _ExtendedGDBusPropertyInfo _%s_property_info_%s =\n" + "{\n" + " {\n" + " -1,\n" + ' (gchar *) "%s",\n' + ' (gchar *) "%s",\n' + " %s,\n" + % (i.name_lower, p.name_lower, p.name, p.arg.signature, access) + ) + if num_anno == 0: + self.outfile.write(" NULL\n") + else: + self.outfile.write( + " (GDBusAnnotationInfo **) &_%s_property_%s_annotation_info_pointers\n" + % (i.name_lower, p.name_lower) + ) + self.outfile.write(" },\n" ' "%s",\n' % (p.name_hyphen)) + if not utils.lookup_annotation( + p.annotations, "org.gtk.GDBus.C.ForceGVariant" + ): + self.outfile.write(" FALSE,\n") + else: + self.outfile.write(" TRUE,\n") + if p.emits_changed_signal: + self.outfile.write(" TRUE\n") + else: + self.outfile.write(" FALSE\n") + self.outfile.write("};\n" "\n") - self.outfile.write('static const GDBusPropertyInfo * const _%s_property_info_pointers[] =\n' - '{\n'%(i.name_lower)) - for p in i.properties: - self.outfile.write(' &_%s_property_info_%s.parent_struct,\n'%(i.name_lower, p.name_lower)) - self.outfile.write(' NULL\n' - '};\n' - '\n') - - num_anno = self.generate_annotations('_%s_annotation_info'%(i.name_lower), i.annotations) - self.outfile.write('static const _ExtendedGDBusInterfaceInfo _%s_interface_info =\n' - '{\n' - ' {\n' - ' -1,\n' - ' (gchar *) "%s",\n'%(i.name_lower, i.name)) - if len(i.methods) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusMethodInfo **) &_%s_method_info_pointers,\n'%(i.name_lower)) - if len(i.signals) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusSignalInfo **) &_%s_signal_info_pointers,\n'%(i.name_lower)) - if len(i.properties) == 0: - self.outfile.write(' NULL,\n') - else: - self.outfile.write(' (GDBusPropertyInfo **) &_%s_property_info_pointers,\n'%(i.name_lower)) - if num_anno == 0: - self.outfile.write(' NULL\n') - else: - self.outfile.write(' (GDBusAnnotationInfo **) &_%s_annotation_info_pointers\n'%(i.name_lower)) - self.outfile.write(' },\n' - ' "%s",\n' - '};\n' - '\n' - %(i.name_hyphen)) - self.outfile.write('\n') - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_interface_info:\n' - ' *\n' - ' * Gets a machine-readable description of the #%s D-Bus interface.\n' - ' *\n' - ' * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.\n' - %(i.name_lower, i.name), False)) - self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('GDBusInterfaceInfo *\n' - '%s_interface_info (void)\n' - '{\n' - ' return (GDBusInterfaceInfo *) &_%s_interface_info.parent_struct;\n' - '}\n' - '\n'%(i.name_lower, i.name_lower)) - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_override_properties:\n' - ' * @klass: The class structure for a #GObject derived class.\n' - ' * @property_id_begin: The property id to assign to the first overridden property.\n' - ' *\n' - ' * Overrides all #GObject properties in the #%s interface for a concrete class.\n' - ' * The properties are overridden in the order they are defined.\n' - ' *\n' - ' * Returns: The last property id.\n' - %(i.name_lower, i.camel_name), False)) - self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('guint\n' - '%s_override_properties (GObjectClass *klass, guint property_id_begin)\n' - '{\n'%(i.name_lower)) + self.outfile.write( + "static const GDBusPropertyInfo * const _%s_property_info_pointers[] =\n" + "{\n" % (i.name_lower) + ) for p in i.properties: - self.outfile.write(' g_object_class_override_property (klass, property_id_begin++, "%s");\n'%(p.name_hyphen)) - self.outfile.write(' return property_id_begin - 1;\n' - '}\n' - '\n') - self.outfile.write('\n') + self.outfile.write( + " &_%s_property_info_%s.parent_struct,\n" + % (i.name_lower, p.name_lower) + ) + self.outfile.write(" NULL\n" "};\n" "\n") + + num_anno = self.generate_annotations( + "_%s_annotation_info" % (i.name_lower), i.annotations + ) + self.outfile.write( + "static const _ExtendedGDBusInterfaceInfo _%s_interface_info =\n" + "{\n" + " {\n" + " -1,\n" + ' (gchar *) "%s",\n' % (i.name_lower, i.name) + ) + if len(i.methods) == 0: + self.outfile.write(" NULL,\n") + else: + self.outfile.write( + " (GDBusMethodInfo **) &_%s_method_info_pointers,\n" % (i.name_lower) + ) + if len(i.signals) == 0: + self.outfile.write(" NULL,\n") + else: + self.outfile.write( + " (GDBusSignalInfo **) &_%s_signal_info_pointers,\n" % (i.name_lower) + ) + if len(i.properties) == 0: + self.outfile.write(" NULL,\n") + else: + self.outfile.write( + " (GDBusPropertyInfo **) &_%s_property_info_pointers,\n" + % (i.name_lower) + ) + if num_anno == 0: + self.outfile.write(" NULL\n") + else: + self.outfile.write( + " (GDBusAnnotationInfo **) &_%s_annotation_info_pointers\n" + % (i.name_lower) + ) + self.outfile.write(" },\n" ' "%s",\n' "};\n" "\n" % (i.name_hyphen)) + self.outfile.write("\n") + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_interface_info:\n" + " *\n" + " * Gets a machine-readable description of the #%s D-Bus interface.\n" + " *\n" + " * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.\n" + % (i.name_lower, i.name), + False, + ) + ) + self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) + self.outfile.write( + "GDBusInterfaceInfo *\n" + "%s_interface_info (void)\n" + "{\n" + " return (GDBusInterfaceInfo *) &_%s_interface_info.parent_struct;\n" + "}\n" + "\n" % (i.name_lower, i.name_lower) + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_override_properties:\n" + " * @klass: The class structure for a #GObject derived class.\n" + " * @property_id_begin: The property id to assign to the first overridden property.\n" + " *\n" + " * Overrides all #GObject properties in the #%s interface for a concrete class.\n" + " * The properties are overridden in the order they are defined.\n" + " *\n" + " * Returns: The last property id.\n" % (i.name_lower, i.camel_name), + False, + ) + ) + self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) + self.outfile.write( + "guint\n" "%s_override_properties (GObjectClass *klass" % (i.name_lower) + ) + if len(i.properties) == 0: + self.outfile.write(" G_GNUC_UNUSED") + self.outfile.write(", guint property_id_begin)\n" "{\n") + for p in i.properties: + self.outfile.write( + ' g_object_class_override_property (klass, property_id_begin++, "%s");\n' + % (p.name_hyphen) + ) + self.outfile.write(" return property_id_begin - 1;\n" "}\n" "\n") + self.outfile.write("\n") # ---------------------------------------------------------------------------------------------------- def generate_interface(self, i): - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s:\n' - ' *\n' - ' * Abstract interface type for the D-Bus interface #%s.\n' - %(i.camel_name, i.name), False)) + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s:\n" + " *\n" + " * Abstract interface type for the D-Bus interface #%s.\n" + % (i.camel_name, i.name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('\n') + self.outfile.write("\n") - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sIface:\n' - ' * @parent_iface: The parent interface.\n' - %(i.camel_name), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sIface:\n" + " * @parent_iface: The parent interface.\n" % (i.camel_name), + False, + ) + ) doc_bits = {} if len(i.methods) > 0: for m in i.methods: - key = (m.since, '_method_%s'%m.name_lower) - value = '@handle_%s: '%(m.name_lower) - value += 'Handler for the #%s::handle-%s signal.'%(i.camel_name, m.name_hyphen) + key = (m.since, "_method_%s" % m.name_lower) + value = "@handle_%s: " % (m.name_lower) + value += "Handler for the #%s::handle-%s signal." % ( + i.camel_name, + m.name_hyphen, + ) doc_bits[key] = value if len(i.signals) > 0: for s in i.signals: - key = (s.since, '_signal_%s'%s.name_lower) - value = '@%s: '%(s.name_lower) - value += 'Handler for the #%s::%s signal.'%(i.camel_name, s.name_hyphen) + key = (s.since, "_signal_%s" % s.name_lower) + value = "@%s: " % (s.name_lower) + value += "Handler for the #%s::%s signal." % ( + i.camel_name, + s.name_hyphen, + ) doc_bits[key] = value if len(i.properties) > 0: for p in i.properties: - key = (p.since, '_prop_get_%s'%p.name_lower) - value = '@get_%s: '%(p.name_lower) - value += 'Getter for the #%s:%s property.'%(i.camel_name, p.name_hyphen) + key = (p.since, "_prop_get_%s" % p.name_lower) + value = "@get_%s: " % (p.name_lower) + value += "Getter for the #%s:%s property." % ( + i.camel_name, + p.name_hyphen, + ) doc_bits[key] = value for key in sorted(doc_bits.keys(), key=utils.version_cmp_key): - self.outfile.write(' * %s\n'%doc_bits[key]) - - self.outfile.write(self.docbook_gen.expand( - ' *\n' - ' * Virtual table for the D-Bus interface #%s.\n' - %(i.name), False)) + self.outfile.write(" * %s\n" % doc_bits[key]) + + self.outfile.write( + self.docbook_gen.expand( + " *\n" " * Virtual table for the D-Bus interface #%s.\n" % (i.name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('\n') - - self.outfile.write('typedef %sIface %sInterface;\n'%(i.camel_name, i.camel_name)) - self.outfile.write('G_DEFINE_INTERFACE (%s, %s, G_TYPE_OBJECT)\n'%(i.camel_name, i.name_lower)) - self.outfile.write('\n') - - self.outfile.write('static void\n' - '%s_default_init (%sIface *iface)\n' - '{\n'%(i.name_lower, i.camel_name)); - + self.outfile.write("\n") + + self.outfile.write( + "typedef %sIface %sInterface;\n" % (i.camel_name, i.camel_name) + ) + self.outfile.write( + "G_DEFINE_INTERFACE (%s, %s, G_TYPE_OBJECT)\n" + % (i.camel_name, i.name_lower) + ) + self.outfile.write("\n") + + self.outfile.write( + "static void\n" + "%s_default_init (%sIface *iface" % (i.name_lower, i.camel_name) + ) + if len(i.methods) == 0 and len(i.signals) == 0 and len(i.properties) == 0: + self.outfile.write(" G_GNUC_UNUSED)\n") + else: + self.outfile.write(")\n") + self.outfile.write("{\n") if len(i.methods) > 0: - self.outfile.write(' /* GObject signals for incoming D-Bus method calls: */\n') + self.outfile.write( + " /* GObject signals for incoming D-Bus method calls: */\n" + ) for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True - self.outfile.write(self.docbook_gen.expand( - ' /**\n' - ' * %s::handle-%s:\n' - ' * @object: A #%s.\n' - ' * @invocation: A #GDBusMethodInvocation.\n' - %(i.camel_name, m.name_hyphen, i.camel_name), False)) - if unix_fd: - self.outfile.write(' * @fd_list: (nullable): A #GUnixFDList or %NULL.\n') + self.outfile.write( + self.docbook_gen.expand( + " /**\n" + " * %s::handle-%s:\n" + " * @object: A #%s.\n" + " * @invocation: A #GDBusMethodInvocation.\n" + % (i.camel_name, m.name_hyphen, i.camel_name), + False, + ) + ) + if m.unix_fd: + self.outfile.write( + " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n" + ) for a in m.in_args: - self.outfile.write(' * @arg_%s: Argument passed by remote caller.\n'%(a.name)) - self.outfile.write(self.docbook_gen.expand( - ' *\n' - ' * Signal emitted when a remote caller is invoking the %s.%s() D-Bus method.\n' - ' *\n' - ' * If a signal handler returns %%TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call %s_complete_%s() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %%G_DBUS_ERROR_UNKNOWN_METHOD error is returned.\n' - ' *\n' - ' * Returns: %%TRUE if the invocation was handled, %%FALSE to let other signal handlers run.\n' - %(i.name, m.name, i.name_lower, m.name_lower), False)) + self.outfile.write( + " * @arg_%s: Argument passed by remote caller.\n" % (a.name) + ) + self.outfile.write( + self.docbook_gen.expand( + " *\n" + " * Signal emitted when a remote caller is invoking the %s.%s() D-Bus method.\n" + " *\n" + " * If a signal handler returns %%TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call %s_complete_%s() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %%G_DBUS_ERROR_UNKNOWN_METHOD error is returned.\n" + " *\n" + " * Returns: %%G_DBUS_METHOD_INVOCATION_HANDLED or %%TRUE if the invocation was handled, %%G_DBUS_METHOD_INVOCATION_UNHANDLED or %%FALSE to let other signal handlers run.\n" + % (i.name, m.name, i.name_lower, m.name_lower), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 2) - if unix_fd: + if m.unix_fd: extra_args = 2 else: extra_args = 1 - self.outfile.write(' g_signal_new ("handle-%s",\n' - ' G_TYPE_FROM_INTERFACE (iface),\n' - ' G_SIGNAL_RUN_LAST,\n' - ' G_STRUCT_OFFSET (%sIface, handle_%s),\n' - ' g_signal_accumulator_true_handled,\n' - ' NULL,\n' # accu_data - ' g_cclosure_marshal_generic,\n' - ' G_TYPE_BOOLEAN,\n' - ' %d,\n' - ' G_TYPE_DBUS_METHOD_INVOCATION' - %(m.name_hyphen, i.camel_name, m.name_lower, len(m.in_args) + extra_args)) - if unix_fd: - self.outfile.write(', G_TYPE_UNIX_FD_LIST') + self.outfile.write( + ' g_signal_new ("handle-%s",\n' + " G_TYPE_FROM_INTERFACE (iface),\n" + " G_SIGNAL_RUN_LAST,\n" + " G_STRUCT_OFFSET (%sIface, handle_%s),\n" + " g_signal_accumulator_true_handled,\n" + " NULL,\n" # accu_data + " g_cclosure_marshal_generic,\n" + " G_TYPE_BOOLEAN,\n" + " %d,\n" + " G_TYPE_DBUS_METHOD_INVOCATION" + % ( + m.name_hyphen, + i.camel_name, + m.name_lower, + len(m.in_args) + extra_args, + ) + ) + if m.unix_fd: + self.outfile.write(", G_TYPE_UNIX_FD_LIST") for a in m.in_args: - self.outfile.write(', %s'%(a.gtype)) - self.outfile.write(');\n') - self.outfile.write('\n') + self.outfile.write(", %s" % (a.gtype)) + self.outfile.write(");\n") + self.outfile.write("\n") if len(i.signals) > 0: - self.outfile.write(' /* GObject signals for received D-Bus signals: */\n') + self.outfile.write(" /* GObject signals for received D-Bus signals: */\n") for s in i.signals: - self.outfile.write(self.docbook_gen.expand( - ' /**\n' - ' * %s::%s:\n' - ' * @object: A #%s.\n' - %(i.camel_name, s.name_hyphen, i.camel_name), False)) + self.outfile.write( + self.docbook_gen.expand( + " /**\n" + " * %s::%s:\n" + " * @object: A #%s.\n" + % (i.camel_name, s.name_hyphen, i.camel_name), + False, + ) + ) for a in s.args: - self.outfile.write(' * @arg_%s: Argument.\n'%(a.name)) - self.outfile.write(self.docbook_gen.expand( - ' *\n' - ' * On the client-side, this signal is emitted whenever the D-Bus signal #%s::%s is received.\n' - ' *\n' - ' * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.\n' - %(i.name, s.name), False)) + self.outfile.write(" * @arg_%s: Argument.\n" % (a.name)) + self.outfile.write( + self.docbook_gen.expand( + " *\n" + " * On the client-side, this signal is emitted whenever the D-Bus signal #%s::%s is received.\n" + " *\n" + " * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.\n" + % (i.name, s.name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(s, self.outfile, 2) - self.outfile.write(' g_signal_new ("%s",\n' - ' G_TYPE_FROM_INTERFACE (iface),\n' - ' G_SIGNAL_RUN_LAST,\n' - ' G_STRUCT_OFFSET (%sIface, %s),\n' - ' NULL,\n' # accumulator - ' NULL,\n' # accu_data - ' g_cclosure_marshal_generic,\n' - ' G_TYPE_NONE,\n' - ' %d' - %(s.name_hyphen, i.camel_name, s.name_lower, len(s.args))) + self.outfile.write( + ' g_signal_new ("%s",\n' + " G_TYPE_FROM_INTERFACE (iface),\n" + " G_SIGNAL_RUN_LAST,\n" + " G_STRUCT_OFFSET (%sIface, %s),\n" + " NULL,\n" # accumulator + " NULL,\n" # accu_data + " g_cclosure_marshal_generic,\n" + " G_TYPE_NONE,\n" + " %d" % (s.name_hyphen, i.camel_name, s.name_lower, len(s.args)) + ) for a in s.args: - self.outfile.write(', %s'%(a.gtype)) - self.outfile.write(');\n') - self.outfile.write('\n') + self.outfile.write(", %s" % (a.gtype)) + self.outfile.write(");\n") + self.outfile.write("\n") if len(i.properties) > 0: - self.outfile.write(' /* GObject properties for D-Bus properties: */\n') + self.outfile.write(" /* GObject properties for D-Bus properties: */\n") for p in i.properties: if p.readable and p.writable: - hint = 'Since the D-Bus property for this #GObject property is both readable and writable, it is meaningful to both read from it and write to it on both the service- and client-side.' + hint = "Since the D-Bus property for this #GObject property is both readable and writable, it is meaningful to both read from it and write to it on both the service- and client-side." elif p.readable: - hint = 'Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side.' + hint = "Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side." elif p.writable: - hint = 'Since the D-Bus property for this #GObject property is writable but not readable, it is meaningful to write to it on both the client- and service-side. It is only meaningful, however, to read from it on the service-side.' + hint = "Since the D-Bus property for this #GObject property is writable but not readable, it is meaningful to write to it on both the client- and service-side. It is only meaningful, however, to read from it on the service-side." else: - print_error('Cannot handle property "{}" that neither readable nor writable'.format(p.name)) - self.outfile.write(self.docbook_gen.expand( - ' /**\n' - ' * %s:%s:\n' - ' *\n' - ' * Represents the D-Bus property #%s:%s.\n' - ' *\n' - ' * %s\n' - %(i.camel_name, p.name_hyphen, i.name, p.name, hint), False)) + print_error( + 'Cannot handle property "{}" that neither readable nor writable'.format( + p.name + ) + ) + self.outfile.write( + self.docbook_gen.expand( + " /**\n" + " * %s:%s:\n" + " *\n" + " * Represents the D-Bus property #%s:%s.\n" + " *\n" + " * %s\n" + % (i.camel_name, p.name_hyphen, i.name, p.name, hint), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 2) - self.outfile.write(' g_object_interface_install_property (iface,\n') - if p.arg.gtype == 'G_TYPE_VARIANT': - s = 'g_param_spec_variant ("%s", "%s", "%s", G_VARIANT_TYPE ("%s"), NULL'%(p.name_hyphen, p.name, p.name, p.arg.signature) - elif p.arg.signature == 'b': - s = 'g_param_spec_boolean ("%s", "%s", "%s", FALSE'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'y': - s = 'g_param_spec_uchar ("%s", "%s", "%s", 0, 255, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'n': - s = 'g_param_spec_int ("%s", "%s", "%s", G_MININT16, G_MAXINT16, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'q': - s = 'g_param_spec_uint ("%s", "%s", "%s", 0, G_MAXUINT16, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'i': - s = 'g_param_spec_int ("%s", "%s", "%s", G_MININT32, G_MAXINT32, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'u': - s = 'g_param_spec_uint ("%s", "%s", "%s", 0, G_MAXUINT32, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'x': - s = 'g_param_spec_int64 ("%s", "%s", "%s", G_MININT64, G_MAXINT64, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 't': - s = 'g_param_spec_uint64 ("%s", "%s", "%s", 0, G_MAXUINT64, 0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'd': - s = 'g_param_spec_double ("%s", "%s", "%s", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 's': - s = 'g_param_spec_string ("%s", "%s", "%s", NULL'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'o': - s = 'g_param_spec_string ("%s", "%s", "%s", NULL'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'g': - s = 'g_param_spec_string ("%s", "%s", "%s", NULL'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'ay': - s = 'g_param_spec_string ("%s", "%s", "%s", NULL'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'as': - s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'ao': - s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV'%(p.name_hyphen, p.name, p.name) - elif p.arg.signature == 'aay': - s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV'%(p.name_hyphen, p.name, p.name) + self.outfile.write(" g_object_interface_install_property (iface,\n") + if p.arg.gtype == "G_TYPE_VARIANT": + s = ( + 'g_param_spec_variant ("%s", "%s", "%s", G_VARIANT_TYPE ("%s"), NULL' + % (p.name_hyphen, p.name, p.name, p.arg.signature) + ) + elif p.arg.signature == "b": + s = 'g_param_spec_boolean ("%s", "%s", "%s", FALSE' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "y": + s = 'g_param_spec_uchar ("%s", "%s", "%s", 0, 255, 0' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "n": + s = ( + 'g_param_spec_int ("%s", "%s", "%s", G_MININT16, G_MAXINT16, 0' + % (p.name_hyphen, p.name, p.name) + ) + elif p.arg.signature == "q": + s = 'g_param_spec_uint ("%s", "%s", "%s", 0, G_MAXUINT16, 0' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "i": + s = ( + 'g_param_spec_int ("%s", "%s", "%s", G_MININT32, G_MAXINT32, 0' + % (p.name_hyphen, p.name, p.name) + ) + elif p.arg.signature == "u": + s = 'g_param_spec_uint ("%s", "%s", "%s", 0, G_MAXUINT32, 0' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "x": + s = ( + 'g_param_spec_int64 ("%s", "%s", "%s", G_MININT64, G_MAXINT64, 0' + % (p.name_hyphen, p.name, p.name) + ) + elif p.arg.signature == "t": + s = 'g_param_spec_uint64 ("%s", "%s", "%s", 0, G_MAXUINT64, 0' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "d": + s = ( + 'g_param_spec_double ("%s", "%s", "%s", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0' + % (p.name_hyphen, p.name, p.name) + ) + elif p.arg.signature == "s": + s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "o": + s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "g": + s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "ay": + s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "as": + s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "ao": + s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV' % ( + p.name_hyphen, + p.name, + p.name, + ) + elif p.arg.signature == "aay": + s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV' % ( + p.name_hyphen, + p.name, + p.name, + ) else: - print_error('Unsupported gtype "{}" for GParamSpec'.format(p.arg.gtype)) - flags = 'G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS' + print_error( + 'Unsupported gtype "{}" for GParamSpec'.format(p.arg.gtype) + ) + flags = "G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS" if p.deprecated: - flags = 'G_PARAM_DEPRECATED | ' + flags - self.outfile.write(' %s, %s));'%(s, flags)); - self.outfile.write('\n') + flags = "G_PARAM_DEPRECATED | " + flags + self.outfile.write(" %s, %s));" % (s, flags)) + self.outfile.write("\n") - self.outfile.write('}\n' - '\n') + self.outfile.write("}\n" "\n") # ---------------------------------------------------------------------------------------------------- @@ -1547,1219 +2323,1607 @@ class CodeGenerator: for p in i.properties: # getter if p.readable and p.writable: - hint = 'Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.' + hint = "Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side." elif p.readable: - hint = 'Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.' + hint = "Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side." elif p.writable: - hint = 'Since this D-Bus property is not readable, it is only meaningful to use this function on the service-side.' + hint = "Since this D-Bus property is not readable, it is only meaningful to use this function on the service-side." else: - print_error('Cannot handle property "{}" that neither readable nor writable'.format(p.name)) - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_get_%s: (skip)\n' - ' * @object: A #%s.\n' - ' *\n' - ' * Gets the value of the #%s:%s D-Bus property.\n' - ' *\n' - ' * %s\n' - ' *\n' - %(i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint), False)) - if p.arg.free_func != None: - self.outfile.write(' * The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use %s_dup_%s() if on another thread.\n' - ' *\n' - ' * Returns: (transfer none) (nullable): The property value or %%NULL if the property is not set. Do not free the returned value, it belongs to @object.\n' - %(i.name_lower, p.name_lower)) + print_error( + 'Cannot handle property "{}" that neither readable nor writable'.format( + p.name + ) + ) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_get_%s: (skip)\n" + " * @object: A #%s.\n" + " *\n" + " * Gets the value of the #%s:%s D-Bus property.\n" + " *\n" + " * %s\n" + " *\n" + % (i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint), + False, + ) + ) + if p.arg.free_func is not None: + self.outfile.write( + " * The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use %s_dup_%s() if on another thread.\n" + " *\n" + " * Returns: (transfer none) (nullable): The property value or %%NULL if the property is not set. Do not free the returned value, it belongs to @object.\n" + % (i.name_lower, p.name_lower) + ) else: - self.outfile.write(' * Returns: The property value.\n') + self.outfile.write(" * Returns: The property value.\n") self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 0) - self.outfile.write('%s\n' - '%s_get_%s (%s *object)\n' - '{\n'%(p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)) - self.outfile.write(' return %s%s_GET_IFACE (object)->get_%s (object);\n'%(i.ns_upper, i.name_upper, p.name_lower)) - self.outfile.write('}\n') - self.outfile.write('\n') - if p.arg.free_func != None: - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_dup_%s: (skip)\n' - ' * @object: A #%s.\n' - ' *\n' - ' * Gets a copy of the #%s:%s D-Bus property.\n' - ' *\n' - ' * %s\n' - ' *\n' - ' * Returns: (transfer full) (nullable): The property value or %%NULL if the property is not set. The returned value should be freed with %s().\n' - %(i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint, p.arg.free_func), False)) + self.outfile.write( + "%s\n" + "%s_get_%s (%s *object)\n" + "{\n" % (p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name) + ) + self.outfile.write( + " return %s%s_GET_IFACE (object)->get_%s (object);\n" + % (i.ns_upper, i.name_upper, p.name_lower) + ) + self.outfile.write("}\n") + self.outfile.write("\n") + if p.arg.free_func is not None: + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_dup_%s: (skip)\n" + " * @object: A #%s.\n" + " *\n" + " * Gets a copy of the #%s:%s D-Bus property.\n" + " *\n" + " * %s\n" + " *\n" + " * Returns: (transfer full) (nullable): The property value or %%NULL if the property is not set. The returned value should be freed with %s().\n" + % ( + i.name_lower, + p.name_lower, + i.camel_name, + i.name, + p.name, + hint, + p.arg.free_func, + ), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 0) - self.outfile.write('%s\n' - '%s_dup_%s (%s *object)\n' - '{\n' - ' %svalue;\n'%(p.arg.ctype_in_dup, i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in_dup)) - self.outfile.write(' g_object_get (G_OBJECT (object), "%s", &value, NULL);\n'%(p.name_hyphen)) - self.outfile.write(' return value;\n') - self.outfile.write('}\n') - self.outfile.write('\n') + self.outfile.write( + "%s\n" + "%s_dup_%s (%s *object)\n" + "{\n" + " %svalue;\n" + % ( + p.arg.ctype_in_dup, + i.name_lower, + p.name_lower, + i.camel_name, + p.arg.ctype_in_dup, + ) + ) + self.outfile.write( + ' g_object_get (G_OBJECT (object), "%s", &value, NULL);\n' + % (p.name_hyphen) + ) + self.outfile.write(" return value;\n") + self.outfile.write("}\n") + self.outfile.write("\n") # setter if p.readable and p.writable: - hint = 'Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.' + hint = "Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side." elif p.readable: - hint = 'Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side.' + hint = "Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side." elif p.writable: - hint = 'Since this D-Bus property is writable, it is meaningful to use this function on both the client- and service-side.' + hint = "Since this D-Bus property is writable, it is meaningful to use this function on both the client- and service-side." else: - print_error('Cannot handle property "{}" that neither readable nor writable'.format(p.name)) - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_set_%s: (skip)\n' - ' * @object: A #%s.\n' - ' * @value: The value to set.\n' - ' *\n' - ' * Sets the #%s:%s D-Bus property to @value.\n' - ' *\n' - ' * %s\n' - %(i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint), False)) + print_error( + 'Cannot handle property "{}" that neither readable nor writable'.format( + p.name + ) + ) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_set_%s: (skip)\n" + " * @object: A #%s.\n" + " * @value: The value to set.\n" + " *\n" + " * Sets the #%s:%s D-Bus property to @value.\n" + " *\n" + " * %s\n" + % (i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 0) - self.outfile.write('void\n' - '%s_set_%s (%s *object, %svalue)\n' - '{\n'%(i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in, )) - self.outfile.write(' g_object_set (G_OBJECT (object), "%s", value, NULL);\n'%(p.name_hyphen)) - self.outfile.write('}\n') - self.outfile.write('\n') + self.outfile.write( + "void\n" + "%s_set_%s (%s *object, %svalue)\n" + "{\n" % (i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in) + ) + self.outfile.write( + ' g_object_set (G_OBJECT (object), "%s", value, NULL);\n' + % (p.name_hyphen) + ) + self.outfile.write("}\n") + self.outfile.write("\n") # --------------------------------------------------------------------------------------------------- def generate_signal_emitters(self, i): for s in i.signals: - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_emit_%s:\n' - ' * @object: A #%s.\n' - %(i.name_lower, s.name_lower, i.camel_name), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_emit_%s:\n" + " * @object: A #%s.\n" % (i.name_lower, s.name_lower, i.camel_name), + False, + ) + ) for a in s.args: - self.outfile.write(' * @arg_%s: Argument to pass with the signal.\n'%(a.name)) - self.outfile.write(self.docbook_gen.expand( - ' *\n' - ' * Emits the #%s::%s D-Bus signal.\n' - %(i.name, s.name), False)) + self.outfile.write( + " * @arg_%s: Argument to pass with the signal.\n" % (a.name) + ) + self.outfile.write( + self.docbook_gen.expand( + " *\n" " * Emits the #%s::%s D-Bus signal.\n" % (i.name, s.name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(s, self.outfile, 0) - self.outfile.write('void\n' - '%s_emit_%s (\n' - ' %s *object'%(i.name_lower, s.name_lower, i.camel_name)) + self.outfile.write( + "void\n" + "%s_emit_%s (\n" + " %s *object" % (i.name_lower, s.name_lower, i.camel_name) + ) for a in s.args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - self.outfile.write(')\n' - '{\n' - ' g_signal_emit_by_name (object, "%s"'%(s.name_hyphen)) + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + self.outfile.write( + ")\n" "{\n" ' g_signal_emit_by_name (object, "%s"' % (s.name_hyphen) + ) for a in s.args: - self.outfile.write(', arg_%s'%a.name) - self.outfile.write(');\n') - self.outfile.write('}\n' - '\n') + self.outfile.write(", arg_%s" % a.name) + self.outfile.write(");\n") + self.outfile.write("}\n" "\n") # --------------------------------------------------------------------------------------------------- def generate_method_calls(self, i): for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True # async begin - self.outfile.write('/**\n' - ' * %s_call_%s:\n' - ' * @proxy: A #%sProxy.\n' - %(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write( + "/**\n" + " * %s_call_%s:\n" + " * @proxy: A #%sProxy.\n" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.in_args: - self.outfile.write(' * @arg_%s: Argument to pass with the method invocation.\n'%(a.name)) - if unix_fd: - self.outfile.write(' * @fd_list: (nullable): A #GUnixFDList or %NULL.\n') - self.outfile.write(self.docbook_gen.expand( - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %%NULL.\n' - ' * @user_data: User data to pass to @callback.\n' - ' *\n' - ' * Asynchronously invokes the %s.%s() D-Bus method on @proxy.\n' - ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' - ' * You can then call %s_call_%s_finish() to get the result of the operation.\n' - ' *\n' - ' * See %s_call_%s_sync() for the synchronous, blocking version of this method.\n' - %(i.name, m.name, i.name_lower, m.name_lower, i.name_lower, m.name_lower), False)) + self.outfile.write( + " * @arg_%s: Argument to pass with the method invocation.\n" + % (a.name) + ) + if self.glib_min_required >= (2, 64): + self.outfile.write( + " * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n" + " authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n" + ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n' + " -1 to use the proxy default timeout.\n" + ) + if m.unix_fd: + self.outfile.write( + " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n" + ) + self.outfile.write( + self.docbook_gen.expand( + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %%NULL.\n" + " * @user_data: User data to pass to @callback.\n" + " *\n" + " * Asynchronously invokes the %s.%s() D-Bus method on @proxy.\n" + " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n" + " * You can then call %s_call_%s_finish() to get the result of the operation.\n" + " *\n" + " * See %s_call_%s_sync() for the synchronous, blocking version of this method.\n" + % ( + i.name, + m.name, + i.name_lower, + m.name_lower, + i.name_lower, + m.name_lower, + ), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0) - self.outfile.write('void\n' - '%s_call_%s (\n' - ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write( + "void\n" + "%s_call_%s (\n" + " %s *proxy" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.in_args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList *fd_list') - self.outfile.write(',\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data)\n' - '{\n') - if unix_fd: - self.outfile.write(' g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy),\n') + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + if self.glib_min_required >= (2, 64): + self.outfile.write( + ",\n GDBusCallFlags call_flags" ",\n gint timeout_msec" + ) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList *fd_list") + self.outfile.write( + ",\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data)\n" + "{\n" + ) + if m.unix_fd: + self.outfile.write( + " g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy),\n" + ) else: - self.outfile.write(' g_dbus_proxy_call (G_DBUS_PROXY (proxy),\n') - self.outfile.write(' "%s",\n' - ' g_variant_new ("('%(m.name)) + self.outfile.write(" g_dbus_proxy_call (G_DBUS_PROXY (proxy),\n") + self.outfile.write(' "%s",\n' ' g_variant_new ("(' % (m.name)) for a in m.in_args: - self.outfile.write('%s'%(a.format_in)) + self.outfile.write("%s" % (a.format_in)) self.outfile.write(')"') for a in m.in_args: - self.outfile.write(',\n arg_%s'%(a.name)) - self.outfile.write('),\n' - ' G_DBUS_CALL_FLAGS_NONE,\n' - ' -1,\n') - if unix_fd: - self.outfile.write(' fd_list,\n') - self.outfile.write(' cancellable,\n' - ' callback,\n' - ' user_data);\n') - self.outfile.write('}\n' - '\n') + self.outfile.write(",\n arg_%s" % (a.name)) + self.outfile.write("),\n") + if self.glib_min_required >= (2, 64): + self.outfile.write(" call_flags,\n" " timeout_msec,\n") + else: + self.outfile.write(" G_DBUS_CALL_FLAGS_NONE,\n" " -1,\n") + if m.unix_fd: + self.outfile.write(" fd_list,\n") + self.outfile.write( + " cancellable,\n" " callback,\n" " user_data);\n" + ) + self.outfile.write("}\n" "\n") # async finish - self.outfile.write('/**\n' - ' * %s_call_%s_finish:\n' - ' * @proxy: A #%sProxy.\n' - %(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write( + "/**\n" + " * %s_call_%s_finish:\n" + " * @proxy: A #%sProxy.\n" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.out_args: - self.outfile.write(' * @out_%s: (out) (optional)%s: Return location for return parameter or %%NULL to ignore.\n'%(a.name, ' ' + a.array_annotation if a.array_annotation else '')) - if unix_fd: - self.outfile.write(' * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore.\n') - self.outfile.write(self.docbook_gen.expand( - ' * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_call_%s().\n' - ' * @error: Return location for error or %%NULL.\n' - ' *\n' - ' * Finishes an operation started with %s_call_%s().\n' - ' *\n' - ' * Returns: (skip): %%TRUE if the call succeded, %%FALSE if @error is set.\n' - %(i.name_lower, m.name_lower, i.name_lower, m.name_lower), False)) + self.outfile.write( + " * @out_%s: (out) (optional)%s: Return location for return parameter or %%NULL to ignore.\n" + % (a.name, " " + a.array_annotation if a.array_annotation else "") + ) + if m.unix_fd: + self.outfile.write( + " * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore.\n" + ) + self.outfile.write( + self.docbook_gen.expand( + " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_call_%s().\n" + " * @error: Return location for error or %%NULL.\n" + " *\n" + " * Finishes an operation started with %s_call_%s().\n" + " *\n" + " * Returns: (skip): %%TRUE if the call succeeded, %%FALSE if @error is set.\n" + % (i.name_lower, m.name_lower, i.name_lower, m.name_lower), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0) - self.outfile.write('gboolean\n' - '%s_call_%s_finish (\n' - ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write( + "gboolean\n" + "%s_call_%s_finish (\n" + " %s *proxy" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.out_args: - self.outfile.write(',\n %sout_%s'%(a.ctype_out, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList **out_fd_list') - self.outfile.write(',\n' - ' GAsyncResult *res,\n' - ' GError **error)\n' - '{\n' - ' GVariant *_ret;\n') - if unix_fd: - self.outfile.write(' _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error);\n') + self.outfile.write(",\n %sout_%s" % (a.ctype_out, a.name)) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList **out_fd_list") + self.outfile.write( + ",\n" + " GAsyncResult *res,\n" + " GError **error)\n" + "{\n" + " GVariant *_ret;\n" + ) + if m.unix_fd: + self.outfile.write( + " _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error);\n" + ) else: - self.outfile.write(' _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);\n') - self.outfile.write(' if (_ret == NULL)\n' - ' goto _out;\n') - self.outfile.write(' g_variant_get (_ret,\n' - ' \"(') + self.outfile.write( + " _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);\n" + ) + self.outfile.write(" if (_ret == NULL)\n" " goto _out;\n") + self.outfile.write(" g_variant_get (_ret,\n" ' "(') for a in m.out_args: - self.outfile.write('%s'%(a.format_out)) + self.outfile.write("%s" % (a.format_out)) self.outfile.write(')"') for a in m.out_args: - self.outfile.write(',\n out_%s'%(a.name)) - self.outfile.write(');\n' - ' g_variant_unref (_ret);\n') - self.outfile.write('_out:\n' - ' return _ret != NULL;\n' - '}\n' - '\n') - + self.outfile.write(",\n out_%s" % (a.name)) + self.outfile.write(");\n" " g_variant_unref (_ret);\n") + self.outfile.write("_out:\n" " return _ret != NULL;\n" "}\n" "\n") # sync - self.outfile.write('/**\n' - ' * %s_call_%s_sync:\n' - ' * @proxy: A #%sProxy.\n' - %(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write( + "/**\n" + " * %s_call_%s_sync:\n" + " * @proxy: A #%sProxy.\n" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.in_args: - self.outfile.write(' * @arg_%s: Argument to pass with the method invocation.\n'%(a.name)) - if unix_fd: - self.outfile.write(' * @fd_list: (nullable): A #GUnixFDList or %NULL.\n') + self.outfile.write( + " * @arg_%s: Argument to pass with the method invocation.\n" + % (a.name) + ) + if self.glib_min_required >= (2, 64): + self.outfile.write( + " * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n" + " authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n" + ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n' + " -1 to use the proxy default timeout.\n" + ) + if m.unix_fd: + self.outfile.write( + " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n" + ) for a in m.out_args: - self.outfile.write(' * @out_%s: (out) (optional)%s: Return location for return parameter or %%NULL to ignore.\n'%(a.name, ' ' + a.array_annotation if a.array_annotation else '')) - if unix_fd: - self.outfile.write(' * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.\n') - self.outfile.write(self.docbook_gen.expand( - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @error: Return location for error or %%NULL.\n' - ' *\n' - ' * Synchronously invokes the %s.%s() D-Bus method on @proxy. The calling thread is blocked until a reply is received.\n' - ' *\n' - ' * See %s_call_%s() for the asynchronous version of this method.\n' - ' *\n' - ' * Returns: (skip): %%TRUE if the call succeded, %%FALSE if @error is set.\n' - %(i.name, m.name, i.name_lower, m.name_lower), False)) + self.outfile.write( + " * @out_%s: (out) (optional)%s: Return location for return parameter or %%NULL to ignore.\n" + % (a.name, " " + a.array_annotation if a.array_annotation else "") + ) + if m.unix_fd: + self.outfile.write( + " * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.\n" + ) + self.outfile.write( + self.docbook_gen.expand( + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @error: Return location for error or %%NULL.\n" + " *\n" + " * Synchronously invokes the %s.%s() D-Bus method on @proxy. The calling thread is blocked until a reply is received.\n" + " *\n" + " * See %s_call_%s() for the asynchronous version of this method.\n" + " *\n" + " * Returns: (skip): %%TRUE if the call succeeded, %%FALSE if @error is set.\n" + % (i.name, m.name, i.name_lower, m.name_lower), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0) - self.outfile.write('gboolean\n' - '%s_call_%s_sync (\n' - ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) + self.outfile.write( + "gboolean\n" + "%s_call_%s_sync (\n" + " %s *proxy" % (i.name_lower, m.name_lower, i.camel_name) + ) for a in m.in_args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList *fd_list') + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + if self.glib_min_required >= (2, 64): + self.outfile.write( + ",\n GDBusCallFlags call_flags" ",\n gint timeout_msec" + ) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList *fd_list") for a in m.out_args: - self.outfile.write(',\n %sout_%s'%(a.ctype_out, a.name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList **out_fd_list') - self.outfile.write(',\n' - ' GCancellable *cancellable,\n' - ' GError **error)\n' - '{\n' - ' GVariant *_ret;\n') - if unix_fd: - self.outfile.write(' _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy),\n') + self.outfile.write(",\n %sout_%s" % (a.ctype_out, a.name)) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList **out_fd_list") + self.outfile.write( + ",\n" + " GCancellable *cancellable,\n" + " GError **error)\n" + "{\n" + " GVariant *_ret;\n" + ) + if m.unix_fd: + self.outfile.write( + " _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy),\n" + ) else: - self.outfile.write(' _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),\n') - self.outfile.write(' "%s",\n' - ' g_variant_new ("('%(m.name)) + self.outfile.write( + " _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),\n" + ) + self.outfile.write(' "%s",\n' ' g_variant_new ("(' % (m.name)) for a in m.in_args: - self.outfile.write('%s'%(a.format_in)) + self.outfile.write("%s" % (a.format_in)) self.outfile.write(')"') for a in m.in_args: - self.outfile.write(',\n arg_%s'%(a.name)) - self.outfile.write('),\n' - ' G_DBUS_CALL_FLAGS_NONE,\n' - ' -1,\n') - if unix_fd: - self.outfile.write(' fd_list,\n' - ' out_fd_list,\n') - self.outfile.write(' cancellable,\n' - ' error);\n' - ' if (_ret == NULL)\n' - ' goto _out;\n') - self.outfile.write(' g_variant_get (_ret,\n' - ' \"(') + self.outfile.write(",\n arg_%s" % (a.name)) + self.outfile.write("),\n") + if self.glib_min_required >= (2, 64): + self.outfile.write(" call_flags,\n" " timeout_msec,\n") + else: + self.outfile.write(" G_DBUS_CALL_FLAGS_NONE,\n" " -1,\n") + if m.unix_fd: + self.outfile.write(" fd_list,\n" " out_fd_list,\n") + self.outfile.write( + " cancellable,\n" + " error);\n" + " if (_ret == NULL)\n" + " goto _out;\n" + ) + self.outfile.write(" g_variant_get (_ret,\n" ' "(') for a in m.out_args: - self.outfile.write('%s'%(a.format_out)) + self.outfile.write("%s" % (a.format_out)) self.outfile.write(')"') for a in m.out_args: - self.outfile.write(',\n out_%s'%(a.name)) - self.outfile.write(');\n' - ' g_variant_unref (_ret);\n') - self.outfile.write('_out:\n' - ' return _ret != NULL;\n' - '}\n' - '\n') + self.outfile.write(",\n out_%s" % (a.name)) + self.outfile.write(");\n" " g_variant_unref (_ret);\n") + self.outfile.write("_out:\n" " return _ret != NULL;\n" "}\n" "\n") # --------------------------------------------------------------------------------------------------- def generate_method_completers(self, i): for m in i.methods: - unix_fd = False - if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'): - unix_fd = True - self.outfile.write('/**\n' - ' * %s_complete_%s:\n' - ' * @object: A #%s.\n' - ' * @invocation: (transfer full): A #GDBusMethodInvocation.\n' - %(i.name_lower, m.name_lower, i.camel_name)) - if unix_fd: - self.outfile.write(' * @fd_list: (nullable): A #GUnixFDList or %NULL.\n') + self.outfile.write( + "/**\n" + " * %s_complete_%s:\n" + " * @object: A #%s.\n" + " * @invocation: (transfer full): A #GDBusMethodInvocation.\n" + % (i.name_lower, m.name_lower, i.camel_name) + ) + if m.unix_fd: + self.outfile.write( + " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n" + ) for a in m.out_args: - self.outfile.write(' * @%s: Parameter to return.\n'%(a.name)) - self.outfile.write(self.docbook_gen.expand( - ' *\n' - ' * Helper function used in service implementations to finish handling invocations of the %s.%s() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.\n' - ' *\n' - ' * This method will free @invocation, you cannot use it afterwards.\n' - %(i.name, m.name), False)) + self.outfile.write(" * @%s: Parameter to return.\n" % (a.name)) + self.outfile.write( + self.docbook_gen.expand( + " *\n" + " * Helper function used in service implementations to finish handling invocations of the %s.%s() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.\n" + " *\n" + " * This method will free @invocation, you cannot use it afterwards.\n" + % (i.name, m.name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0) - self.outfile.write('void\n' - '%s_complete_%s (\n' - ' %s *object,\n' - ' GDBusMethodInvocation *invocation'%(i.name_lower, m.name_lower, i.camel_name)) - if unix_fd: - self.outfile.write(',\n GUnixFDList *fd_list') + self.outfile.write( + "void\n" + "%s_complete_%s (\n" + " %s *object G_GNUC_UNUSED,\n" + " GDBusMethodInvocation *invocation" + % (i.name_lower, m.name_lower, i.camel_name) + ) + if m.unix_fd: + self.outfile.write(",\n GUnixFDList *fd_list") for a in m.out_args: - self.outfile.write(',\n %s%s'%(a.ctype_in, a.name)) - self.outfile.write(')\n' - '{\n') - - if unix_fd: - self.outfile.write(' g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,\n' - ' g_variant_new ("(') + self.outfile.write(",\n %s%s" % (a.ctype_in, a.name)) + self.outfile.write(")\n" "{\n") + + if m.unix_fd: + self.outfile.write( + " g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,\n" + ' g_variant_new ("(' + ) else: - self.outfile.write(' g_dbus_method_invocation_return_value (invocation,\n' - ' g_variant_new ("(') + self.outfile.write( + " g_dbus_method_invocation_return_value (invocation,\n" + ' g_variant_new ("(' + ) for a in m.out_args: - self.outfile.write('%s'%(a.format_in)) + self.outfile.write("%s" % (a.format_in)) self.outfile.write(')"') for a in m.out_args: - self.outfile.write(',\n %s'%(a.name)) - if unix_fd: - self.outfile.write('),\n fd_list);\n') + self.outfile.write(",\n %s" % (a.name)) + if m.unix_fd: + self.outfile.write("),\n fd_list);\n") else: - self.outfile.write('));\n') - self.outfile.write('}\n' - '\n') + self.outfile.write("));\n") + self.outfile.write("}\n" "\n") # --------------------------------------------------------------------------------------------------- def generate_proxy(self, i): # class boilerplate - self.outfile.write('/* ------------------------------------------------------------------------ */\n' - '\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sProxy:\n' - ' *\n' - ' * The #%sProxy structure contains only private data and should only be accessed using the provided API.\n' - %(i.camel_name, i.camel_name), False)) + self.outfile.write( + "/* ------------------------------------------------------------------------ */\n" + "\n" + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sProxy:\n" + " *\n" + " * The #%sProxy structure contains only private data and should only be accessed using the provided API.\n" + % (i.camel_name, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sProxyClass:\n' - ' * @parent_class: The parent class.\n' - ' *\n' - ' * Class structure for #%sProxy.\n' - %(i.camel_name, i.camel_name), False)) + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sProxyClass:\n" + " * @parent_class: The parent class.\n" + " *\n" + " * Class structure for #%sProxy.\n" % (i.camel_name, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('\n') - - self.outfile.write('struct _%sProxyPrivate\n' - '{\n' - ' GData *qdata;\n' - '};\n' - '\n'%i.camel_name) - - self.outfile.write('static void %s_proxy_iface_init (%sIface *iface);\n' - '\n'%(i.name_lower, i.camel_name)) - self.outfile.write('#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n') - self.outfile.write('G_DEFINE_TYPE_WITH_CODE (%sProxy, %s_proxy, G_TYPE_DBUS_PROXY,\n'%(i.camel_name, i.name_lower)) - self.outfile.write(' G_ADD_PRIVATE (%sProxy)\n'%(i.camel_name)) - self.outfile.write(' G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_proxy_iface_init))\n\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#else\n') - self.outfile.write('G_DEFINE_TYPE_WITH_CODE (%sProxy, %s_proxy, G_TYPE_DBUS_PROXY,\n'%(i.camel_name, i.name_lower)) - self.outfile.write(' G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_proxy_iface_init))\n\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#endif\n') + self.outfile.write("\n") + + self.outfile.write( + "struct _%sProxyPrivate\n" + "{\n" + " GData *qdata;\n" + "};\n" + "\n" % i.camel_name + ) + + self.outfile.write( + "static void %s_proxy_iface_init (%sIface *iface);\n" + "\n" % (i.name_lower, i.camel_name) + ) + self.outfile.write("#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n") + self.outfile.write( + "G_DEFINE_TYPE_WITH_CODE (%sProxy, %s_proxy, G_TYPE_DBUS_PROXY,\n" + % (i.camel_name, i.name_lower) + ) + self.outfile.write( + " G_ADD_PRIVATE (%sProxy)\n" % (i.camel_name) + ) + self.outfile.write( + " G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_proxy_iface_init))\n\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write("#else\n") + self.outfile.write( + "G_DEFINE_TYPE_WITH_CODE (%sProxy, %s_proxy, G_TYPE_DBUS_PROXY,\n" + % (i.camel_name, i.name_lower) + ) + self.outfile.write( + " G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_proxy_iface_init))\n\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write("#endif\n") # finalize - self.outfile.write('static void\n' - '%s_proxy_finalize (GObject *object)\n' - '{\n'%(i.name_lower)) - self.outfile.write(' %sProxy *proxy = %s%s_PROXY (object);\n'%(i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write(' g_datalist_clear (&proxy->priv->qdata);\n') - self.outfile.write(' G_OBJECT_CLASS (%s_proxy_parent_class)->finalize (object);\n' - '}\n' - '\n'%(i.name_lower)) + self.outfile.write( + "static void\n" + "%s_proxy_finalize (GObject *object)\n" + "{\n" % (i.name_lower) + ) + self.outfile.write( + " %sProxy *proxy = %s%s_PROXY (object);\n" + % (i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write(" g_datalist_clear (&proxy->priv->qdata);\n") + self.outfile.write( + " G_OBJECT_CLASS (%s_proxy_parent_class)->finalize (object);\n" + "}\n" + "\n" % (i.name_lower) + ) # property accessors # # Note that we are guaranteed that prop_id starts at 1 and is # laid out in the same order as introspection data pointers # - self.outfile.write('static void\n' - '%s_proxy_get_property (GObject *object,\n' - ' guint prop_id,\n' - ' GValue *value,\n' - ' GParamSpec *pspec G_GNUC_UNUSED)\n' - '{\n'%(i.name_lower)) + self.outfile.write( + "static void\n" + "%s_proxy_get_property (GObject *object" % (i.name_lower) + ) + if len(i.properties) == 0: + self.outfile.write( + " G_GNUC_UNUSED,\n" + " guint prop_id G_GNUC_UNUSED,\n" + " GValue *value G_GNUC_UNUSED,\n" + ) + else: + self.outfile.write( + ",\n" " guint prop_id,\n" " GValue *value,\n" + ) + self.outfile.write(" GParamSpec *pspec G_GNUC_UNUSED)\n" "{\n") if len(i.properties) > 0: - self.outfile.write(' const _ExtendedGDBusPropertyInfo *info;\n' - ' GVariant *variant;\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' - ' info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n' - ' variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);\n' - ' if (info->use_gvariant)\n' - ' {\n' - ' g_value_set_variant (value, variant);\n' - ' }\n' - ' else\n' - ' {\n' - # could be that we don't have the value in cache - in that case, we do - # nothing and the user gets the default value for the GType - ' if (variant != NULL)\n' - ' g_dbus_gvariant_to_gvalue (variant, value);\n' - ' }\n' - ' if (variant != NULL)\n' - ' g_variant_unref (variant);\n' - %(len(i.properties), i.name_lower)) - self.outfile.write('}\n' - '\n') + self.outfile.write( + " const _ExtendedGDBusPropertyInfo *info;\n" + " GVariant *variant;\n" + " g_assert (prop_id != 0 && prop_id - 1 < %d);\n" + " info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n" + " variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);\n" + " if (info->use_gvariant)\n" + " {\n" + " g_value_set_variant (value, variant);\n" + " }\n" + " else\n" + " {\n" + # could be that we don't have the value in cache - in that case, we do + # nothing and the user gets the default value for the GType + " if (variant != NULL)\n" + " g_dbus_gvariant_to_gvalue (variant, value);\n" + " }\n" + " if (variant != NULL)\n" + " g_variant_unref (variant);\n" % (len(i.properties), i.name_lower) + ) + self.outfile.write("}\n" "\n") if len(i.properties) > 0: - self.outfile.write('static void\n' - '%s_proxy_set_property_cb (GDBusProxy *proxy,\n' - ' GAsyncResult *res,\n' - ' gpointer user_data)\n' - '{\n'%(i.name_lower)) - self.outfile.write(' const _ExtendedGDBusPropertyInfo *info = user_data;\n' - ' GError *error;\n' - ' GVariant *_ret;\n' - ' error = NULL;\n' - ' _ret = g_dbus_proxy_call_finish (proxy, res, &error);\n' - ' if (!_ret)\n' - ' {\n' - ' g_warning ("Error setting property \'%%s\' on interface %s: %%s (%%s, %%d)",\n' - ' info->parent_struct.name, \n' - ' error->message, g_quark_to_string (error->domain), error->code);\n' - ' g_error_free (error);\n' - ' }\n' - ' else\n' - ' {\n' - ' g_variant_unref (_ret);\n' - ' }\n' - %(i.name)) - self.outfile.write('}\n' - '\n') - self.outfile.write('static void\n' - '%s_proxy_set_property (GObject *object,\n' - ' guint prop_id,\n' - ' const GValue *value,\n' - ' GParamSpec *pspec G_GNUC_UNUSED)\n' - '{\n'%(i.name_lower)) + self.outfile.write( + "static void\n" + "%s_proxy_set_property_cb (GDBusProxy *proxy,\n" + " GAsyncResult *res,\n" + " gpointer user_data)\n" + "{\n" % (i.name_lower) + ) + self.outfile.write( + " const _ExtendedGDBusPropertyInfo *info = user_data;\n" + " GError *error;\n" + " GVariant *_ret;\n" + " error = NULL;\n" + " _ret = g_dbus_proxy_call_finish (proxy, res, &error);\n" + " if (!_ret)\n" + " {\n" + " g_warning (\"Error setting property '%%s' on interface %s: %%s (%%s, %%d)\",\n" + " info->parent_struct.name, \n" + " error->message, g_quark_to_string (error->domain), error->code);\n" + " g_error_free (error);\n" + " }\n" + " else\n" + " {\n" + " g_variant_unref (_ret);\n" + " }\n" % (i.name) + ) + self.outfile.write("}\n" "\n") + self.outfile.write("static void\n" "%s_proxy_set_property (" % (i.name_lower)) + if len(i.properties) == 0: + self.outfile.write( + "GObject *object G_GNUC_UNUSED,\n" + " guint prop_id G_GNUC_UNUSED,\n" + " const GValue *value G_GNUC_UNUSED,\n" + ) + else: + self.outfile.write( + "GObject *object,\n" + " guint prop_id,\n" + " const GValue *value,\n" + ) + self.outfile.write(" GParamSpec *pspec G_GNUC_UNUSED)\n" "{\n") if len(i.properties) > 0: - self.outfile.write(' const _ExtendedGDBusPropertyInfo *info;\n' - ' GVariant *variant;\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' - ' info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n' - ' variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));\n' - ' g_dbus_proxy_call (G_DBUS_PROXY (object),\n' - ' "org.freedesktop.DBus.Properties.Set",\n' - ' g_variant_new ("(ssv)", "%s", info->parent_struct.name, variant),\n' - ' G_DBUS_CALL_FLAGS_NONE,\n' - ' -1,\n' - ' NULL, (GAsyncReadyCallback) %s_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct);\n' - ' g_variant_unref (variant);\n' - %(len(i.properties), i.name_lower, i.name, i.name_lower)) - self.outfile.write('}\n' - '\n') + self.outfile.write( + " const _ExtendedGDBusPropertyInfo *info;\n" + " GVariant *variant;\n" + " g_assert (prop_id != 0 && prop_id - 1 < %d);\n" + " info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n" + " variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));\n" + " g_dbus_proxy_call (G_DBUS_PROXY (object),\n" + ' "org.freedesktop.DBus.Properties.Set",\n' + ' g_variant_new ("(ssv)", "%s", info->parent_struct.name, variant),\n' + " G_DBUS_CALL_FLAGS_NONE,\n" + " -1,\n" + " NULL, (GAsyncReadyCallback) %s_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct);\n" + " g_variant_unref (variant);\n" + % (len(i.properties), i.name_lower, i.name, i.name_lower) + ) + self.outfile.write("}\n" "\n") # signal received - self.outfile.write('static void\n' - '%s_proxy_g_signal (GDBusProxy *proxy,\n' - ' const gchar *sender_name G_GNUC_UNUSED,\n' - ' const gchar *signal_name,\n' - ' GVariant *parameters)\n' - '{\n'%(i.name_lower)) - self.outfile.write(' _ExtendedGDBusSignalInfo *info;\n' - ' GVariantIter iter;\n' - ' GVariant *child;\n' - ' GValue *paramv;\n' - ' gsize num_params;\n' - ' gsize n;\n' - ' guint signal_id;\n'); + self.outfile.write( + "static void\n" + "%s_proxy_g_signal (GDBusProxy *proxy,\n" + " const gchar *sender_name G_GNUC_UNUSED,\n" + " const gchar *signal_name,\n" + " GVariant *parameters)\n" + "{\n" % (i.name_lower) + ) + self.outfile.write( + " _ExtendedGDBusSignalInfo *info;\n" + " GVariantIter iter;\n" + " GVariant *child;\n" + " GValue *paramv;\n" + " gsize num_params;\n" + " gsize n;\n" + " guint signal_id;\n" + ) # Note: info could be NULL if we are talking to a newer version of the interface - self.outfile.write(' info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, signal_name);\n' - ' if (info == NULL)\n' - ' return;\n' - %(i.name_lower)) - self.outfile.write(' num_params = g_variant_n_children (parameters);\n' - ' paramv = g_new0 (GValue, num_params + 1);\n' - ' g_value_init (¶mv[0], %sTYPE_%s);\n' - ' g_value_set_object (¶mv[0], proxy);\n' - %(i.ns_upper, i.name_upper)) - self.outfile.write(' g_variant_iter_init (&iter, parameters);\n' - ' n = 1;\n' - ' while ((child = g_variant_iter_next_value (&iter)) != NULL)\n' - ' {\n' - ' _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];\n' - ' if (arg_info->use_gvariant)\n' - ' {\n' - ' g_value_init (¶mv[n], G_TYPE_VARIANT);\n' - ' g_value_set_variant (¶mv[n], child);\n' - ' n++;\n' - ' }\n' - ' else\n' - ' g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);\n' - ' g_variant_unref (child);\n' - ' }\n' - ) - self.outfile.write(' signal_id = g_signal_lookup (info->signal_name, %sTYPE_%s);\n' - %(i.ns_upper, i.name_upper)) - self.outfile.write(' g_signal_emitv (paramv, signal_id, 0, NULL);\n') - self.outfile.write(' for (n = 0; n < num_params + 1; n++)\n' - ' g_value_unset (¶mv[n]);\n' - ' g_free (paramv);\n') - self.outfile.write('}\n' - '\n') + self.outfile.write( + " info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, signal_name);\n" + " if (info == NULL)\n" + " return;\n" % (i.name_lower) + ) + self.outfile.write( + " num_params = g_variant_n_children (parameters);\n" + " paramv = g_new0 (GValue, num_params + 1);\n" + " g_value_init (¶mv[0], %sTYPE_%s);\n" + " g_value_set_object (¶mv[0], proxy);\n" % (i.ns_upper, i.name_upper) + ) + self.outfile.write( + " g_variant_iter_init (&iter, parameters);\n" + " n = 1;\n" + " while ((child = g_variant_iter_next_value (&iter)) != NULL)\n" + " {\n" + " _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];\n" + " if (arg_info->use_gvariant)\n" + " {\n" + " g_value_init (¶mv[n], G_TYPE_VARIANT);\n" + " g_value_set_variant (¶mv[n], child);\n" + " n++;\n" + " }\n" + " else\n" + " g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);\n" + " g_variant_unref (child);\n" + " }\n" + ) + self.outfile.write( + " signal_id = g_signal_lookup (info->signal_name, %sTYPE_%s);\n" + % (i.ns_upper, i.name_upper) + ) + self.outfile.write(" g_signal_emitv (paramv, signal_id, 0, NULL);\n") + self.outfile.write( + " for (n = 0; n < num_params + 1; n++)\n" + " g_value_unset (¶mv[n]);\n" + " g_free (paramv);\n" + ) + self.outfile.write("}\n" "\n") # property changed - self.outfile.write('static void\n' - '%s_proxy_g_properties_changed (GDBusProxy *_proxy,\n' - ' GVariant *changed_properties,\n' - ' const gchar *const *invalidated_properties)\n' - '{\n'%(i.name_lower)) + self.outfile.write( + "static void\n" + "%s_proxy_g_properties_changed (GDBusProxy *_proxy,\n" + " GVariant *changed_properties,\n" + " const gchar *const *invalidated_properties)\n" + "{\n" % (i.name_lower) + ) # Note: info could be NULL if we are talking to a newer version of the interface - self.outfile.write(' %sProxy *proxy = %s%s_PROXY (_proxy);\n' - ' guint n;\n' - ' const gchar *key;\n' - ' GVariantIter *iter;\n' - ' _ExtendedGDBusPropertyInfo *info;\n' - ' g_variant_get (changed_properties, "a{sv}", &iter);\n' - ' while (g_variant_iter_next (iter, "{&sv}", &key, NULL))\n' - ' {\n' - ' info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, key);\n' - ' g_datalist_remove_data (&proxy->priv->qdata, key);\n' - ' if (info != NULL)\n' - ' g_object_notify (G_OBJECT (proxy), info->hyphen_name);\n' - ' }\n' - ' g_variant_iter_free (iter);\n' - ' for (n = 0; invalidated_properties[n] != NULL; n++)\n' - ' {\n' - ' info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, invalidated_properties[n]);\n' - ' g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);\n' - ' if (info != NULL)\n' - ' g_object_notify (G_OBJECT (proxy), info->hyphen_name);\n' - ' }\n' - '}\n' - '\n' - %(i.camel_name, i.ns_upper, i.name_upper, - i.name_lower, i.name_lower)) + self.outfile.write( + " %sProxy *proxy = %s%s_PROXY (_proxy);\n" + " guint n;\n" + " const gchar *key;\n" + " GVariantIter *iter;\n" + " _ExtendedGDBusPropertyInfo *info;\n" + ' g_variant_get (changed_properties, "a{sv}", &iter);\n' + ' while (g_variant_iter_next (iter, "{&sv}", &key, NULL))\n' + " {\n" + " info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, key);\n" + " g_datalist_remove_data (&proxy->priv->qdata, key);\n" + " if (info != NULL)\n" + " g_object_notify (G_OBJECT (proxy), info->hyphen_name);\n" + " }\n" + " g_variant_iter_free (iter);\n" + " for (n = 0; invalidated_properties[n] != NULL; n++)\n" + " {\n" + " info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, invalidated_properties[n]);\n" + " g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);\n" + " if (info != NULL)\n" + " g_object_notify (G_OBJECT (proxy), info->hyphen_name);\n" + " }\n" + "}\n" + "\n" % (i.camel_name, i.ns_upper, i.name_upper, i.name_lower, i.name_lower) + ) # property vfuncs for p in i.properties: - nul_value = '0' - if p.arg.free_func != None: - nul_value = 'NULL' - self.outfile.write('static %s\n' - '%s_proxy_get_%s (%s *object)\n' - '{\n' - ' %sProxy *proxy = %s%s_PROXY (object);\n' - ' GVariant *variant;\n' - ' %svalue = %s;\n'%(p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name, - i.camel_name, i.ns_upper, i.name_upper, - p.arg.ctype_in, nul_value)) + nul_value = "0" + if p.arg.free_func is not None: + nul_value = "NULL" + self.outfile.write( + "static %s\n" + "%s_proxy_get_%s (%s *object)\n" + "{\n" + " %sProxy *proxy = %s%s_PROXY (object);\n" + " GVariant *variant;\n" + " %svalue = %s;\n" + % ( + p.arg.ctype_in, + i.name_lower, + p.name_lower, + i.camel_name, + i.camel_name, + i.ns_upper, + i.name_upper, + p.arg.ctype_in, + nul_value, + ) + ) # For some property types, we have to free the returned # value (or part of it, e.g. the container) because of how # GVariant works.. see https://bugzilla.gnome.org/show_bug.cgi?id=657100 # for details # - free_container = False; - if p.arg.gvariant_get == 'g_variant_get_strv' or p.arg.gvariant_get == 'g_variant_get_objv' or p.arg.gvariant_get == 'g_variant_get_bytestring_array': - free_container = True; + free_container = False + if ( + p.arg.gvariant_get == "g_variant_get_strv" + or p.arg.gvariant_get == "g_variant_get_objv" + or p.arg.gvariant_get == "g_variant_get_bytestring_array" + ): + free_container = True # If already using an old value for strv, objv, bytestring_array (see below), # then just return that... that way the result from multiple consecutive calls # to the getter are valid as long as they're freed # if free_container: - self.outfile.write(' value = g_datalist_get_data (&proxy->priv->qdata, \"%s\");\n' - ' if (value != NULL)\n' - ' return value;\n' - %(p.name)) - self.outfile.write(' variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), \"%s\");\n'%(p.name)) - if p.arg.gtype == 'G_TYPE_VARIANT': - self.outfile.write(' value = variant;\n') - self.outfile.write(' if (variant != NULL)\n') - self.outfile.write(' g_variant_unref (variant);\n') + self.outfile.write( + ' value = g_datalist_get_data (&proxy->priv->qdata, "%s");\n' + " if (value != NULL)\n" + " return value;\n" % (p.name) + ) + self.outfile.write( + ' variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "%s");\n' + % (p.name) + ) + if p.arg.gtype == "G_TYPE_VARIANT": + self.outfile.write(" value = variant;\n") + self.outfile.write(" if (variant != NULL)\n") + self.outfile.write(" g_variant_unref (variant);\n") else: - self.outfile.write(' if (variant != NULL)\n' - ' {\n') - extra_len = '' - if p.arg.gvariant_get == 'g_variant_get_string' or p.arg.gvariant_get == 'g_variant_get_strv' or p.arg.gvariant_get == 'g_variant_get_objv' or p.arg.gvariant_get == 'g_variant_get_bytestring_array': - extra_len = ', NULL' - self.outfile.write(' value = %s (variant%s);\n'%(p.arg.gvariant_get, extra_len)) + self.outfile.write(" if (variant != NULL)\n" " {\n") + extra_len = "" + if ( + p.arg.gvariant_get == "g_variant_get_string" + or p.arg.gvariant_get == "g_variant_get_strv" + or p.arg.gvariant_get == "g_variant_get_objv" + or p.arg.gvariant_get == "g_variant_get_bytestring_array" + ): + extra_len = ", NULL" + self.outfile.write( + " value = %s (variant%s);\n" % (p.arg.gvariant_get, extra_len) + ) if free_container: - self.outfile.write(' g_datalist_set_data_full (&proxy->priv->qdata, \"%s\", (gpointer) value, g_free);\n' - %(p.name)) - self.outfile.write(' g_variant_unref (variant);\n') - self.outfile.write(' }\n') - self.outfile.write(' return value;\n') - self.outfile.write('}\n') - self.outfile.write('\n') + self.outfile.write( + ' g_datalist_set_data_full (&proxy->priv->qdata, "%s", (gpointer) value, g_free);\n' + % (p.name) + ) + self.outfile.write(" g_variant_unref (variant);\n") + self.outfile.write(" }\n") + self.outfile.write(" return value;\n") + self.outfile.write("}\n") + self.outfile.write("\n") # class boilerplate - self.outfile.write('static void\n' - '%s_proxy_init (%sProxy *proxy)\n' - '{\n' - '#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n' - ' proxy->priv = %s_proxy_get_instance_private (proxy);\n' - '#else\n' - ' proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, %sTYPE_%s_PROXY, %sProxyPrivate);\n' - '#endif\n\n' - ' g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), %s_interface_info ());\n' - '}\n' - '\n' - %(i.name_lower, i.camel_name, - i.name_lower, - i.ns_upper, i.name_upper, i.camel_name, - i.name_lower)) - self.outfile.write('static void\n' - '%s_proxy_class_init (%sProxyClass *klass)\n' - '{\n' - ' GObjectClass *gobject_class;\n' - ' GDBusProxyClass *proxy_class;\n' - '\n' - ' gobject_class = G_OBJECT_CLASS (klass);\n' - ' gobject_class->finalize = %s_proxy_finalize;\n' - ' gobject_class->get_property = %s_proxy_get_property;\n' - ' gobject_class->set_property = %s_proxy_set_property;\n' - '\n' - ' proxy_class = G_DBUS_PROXY_CLASS (klass);\n' - ' proxy_class->g_signal = %s_proxy_g_signal;\n' - ' proxy_class->g_properties_changed = %s_proxy_g_properties_changed;\n' - '\n'%(i.name_lower, i.camel_name, - i.name_lower, i.name_lower, i.name_lower, i.name_lower, i.name_lower)) + self.outfile.write( + "static void\n" + "%s_proxy_init (%sProxy *proxy)\n" + "{\n" + "#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n" + " proxy->priv = %s_proxy_get_instance_private (proxy);\n" + "#else\n" + " proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, %sTYPE_%s_PROXY, %sProxyPrivate);\n" + "#endif\n\n" + " g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), %s_interface_info ());\n" + "}\n" + "\n" + % ( + i.name_lower, + i.camel_name, + i.name_lower, + i.ns_upper, + i.name_upper, + i.camel_name, + i.name_lower, + ) + ) + self.outfile.write( + "static void\n" + "%s_proxy_class_init (%sProxyClass *klass)\n" + "{\n" + " GObjectClass *gobject_class;\n" + " GDBusProxyClass *proxy_class;\n" + "\n" + " gobject_class = G_OBJECT_CLASS (klass);\n" + " gobject_class->finalize = %s_proxy_finalize;\n" + " gobject_class->get_property = %s_proxy_get_property;\n" + " gobject_class->set_property = %s_proxy_set_property;\n" + "\n" + " proxy_class = G_DBUS_PROXY_CLASS (klass);\n" + " proxy_class->g_signal = %s_proxy_g_signal;\n" + " proxy_class->g_properties_changed = %s_proxy_g_properties_changed;\n" + "\n" + % ( + i.name_lower, + i.camel_name, + i.name_lower, + i.name_lower, + i.name_lower, + i.name_lower, + i.name_lower, + ) + ) if len(i.properties) > 0: - self.outfile.write(' %s_override_properties (gobject_class, 1);\n\n'%(i.name_lower)) - self.outfile.write('#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38\n' - ' g_type_class_add_private (klass, sizeof (%sProxyPrivate));\n' - '#endif\n'%(i.camel_name)) - self.outfile.write('}\n' - '\n') - - self.outfile.write('static void\n' - '%s_proxy_iface_init (%sIface *iface)\n' - '{\n'%(i.name_lower, i.camel_name)) + self.outfile.write( + " %s_override_properties (gobject_class, 1);\n\n" % (i.name_lower) + ) + self.outfile.write( + "#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38\n" + " g_type_class_add_private (klass, sizeof (%sProxyPrivate));\n" + "#endif\n" % (i.camel_name) + ) + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static void\n" + "%s_proxy_iface_init (%sIface *iface" % (i.name_lower, i.camel_name) + ) + if len(i.properties) == 0: + self.outfile.write(" G_GNUC_UNUSED)\n") + else: + self.outfile.write(")\n") + self.outfile.write("{\n") for p in i.properties: - self.outfile.write(' iface->get_%s = %s_proxy_get_%s;\n'%(p.name_lower, i.name_lower, p.name_lower)) - self.outfile.write('}\n' - '\n') + self.outfile.write( + " iface->get_%s = %s_proxy_get_%s;\n" + % (p.name_lower, i.name_lower, p.name_lower) + ) + self.outfile.write("}\n" "\n") # constructors - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_proxy_new:\n' - ' * @connection: A #GDBusConnection.\n' - ' * @flags: Flags from the #GDBusProxyFlags enumeration.\n' - ' * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n' - ' * @user_data: User data to pass to @callback.\n' - ' *\n' - ' * Asynchronously creates a proxy for the D-Bus interface #%s. See g_dbus_proxy_new() for more details.\n' - ' *\n' - ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' - ' * You can then call %s_proxy_new_finish() to get the result of the operation.\n' - ' *\n' - ' * See %s_proxy_new_sync() for the synchronous, blocking version of this constructor.\n' - %(i.name_lower, i.name, i.name_lower, i.name_lower), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_proxy_new:\n" + " * @connection: A #GDBusConnection.\n" + " * @flags: Flags from the #GDBusProxyFlags enumeration.\n" + " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n" + " * @user_data: User data to pass to @callback.\n" + " *\n" + " * Asynchronously creates a proxy for the D-Bus interface #%s. See g_dbus_proxy_new() for more details.\n" + " *\n" + " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n" + " * You can then call %s_proxy_new_finish() to get the result of the operation.\n" + " *\n" + " * See %s_proxy_new_sync() for the synchronous, blocking version of this constructor.\n" + % (i.name_lower, i.name, i.name_lower, i.name_lower), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('void\n' - '%s_proxy_new (\n' - ' GDBusConnection *connection,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data)\n' - '{\n' - ' g_async_initable_new_async (%sTYPE_%s_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' - '}\n' - '\n' - %(i.name_lower, i.ns_upper, i.name_upper, i.name)) - self.outfile.write('/**\n' - ' * %s_proxy_new_finish:\n' - ' * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_proxy_new().\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Finishes an operation started with %s_proxy_new().\n' - ' *\n' - ' * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n' - %(i.name_lower, i.name_lower, i.name_lower, i.camel_name)) + self.outfile.write( + "void\n" + "%s_proxy_new (\n" + " GDBusConnection *connection,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data)\n" + "{\n" + ' g_async_initable_new_async (%sTYPE_%s_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' + "}\n" + "\n" % (i.name_lower, i.ns_upper, i.name_upper, i.name) + ) + self.outfile.write( + "/**\n" + " * %s_proxy_new_finish:\n" + " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_proxy_new().\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Finishes an operation started with %s_proxy_new().\n" + " *\n" + " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n" + % (i.name_lower, i.name_lower, i.name_lower, i.camel_name) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *\n' - '%s_proxy_new_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error)\n' - '{\n' - ' GObject *ret;\n' - ' GObject *source_object;\n' - ' source_object = g_async_result_get_source_object (res);\n' - ' ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n' - ' g_object_unref (source_object);\n' - ' if (ret != NULL)\n' - ' return %s%s (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(i.camel_name, i.name_lower, i.ns_upper, i.name_upper)) - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_proxy_new_sync:\n' - ' * @connection: A #GDBusConnection.\n' - ' * @flags: Flags from the #GDBusProxyFlags enumeration.\n' - ' * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Synchronously creates a proxy for the D-Bus interface #%s. See g_dbus_proxy_new_sync() for more details.\n' - ' *\n' - ' * The calling thread is blocked until a reply is received.\n' - ' *\n' - ' * See %s_proxy_new() for the asynchronous version of this constructor.\n' - ' *\n' - ' * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n' - %(i.name_lower, i.name, i.name_lower, i.camel_name), False)) + self.outfile.write( + "%s *\n" + "%s_proxy_new_finish (\n" + " GAsyncResult *res,\n" + " GError **error)\n" + "{\n" + " GObject *ret;\n" + " GObject *source_object;\n" + " source_object = g_async_result_get_source_object (res);\n" + " ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n" + " g_object_unref (source_object);\n" + " if (ret != NULL)\n" + " return %s%s (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" % (i.camel_name, i.name_lower, i.ns_upper, i.name_upper) + ) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_proxy_new_sync:\n" + " * @connection: A #GDBusConnection.\n" + " * @flags: Flags from the #GDBusProxyFlags enumeration.\n" + " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Synchronously creates a proxy for the D-Bus interface #%s. See g_dbus_proxy_new_sync() for more details.\n" + " *\n" + " * The calling thread is blocked until a reply is received.\n" + " *\n" + " * See %s_proxy_new() for the asynchronous version of this constructor.\n" + " *\n" + " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n" + % (i.name_lower, i.name, i.name_lower, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *\n' - '%s_proxy_new_sync (\n' - ' GDBusConnection *connection,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error)\n' - '{\n' - ' GInitable *ret;\n' - ' ret = g_initable_new (%sTYPE_%s_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' - ' if (ret != NULL)\n' - ' return %s%s (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(i.camel_name, i.name_lower, i.ns_upper, i.name_upper, i.name, i.ns_upper, i.name_upper)) - self.outfile.write('\n') - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_proxy_new_for_bus:\n' - ' * @bus_type: A #GBusType.\n' - ' * @flags: Flags from the #GDBusProxyFlags enumeration.\n' - ' * @name: A bus name (well-known or unique).\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n' - ' * @user_data: User data to pass to @callback.\n' - ' *\n' - ' * Like %s_proxy_new() but takes a #GBusType instead of a #GDBusConnection.\n' - ' *\n' - ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' - ' * You can then call %s_proxy_new_for_bus_finish() to get the result of the operation.\n' - ' *\n' - ' * See %s_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.\n' - %(i.name_lower, i.name_lower, i.name_lower, i.name_lower), False)) + self.outfile.write( + "%s *\n" + "%s_proxy_new_sync (\n" + " GDBusConnection *connection,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error)\n" + "{\n" + " GInitable *ret;\n" + ' ret = g_initable_new (%sTYPE_%s_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' + " if (ret != NULL)\n" + " return %s%s (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" + % ( + i.camel_name, + i.name_lower, + i.ns_upper, + i.name_upper, + i.name, + i.ns_upper, + i.name_upper, + ) + ) + self.outfile.write("\n") + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_proxy_new_for_bus:\n" + " * @bus_type: A #GBusType.\n" + " * @flags: Flags from the #GDBusProxyFlags enumeration.\n" + " * @name: A bus name (well-known or unique).\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n" + " * @user_data: User data to pass to @callback.\n" + " *\n" + " * Like %s_proxy_new() but takes a #GBusType instead of a #GDBusConnection.\n" + " *\n" + " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n" + " * You can then call %s_proxy_new_for_bus_finish() to get the result of the operation.\n" + " *\n" + " * See %s_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.\n" + % (i.name_lower, i.name_lower, i.name_lower, i.name_lower), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('void\n' - '%s_proxy_new_for_bus (\n' - ' GBusType bus_type,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data)\n' - '{\n' - ' g_async_initable_new_async (%sTYPE_%s_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' - '}\n' - '\n' - %(i.name_lower, i.ns_upper, i.name_upper, i.name)) - self.outfile.write('/**\n' - ' * %s_proxy_new_for_bus_finish:\n' - ' * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_proxy_new_for_bus().\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Finishes an operation started with %s_proxy_new_for_bus().\n' - ' *\n' - ' * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n' - %(i.name_lower, i.name_lower, i.name_lower, i.camel_name)) + self.outfile.write( + "void\n" + "%s_proxy_new_for_bus (\n" + " GBusType bus_type,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data)\n" + "{\n" + ' g_async_initable_new_async (%sTYPE_%s_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' + "}\n" + "\n" % (i.name_lower, i.ns_upper, i.name_upper, i.name) + ) + self.outfile.write( + "/**\n" + " * %s_proxy_new_for_bus_finish:\n" + " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_proxy_new_for_bus().\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Finishes an operation started with %s_proxy_new_for_bus().\n" + " *\n" + " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n" + % (i.name_lower, i.name_lower, i.name_lower, i.camel_name) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *\n' - '%s_proxy_new_for_bus_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error)\n' - '{\n' - ' GObject *ret;\n' - ' GObject *source_object;\n' - ' source_object = g_async_result_get_source_object (res);\n' - ' ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n' - ' g_object_unref (source_object);\n' - ' if (ret != NULL)\n' - ' return %s%s (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(i.camel_name, i.name_lower, i.ns_upper, i.name_upper)) - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_proxy_new_for_bus_sync:\n' - ' * @bus_type: A #GBusType.\n' - ' * @flags: Flags from the #GDBusProxyFlags enumeration.\n' - ' * @name: A bus name (well-known or unique).\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Like %s_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.\n' - ' *\n' - ' * The calling thread is blocked until a reply is received.\n' - ' *\n' - ' * See %s_proxy_new_for_bus() for the asynchronous version of this constructor.\n' - ' *\n' - ' * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n' - %(i.name_lower, i.name_lower, i.name_lower, i.camel_name), False)) + self.outfile.write( + "%s *\n" + "%s_proxy_new_for_bus_finish (\n" + " GAsyncResult *res,\n" + " GError **error)\n" + "{\n" + " GObject *ret;\n" + " GObject *source_object;\n" + " source_object = g_async_result_get_source_object (res);\n" + " ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n" + " g_object_unref (source_object);\n" + " if (ret != NULL)\n" + " return %s%s (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" % (i.camel_name, i.name_lower, i.ns_upper, i.name_upper) + ) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_proxy_new_for_bus_sync:\n" + " * @bus_type: A #GBusType.\n" + " * @flags: Flags from the #GDBusProxyFlags enumeration.\n" + " * @name: A bus name (well-known or unique).\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Like %s_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.\n" + " *\n" + " * The calling thread is blocked until a reply is received.\n" + " *\n" + " * See %s_proxy_new_for_bus() for the asynchronous version of this constructor.\n" + " *\n" + " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n" + % (i.name_lower, i.name_lower, i.name_lower, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *\n' - '%s_proxy_new_for_bus_sync (\n' - ' GBusType bus_type,\n' - ' GDBusProxyFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error)\n' - '{\n' - ' GInitable *ret;\n' - ' ret = g_initable_new (%sTYPE_%s_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' - ' if (ret != NULL)\n' - ' return %s%s (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(i.camel_name, i.name_lower, i.ns_upper, i.name_upper, i.name, i.ns_upper, i.name_upper)) - self.outfile.write('\n') + self.outfile.write( + "%s *\n" + "%s_proxy_new_for_bus_sync (\n" + " GBusType bus_type,\n" + " GDBusProxyFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error)\n" + "{\n" + " GInitable *ret;\n" + ' ret = g_initable_new (%sTYPE_%s_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n' + " if (ret != NULL)\n" + " return %s%s (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" + % ( + i.camel_name, + i.name_lower, + i.ns_upper, + i.name_upper, + i.name, + i.ns_upper, + i.name_upper, + ) + ) + self.outfile.write("\n") # --------------------------------------------------------------------------------------------------- def generate_skeleton(self, i): # class boilerplate - self.outfile.write('/* ------------------------------------------------------------------------ */\n' - '\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sSkeleton:\n' - ' *\n' - ' * The #%sSkeleton structure contains only private data and should only be accessed using the provided API.\n' - %(i.camel_name, i.camel_name), False)) + self.outfile.write( + "/* ------------------------------------------------------------------------ */\n" + "\n" + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sSkeleton:\n" + " *\n" + " * The #%sSkeleton structure contains only private data and should only be accessed using the provided API.\n" + % (i.camel_name, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sSkeletonClass:\n' - ' * @parent_class: The parent class.\n' - ' *\n' - ' * Class structure for #%sSkeleton.\n' - %(i.camel_name, i.camel_name), False)) + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sSkeletonClass:\n" + " * @parent_class: The parent class.\n" + " *\n" + " * Class structure for #%sSkeleton.\n" % (i.camel_name, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('\n') - - self.outfile.write('struct _%sSkeletonPrivate\n' - '{\n' - ' GValue *properties;\n' - ' GList *changed_properties;\n' - ' GSource *changed_properties_idle_source;\n' - ' GMainContext *context;\n' - ' GMutex lock;\n' - '};\n' - '\n'%i.camel_name) - - self.outfile.write('static void\n' - '_%s_skeleton_handle_method_call (\n' - ' GDBusConnection *connection G_GNUC_UNUSED,\n' - ' const gchar *sender G_GNUC_UNUSED,\n' - ' const gchar *object_path G_GNUC_UNUSED,\n' - ' const gchar *interface_name,\n' - ' const gchar *method_name,\n' - ' GVariant *parameters,\n' - ' GDBusMethodInvocation *invocation,\n' - ' gpointer user_data)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n' - ' _ExtendedGDBusMethodInfo *info;\n' - ' GVariantIter iter;\n' - ' GVariant *child;\n' - ' GValue *paramv;\n' - ' gsize num_params;\n' - ' guint num_extra;\n' - ' gsize n;\n' - ' guint signal_id;\n' - ' GValue return_value = G_VALUE_INIT;\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write(' info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);\n' - ' g_assert (info != NULL);\n' - %()) - self.outfile.write(' num_params = g_variant_n_children (parameters);\n' - ' num_extra = info->pass_fdlist ? 3 : 2;' - ' paramv = g_new0 (GValue, num_params + num_extra);\n' - ' n = 0;\n' - ' g_value_init (¶mv[n], %sTYPE_%s);\n' - ' g_value_set_object (¶mv[n++], skeleton);\n' - ' g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION);\n' - ' g_value_set_object (¶mv[n++], invocation);\n' - ' if (info->pass_fdlist)\n' - ' {\n' - '#ifdef G_OS_UNIX\n' - ' g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST);\n' - ' g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));\n' - '#else\n' - ' g_assert_not_reached ();\n' - '#endif\n' - ' }\n' - %(i.ns_upper, i.name_upper)) - self.outfile.write(' g_variant_iter_init (&iter, parameters);\n' - ' while ((child = g_variant_iter_next_value (&iter)) != NULL)\n' - ' {\n' - ' _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];\n' - ' if (arg_info->use_gvariant)\n' - ' {\n' - ' g_value_init (¶mv[n], G_TYPE_VARIANT);\n' - ' g_value_set_variant (¶mv[n], child);\n' - ' n++;\n' - ' }\n' - ' else\n' - ' g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);\n' - ' g_variant_unref (child);\n' - ' }\n') - self.outfile.write(' signal_id = g_signal_lookup (info->signal_name, %sTYPE_%s);\n' - %(i.ns_upper, i.name_upper)) - self.outfile.write(' g_value_init (&return_value, G_TYPE_BOOLEAN);\n' - ' g_signal_emitv (paramv, signal_id, 0, &return_value);\n' - ' if (!g_value_get_boolean (&return_value))\n' - ' g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);\n' - ' g_value_unset (&return_value);\n') - self.outfile.write(' for (n = 0; n < num_params + num_extra; n++)\n' - ' g_value_unset (¶mv[n]);\n' - ' g_free (paramv);\n') - self.outfile.write('}\n' - '\n') - - self.outfile.write('static GVariant *\n' - '_%s_skeleton_handle_get_property (\n' - ' GDBusConnection *connection G_GNUC_UNUSED,\n' - ' const gchar *sender G_GNUC_UNUSED,\n' - ' const gchar *object_path G_GNUC_UNUSED,\n' - ' const gchar *interface_name G_GNUC_UNUSED,\n' - ' const gchar *property_name,\n' - ' GError **error,\n' - ' gpointer user_data)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n' - ' GValue value = G_VALUE_INIT;\n' - ' GParamSpec *pspec;\n' - ' _ExtendedGDBusPropertyInfo *info;\n' - ' GVariant *ret;\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write(' ret = NULL;\n' - ' info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, property_name);\n' - ' g_assert (info != NULL);\n' - ' pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);\n' - ' if (pspec == NULL)\n' - ' {\n' - ' g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %%s", property_name);\n' - ' }\n' - ' else\n' - ' {\n' - ' g_value_init (&value, pspec->value_type);\n' - ' g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);\n' - ' ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));\n' - ' g_value_unset (&value);\n' - ' }\n' - ' return ret;\n' - '}\n' - '\n' - %(i.name_lower)) - - self.outfile.write('static gboolean\n' - '_%s_skeleton_handle_set_property (\n' - ' GDBusConnection *connection G_GNUC_UNUSED,\n' - ' const gchar *sender G_GNUC_UNUSED,\n' - ' const gchar *object_path G_GNUC_UNUSED,\n' - ' const gchar *interface_name G_GNUC_UNUSED,\n' - ' const gchar *property_name,\n' - ' GVariant *variant,\n' - ' GError **error,\n' - ' gpointer user_data)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n' - ' GValue value = G_VALUE_INIT;\n' - ' GParamSpec *pspec;\n' - ' _ExtendedGDBusPropertyInfo *info;\n' - ' gboolean ret;\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write(' ret = FALSE;\n' - ' info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, property_name);\n' - ' g_assert (info != NULL);\n' - ' pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);\n' - ' if (pspec == NULL)\n' - ' {\n' - ' g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %%s", property_name);\n' - ' }\n' - ' else\n' - ' {\n' - ' if (info->use_gvariant)\n' - ' g_value_set_variant (&value, variant);\n' - ' else\n' - ' g_dbus_gvariant_to_gvalue (variant, &value);\n' - ' g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);\n' - ' g_value_unset (&value);\n' - ' ret = TRUE;\n' - ' }\n' - ' return ret;\n' - '}\n' - '\n' - %(i.name_lower)) - - - self.outfile.write('static const GDBusInterfaceVTable _%s_skeleton_vtable =\n' - '{\n' - ' _%s_skeleton_handle_method_call,\n' - ' _%s_skeleton_handle_get_property,\n' - ' _%s_skeleton_handle_set_property,\n' - ' {NULL}\n' - '};\n' - '\n'%(i.name_lower, i.name_lower, i.name_lower, i.name_lower)) - - self.outfile.write('static GDBusInterfaceInfo *\n' - '%s_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)\n' - '{\n' - ' return %s_interface_info ();\n' - %(i.name_lower, i.name_lower)) - self.outfile.write('}\n' - '\n') - - self.outfile.write('static GDBusInterfaceVTable *\n' - '%s_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)\n' - '{\n' - ' return (GDBusInterfaceVTable *) &_%s_skeleton_vtable;\n' - %(i.name_lower, i.name_lower)) - self.outfile.write('}\n' - '\n') - - self.outfile.write('static GVariant *\n' - '%s_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (_skeleton);\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write('\n' - ' GVariantBuilder builder;\n' - ' guint n;\n' - ' g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));\n' - ' if (_%s_interface_info.parent_struct.properties == NULL)\n' - ' goto out;\n' - ' for (n = 0; _%s_interface_info.parent_struct.properties[n] != NULL; n++)\n' - ' {\n' - ' GDBusPropertyInfo *info = _%s_interface_info.parent_struct.properties[n];\n' - ' if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)\n' - ' {\n' - ' GVariant *value;\n' - ' value = _%s_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "%s", info->name, NULL, skeleton);\n' - ' if (value != NULL)\n' - ' {\n' - ' g_variant_take_ref (value);\n' - ' g_variant_builder_add (&builder, "{sv}", info->name, value);\n' - ' g_variant_unref (value);\n' - ' }\n' - ' }\n' - ' }\n' - 'out:\n' - ' return g_variant_builder_end (&builder);\n' - '}\n' - '\n' - %(i.name_lower, i.name_lower, i.name_lower, i.name_lower, i.name)) + self.outfile.write("\n") + + self.outfile.write( + "struct _%sSkeletonPrivate\n" + "{\n" + " GValue *properties;\n" + " GList *changed_properties;\n" + " GSource *changed_properties_idle_source;\n" + " GMainContext *context;\n" + " GMutex lock;\n" + "};\n" + "\n" % i.camel_name + ) + + self.outfile.write( + "static void\n" + "_%s_skeleton_handle_method_call (\n" + " GDBusConnection *connection G_GNUC_UNUSED,\n" + " const gchar *sender G_GNUC_UNUSED,\n" + " const gchar *object_path G_GNUC_UNUSED,\n" + " const gchar *interface_name,\n" + " const gchar *method_name,\n" + " GVariant *parameters,\n" + " GDBusMethodInvocation *invocation,\n" + " gpointer user_data)\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n" + " _ExtendedGDBusMethodInfo *info;\n" + " GVariantIter iter;\n" + " GVariant *child;\n" + " GValue *paramv;\n" + " gsize num_params;\n" + " guint num_extra;\n" + " gsize n;\n" + " guint signal_id;\n" + " GValue return_value = G_VALUE_INIT;\n" + % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + " info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);\n" + " g_assert (info != NULL);\n" + ) + self.outfile.write( + " num_params = g_variant_n_children (parameters);\n" + " num_extra = info->pass_fdlist ? 3 : 2;" + " paramv = g_new0 (GValue, num_params + num_extra);\n" + " n = 0;\n" + " g_value_init (¶mv[n], %sTYPE_%s);\n" + " g_value_set_object (¶mv[n++], skeleton);\n" + " g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION);\n" + " g_value_set_object (¶mv[n++], invocation);\n" + " if (info->pass_fdlist)\n" + " {\n" + "#ifdef G_OS_UNIX\n" + " g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST);\n" + " g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));\n" + "#else\n" + " g_assert_not_reached ();\n" + "#endif\n" + " }\n" % (i.ns_upper, i.name_upper) + ) + self.outfile.write( + " g_variant_iter_init (&iter, parameters);\n" + " while ((child = g_variant_iter_next_value (&iter)) != NULL)\n" + " {\n" + " _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];\n" + " if (arg_info->use_gvariant)\n" + " {\n" + " g_value_init (¶mv[n], G_TYPE_VARIANT);\n" + " g_value_set_variant (¶mv[n], child);\n" + " n++;\n" + " }\n" + " else\n" + " g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);\n" + " g_variant_unref (child);\n" + " }\n" + ) + self.outfile.write( + " signal_id = g_signal_lookup (info->signal_name, %sTYPE_%s);\n" + % (i.ns_upper, i.name_upper) + ) + self.outfile.write( + " g_value_init (&return_value, G_TYPE_BOOLEAN);\n" + " g_signal_emitv (paramv, signal_id, 0, &return_value);\n" + " if (!g_value_get_boolean (&return_value))\n" + ' g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);\n' + " g_value_unset (&return_value);\n" + ) + self.outfile.write( + " for (n = 0; n < num_params + num_extra; n++)\n" + " g_value_unset (¶mv[n]);\n" + " g_free (paramv);\n" + ) + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static GVariant *\n" + "_%s_skeleton_handle_get_property (\n" + " GDBusConnection *connection G_GNUC_UNUSED,\n" + " const gchar *sender G_GNUC_UNUSED,\n" + " const gchar *object_path G_GNUC_UNUSED,\n" + " const gchar *interface_name G_GNUC_UNUSED,\n" + " const gchar *property_name,\n" + " GError **error,\n" + " gpointer user_data)\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n" + " GValue value = G_VALUE_INIT;\n" + " GParamSpec *pspec;\n" + " _ExtendedGDBusPropertyInfo *info;\n" + " GVariant *ret;\n" + % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + " ret = NULL;\n" + " info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, property_name);\n" + " g_assert (info != NULL);\n" + " pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);\n" + " if (pspec == NULL)\n" + " {\n" + ' g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %%s", property_name);\n' + " }\n" + " else\n" + " {\n" + " g_value_init (&value, pspec->value_type);\n" + " g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);\n" + " ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));\n" + " g_value_unset (&value);\n" + " }\n" + " return ret;\n" + "}\n" + "\n" % (i.name_lower) + ) + + self.outfile.write( + "static gboolean\n" + "_%s_skeleton_handle_set_property (\n" + " GDBusConnection *connection G_GNUC_UNUSED,\n" + " const gchar *sender G_GNUC_UNUSED,\n" + " const gchar *object_path G_GNUC_UNUSED,\n" + " const gchar *interface_name G_GNUC_UNUSED,\n" + " const gchar *property_name,\n" + " GVariant *variant,\n" + " GError **error,\n" + " gpointer user_data)\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n" + " GValue value = G_VALUE_INIT;\n" + " GParamSpec *pspec;\n" + " _ExtendedGDBusPropertyInfo *info;\n" + " gboolean ret;\n" % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + " ret = FALSE;\n" + " info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, property_name);\n" + " g_assert (info != NULL);\n" + " pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);\n" + " if (pspec == NULL)\n" + " {\n" + ' g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %%s", property_name);\n' + " }\n" + " else\n" + " {\n" + " if (info->use_gvariant)\n" + " g_value_set_variant (&value, variant);\n" + " else\n" + " g_dbus_gvariant_to_gvalue (variant, &value);\n" + " g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);\n" + " g_value_unset (&value);\n" + " ret = TRUE;\n" + " }\n" + " return ret;\n" + "}\n" + "\n" % (i.name_lower) + ) + + self.outfile.write( + "static const GDBusInterfaceVTable _%s_skeleton_vtable =\n" + "{\n" + " _%s_skeleton_handle_method_call,\n" + " _%s_skeleton_handle_get_property,\n" + " _%s_skeleton_handle_set_property,\n" + " {NULL}\n" + "};\n" + "\n" % (i.name_lower, i.name_lower, i.name_lower, i.name_lower) + ) + + self.outfile.write( + "static GDBusInterfaceInfo *\n" + "%s_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)\n" + "{\n" + " return %s_interface_info ();\n" % (i.name_lower, i.name_lower) + ) + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static GDBusInterfaceVTable *\n" + "%s_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)\n" + "{\n" + " return (GDBusInterfaceVTable *) &_%s_skeleton_vtable;\n" + % (i.name_lower, i.name_lower) + ) + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static GVariant *\n" + "%s_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (_skeleton);\n" + % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + "\n" + " GVariantBuilder builder;\n" + " guint n;\n" + ' g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));\n' + " if (_%s_interface_info.parent_struct.properties == NULL)\n" + " goto out;\n" + " for (n = 0; _%s_interface_info.parent_struct.properties[n] != NULL; n++)\n" + " {\n" + " GDBusPropertyInfo *info = _%s_interface_info.parent_struct.properties[n];\n" + " if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)\n" + " {\n" + " GVariant *value;\n" + ' value = _%s_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "%s", info->name, NULL, skeleton);\n' + " if (value != NULL)\n" + " {\n" + " g_variant_take_ref (value);\n" + ' g_variant_builder_add (&builder, "{sv}", info->name, value);\n' + " g_variant_unref (value);\n" + " }\n" + " }\n" + " }\n" + "out:\n" + " return g_variant_builder_end (&builder);\n" + "}\n" + "\n" % (i.name_lower, i.name_lower, i.name_lower, i.name_lower, i.name) + ) if len(i.properties) > 0: - self.outfile.write('static gboolean _%s_emit_changed (gpointer user_data);\n' - '\n' - %(i.name_lower)) - - self.outfile.write('static void\n' - '%s_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)\n' - '{\n' - %(i.name_lower)) + self.outfile.write( + "static gboolean _%s_emit_changed (gpointer user_data);\n" + "\n" % (i.name_lower) + ) + + self.outfile.write( + "static void\n" + "%s_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton" + % (i.name_lower) + ) + if len(i.properties) == 0: + self.outfile.write(" G_GNUC_UNUSED)\n") + else: + self.outfile.write(")\n") + self.outfile.write("{\n") if len(i.properties) > 0: - self.outfile.write(' %sSkeleton *skeleton = %s%s_SKELETON (_skeleton);\n' - ' gboolean emit_changed = FALSE;\n' - '\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' if (skeleton->priv->changed_properties_idle_source != NULL)\n' - ' {\n' - ' g_source_destroy (skeleton->priv->changed_properties_idle_source);\n' - ' skeleton->priv->changed_properties_idle_source = NULL;\n' - ' emit_changed = TRUE;\n' - ' }\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - '\n' - ' if (emit_changed)\n' - ' _%s_emit_changed (skeleton);\n' - %(i.camel_name, i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('}\n' - '\n') + self.outfile.write( + " %sSkeleton *skeleton = %s%s_SKELETON (_skeleton);\n" + " gboolean emit_changed = FALSE;\n" + "\n" + " g_mutex_lock (&skeleton->priv->lock);\n" + " if (skeleton->priv->changed_properties_idle_source != NULL)\n" + " {\n" + " g_source_destroy (skeleton->priv->changed_properties_idle_source);\n" + " skeleton->priv->changed_properties_idle_source = NULL;\n" + " emit_changed = TRUE;\n" + " }\n" + " g_mutex_unlock (&skeleton->priv->lock);\n" + "\n" + " if (emit_changed)\n" + " _%s_emit_changed (skeleton);\n" + % (i.camel_name, i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write("}\n" "\n") for s in i.signals: - self.outfile.write('static void\n' - '_%s_on_signal_%s (\n' - ' %s *object'%(i.name_lower, s.name_lower, i.camel_name)) + self.outfile.write( + "static void\n" + "_%s_on_signal_%s (\n" + " %s *object" % (i.name_lower, s.name_lower, i.camel_name) + ) for a in s.args: - self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - self.outfile.write(')\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (object);\n\n' - ' GList *connections, *l;\n' - ' GVariant *signal_variant;\n' - ' connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));\n' - %(i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write('\n' - ' signal_variant = g_variant_ref_sink (g_variant_new ("(') + self.outfile.write(",\n %sarg_%s" % (a.ctype_in, a.name)) + self.outfile.write( + ")\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (object);\n\n" + " GList *connections, *l;\n" + " GVariant *signal_variant;\n" + " connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));\n" + % (i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + "\n" ' signal_variant = g_variant_ref_sink (g_variant_new ("(' + ) for a in s.args: - self.outfile.write('%s'%(a.format_in)) + self.outfile.write("%s" % (a.format_in)) self.outfile.write(')"') for a in s.args: - self.outfile.write(',\n arg_%s'%(a.name)) - self.outfile.write('));\n') - - self.outfile.write(' for (l = connections; l != NULL; l = l->next)\n' - ' {\n' - ' GDBusConnection *connection = l->data;\n' - ' g_dbus_connection_emit_signal (connection,\n' - ' NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "%s", "%s",\n' - ' signal_variant, NULL);\n' - ' }\n' - %(i.name, s.name)) - self.outfile.write(' g_variant_unref (signal_variant);\n') - self.outfile.write(' g_list_free_full (connections, g_object_unref);\n') - self.outfile.write('}\n' - '\n') - - self.outfile.write('static void %s_skeleton_iface_init (%sIface *iface);\n' - %(i.name_lower, i.camel_name)) - - self.outfile.write('#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n') - self.outfile.write('G_DEFINE_TYPE_WITH_CODE (%sSkeleton, %s_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,\n'%(i.camel_name, i.name_lower)) - self.outfile.write(' G_ADD_PRIVATE (%sSkeleton)\n'%(i.camel_name)) - self.outfile.write(' G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_skeleton_iface_init))\n\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#else\n') - self.outfile.write('G_DEFINE_TYPE_WITH_CODE (%sSkeleton, %s_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,\n'%(i.camel_name, i.name_lower)) - self.outfile.write(' G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_skeleton_iface_init))\n\n'%(i.ns_upper, i.name_upper, i.name_lower)) - self.outfile.write('#endif\n') + self.outfile.write(",\n arg_%s" % (a.name)) + self.outfile.write("));\n") + + self.outfile.write( + " for (l = connections; l != NULL; l = l->next)\n" + " {\n" + " GDBusConnection *connection = l->data;\n" + " g_dbus_connection_emit_signal (connection,\n" + ' NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "%s", "%s",\n' + " signal_variant, NULL);\n" + " }\n" % (i.name, s.name) + ) + self.outfile.write(" g_variant_unref (signal_variant);\n") + self.outfile.write(" g_list_free_full (connections, g_object_unref);\n") + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static void %s_skeleton_iface_init (%sIface *iface);\n" + % (i.name_lower, i.camel_name) + ) + + self.outfile.write("#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n") + self.outfile.write( + "G_DEFINE_TYPE_WITH_CODE (%sSkeleton, %s_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,\n" + % (i.camel_name, i.name_lower) + ) + self.outfile.write( + " G_ADD_PRIVATE (%sSkeleton)\n" % (i.camel_name) + ) + self.outfile.write( + " G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_skeleton_iface_init))\n\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write("#else\n") + self.outfile.write( + "G_DEFINE_TYPE_WITH_CODE (%sSkeleton, %s_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,\n" + % (i.camel_name, i.name_lower) + ) + self.outfile.write( + " G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_skeleton_iface_init))\n\n" + % (i.ns_upper, i.name_upper, i.name_lower) + ) + self.outfile.write("#endif\n") # finalize - self.outfile.write('static void\n' - '%s_skeleton_finalize (GObject *object)\n' - '{\n'%(i.name_lower)) - self.outfile.write(' %sSkeleton *skeleton = %s%s_SKELETON (object);\n'%(i.camel_name, i.ns_upper, i.name_upper)) + self.outfile.write( + "static void\n" + "%s_skeleton_finalize (GObject *object)\n" + "{\n" % (i.name_lower) + ) + self.outfile.write( + " %sSkeleton *skeleton = %s%s_SKELETON (object);\n" + % (i.camel_name, i.ns_upper, i.name_upper) + ) if len(i.properties) > 0: - self.outfile.write(' guint n;\n' - ' for (n = 0; n < %d; n++)\n' - ' g_value_unset (&skeleton->priv->properties[n]);\n'%(len(i.properties))) - self.outfile.write(' g_free (skeleton->priv->properties);\n') - self.outfile.write(' g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);\n') - self.outfile.write(' if (skeleton->priv->changed_properties_idle_source != NULL)\n') - self.outfile.write(' g_source_destroy (skeleton->priv->changed_properties_idle_source);\n') - self.outfile.write(' g_main_context_unref (skeleton->priv->context);\n') - self.outfile.write(' g_mutex_clear (&skeleton->priv->lock);\n') - self.outfile.write(' G_OBJECT_CLASS (%s_skeleton_parent_class)->finalize (object);\n' - '}\n' - '\n'%(i.name_lower)) + self.outfile.write( + " guint n;\n" + " for (n = 0; n < %d; n++)\n" + " g_value_unset (&skeleton->priv->properties[n]);\n" + % (len(i.properties)) + ) + self.outfile.write(" g_free (skeleton->priv->properties);\n") + self.outfile.write( + " g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);\n" + ) + self.outfile.write( + " if (skeleton->priv->changed_properties_idle_source != NULL)\n" + ) + self.outfile.write( + " g_source_destroy (skeleton->priv->changed_properties_idle_source);\n" + ) + self.outfile.write(" g_main_context_unref (skeleton->priv->context);\n") + self.outfile.write(" g_mutex_clear (&skeleton->priv->lock);\n") + self.outfile.write( + " G_OBJECT_CLASS (%s_skeleton_parent_class)->finalize (object);\n" + "}\n" + "\n" % (i.name_lower) + ) # property accessors (TODO: generate PropertiesChanged signals in setter) if len(i.properties) > 0: - self.outfile.write('static void\n' - '%s_skeleton_get_property (GObject *object,\n' - ' guint prop_id,\n' - ' GValue *value,\n' - ' GParamSpec *pspec G_GNUC_UNUSED)\n' - '{\n'%(i.name_lower)) - self.outfile.write(' %sSkeleton *skeleton = %s%s_SKELETON (object);\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' g_value_copy (&skeleton->priv->properties[prop_id - 1], value);\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - %(i.camel_name, i.ns_upper, i.name_upper, len(i.properties))) - self.outfile.write('}\n' - '\n') + self.outfile.write( + "static void\n" + "%s_skeleton_get_property (GObject *object,\n" + " guint prop_id,\n" + " GValue *value,\n" + " GParamSpec *pspec G_GNUC_UNUSED)\n" + "{\n" % (i.name_lower) + ) + self.outfile.write( + " %sSkeleton *skeleton = %s%s_SKELETON (object);\n" + " g_assert (prop_id != 0 && prop_id - 1 < %d);\n" + " g_mutex_lock (&skeleton->priv->lock);\n" + " g_value_copy (&skeleton->priv->properties[prop_id - 1], value);\n" + " g_mutex_unlock (&skeleton->priv->lock);\n" + % (i.camel_name, i.ns_upper, i.name_upper, len(i.properties)) + ) + self.outfile.write("}\n" "\n") # if property is already scheduled then re-use entry.. though it could be # that the user did @@ -2773,992 +3937,1285 @@ class CodeGenerator: # change event. If the latest value is not different from the original # one, we can simply ignore the ChangedProperty # - self.outfile.write('static gboolean\n' - '_%s_emit_changed (gpointer user_data)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write(' GList *l;\n' - ' GVariantBuilder builder;\n' - ' GVariantBuilder invalidated_builder;\n' - ' guint num_changes;\n' - '\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));\n' - ' g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));\n' - ' for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next)\n' - ' {\n' - ' ChangedProperty *cp = l->data;\n' - ' GVariant *variant;\n' - ' const GValue *cur_value;\n' - '\n' - ' cur_value = &skeleton->priv->properties[cp->prop_id - 1];\n' - ' if (!_g_value_equal (cur_value, &cp->orig_value))\n' - ' {\n' - ' variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature));\n' - ' g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant);\n' - ' g_variant_unref (variant);\n' - ' num_changes++;\n' - ' }\n' - ' }\n' - ' if (num_changes > 0)\n' - ' {\n' - ' GList *connections, *ll;\n' - ' GVariant *signal_variant;' - '\n' - ' signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "%s",\n' - ' &builder, &invalidated_builder));\n' - ' connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));\n' - ' for (ll = connections; ll != NULL; ll = ll->next)\n' - ' {\n' - ' GDBusConnection *connection = ll->data;\n' - '\n' - ' g_dbus_connection_emit_signal (connection,\n' - ' NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)),\n' - ' "org.freedesktop.DBus.Properties",\n' - ' "PropertiesChanged",\n' - ' signal_variant,\n' - ' NULL);\n' - ' }\n' - ' g_variant_unref (signal_variant);\n' - ' g_list_free_full (connections, g_object_unref);\n' - ' }\n' - ' else\n' - ' {\n' - ' g_variant_builder_clear (&builder);\n' - ' g_variant_builder_clear (&invalidated_builder);\n' - ' }\n' - %(i.name)) - self.outfile.write(' g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);\n') - self.outfile.write(' skeleton->priv->changed_properties = NULL;\n') - self.outfile.write(' skeleton->priv->changed_properties_idle_source = NULL;\n') - self.outfile.write(' g_mutex_unlock (&skeleton->priv->lock);\n') - self.outfile.write(' return FALSE;\n' - '}\n' - '\n') + self.outfile.write( + "static gboolean\n" + "_%s_emit_changed (gpointer user_data)\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n" + % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + " GList *l;\n" + " GVariantBuilder builder;\n" + " GVariantBuilder invalidated_builder;\n" + " guint num_changes;\n" + "\n" + " g_mutex_lock (&skeleton->priv->lock);\n" + ' g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));\n' + ' g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));\n' + " for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next)\n" + " {\n" + " ChangedProperty *cp = l->data;\n" + " GVariant *variant;\n" + " const GValue *cur_value;\n" + "\n" + " cur_value = &skeleton->priv->properties[cp->prop_id - 1];\n" + " if (!_g_value_equal (cur_value, &cp->orig_value))\n" + " {\n" + " variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature));\n" + ' g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant);\n' + " g_variant_unref (variant);\n" + " num_changes++;\n" + " }\n" + " }\n" + " if (num_changes > 0)\n" + " {\n" + " GList *connections, *ll;\n" + " GVariant *signal_variant;" + "\n" + ' signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "%s",\n' + " &builder, &invalidated_builder));\n" + " connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));\n" + " for (ll = connections; ll != NULL; ll = ll->next)\n" + " {\n" + " GDBusConnection *connection = ll->data;\n" + "\n" + " g_dbus_connection_emit_signal (connection,\n" + " NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)),\n" + ' "org.freedesktop.DBus.Properties",\n' + ' "PropertiesChanged",\n' + " signal_variant,\n" + " NULL);\n" + " }\n" + " g_variant_unref (signal_variant);\n" + " g_list_free_full (connections, g_object_unref);\n" + " }\n" + " else\n" + " {\n" + " g_variant_builder_clear (&builder);\n" + " g_variant_builder_clear (&invalidated_builder);\n" + " }\n" % (i.name) + ) + self.outfile.write( + " g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);\n" + ) + self.outfile.write(" skeleton->priv->changed_properties = NULL;\n") + self.outfile.write( + " skeleton->priv->changed_properties_idle_source = NULL;\n" + ) + self.outfile.write(" g_mutex_unlock (&skeleton->priv->lock);\n") + self.outfile.write(" return FALSE;\n" "}\n" "\n") # holding lock while being called - self.outfile.write('static void\n' - '_%s_schedule_emit_changed (%sSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value)\n' - '{\n' - ' ChangedProperty *cp;\n' - ' GList *l;\n' - ' cp = NULL;\n' - ' for (l = skeleton->priv->changed_properties; l != NULL; l = l->next)\n' - ' {\n' - ' ChangedProperty *i_cp = l->data;\n' - ' if (i_cp->info == info)\n' - ' {\n' - ' cp = i_cp;\n' - ' break;\n' - ' }\n' - ' }\n' - %(i.name_lower, i.camel_name)) - self.outfile.write(' if (cp == NULL)\n' - ' {\n' - ' cp = g_new0 (ChangedProperty, 1);\n' - ' cp->prop_id = prop_id;\n' - ' cp->info = info;\n' - ' skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp);\n' - ' g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value));\n' - ' g_value_copy (orig_value, &cp->orig_value);\n' - ' }\n' - '}\n' - '\n' - %()) + self.outfile.write( + "static void\n" + "_%s_schedule_emit_changed (%sSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value)\n" + "{\n" + " ChangedProperty *cp;\n" + " GList *l;\n" + " cp = NULL;\n" + " for (l = skeleton->priv->changed_properties; l != NULL; l = l->next)\n" + " {\n" + " ChangedProperty *i_cp = l->data;\n" + " if (i_cp->info == info)\n" + " {\n" + " cp = i_cp;\n" + " break;\n" + " }\n" + " }\n" % (i.name_lower, i.camel_name) + ) + self.outfile.write( + " if (cp == NULL)\n" + " {\n" + " cp = g_new0 (ChangedProperty, 1);\n" + " cp->prop_id = prop_id;\n" + " cp->info = info;\n" + " skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp);\n" + " g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value));\n" + " g_value_copy (orig_value, &cp->orig_value);\n" + " }\n" + "}\n" + "\n" + ) # Postpone setting up the refresh source until the ::notify signal is emitted as # this allows use of g_object_freeze_notify()/g_object_thaw_notify() ... # This is useful when updating several properties from another thread than # where the idle will be emitted from - self.outfile.write('static void\n' - '%s_skeleton_notify (GObject *object,\n' - ' GParamSpec *pspec G_GNUC_UNUSED)\n' - '{\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (object);\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' if (skeleton->priv->changed_properties != NULL &&\n' - ' skeleton->priv->changed_properties_idle_source == NULL)\n' - ' {\n' - ' skeleton->priv->changed_properties_idle_source = g_idle_source_new ();\n' - ' g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);\n' - ' g_source_set_callback (skeleton->priv->changed_properties_idle_source, _%s_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);\n' - ' g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _%s_emit_changed");\n' - ' g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);\n' - ' g_source_unref (skeleton->priv->changed_properties_idle_source);\n' - ' }\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - '}\n' - '\n' - %(i.name_lower, i.camel_name, i.ns_upper, i.name_upper, i.name_lower, i.name_lower)) - - self.outfile.write('static void\n' - '%s_skeleton_set_property (GObject *object,\n' - ' guint prop_id,\n' - ' const GValue *value,\n' - ' GParamSpec *pspec)\n' - '{\n'%(i.name_lower)) - self.outfile.write(' const _ExtendedGDBusPropertyInfo *info;\n' - ' %sSkeleton *skeleton = %s%s_SKELETON (object);\n' - ' g_assert (prop_id != 0 && prop_id - 1 < %d);\n' - ' info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' g_object_freeze_notify (object);\n' - ' if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))\n' - ' {\n' - ' if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL &&\n' - ' info->emits_changed_signal)\n' - ' _%s_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]);\n' - ' g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);\n' - ' g_object_notify_by_pspec (object, pspec);\n' - ' }\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - ' g_object_thaw_notify (object);\n' - %(i.camel_name, i.ns_upper, i.name_upper, len(i.properties), i.name_lower, i.name_lower)) - self.outfile.write('}\n' - '\n') - - self.outfile.write('static void\n' - '%s_skeleton_init (%sSkeleton *skeleton)\n' - '{\n' - '#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n' - ' skeleton->priv = %s_skeleton_get_instance_private (skeleton);\n' - '#else\n' - ' skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, %sTYPE_%s_SKELETON, %sSkeletonPrivate);\n' - '#endif\n\n' - %(i.name_lower, i.camel_name, - i.name_lower, - i.ns_upper, i.name_upper, i.camel_name)) - self.outfile.write(' g_mutex_init (&skeleton->priv->lock);\n') - self.outfile.write(' skeleton->priv->context = g_main_context_ref_thread_default ();\n') + self.outfile.write( + "static void\n" + "%s_skeleton_notify (GObject *object,\n" + " GParamSpec *pspec G_GNUC_UNUSED)\n" + "{\n" + " %sSkeleton *skeleton = %s%s_SKELETON (object);\n" + " g_mutex_lock (&skeleton->priv->lock);\n" + " if (skeleton->priv->changed_properties != NULL &&\n" + " skeleton->priv->changed_properties_idle_source == NULL)\n" + " {\n" + " skeleton->priv->changed_properties_idle_source = g_idle_source_new ();\n" + " g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);\n" + " g_source_set_callback (skeleton->priv->changed_properties_idle_source, _%s_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);\n" + ' g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _%s_emit_changed");\n' + " g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);\n" + " g_source_unref (skeleton->priv->changed_properties_idle_source);\n" + " }\n" + " g_mutex_unlock (&skeleton->priv->lock);\n" + "}\n" + "\n" + % ( + i.name_lower, + i.camel_name, + i.ns_upper, + i.name_upper, + i.name_lower, + i.name_lower, + ) + ) + + self.outfile.write( + "static void\n" + "%s_skeleton_set_property (GObject *object,\n" + " guint prop_id,\n" + " const GValue *value,\n" + " GParamSpec *pspec)\n" + "{\n" % (i.name_lower) + ) + self.outfile.write( + " const _ExtendedGDBusPropertyInfo *info;\n" + " %sSkeleton *skeleton = %s%s_SKELETON (object);\n" + " g_assert (prop_id != 0 && prop_id - 1 < %d);\n" + " info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n" + " g_mutex_lock (&skeleton->priv->lock);\n" + " g_object_freeze_notify (object);\n" + " if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))\n" + " {\n" + " if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL &&\n" + " info->emits_changed_signal)\n" + " _%s_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]);\n" + " g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);\n" + " g_object_notify_by_pspec (object, pspec);\n" + " }\n" + " g_mutex_unlock (&skeleton->priv->lock);\n" + " g_object_thaw_notify (object);\n" + % ( + i.camel_name, + i.ns_upper, + i.name_upper, + len(i.properties), + i.name_lower, + i.name_lower, + ) + ) + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static void\n" + "%s_skeleton_init (%sSkeleton *skeleton)\n" + "{\n" + "#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n" + " skeleton->priv = %s_skeleton_get_instance_private (skeleton);\n" + "#else\n" + " skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, %sTYPE_%s_SKELETON, %sSkeletonPrivate);\n" + "#endif\n\n" + % ( + i.name_lower, + i.camel_name, + i.name_lower, + i.ns_upper, + i.name_upper, + i.camel_name, + ) + ) + self.outfile.write(" g_mutex_init (&skeleton->priv->lock);\n") + self.outfile.write( + " skeleton->priv->context = g_main_context_ref_thread_default ();\n" + ) if len(i.properties) > 0: - self.outfile.write(' skeleton->priv->properties = g_new0 (GValue, %d);\n'%(len(i.properties))) + self.outfile.write( + " skeleton->priv->properties = g_new0 (GValue, %d);\n" + % (len(i.properties)) + ) n = 0 for p in i.properties: - self.outfile.write(' g_value_init (&skeleton->priv->properties[%d], %s);\n'%(n, p.arg.gtype)) + self.outfile.write( + " g_value_init (&skeleton->priv->properties[%d], %s);\n" + % (n, p.arg.gtype) + ) n += 1 - self.outfile.write('}\n' - '\n') + self.outfile.write("}\n" "\n") # property vfuncs n = 0 for p in i.properties: - self.outfile.write('static %s\n' - '%s_skeleton_get_%s (%s *object)\n' - '{\n' - %(p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)) - self.outfile.write(' %sSkeleton *skeleton = %s%s_SKELETON (object);\n'%(i.camel_name, i.ns_upper, i.name_upper)) - self.outfile.write(' %svalue;\n' - ' g_mutex_lock (&skeleton->priv->lock);\n' - ' value = %s (&(skeleton->priv->properties[%d]));\n' - ' g_mutex_unlock (&skeleton->priv->lock);\n' - %(p.arg.ctype_in_g, p.arg.gvalue_get, n)) - self.outfile.write(' return value;\n') - self.outfile.write('}\n') - self.outfile.write('\n') + self.outfile.write( + "static %s\n" + "%s_skeleton_get_%s (%s *object)\n" + "{\n" % (p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name) + ) + self.outfile.write( + " %sSkeleton *skeleton = %s%s_SKELETON (object);\n" + % (i.camel_name, i.ns_upper, i.name_upper) + ) + self.outfile.write( + " %svalue;\n" + " g_mutex_lock (&skeleton->priv->lock);\n" + " value = %s (&(skeleton->priv->properties[%d]));\n" + " g_mutex_unlock (&skeleton->priv->lock);\n" + % (p.arg.ctype_in_g, p.arg.gvalue_get, n) + ) + self.outfile.write(" return value;\n") + self.outfile.write("}\n") + self.outfile.write("\n") n += 1 - self.outfile.write('static void\n' - '%s_skeleton_class_init (%sSkeletonClass *klass)\n' - '{\n' - ' GObjectClass *gobject_class;\n' - ' GDBusInterfaceSkeletonClass *skeleton_class;\n' - '\n' - ' gobject_class = G_OBJECT_CLASS (klass);\n' - ' gobject_class->finalize = %s_skeleton_finalize;\n' - %(i.name_lower, i.camel_name, i.name_lower)) + self.outfile.write( + "static void\n" + "%s_skeleton_class_init (%sSkeletonClass *klass)\n" + "{\n" + " GObjectClass *gobject_class;\n" + " GDBusInterfaceSkeletonClass *skeleton_class;\n" + "\n" + " gobject_class = G_OBJECT_CLASS (klass);\n" + " gobject_class->finalize = %s_skeleton_finalize;\n" + % (i.name_lower, i.camel_name, i.name_lower) + ) if len(i.properties) > 0: - self.outfile.write(' gobject_class->get_property = %s_skeleton_get_property;\n' - ' gobject_class->set_property = %s_skeleton_set_property;\n' - ' gobject_class->notify = %s_skeleton_notify;\n' - '\n'%(i.name_lower, i.name_lower, i.name_lower)) - self.outfile.write('\n' - ' %s_override_properties (gobject_class, 1);\n'%(i.name_lower)) - self.outfile.write('\n' - ' skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);\n'); - self.outfile.write(' skeleton_class->get_info = %s_skeleton_dbus_interface_get_info;\n'%(i.name_lower)) - self.outfile.write(' skeleton_class->get_properties = %s_skeleton_dbus_interface_get_properties;\n'%(i.name_lower)) - self.outfile.write(' skeleton_class->flush = %s_skeleton_dbus_interface_flush;\n'%(i.name_lower)) - self.outfile.write(' skeleton_class->get_vtable = %s_skeleton_dbus_interface_get_vtable;\n'%(i.name_lower)) - - self.outfile.write('\n' - '#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38\n' - ' g_type_class_add_private (klass, sizeof (%sSkeletonPrivate));\n' - '#endif\n'%(i.camel_name)) - - self.outfile.write('}\n' - '\n') - - self.outfile.write('static void\n' - '%s_skeleton_iface_init (%sIface *iface)\n' - '{\n' - %(i.name_lower, i.camel_name)) + self.outfile.write( + " gobject_class->get_property = %s_skeleton_get_property;\n" + " gobject_class->set_property = %s_skeleton_set_property;\n" + " gobject_class->notify = %s_skeleton_notify;\n" + "\n" % (i.name_lower, i.name_lower, i.name_lower) + ) + self.outfile.write( + "\n" " %s_override_properties (gobject_class, 1);\n" % (i.name_lower) + ) + self.outfile.write( + "\n" " skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);\n" + ) + self.outfile.write( + " skeleton_class->get_info = %s_skeleton_dbus_interface_get_info;\n" + % (i.name_lower) + ) + self.outfile.write( + " skeleton_class->get_properties = %s_skeleton_dbus_interface_get_properties;\n" + % (i.name_lower) + ) + self.outfile.write( + " skeleton_class->flush = %s_skeleton_dbus_interface_flush;\n" + % (i.name_lower) + ) + self.outfile.write( + " skeleton_class->get_vtable = %s_skeleton_dbus_interface_get_vtable;\n" + % (i.name_lower) + ) + + self.outfile.write( + "\n" + "#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38\n" + " g_type_class_add_private (klass, sizeof (%sSkeletonPrivate));\n" + "#endif\n" % (i.camel_name) + ) + + self.outfile.write("}\n" "\n") + + self.outfile.write( + "static void\n" + "%s_skeleton_iface_init (%sIface *iface" % (i.name_lower, i.camel_name) + ) + if len(i.signals) == 0 and len(i.properties) == 0: + self.outfile.write(" G_GNUC_UNUSED)\n") + else: + self.outfile.write(")\n") + self.outfile.write("{\n") for s in i.signals: - self.outfile.write(' iface->%s = _%s_on_signal_%s;\n' - %(s.name_lower, i.name_lower, s.name_lower)) + self.outfile.write( + " iface->%s = _%s_on_signal_%s;\n" + % (s.name_lower, i.name_lower, s.name_lower) + ) for p in i.properties: - self.outfile.write(' iface->get_%s = %s_skeleton_get_%s;\n'%(p.name_lower, i.name_lower, p.name_lower)) - self.outfile.write('}\n' - '\n') + self.outfile.write( + " iface->get_%s = %s_skeleton_get_%s;\n" + % (p.name_lower, i.name_lower, p.name_lower) + ) + self.outfile.write("}\n" "\n") # constructors - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %s_skeleton_new:\n' - ' *\n' - ' * Creates a skeleton object for the D-Bus interface #%s.\n' - ' *\n' - ' * Returns: (transfer full) (type %sSkeleton): The skeleton object.\n' - %(i.name_lower, i.name, i.camel_name), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %s_skeleton_new:\n" + " *\n" + " * Creates a skeleton object for the D-Bus interface #%s.\n" + " *\n" + " * Returns: (transfer full) (type %sSkeleton): The skeleton object.\n" + % (i.name_lower, i.name, i.camel_name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *\n' - '%s_skeleton_new (void)\n' - '{\n' - ' return %s%s (g_object_new (%sTYPE_%s_SKELETON, NULL));\n' - '}\n' - '\n'%(i.camel_name, i.name_lower, i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)) + self.outfile.write( + "%s *\n" + "%s_skeleton_new (void)\n" + "{\n" + " return %s%s (g_object_new (%sTYPE_%s_SKELETON, NULL));\n" + "}\n" + "\n" + % ( + i.camel_name, + i.name_lower, + i.ns_upper, + i.name_upper, + i.ns_upper, + i.name_upper, + ) + ) # --------------------------------------------------------------------------------------------------- def generate_object(self): - self.outfile.write('/* ------------------------------------------------------------------------\n' - ' * Code for Object, ObjectProxy and ObjectSkeleton\n' - ' * ------------------------------------------------------------------------\n' - ' */\n' - '\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * SECTION:%sObject\n' - ' * @title: %sObject\n' - ' * @short_description: Specialized GDBusObject types\n' - ' *\n' - ' * This section contains the #%sObject, #%sObjectProxy, and #%sObjectSkeleton types which make it easier to work with objects implementing generated types for D-Bus interfaces.\n' - ' */\n' - %(self.namespace, self.namespace, self.namespace, self.namespace, self.namespace), False)) - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObject:\n' - ' *\n' - ' * The #%sObject type is a specialized container of interfaces.\n' - ' */\n' - %(self.namespace, self.namespace), False)) - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectIface:\n' - ' * @parent_iface: The parent interface.\n' - ' *\n' - ' * Virtual table for the #%sObject interface.\n' - ' */\n' - %(self.namespace, self.namespace), False)) - self.outfile.write('\n') - - self.outfile.write('typedef %sObjectIface %sObjectInterface;\n'%(self.namespace, self.namespace)) - self.outfile.write('G_DEFINE_INTERFACE_WITH_CODE (%sObject, %sobject, G_TYPE_OBJECT, g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_DBUS_OBJECT);)\n'%(self.namespace, self.ns_lower)) - self.outfile.write('\n') - self.outfile.write('static void\n' - '%sobject_default_init (%sObjectIface *iface)\n' - '{\n' - %(self.ns_lower, self.namespace)); + self.outfile.write( + "/* ------------------------------------------------------------------------\n" + " * Code for Object, ObjectProxy and ObjectSkeleton\n" + " * ------------------------------------------------------------------------\n" + " */\n" + "\n" + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * SECTION:%sObject\n" + " * @title: %sObject\n" + " * @short_description: Specialized GDBusObject types\n" + " *\n" + " * This section contains the #%sObject, #%sObjectProxy, and #%sObjectSkeleton types which make it easier to work with objects implementing generated types for D-Bus interfaces.\n" + " */\n" + % ( + self.namespace, + self.namespace, + self.namespace, + self.namespace, + self.namespace, + ), + False, + ) + ) + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObject:\n" + " *\n" + " * The #%sObject type is a specialized container of interfaces.\n" + " */\n" % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectIface:\n" + " * @parent_iface: The parent interface.\n" + " *\n" + " * Virtual table for the #%sObject interface.\n" + " */\n" % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write("\n") + + self.outfile.write( + "typedef %sObjectIface %sObjectInterface;\n" + % (self.namespace, self.namespace) + ) + self.outfile.write( + "G_DEFINE_INTERFACE_WITH_CODE (%sObject, %sobject, G_TYPE_OBJECT, g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_DBUS_OBJECT);)\n" + % (self.namespace, self.ns_lower) + ) + self.outfile.write("\n") + self.outfile.write( + "static void\n" + "%sobject_default_init (%sObjectIface *iface)\n" + "{\n" % (self.ns_lower, self.namespace) + ) for i in self.ifaces: - self.outfile.write(self.docbook_gen.expand( - ' /**\n' - ' * %sObject:%s:\n' - ' *\n' - ' * The #%s instance corresponding to the D-Bus interface #%s, if any.\n' - ' *\n' - ' * Connect to the #GObject::notify signal to get informed of property changes.\n' - %(self.namespace, i.name_hyphen, i.camel_name, i.name), False)) + self.outfile.write( + self.docbook_gen.expand( + " /**\n" + " * %sObject:%s:\n" + " *\n" + " * The #%s instance corresponding to the D-Bus interface #%s, if any.\n" + " *\n" + " * Connect to the #GObject::notify signal to get informed of property changes.\n" + % (self.namespace, i.name_hyphen, i.camel_name, i.name), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 2) - flags = 'G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS' + flags = "G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS" if i.deprecated: - flags = 'G_PARAM_DEPRECATED | ' + flags - self.outfile.write(' g_object_interface_install_property (iface, g_param_spec_object ("%s", "%s", "%s", %sTYPE_%s, %s));\n' - '\n' - %(i.name_hyphen, i.name_hyphen, i.name_hyphen, self.ns_upper, i.name_upper, flags)) - self.outfile.write('}\n' - '\n') + flags = "G_PARAM_DEPRECATED | " + flags + self.outfile.write( + ' g_object_interface_install_property (iface, g_param_spec_object ("%s", "%s", "%s", %sTYPE_%s, %s));\n' + "\n" + % ( + i.name_hyphen, + i.name_hyphen, + i.name_hyphen, + self.ns_upper, + i.name_upper, + flags, + ) + ) + self.outfile.write("}\n" "\n") for i in self.ifaces: - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_get_%s:\n' - ' * @object: A #%sObject.\n' - ' *\n' - ' * Gets the #%s instance for the D-Bus interface #%s on @object, if any.\n' - ' *\n' - ' * Returns: (transfer full) (nullable): A #%s that must be freed with g_object_unref() or %%NULL if @object does not implement the interface.\n' - %(self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name, i.name, i.camel_name), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_get_%s:\n" + " * @object: A #%sObject.\n" + " *\n" + " * Gets the #%s instance for the D-Bus interface #%s on @object, if any.\n" + " *\n" + " * Returns: (transfer full) (nullable): A #%s that must be freed with g_object_unref() or %%NULL if @object does not implement the interface.\n" + % ( + self.ns_lower, + i.name_upper.lower(), + self.namespace, + i.camel_name, + i.name, + i.camel_name, + ), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *%sobject_get_%s (%sObject *object)\n' - %(i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)) - self.outfile.write('{\n' - ' GDBusInterface *ret;\n' - ' ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' - ' if (ret == NULL)\n' - ' return NULL;\n' - ' return %s%s (ret);\n' - '}\n' - '\n' - %(i.name, self.ns_upper, i.name_upper)) - self.outfile.write('\n') + self.outfile.write( + "%s *%sobject_get_%s (%sObject *object)\n" + % (i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace) + ) + self.outfile.write( + "{\n" + " GDBusInterface *ret;\n" + ' ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' + " if (ret == NULL)\n" + " return NULL;\n" + " return %s%s (ret);\n" + "}\n" + "\n" % (i.name, self.ns_upper, i.name_upper) + ) + self.outfile.write("\n") for i in self.ifaces: - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_peek_%s: (skip)\n' - ' * @object: A #%sObject.\n' - ' *\n' - ' * Like %sobject_get_%s() but doesn\'t increase the reference count on the returned object.\n' - ' *\n' - ' * It is not safe to use the returned object if you are on another thread than the one where the #GDBusObjectManagerClient or #GDBusObjectManagerServer for @object is running.\n' - ' *\n' - ' * Returns: (transfer none) (nullable): A #%s or %%NULL if @object does not implement the interface. Do not free the returned object, it is owned by @object.\n' - %(self.ns_lower, i.name_upper.lower(), self.namespace, self.ns_lower, i.name_upper.lower(), i.camel_name), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_peek_%s: (skip)\n" + " * @object: A #%sObject.\n" + " *\n" + " * Like %sobject_get_%s() but doesn't increase the reference count on the returned object.\n" + " *\n" + " * It is not safe to use the returned object if you are on another thread than the one where the #GDBusObjectManagerClient or #GDBusObjectManagerServer for @object is running.\n" + " *\n" + " * Returns: (transfer none) (nullable): A #%s or %%NULL if @object does not implement the interface. Do not free the returned object, it is owned by @object.\n" + % ( + self.ns_lower, + i.name_upper.lower(), + self.namespace, + self.ns_lower, + i.name_upper.lower(), + i.camel_name, + ), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('%s *%sobject_peek_%s (%sObject *object)\n' - %(i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)) - self.outfile.write('{\n' - ' GDBusInterface *ret;\n' - ' ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' - ' if (ret == NULL)\n' - ' return NULL;\n' - ' g_object_unref (ret);\n' - ' return %s%s (ret);\n' - '}\n' - '\n' - %(i.name, self.ns_upper, i.name_upper)) - self.outfile.write('\n') + self.outfile.write( + "%s *%sobject_peek_%s (%sObject *object)\n" + % (i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace) + ) + self.outfile.write( + "{\n" + " GDBusInterface *ret;\n" + ' ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' + " if (ret == NULL)\n" + " return NULL;\n" + " g_object_unref (ret);\n" + " return %s%s (ret);\n" + "}\n" + "\n" % (i.name, self.ns_upper, i.name_upper) + ) + self.outfile.write("\n") # shared by ObjectProxy and ObjectSkeleton classes - self.outfile.write('static void\n' - '%sobject_notify (GDBusObject *object, GDBusInterface *interface)\n' - '{\n' - ' _ExtendedGDBusInterfaceInfo *info = (_ExtendedGDBusInterfaceInfo *) g_dbus_interface_get_info (interface);\n' - ' /* info can be NULL if the other end is using a D-Bus interface we don\'t know\n' - ' * anything about, for example old generated code in this process talking to\n' - ' * newer generated code in the other process. */\n' - ' if (info != NULL)\n' - ' g_object_notify (G_OBJECT (object), info->hyphen_name);\n' - '}\n' - '\n' - %(self.ns_lower)) - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectProxy:\n' - ' *\n' - ' * The #%sObjectProxy structure contains only private data and should only be accessed using the provided API.\n' - %(self.namespace, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('\n') - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectProxyClass:\n' - ' * @parent_class: The parent class.\n' - ' *\n' - ' * Class structure for #%sObjectProxy.\n' - %(self.namespace, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('\n') + self.outfile.write( + "static void\n" + "%sobject_notify (GDBusObject *object, GDBusInterface *interface)\n" + "{\n" + " _ExtendedGDBusInterfaceInfo *info = (_ExtendedGDBusInterfaceInfo *) g_dbus_interface_get_info (interface);\n" + " /* info can be NULL if the other end is using a D-Bus interface we don't know\n" + " * anything about, for example old generated code in this process talking to\n" + " * newer generated code in the other process. */\n" + " if (info != NULL)\n" + " g_object_notify (G_OBJECT (object), info->hyphen_name);\n" + "}\n" + "\n" % (self.ns_lower) + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectProxy:\n" + " *\n" + " * The #%sObjectProxy structure contains only private data and should only be accessed using the provided API.\n" + % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write("\n") + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectProxyClass:\n" + " * @parent_class: The parent class.\n" + " *\n" + " * Class structure for #%sObjectProxy.\n" + % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write("\n") # class boilerplate - self.outfile.write('static void\n' - '%sobject_proxy__%sobject_iface_init (%sObjectIface *iface G_GNUC_UNUSED)\n' - '{\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_lower, self.namespace)) - self.outfile.write('static void\n' - '%sobject_proxy__g_dbus_object_iface_init (GDBusObjectIface *iface)\n' - '{\n' - ' iface->interface_added = %sobject_notify;\n' - ' iface->interface_removed = %sobject_notify;\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_lower, self.ns_lower)) - self.outfile.write('\n') - self.outfile.write('G_DEFINE_TYPE_WITH_CODE (%sObjectProxy, %sobject_proxy, G_TYPE_DBUS_OBJECT_PROXY,\n' - ' G_IMPLEMENT_INTERFACE (%sTYPE_OBJECT, %sobject_proxy__%sobject_iface_init)\n' - ' G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, %sobject_proxy__g_dbus_object_iface_init))\n' - '\n' - %(self.namespace, self.ns_lower, self.ns_upper, self.ns_lower, self.ns_lower, self.ns_lower)) + self.outfile.write( + "static void\n" + "%sobject_proxy__%sobject_iface_init (%sObjectIface *iface G_GNUC_UNUSED)\n" + "{\n" + "}\n" + "\n" % (self.ns_lower, self.ns_lower, self.namespace) + ) + self.outfile.write( + "static void\n" + "%sobject_proxy__g_dbus_object_iface_init (GDBusObjectIface *iface)\n" + "{\n" + " iface->interface_added = %sobject_notify;\n" + " iface->interface_removed = %sobject_notify;\n" + "}\n" + "\n" % (self.ns_lower, self.ns_lower, self.ns_lower) + ) + self.outfile.write("\n") + self.outfile.write( + "G_DEFINE_TYPE_WITH_CODE (%sObjectProxy, %sobject_proxy, G_TYPE_DBUS_OBJECT_PROXY,\n" + " G_IMPLEMENT_INTERFACE (%sTYPE_OBJECT, %sobject_proxy__%sobject_iface_init)\n" + " G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, %sobject_proxy__g_dbus_object_iface_init))\n" + "\n" + % ( + self.namespace, + self.ns_lower, + self.ns_upper, + self.ns_lower, + self.ns_lower, + self.ns_lower, + ) + ) # class boilerplate - self.outfile.write('static void\n' - '%sobject_proxy_init (%sObjectProxy *object G_GNUC_UNUSED)\n' - '{\n' - '}\n' - '\n'%(self.ns_lower, self.namespace)) - self.outfile.write('static void\n' - '%sobject_proxy_set_property (GObject *gobject,\n' - ' guint prop_id,\n' - ' const GValue *value G_GNUC_UNUSED,\n' - ' GParamSpec *pspec)\n' - '{\n' - ' G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n' - %(self.ns_lower)) - self.outfile.write('}\n' - '\n'%()) - self.outfile.write('static void\n' - '%sobject_proxy_get_property (GObject *gobject,\n' - ' guint prop_id,\n' - ' GValue *value,\n' - ' GParamSpec *pspec)\n' - '{\n' - ' %sObjectProxy *object = %sOBJECT_PROXY (gobject);\n' - ' GDBusInterface *interface;\n' - '\n' - ' switch (prop_id)\n' - ' {\n' - %(self.ns_lower, self.namespace, self.ns_upper)) + self.outfile.write( + "static void\n" + "%sobject_proxy_init (%sObjectProxy *object G_GNUC_UNUSED)\n" + "{\n" + "}\n" + "\n" % (self.ns_lower, self.namespace) + ) + self.outfile.write( + "static void\n" + "%sobject_proxy_set_property (GObject *gobject,\n" + " guint prop_id,\n" + " const GValue *value G_GNUC_UNUSED,\n" + " GParamSpec *pspec)\n" + "{\n" + " G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n" + % (self.ns_lower) + ) + self.outfile.write("}\n" "\n") + self.outfile.write( + "static void\n" + "%sobject_proxy_get_property (GObject *gobject,\n" + " guint prop_id,\n" + " GValue *value,\n" + " GParamSpec *pspec)\n" + "{\n" + " %sObjectProxy *object = %sOBJECT_PROXY (gobject);\n" + " GDBusInterface *interface;\n" + "\n" + " switch (prop_id)\n" + " {\n" % (self.ns_lower, self.namespace, self.ns_upper) + ) n = 1 for i in self.ifaces: - self.outfile.write(' case %d:\n' - ' interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' - ' g_value_take_object (value, interface);\n' - ' break;\n' - '\n' - %(n, i.name)) + self.outfile.write( + " case %d:\n" + ' interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' + " g_value_take_object (value, interface);\n" + " break;\n" + "\n" % (n, i.name) + ) n += 1 - self.outfile.write(' default:\n' - ' G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n' - ' break;\n' - ' }\n' - '}\n' - '\n'%()) - self.outfile.write('static void\n' - '%sobject_proxy_class_init (%sObjectProxyClass *klass)\n' - '{\n' - ' GObjectClass *gobject_class = G_OBJECT_CLASS (klass);\n' - '\n' - ' gobject_class->set_property = %sobject_proxy_set_property;\n' - ' gobject_class->get_property = %sobject_proxy_get_property;\n' - '\n' - %(self.ns_lower, self.namespace, self.ns_lower, self.ns_lower)) + self.outfile.write( + " default:\n" + " G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n" + " break;\n" + " }\n" + "}\n" + "\n" + ) + self.outfile.write( + "static void\n" + "%sobject_proxy_class_init (%sObjectProxyClass *klass)\n" + "{\n" + " GObjectClass *gobject_class = G_OBJECT_CLASS (klass);\n" + "\n" + " gobject_class->set_property = %sobject_proxy_set_property;\n" + " gobject_class->get_property = %sobject_proxy_get_property;\n" + "\n" % (self.ns_lower, self.namespace, self.ns_lower, self.ns_lower) + ) n = 1 for i in self.ifaces: - self.outfile.write(' g_object_class_override_property (gobject_class, %d, "%s");' - '\n' - %(n, i.name_hyphen)) + self.outfile.write( + ' g_object_class_override_property (gobject_class, %d, "%s");' + "\n" % (n, i.name_hyphen) + ) n += 1 - self.outfile.write('}\n' - '\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_proxy_new:\n' - ' * @connection: A #GDBusConnection.\n' - ' * @object_path: An object path.\n' - ' *\n' - ' * Creates a new proxy object.\n' - ' *\n' - ' * Returns: (transfer full): The proxy object.\n' - ' */\n' - %(self.ns_lower), False)) - self.outfile.write('%sObjectProxy *\n' - '%sobject_proxy_new (GDBusConnection *connection,\n' - ' const gchar *object_path)\n' - '{\n' - ' g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);\n' - ' g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);\n' - ' return %sOBJECT_PROXY (g_object_new (%sTYPE_OBJECT_PROXY, "g-connection", connection, "g-object-path", object_path, NULL));\n' - '}\n' - '\n'%(self.namespace, self.ns_lower, self.ns_upper, self.ns_upper)) - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectSkeleton:\n' - ' *\n' - ' * The #%sObjectSkeleton structure contains only private data and should only be accessed using the provided API.\n' - %(self.namespace, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('\n') - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectSkeletonClass:\n' - ' * @parent_class: The parent class.\n' - ' *\n' - ' * Class structure for #%sObjectSkeleton.\n' - %(self.namespace, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('\n') + self.outfile.write("}\n" "\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_proxy_new:\n" + " * @connection: A #GDBusConnection.\n" + " * @object_path: An object path.\n" + " *\n" + " * Creates a new proxy object.\n" + " *\n" + " * Returns: (transfer full): The proxy object.\n" + " */\n" % (self.ns_lower), + False, + ) + ) + self.outfile.write( + "%sObjectProxy *\n" + "%sobject_proxy_new (GDBusConnection *connection,\n" + " const gchar *object_path)\n" + "{\n" + " g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);\n" + " g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);\n" + ' return %sOBJECT_PROXY (g_object_new (%sTYPE_OBJECT_PROXY, "g-connection", connection, "g-object-path", object_path, NULL));\n' + "}\n" + "\n" % (self.namespace, self.ns_lower, self.ns_upper, self.ns_upper) + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectSkeleton:\n" + " *\n" + " * The #%sObjectSkeleton structure contains only private data and should only be accessed using the provided API.\n" + % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write("\n") + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectSkeletonClass:\n" + " * @parent_class: The parent class.\n" + " *\n" + " * Class structure for #%sObjectSkeleton.\n" + % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write("\n") # class boilerplate - self.outfile.write('static void\n' - '%sobject_skeleton__%sobject_iface_init (%sObjectIface *iface G_GNUC_UNUSED)\n' - '{\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_lower, self.namespace)) - self.outfile.write('\n') - self.outfile.write('static void\n' - '%sobject_skeleton__g_dbus_object_iface_init (GDBusObjectIface *iface)\n' - '{\n' - ' iface->interface_added = %sobject_notify;\n' - ' iface->interface_removed = %sobject_notify;\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_lower, self.ns_lower)) - self.outfile.write('G_DEFINE_TYPE_WITH_CODE (%sObjectSkeleton, %sobject_skeleton, G_TYPE_DBUS_OBJECT_SKELETON,\n' - ' G_IMPLEMENT_INTERFACE (%sTYPE_OBJECT, %sobject_skeleton__%sobject_iface_init)\n' - ' G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, %sobject_skeleton__g_dbus_object_iface_init))\n' - '\n' - %(self.namespace, self.ns_lower, self.ns_upper, self.ns_lower, self.ns_lower, self.ns_lower)) + self.outfile.write( + "static void\n" + "%sobject_skeleton__%sobject_iface_init (%sObjectIface *iface G_GNUC_UNUSED)\n" + "{\n" + "}\n" + "\n" % (self.ns_lower, self.ns_lower, self.namespace) + ) + self.outfile.write("\n") + self.outfile.write( + "static void\n" + "%sobject_skeleton__g_dbus_object_iface_init (GDBusObjectIface *iface)\n" + "{\n" + " iface->interface_added = %sobject_notify;\n" + " iface->interface_removed = %sobject_notify;\n" + "}\n" + "\n" % (self.ns_lower, self.ns_lower, self.ns_lower) + ) + self.outfile.write( + "G_DEFINE_TYPE_WITH_CODE (%sObjectSkeleton, %sobject_skeleton, G_TYPE_DBUS_OBJECT_SKELETON,\n" + " G_IMPLEMENT_INTERFACE (%sTYPE_OBJECT, %sobject_skeleton__%sobject_iface_init)\n" + " G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, %sobject_skeleton__g_dbus_object_iface_init))\n" + "\n" + % ( + self.namespace, + self.ns_lower, + self.ns_upper, + self.ns_lower, + self.ns_lower, + self.ns_lower, + ) + ) # class boilerplate - self.outfile.write('static void\n' - '%sobject_skeleton_init (%sObjectSkeleton *object G_GNUC_UNUSED)\n' - '{\n' - '}\n' - '\n'%(self.ns_lower, self.namespace)) - self.outfile.write('static void\n' - '%sobject_skeleton_set_property (GObject *gobject,\n' - ' guint prop_id,\n' - ' const GValue *value,\n' - ' GParamSpec *pspec)\n' - '{\n' - ' %sObjectSkeleton *object = %sOBJECT_SKELETON (gobject);\n' - ' GDBusInterfaceSkeleton *interface;\n' - '\n' - ' switch (prop_id)\n' - ' {\n' - %(self.ns_lower, self.namespace, self.ns_upper)) + self.outfile.write( + "static void\n" + "%sobject_skeleton_init (%sObjectSkeleton *object G_GNUC_UNUSED)\n" + "{\n" + "}\n" + "\n" % (self.ns_lower, self.namespace) + ) + self.outfile.write( + "static void\n" + "%sobject_skeleton_set_property (GObject *gobject,\n" + " guint prop_id,\n" + " const GValue *value,\n" + " GParamSpec *pspec)\n" + "{\n" + " %sObjectSkeleton *object = %sOBJECT_SKELETON (gobject);\n" + " GDBusInterfaceSkeleton *interface;\n" + "\n" + " switch (prop_id)\n" + " {\n" % (self.ns_lower, self.namespace, self.ns_upper) + ) n = 1 for i in self.ifaces: - self.outfile.write(' case %d:\n' - ' interface = g_value_get_object (value);\n' - ' if (interface != NULL)\n' - ' {\n' - ' g_warn_if_fail (%sIS_%s (interface));\n' - ' g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object), interface);\n' - ' }\n' - ' else\n' - ' {\n' - ' g_dbus_object_skeleton_remove_interface_by_name (G_DBUS_OBJECT_SKELETON (object), "%s");\n' - ' }\n' - ' break;\n' - '\n' - %(n, self.ns_upper, i.name_upper, i.name)) + self.outfile.write( + " case %d:\n" + " interface = g_value_get_object (value);\n" + " if (interface != NULL)\n" + " {\n" + " g_warn_if_fail (%sIS_%s (interface));\n" + " g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object), interface);\n" + " }\n" + " else\n" + " {\n" + ' g_dbus_object_skeleton_remove_interface_by_name (G_DBUS_OBJECT_SKELETON (object), "%s");\n' + " }\n" + " break;\n" + "\n" % (n, self.ns_upper, i.name_upper, i.name) + ) n += 1 - self.outfile.write(' default:\n' - ' G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n' - ' break;\n' - ' }\n' - '}\n' - '\n'%()) - self.outfile.write('static void\n' - '%sobject_skeleton_get_property (GObject *gobject,\n' - ' guint prop_id,\n' - ' GValue *value,\n' - ' GParamSpec *pspec)\n' - '{\n' - ' %sObjectSkeleton *object = %sOBJECT_SKELETON (gobject);\n' - ' GDBusInterface *interface;\n' - '\n' - ' switch (prop_id)\n' - ' {\n' - %(self.ns_lower, self.namespace, self.ns_upper)) + self.outfile.write( + " default:\n" + " G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n" + " break;\n" + " }\n" + "}\n" + "\n" + ) + self.outfile.write( + "static void\n" + "%sobject_skeleton_get_property (GObject *gobject,\n" + " guint prop_id,\n" + " GValue *value,\n" + " GParamSpec *pspec)\n" + "{\n" + " %sObjectSkeleton *object = %sOBJECT_SKELETON (gobject);\n" + " GDBusInterface *interface;\n" + "\n" + " switch (prop_id)\n" + " {\n" % (self.ns_lower, self.namespace, self.ns_upper) + ) n = 1 for i in self.ifaces: - self.outfile.write(' case %d:\n' - ' interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' - ' g_value_take_object (value, interface);\n' - ' break;\n' - '\n' - %(n, i.name)) + self.outfile.write( + " case %d:\n" + ' interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n' + " g_value_take_object (value, interface);\n" + " break;\n" + "\n" % (n, i.name) + ) n += 1 - self.outfile.write(' default:\n' - ' G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n' - ' break;\n' - ' }\n' - '}\n' - '\n'%()) - self.outfile.write('static void\n' - '%sobject_skeleton_class_init (%sObjectSkeletonClass *klass)\n' - '{\n' - ' GObjectClass *gobject_class = G_OBJECT_CLASS (klass);\n' - '\n' - ' gobject_class->set_property = %sobject_skeleton_set_property;\n' - ' gobject_class->get_property = %sobject_skeleton_get_property;\n' - '\n' - %(self.ns_lower, self.namespace, self.ns_lower, self.ns_lower)) + self.outfile.write( + " default:\n" + " G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n" + " break;\n" + " }\n" + "}\n" + "\n" + ) + self.outfile.write( + "static void\n" + "%sobject_skeleton_class_init (%sObjectSkeletonClass *klass)\n" + "{\n" + " GObjectClass *gobject_class = G_OBJECT_CLASS (klass);\n" + "\n" + " gobject_class->set_property = %sobject_skeleton_set_property;\n" + " gobject_class->get_property = %sobject_skeleton_get_property;\n" + "\n" % (self.ns_lower, self.namespace, self.ns_lower, self.ns_lower) + ) n = 1 for i in self.ifaces: - self.outfile.write(' g_object_class_override_property (gobject_class, %d, "%s");' - '\n' - %(n, i.name_hyphen)) + self.outfile.write( + ' g_object_class_override_property (gobject_class, %d, "%s");' + "\n" % (n, i.name_hyphen) + ) n += 1 - self.outfile.write('}\n' - '\n') - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_skeleton_new:\n' - ' * @object_path: An object path.\n' - ' *\n' - ' * Creates a new skeleton object.\n' - ' *\n' - ' * Returns: (transfer full): The skeleton object.\n' - ' */\n' - %(self.ns_lower), False)) - self.outfile.write('%sObjectSkeleton *\n' - '%sobject_skeleton_new (const gchar *object_path)\n' - '{\n' - ' g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);\n' - ' return %sOBJECT_SKELETON (g_object_new (%sTYPE_OBJECT_SKELETON, "g-object-path", object_path, NULL));\n' - '}\n' - '\n'%(self.namespace, self.ns_lower, self.ns_upper, self.ns_upper)) + self.outfile.write("}\n" "\n") + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_skeleton_new:\n" + " * @object_path: An object path.\n" + " *\n" + " * Creates a new skeleton object.\n" + " *\n" + " * Returns: (transfer full): The skeleton object.\n" + " */\n" % (self.ns_lower), + False, + ) + ) + self.outfile.write( + "%sObjectSkeleton *\n" + "%sobject_skeleton_new (const gchar *object_path)\n" + "{\n" + " g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);\n" + ' return %sOBJECT_SKELETON (g_object_new (%sTYPE_OBJECT_SKELETON, "g-object-path", object_path, NULL));\n' + "}\n" + "\n" % (self.namespace, self.ns_lower, self.ns_upper, self.ns_upper) + ) for i in self.ifaces: - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_skeleton_set_%s:\n' - ' * @object: A #%sObjectSkeleton.\n' - ' * @interface_: (nullable): A #%s or %%NULL to clear the interface.\n' - ' *\n' - ' * Sets the #%s instance for the D-Bus interface #%s on @object.\n' - %(self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name, i.camel_name, i.name), False)) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_skeleton_set_%s:\n" + " * @object: A #%sObjectSkeleton.\n" + " * @interface_: (nullable): A #%s or %%NULL to clear the interface.\n" + " *\n" + " * Sets the #%s instance for the D-Bus interface #%s on @object.\n" + % ( + self.ns_lower, + i.name_upper.lower(), + self.namespace, + i.camel_name, + i.camel_name, + i.name, + ), + False, + ) + ) self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0) - self.outfile.write('void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_)\n' - %(self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name)) - self.outfile.write('{\n' - ' g_object_set (G_OBJECT (object), "%s", interface_, NULL);\n' - '}\n' - '\n' - %(i.name_hyphen)) - self.outfile.write('\n') - + self.outfile.write( + "void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_)\n" + % (self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name) + ) + self.outfile.write( + "{\n" + ' g_object_set (G_OBJECT (object), "%s", interface_, NULL);\n' + "}\n" + "\n" % (i.name_hyphen) + ) + self.outfile.write("\n") def generate_object_manager_client(self): - self.outfile.write('/* ------------------------------------------------------------------------\n' - ' * Code for ObjectManager client\n' - ' * ------------------------------------------------------------------------\n' - ' */\n' - '\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * SECTION:%sObjectManagerClient\n' - ' * @title: %sObjectManagerClient\n' - ' * @short_description: Generated GDBusObjectManagerClient type\n' - ' *\n' - ' * This section contains a #GDBusObjectManagerClient that uses %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc.\n' - ' */\n' - %(self.namespace, self.namespace, self.ns_lower), False)) - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectManagerClient:\n' - ' *\n' - ' * The #%sObjectManagerClient structure contains only private data and should only be accessed using the provided API.\n' - %(self.namespace, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('\n') - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sObjectManagerClientClass:\n' - ' * @parent_class: The parent class.\n' - ' *\n' - ' * Class structure for #%sObjectManagerClient.\n' - %(self.namespace, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('\n') + self.outfile.write( + "/* ------------------------------------------------------------------------\n" + " * Code for ObjectManager client\n" + " * ------------------------------------------------------------------------\n" + " */\n" + "\n" + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * SECTION:%sObjectManagerClient\n" + " * @title: %sObjectManagerClient\n" + " * @short_description: Generated GDBusObjectManagerClient type\n" + " *\n" + " * This section contains a #GDBusObjectManagerClient that uses %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc.\n" + " */\n" % (self.namespace, self.namespace, self.ns_lower), + False, + ) + ) + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectManagerClient:\n" + " *\n" + " * The #%sObjectManagerClient structure contains only private data and should only be accessed using the provided API.\n" + % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write("\n") + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sObjectManagerClientClass:\n" + " * @parent_class: The parent class.\n" + " *\n" + " * Class structure for #%sObjectManagerClient.\n" + % (self.namespace, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write("\n") # class boilerplate - self.outfile.write('G_DEFINE_TYPE (%sObjectManagerClient, %sobject_manager_client, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT)\n' - '\n' - %(self.namespace, self.ns_lower)) + self.outfile.write( + "G_DEFINE_TYPE (%sObjectManagerClient, %sobject_manager_client, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT)\n" + "\n" % (self.namespace, self.ns_lower) + ) # class boilerplate - self.outfile.write('static void\n' - '%sobject_manager_client_init (%sObjectManagerClient *manager G_GNUC_UNUSED)\n' - '{\n' - '}\n' - '\n'%(self.ns_lower, self.namespace)) - self.outfile.write('static void\n' - '%sobject_manager_client_class_init (%sObjectManagerClientClass *klass G_GNUC_UNUSED)\n' - '{\n' - '}\n' - '\n'%(self.ns_lower, self.namespace)) - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_manager_client_get_proxy_type:\n' - ' * @manager: A #GDBusObjectManagerClient.\n' - ' * @object_path: The object path of the remote object (unused).\n' - ' * @interface_name: (nullable): Interface name of the remote object or %%NULL to get the object proxy #GType.\n' - ' * @user_data: User data (unused).\n' - ' *\n' - ' * A #GDBusProxyTypeFunc that maps @interface_name to the generated #GDBusObjectProxy derived and #GDBusProxy derived types.\n' - ' *\n' - ' * Returns: A #GDBusProxy derived #GType if @interface_name is not %%NULL, otherwise the #GType for #%sObjectProxy.\n' - %(self.ns_lower, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('GType\n' - '%sobject_manager_client_get_proxy_type (GDBusObjectManagerClient *manager G_GNUC_UNUSED, const gchar *object_path G_GNUC_UNUSED, const gchar *interface_name, gpointer user_data G_GNUC_UNUSED)\n' - '{\n' - %(self.ns_lower)) - self.outfile.write(' static gsize once_init_value = 0;\n' - ' static GHashTable *lookup_hash;\n' - ' GType ret;\n' - '\n' - ' if (interface_name == NULL)\n' - ' return %sTYPE_OBJECT_PROXY;\n' - ' if (g_once_init_enter (&once_init_value))\n' - ' {\n' - ' lookup_hash = g_hash_table_new (g_str_hash, g_str_equal);\n' - %(self.ns_upper)) + self.outfile.write( + "static void\n" + "%sobject_manager_client_init (%sObjectManagerClient *manager G_GNUC_UNUSED)\n" + "{\n" + "}\n" + "\n" % (self.ns_lower, self.namespace) + ) + self.outfile.write( + "static void\n" + "%sobject_manager_client_class_init (%sObjectManagerClientClass *klass G_GNUC_UNUSED)\n" + "{\n" + "}\n" + "\n" % (self.ns_lower, self.namespace) + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_manager_client_get_proxy_type:\n" + " * @manager: A #GDBusObjectManagerClient.\n" + " * @object_path: The object path of the remote object (unused).\n" + " * @interface_name: (nullable): Interface name of the remote object or %%NULL to get the object proxy #GType.\n" + " * @user_data: User data (unused).\n" + " *\n" + " * A #GDBusProxyTypeFunc that maps @interface_name to the generated #GDBusObjectProxy derived and #GDBusProxy derived types.\n" + " *\n" + " * Returns: A #GDBusProxy derived #GType if @interface_name is not %%NULL, otherwise the #GType for #%sObjectProxy.\n" + % (self.ns_lower, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write( + "GType\n" + "%sobject_manager_client_get_proxy_type (GDBusObjectManagerClient *manager G_GNUC_UNUSED, const gchar *object_path G_GNUC_UNUSED, const gchar *interface_name, gpointer user_data G_GNUC_UNUSED)\n" + "{\n" % (self.ns_lower) + ) + self.outfile.write( + " static gsize once_init_value = 0;\n" + " static GHashTable *lookup_hash;\n" + " GType ret;\n" + "\n" + " if (interface_name == NULL)\n" + " return %sTYPE_OBJECT_PROXY;\n" + " if (g_once_init_enter (&once_init_value))\n" + " {\n" + " lookup_hash = g_hash_table_new (g_str_hash, g_str_equal);\n" + % (self.ns_upper) + ) for i in self.ifaces: - self.outfile.write(' g_hash_table_insert (lookup_hash, (gpointer) "%s", GSIZE_TO_POINTER (%sTYPE_%s_PROXY));\n' - %(i.name, i.ns_upper, i.name_upper)) - self.outfile.write(' g_once_init_leave (&once_init_value, 1);\n' - ' }\n') - self.outfile.write(' ret = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (lookup_hash, interface_name));\n' - ' if (ret == (GType) 0)\n' - ' ret = G_TYPE_DBUS_PROXY;\n') - self.outfile.write(' return ret;\n' - '}\n' - '\n') + self.outfile.write( + ' g_hash_table_insert (lookup_hash, (gpointer) "%s", GSIZE_TO_POINTER (%sTYPE_%s_PROXY));\n' + % (i.name, i.ns_upper, i.name_upper) + ) + self.outfile.write(" g_once_init_leave (&once_init_value, 1);\n" " }\n") + self.outfile.write( + " ret = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (lookup_hash, interface_name));\n" + " if (ret == (GType) 0)\n" + " ret = G_TYPE_DBUS_PROXY;\n" + ) + self.outfile.write(" return ret;\n" "}\n" "\n") # constructors - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_manager_client_new:\n' - ' * @connection: A #GDBusConnection.\n' - ' * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n' - ' * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n' - ' * @user_data: User data to pass to @callback.\n' - ' *\n' - ' * Asynchronously creates #GDBusObjectManagerClient using %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new() for more details.\n' - ' *\n' - ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' - ' * You can then call %sobject_manager_client_new_finish() to get the result of the operation.\n' - ' *\n' - ' * See %sobject_manager_client_new_sync() for the synchronous, blocking version of this constructor.\n' - %(self.ns_lower, self.ns_lower, self.ns_lower, self.ns_lower), False)) - self.outfile.write(' */\n') - self.outfile.write('void\n' - '%sobject_manager_client_new (\n' - ' GDBusConnection *connection,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data)\n' - '{\n' - ' g_async_initable_new_async (%sTYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_upper, self.ns_lower)) - self.outfile.write('/**\n' - ' * %sobject_manager_client_new_finish:\n' - ' * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %sobject_manager_client_new().\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Finishes an operation started with %sobject_manager_client_new().\n' - ' *\n' - ' * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n' - %(self.ns_lower, self.ns_lower, self.ns_lower, self.namespace)) - self.outfile.write(' */\n') - self.outfile.write('GDBusObjectManager *\n' - '%sobject_manager_client_new_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error)\n' - '{\n' - ' GObject *ret;\n' - ' GObject *source_object;\n' - ' source_object = g_async_result_get_source_object (res);\n' - ' ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n' - ' g_object_unref (source_object);\n' - ' if (ret != NULL)\n' - ' return G_DBUS_OBJECT_MANAGER (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(self.ns_lower)) - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_manager_client_new_sync:\n' - ' * @connection: A #GDBusConnection.\n' - ' * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n' - ' * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Synchronously creates #GDBusObjectManagerClient using %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new_sync() for more details.\n' - ' *\n' - ' * The calling thread is blocked until a reply is received.\n' - ' *\n' - ' * See %sobject_manager_client_new() for the asynchronous version of this constructor.\n' - ' *\n' - ' * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n' - %(self.ns_lower, self.ns_lower, self.ns_lower, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('GDBusObjectManager *\n' - '%sobject_manager_client_new_sync (\n' - ' GDBusConnection *connection,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error)\n' - '{\n' - ' GInitable *ret;\n' - ' ret = g_initable_new (%sTYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' - ' if (ret != NULL)\n' - ' return G_DBUS_OBJECT_MANAGER (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_upper, self.ns_lower)) - self.outfile.write('\n') - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_manager_client_new_for_bus:\n' - ' * @bus_type: A #GBusType.\n' - ' * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n' - ' * @name: A bus name (well-known or unique).\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n' - ' * @user_data: User data to pass to @callback.\n' - ' *\n' - ' * Like %sobject_manager_client_new() but takes a #GBusType instead of a #GDBusConnection.\n' - ' *\n' - ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' - ' * You can then call %sobject_manager_client_new_for_bus_finish() to get the result of the operation.\n' - ' *\n' - ' * See %sobject_manager_client_new_for_bus_sync() for the synchronous, blocking version of this constructor.\n' - %(self.ns_lower, self.ns_lower, self.ns_lower, self.ns_lower), False)) - self.outfile.write(' */\n') - self.outfile.write('void\n' - '%sobject_manager_client_new_for_bus (\n' - ' GBusType bus_type,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GAsyncReadyCallback callback,\n' - ' gpointer user_data)\n' - '{\n' - ' g_async_initable_new_async (%sTYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_upper, self.ns_lower)) - self.outfile.write('/**\n' - ' * %sobject_manager_client_new_for_bus_finish:\n' - ' * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %sobject_manager_client_new_for_bus().\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Finishes an operation started with %sobject_manager_client_new_for_bus().\n' - ' *\n' - ' * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n' - %(self.ns_lower, self.ns_lower, self.ns_lower, self.namespace)) - self.outfile.write(' */\n') - self.outfile.write('GDBusObjectManager *\n' - '%sobject_manager_client_new_for_bus_finish (\n' - ' GAsyncResult *res,\n' - ' GError **error)\n' - '{\n' - ' GObject *ret;\n' - ' GObject *source_object;\n' - ' source_object = g_async_result_get_source_object (res);\n' - ' ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n' - ' g_object_unref (source_object);\n' - ' if (ret != NULL)\n' - ' return G_DBUS_OBJECT_MANAGER (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(self.ns_lower)) - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * %sobject_manager_client_new_for_bus_sync:\n' - ' * @bus_type: A #GBusType.\n' - ' * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n' - ' * @name: A bus name (well-known or unique).\n' - ' * @object_path: An object path.\n' - ' * @cancellable: (nullable): A #GCancellable or %%NULL.\n' - ' * @error: Return location for error or %%NULL\n' - ' *\n' - ' * Like %sobject_manager_client_new_sync() but takes a #GBusType instead of a #GDBusConnection.\n' - ' *\n' - ' * The calling thread is blocked until a reply is received.\n' - ' *\n' - ' * See %sobject_manager_client_new_for_bus() for the asynchronous version of this constructor.\n' - ' *\n' - ' * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n' - %(self.ns_lower, self.ns_lower, self.ns_lower, self.namespace), False)) - self.outfile.write(' */\n') - self.outfile.write('GDBusObjectManager *\n' - '%sobject_manager_client_new_for_bus_sync (\n' - ' GBusType bus_type,\n' - ' GDBusObjectManagerClientFlags flags,\n' - ' const gchar *name,\n' - ' const gchar *object_path,\n' - ' GCancellable *cancellable,\n' - ' GError **error)\n' - '{\n' - ' GInitable *ret;\n' - ' ret = g_initable_new (%sTYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' - ' if (ret != NULL)\n' - ' return G_DBUS_OBJECT_MANAGER (ret);\n' - ' else\n' - ' return NULL;\n' - '}\n' - '\n' - %(self.ns_lower, self.ns_upper, self.ns_lower)) - self.outfile.write('\n') + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_manager_client_new:\n" + " * @connection: A #GDBusConnection.\n" + " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n" + " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n" + " * @user_data: User data to pass to @callback.\n" + " *\n" + " * Asynchronously creates #GDBusObjectManagerClient using %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new() for more details.\n" + " *\n" + " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n" + " * You can then call %sobject_manager_client_new_finish() to get the result of the operation.\n" + " *\n" + " * See %sobject_manager_client_new_sync() for the synchronous, blocking version of this constructor.\n" + % (self.ns_lower, self.ns_lower, self.ns_lower, self.ns_lower), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write( + "void\n" + "%sobject_manager_client_new (\n" + " GDBusConnection *connection,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data)\n" + "{\n" + ' g_async_initable_new_async (%sTYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' + "}\n" + "\n" % (self.ns_lower, self.ns_upper, self.ns_lower) + ) + self.outfile.write( + "/**\n" + " * %sobject_manager_client_new_finish:\n" + " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %sobject_manager_client_new().\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Finishes an operation started with %sobject_manager_client_new().\n" + " *\n" + " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n" + % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace) + ) + self.outfile.write(" */\n") + self.outfile.write( + "GDBusObjectManager *\n" + "%sobject_manager_client_new_finish (\n" + " GAsyncResult *res,\n" + " GError **error)\n" + "{\n" + " GObject *ret;\n" + " GObject *source_object;\n" + " source_object = g_async_result_get_source_object (res);\n" + " ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n" + " g_object_unref (source_object);\n" + " if (ret != NULL)\n" + " return G_DBUS_OBJECT_MANAGER (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" % (self.ns_lower) + ) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_manager_client_new_sync:\n" + " * @connection: A #GDBusConnection.\n" + " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n" + " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Synchronously creates #GDBusObjectManagerClient using %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new_sync() for more details.\n" + " *\n" + " * The calling thread is blocked until a reply is received.\n" + " *\n" + " * See %sobject_manager_client_new() for the asynchronous version of this constructor.\n" + " *\n" + " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n" + % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write( + "GDBusObjectManager *\n" + "%sobject_manager_client_new_sync (\n" + " GDBusConnection *connection,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error)\n" + "{\n" + " GInitable *ret;\n" + ' ret = g_initable_new (%sTYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' + " if (ret != NULL)\n" + " return G_DBUS_OBJECT_MANAGER (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" % (self.ns_lower, self.ns_upper, self.ns_lower) + ) + self.outfile.write("\n") + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_manager_client_new_for_bus:\n" + " * @bus_type: A #GBusType.\n" + " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n" + " * @name: A bus name (well-known or unique).\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n" + " * @user_data: User data to pass to @callback.\n" + " *\n" + " * Like %sobject_manager_client_new() but takes a #GBusType instead of a #GDBusConnection.\n" + " *\n" + " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n" + " * You can then call %sobject_manager_client_new_for_bus_finish() to get the result of the operation.\n" + " *\n" + " * See %sobject_manager_client_new_for_bus_sync() for the synchronous, blocking version of this constructor.\n" + % (self.ns_lower, self.ns_lower, self.ns_lower, self.ns_lower), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write( + "void\n" + "%sobject_manager_client_new_for_bus (\n" + " GBusType bus_type,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GAsyncReadyCallback callback,\n" + " gpointer user_data)\n" + "{\n" + ' g_async_initable_new_async (%sTYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' + "}\n" + "\n" % (self.ns_lower, self.ns_upper, self.ns_lower) + ) + self.outfile.write( + "/**\n" + " * %sobject_manager_client_new_for_bus_finish:\n" + " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %sobject_manager_client_new_for_bus().\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Finishes an operation started with %sobject_manager_client_new_for_bus().\n" + " *\n" + " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n" + % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace) + ) + self.outfile.write(" */\n") + self.outfile.write( + "GDBusObjectManager *\n" + "%sobject_manager_client_new_for_bus_finish (\n" + " GAsyncResult *res,\n" + " GError **error)\n" + "{\n" + " GObject *ret;\n" + " GObject *source_object;\n" + " source_object = g_async_result_get_source_object (res);\n" + " ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n" + " g_object_unref (source_object);\n" + " if (ret != NULL)\n" + " return G_DBUS_OBJECT_MANAGER (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" % (self.ns_lower) + ) + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * %sobject_manager_client_new_for_bus_sync:\n" + " * @bus_type: A #GBusType.\n" + " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n" + " * @name: A bus name (well-known or unique).\n" + " * @object_path: An object path.\n" + " * @cancellable: (nullable): A #GCancellable or %%NULL.\n" + " * @error: Return location for error or %%NULL\n" + " *\n" + " * Like %sobject_manager_client_new_sync() but takes a #GBusType instead of a #GDBusConnection.\n" + " *\n" + " * The calling thread is blocked until a reply is received.\n" + " *\n" + " * See %sobject_manager_client_new_for_bus() for the asynchronous version of this constructor.\n" + " *\n" + " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n" + % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace), + False, + ) + ) + self.outfile.write(" */\n") + self.outfile.write( + "GDBusObjectManager *\n" + "%sobject_manager_client_new_for_bus_sync (\n" + " GBusType bus_type,\n" + " GDBusObjectManagerClientFlags flags,\n" + " const gchar *name,\n" + " const gchar *object_path,\n" + " GCancellable *cancellable,\n" + " GError **error)\n" + "{\n" + " GInitable *ret;\n" + ' ret = g_initable_new (%sTYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n' + " if (ret != NULL)\n" + " return G_DBUS_OBJECT_MANAGER (ret);\n" + " else\n" + " return NULL;\n" + "}\n" + "\n" % (self.ns_lower, self.ns_upper, self.ns_lower) + ) + self.outfile.write("\n") # --------------------------------------------------------------------------------------------------- def write_gtkdoc_deprecated_and_since_and_close(self, obj, f, indent): if len(obj.since) > 0: - f.write('%*s *\n' - '%*s * Since: %s\n' - %(indent, '', indent, '', obj.since)) + f.write("%*s *\n" "%*s * Since: %s\n" % (indent, "", indent, "", obj.since)) if obj.deprecated: if isinstance(obj, dbustypes.Interface): - thing = 'The D-Bus interface' + thing = "The D-Bus interface" elif isinstance(obj, dbustypes.Method): - thing = 'The D-Bus method' + thing = "The D-Bus method" elif isinstance(obj, dbustypes.Signal): - thing = 'The D-Bus signal' + thing = "The D-Bus signal" elif isinstance(obj, dbustypes.Property): - thing = 'The D-Bus property' + thing = "The D-Bus property" else: print_error('Cannot handle object "{}"'.format(obj)) - f.write(self.docbook_gen.expand( - '%*s *\n' - '%*s * Deprecated: %s has been deprecated.\n' - %(indent, '', indent, '', thing), False)) - f.write('%*s */\n'%(indent, '')) + f.write( + self.docbook_gen.expand( + "%*s *\n" + "%*s * Deprecated: %s has been deprecated.\n" + % (indent, "", indent, "", thing), + False, + ) + ) + f.write("%*s */\n" % (indent, "")) # --------------------------------------------------------------------------------------------------- def generate_interface_intro(self, i): - self.outfile.write('/* ------------------------------------------------------------------------\n' - ' * Code for interface %s\n' - ' * ------------------------------------------------------------------------\n' - ' */\n' - '\n'%(i.name)) - - self.outfile.write(self.docbook_gen.expand( - '/**\n' - ' * SECTION:%s\n' - ' * @title: %s\n' - ' * @short_description: Generated C code for the %s D-Bus interface\n' - ' *\n' - ' * This section contains code for working with the #%s D-Bus interface in C.\n' - ' */\n' - %(i.camel_name, i.camel_name, i.name, i.name), False)) - self.outfile.write('\n') + self.outfile.write( + "/* ------------------------------------------------------------------------\n" + " * Code for interface %s\n" + " * ------------------------------------------------------------------------\n" + " */\n" + "\n" % (i.name) + ) + + self.outfile.write( + self.docbook_gen.expand( + "/**\n" + " * SECTION:%s\n" + " * @title: %s\n" + " * @short_description: Generated C code for the %s D-Bus interface\n" + " *\n" + " * This section contains code for working with the #%s D-Bus interface in C.\n" + " */\n" % (i.camel_name, i.camel_name, i.name, i.name), + False, + ) + ) + self.outfile.write("\n") def generate(self): self.generate_body_preamble() diff --git a/gio/gdbus-2.0/codegen/codegen_docbook.py b/gio/gdbus-2.0/codegen/codegen_docbook.py index c08aa1a0ed0b7425847fa6a31b3ca5598e888660..4b69e2927457d5b286a8ab224b1e0572809ff17f 100644 --- a/gio/gdbus-2.0/codegen/codegen_docbook.py +++ b/gio/gdbus-2.0/codegen/codegen_docbook.py @@ -19,17 +19,19 @@ # # Author: David Zeuthen -import sys import re from os import path -from . import config from . import utils -from . import dbustypes -from . import parser + + +# Disable line length warnings as wrapping the Docbook templates would be hard +# flake8: noqa: E501 + # ---------------------------------------------------------------------------------------------------- + class DocbookCodeGenerator: def __init__(self, ifaces): self.ifaces = ifaces @@ -57,23 +59,36 @@ class DocbookCodeGenerator: max_signature_len = max(len(a.signature), max_signature_len) if in_synopsis: - self.out.write('%s%*s (' - %(utils.dots_to_hyphens(i.name), m.name, m.name, max_method_len - len(m.name), '')) + self.out.write( + '%s%*s (' + % ( + utils.dots_to_hyphens(i.name), + m.name, + m.name, + max_method_len - len(m.name), + "", + ) + ) else: - self.out.write('%s%*s (' - %(m.name, max_method_len - len(m.name), '')) + self.out.write("%s%*s (" % (m.name, max_method_len - len(m.name), "")) count = 0 for a in m.in_args: - if (count > 0): - self.out.write(',\n%*s'%(max_method_len + 2, '')) - self.out.write('IN %s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name)) + if count > 0: + self.out.write(",\n%*s" % (max_method_len + 2, "")) + self.out.write( + "IN %s%*s %s" + % (a.signature, max_signature_len - len(a.signature), "", a.name) + ) count = count + 1 for a in m.out_args: - if (count > 0): - self.out.write(',\n%*s'%(max_method_len + 2, '')) - self.out.write('OUT %s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name)) + if count > 0: + self.out.write(",\n%*s" % (max_method_len + 2, "")) + self.out.write( + "OUT %s%*s %s" + % (a.signature, max_signature_len - len(a.signature), "", a.name) + ) count = count + 1 - self.out.write(');\n') + self.out.write(");\n") def print_signal_prototype(self, i, s, in_synopsis): max_signal_len = 0 @@ -93,18 +108,28 @@ class DocbookCodeGenerator: max_signature_len = max(len(a.signature), max_signature_len) if in_synopsis: - self.out.write('%s%*s (' - %(utils.dots_to_hyphens(i.name), s.name, s.name, max_signal_len - len(s.name), '')) + self.out.write( + '%s%*s (' + % ( + utils.dots_to_hyphens(i.name), + s.name, + s.name, + max_signal_len - len(s.name), + "", + ) + ) else: - self.out.write('%s%*s (' - %(s.name, max_signal_len - len(s.name), '')) + self.out.write("%s%*s (" % (s.name, max_signal_len - len(s.name), "")) count = 0 for a in s.args: - if (count > 0): - self.out.write(',\n%*s'%(max_signal_len + 2, '')) - self.out.write('%s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name)) + if count > 0: + self.out.write(",\n%*s" % (max_signal_len + 2, "")) + self.out.write( + "%s%*s %s" + % (a.signature, max_signature_len - len(a.signature), "", a.name) + ) count = count + 1 - self.out.write(');\n') + self.out.write(");\n") def print_property_prototype(self, i, p, in_synopsis): max_property_len = 0 @@ -122,109 +147,181 @@ class DocbookCodeGenerator: max_signature_len = max(len(p.signature), max_signature_len) if in_synopsis: - self.out.write('%s%*s' - %(utils.dots_to_hyphens(i.name), p.name, p.name, max_property_len - len(p.name), '')) + self.out.write( + '%s%*s' + % ( + utils.dots_to_hyphens(i.name), + p.name, + p.name, + max_property_len - len(p.name), + "", + ) + ) else: - self.out.write('%s%*s' - %(p.name, max_property_len - len(p.name), '')) + self.out.write("%s%*s" % (p.name, max_property_len - len(p.name), "")) if p.readable and p.writable: - access = 'readwrite' + access = "readwrite" elif p.readable: - access = 'readable ' + access = "readable " else: - access = 'writable ' - self.out.write(' %s %s\n'%(access, p.signature)) - + access = "writable " + self.out.write(" %s %s\n" % (access, p.signature)) def print_synopsis_methods(self, i): - self.out.write(' \n'%()) - self.out.write(' Methods\n'%()) - self.out.write(' \n'%()) + self.out.write(' \n') + self.out.write(' Methods\n') + self.out.write(" \n") for m in i.methods: self.print_method_prototype(i, m, in_synopsis=True) - self.out.write('\n'%()) - self.out.write(' \n'%()) + self.out.write("\n") + self.out.write(" \n") def print_synopsis_signals(self, i): - self.out.write(' \n'%()) - self.out.write(' Signals\n'%()) - self.out.write(' \n'%()) + self.out.write(' \n') + self.out.write(' Signals\n') + self.out.write(" \n") for s in i.signals: self.print_signal_prototype(i, s, in_synopsis=True) - self.out.write('\n'%()) - self.out.write(' \n'%()) + self.out.write("\n") + self.out.write(" \n") def print_synopsis_properties(self, i): - self.out.write(' \n'%()) - self.out.write(' Properties\n'%()) - self.out.write(' \n'%()) + self.out.write(' \n') + self.out.write(' Properties\n') + self.out.write(" \n") for p in i.properties: self.print_property_prototype(i, p, in_synopsis=True) - self.out.write('\n'%()) - self.out.write(' \n'%()) + self.out.write("\n") + self.out.write(" \n") def print_method(self, i, m): - self.out.write('\n'%(utils.dots_to_hyphens(i.name), m.name)) - self.out.write(' The %s() method\n'%(m.name)) - self.out.write(' %s.%s()\n'%(utils.dots_to_hyphens(i.name), m.name, i.name_without_prefix, m.name, i.name, m.name)) - self.out.write('\n') + self.out.write( + '\n' + % (utils.dots_to_hyphens(i.name), m.name) + ) + self.out.write(" The %s() method\n" % (m.name)) + self.out.write( + ' %s.%s()\n' + % ( + utils.dots_to_hyphens(i.name), + m.name, + i.name_without_prefix, + m.name, + i.name, + m.name, + ) + ) + self.out.write("\n") self.print_method_prototype(i, m, in_synopsis=False) - self.out.write('\n') - self.out.write('%s\n'%(self.expand_paras(m.doc_string, True))) + self.out.write("\n") + self.out.write("%s\n" % (self.expand_paras(m.doc_string, True))) if m.in_args or m.out_args: self.out.write('\n') for a in m.in_args: - self.out.write('\n'%()) - self.out.write(' IN %s %s:\n'%(a.signature, a.name)) - self.out.write(' %s\n'%(self.expand_paras(a.doc_string, True))) - self.out.write('\n'%()) + self.out.write("\n") + self.out.write( + " IN %s %s:\n" + % (a.signature, a.name) + ) + self.out.write( + " %s\n" + % (self.expand_paras(a.doc_string, True)) + ) + self.out.write("\n") for a in m.out_args: - self.out.write('\n'%()) - self.out.write(' OUT %s %s:\n'%(a.signature, a.name)) - self.out.write(' %s\n'%(self.expand_paras(a.doc_string, True))) - self.out.write('\n'%()) - self.out.write('\n') + self.out.write("\n") + self.out.write( + " OUT %s %s:\n" + % (a.signature, a.name) + ) + self.out.write( + " %s\n" + % (self.expand_paras(a.doc_string, True)) + ) + self.out.write("\n") + self.out.write("\n") if len(m.since) > 0: - self.out.write('Since %s\n'%(m.since)) + self.out.write('Since %s\n' % (m.since)) if m.deprecated: - self.out.write('The %s() method is deprecated.'%(m.name)) - self.out.write('\n') + self.out.write( + "The %s() method is deprecated." + % (m.name) + ) + self.out.write("\n") def print_signal(self, i, s): - self.out.write('\n'%(utils.dots_to_hyphens(i.name), s.name)) - self.out.write(' The "%s" signal\n'%(s.name)) - self.out.write(' %s::%s\n'%(utils.dots_to_hyphens(i.name), s.name, i.name_without_prefix, s.name, i.name, s.name)) - self.out.write('\n') + self.out.write( + '\n' + % (utils.dots_to_hyphens(i.name), s.name) + ) + self.out.write(' The "%s" signal\n' % (s.name)) + self.out.write( + ' %s::%s\n' + % ( + utils.dots_to_hyphens(i.name), + s.name, + i.name_without_prefix, + s.name, + i.name, + s.name, + ) + ) + self.out.write("\n") self.print_signal_prototype(i, s, in_synopsis=False) - self.out.write('\n') - self.out.write('%s\n'%(self.expand_paras(s.doc_string, True))) + self.out.write("\n") + self.out.write("%s\n" % (self.expand_paras(s.doc_string, True))) if s.args: self.out.write('\n') for a in s.args: - self.out.write('\n'%()) - self.out.write(' %s %s:\n'%(a.signature, a.name)) - self.out.write(' %s\n'%(self.expand_paras(a.doc_string, True))) - self.out.write('\n'%()) - self.out.write('\n') + self.out.write("\n") + self.out.write( + " %s %s:\n" + % (a.signature, a.name) + ) + self.out.write( + " %s\n" + % (self.expand_paras(a.doc_string, True)) + ) + self.out.write("\n") + self.out.write("\n") if len(s.since) > 0: - self.out.write('Since %s\n'%(s.since)) + self.out.write('Since %s\n' % (s.since)) if s.deprecated: - self.out.write('The "%s" signal is deprecated.'%(s.name)) - self.out.write('\n') + self.out.write( + 'The "%s" signal is deprecated.' + % (s.name) + ) + self.out.write("\n") def print_property(self, i, p): - self.out.write('\n'%(utils.dots_to_hyphens(i.name), p.name)) - self.out.write(' The "%s" property\n'%(p.name)) - self.out.write(' %s:%s\n'%(utils.dots_to_hyphens(i.name), p.name, i.name_without_prefix, p.name, i.name, p.name)) - self.out.write('\n') + self.out.write( + '\n' + % (utils.dots_to_hyphens(i.name), p.name) + ) + self.out.write(' The "%s" property\n' % (p.name)) + self.out.write( + ' %s:%s\n' + % ( + utils.dots_to_hyphens(i.name), + p.name, + i.name_without_prefix, + p.name, + i.name, + p.name, + ) + ) + self.out.write("\n") self.print_property_prototype(i, p, in_synopsis=False) - self.out.write('\n') - self.out.write('%s\n'%(self.expand_paras(p.doc_string, True))) + self.out.write("\n") + self.out.write("%s\n" % (self.expand_paras(p.doc_string, True))) if len(p.since) > 0: - self.out.write('Since %s\n'%(p.since)) + self.out.write('Since %s\n' % (p.since)) if p.deprecated: - self.out.write('The "%s" property is deprecated.'%(p.name)) - self.out.write('\n') + self.out.write( + 'The "%s" property is deprecated.' + % (p.name) + ) + self.out.write("\n") def expand(self, s, expandParamsAndConstants): for key in self.expand_member_dict_keys: @@ -233,9 +330,17 @@ class DocbookCodeGenerator: s = s.replace(key, self.expand_iface_dict[key]) if expandParamsAndConstants: # replace @foo with foo - s = re.sub('@[a-zA-Z0-9_]*', lambda m: '' + m.group(0)[1:] + '', s) + s = re.sub( + "@[a-zA-Z0-9_]*", + lambda m: "" + m.group(0)[1:] + "", + s, + ) # replace e.g. %TRUE with TRUE - s = re.sub('%[a-zA-Z0-9_]*', lambda m: '' + m.group(0)[1:] + '', s) + s = re.sub( + "%[a-zA-Z0-9_]*", + lambda m: "" + m.group(0)[1:] + "", + s, + ) return s def expand_paras(self, s, expandParamsAndConstants): @@ -248,44 +353,73 @@ class DocbookCodeGenerator: self.expand_member_dict = {} self.expand_iface_dict = {} for i in self.ifaces: - key = '#%s'%(i.name) - value = '%s'%(utils.dots_to_hyphens(i.name), i.name) + key = "#%s" % (i.name) + value = '%s' % ( + utils.dots_to_hyphens(i.name), + i.name, + ) self.expand_iface_dict[key] = value for m in i.methods: - key = '%s.%s()'%(i.name, m.name) - value = '%s()'%(utils.dots_to_hyphens(i.name), m.name, m.name) + key = "%s.%s()" % (i.name, m.name) + value = '%s()' % ( + utils.dots_to_hyphens(i.name), + m.name, + m.name, + ) self.expand_member_dict[key] = value for s in i.signals: - key = '#%s::%s'%(i.name, s.name) - value = '"%s"'%(utils.dots_to_hyphens(i.name), s.name, s.name) + key = "#%s::%s" % (i.name, s.name) + value = '"%s"' % ( + utils.dots_to_hyphens(i.name), + s.name, + s.name, + ) self.expand_member_dict[key] = value for p in i.properties: - key = '#%s:%s'%(i.name, p.name) - value = '"%s"'%(utils.dots_to_hyphens(i.name), p.name, p.name) + key = "#%s:%s" % (i.name, p.name) + value = '"%s"' % ( + utils.dots_to_hyphens(i.name), + p.name, + p.name, + ) self.expand_member_dict[key] = value # Make sure to expand the keys in reverse order so e.g. #org.foo.Iface:MediaCompat # is evaluated before #org.foo.Iface:Media ... - self.expand_member_dict_keys = sorted(self.expand_member_dict.keys(), reverse=True) - self.expand_iface_dict_keys = sorted(self.expand_iface_dict.keys(), reverse=True) + self.expand_member_dict_keys = sorted( + self.expand_member_dict.keys(), reverse=True + ) + self.expand_iface_dict_keys = sorted( + self.expand_iface_dict.keys(), reverse=True + ) def generate(self, docbook, outdir): for i in self.ifaces: - self.out = open(path.join(outdir, '%s-%s.xml'%(docbook, i.name)), 'w') - self.out.write(''%()) - self.out.write('\n'%()) - self.out.write('\n'%()) - self.out.write('\n'%(i.name)) - self.out.write(' '%()) - self.out.write(' %s\n'%(utils.dots_to_hyphens(i.name), i.name)) - self.out.write(' %s\n'%(utils.dots_to_hyphens(i.name), i.name_without_prefix, i.name)) - self.out.write(' '%()) - - self.out.write(' '%()) - self.out.write(' %s'%(i.name)) - self.out.write(' %s'%(i.doc_string_brief)) - self.out.write(' '%()) + self.out = open(path.join(outdir, "%s-%s.xml" % (docbook, i.name)), "w") + self.out.write("") + self.out.write('\n') + self.out.write( + '\n") + self.out.write('\n' % (i.name)) + self.out.write(" ") + self.out.write( + ' %s\n' + % (utils.dots_to_hyphens(i.name), i.name) + ) + self.out.write( + ' %s\n' + % (utils.dots_to_hyphens(i.name), i.name_without_prefix, i.name) + ) + self.out.write(" ") + + self.out.write(" ") + self.out.write(" %s" % (i.name)) + self.out.write(" %s" % (i.doc_string_brief)) + self.out.write(" ") if len(i.methods) > 0: self.print_synopsis_methods(i) @@ -294,36 +428,49 @@ class DocbookCodeGenerator: if len(i.properties) > 0: self.print_synopsis_properties(i) - self.out.write('\n'%(utils.dots_to_hyphens(i.name))) - self.out.write(' Description\n'%()) - self.out.write(' %s\n'%(self.expand_paras(i.doc_string, True))) + self.out.write( + '\n' + % (utils.dots_to_hyphens(i.name)) + ) + self.out.write(' Description\n') + self.out.write(" %s\n" % (self.expand_paras(i.doc_string, True))) if len(i.since) > 0: - self.out.write(' Since %s\n'%(i.since)) + self.out.write(' Since %s\n' % (i.since)) if i.deprecated: - self.out.write('The %s interface is deprecated.'%(i.name)) - self.out.write('\n'%()) + self.out.write( + "The %s interface is deprecated." + % (i.name) + ) + self.out.write("\n") if len(i.methods) > 0: - self.out.write('\n'%(i.name)) - self.out.write(' Method Details\n'%()) + self.out.write( + '\n' % (i.name) + ) + self.out.write(' Method Details\n') for m in i.methods: self.print_method(i, m) - self.out.write('\n'%()) + self.out.write("\n") if len(i.signals) > 0: - self.out.write('\n'%(i.name)) - self.out.write(' Signal Details\n'%()) + self.out.write( + '\n' % (i.name) + ) + self.out.write(' Signal Details\n') for s in i.signals: self.print_signal(i, s) - self.out.write('\n'%()) + self.out.write("\n") if len(i.properties) > 0: - self.out.write('\n'%(i.name)) - self.out.write(' Property Details\n'%()) + self.out.write( + '\n' % (i.name) + ) + self.out.write( + ' Property Details\n' + ) for s in i.properties: self.print_property(i, s) - self.out.write('\n'%()) - - self.out.write('\n') - self.out.write('\n') + self.out.write("\n") + self.out.write("\n") + self.out.write("\n") diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py index 7683f0af58357e3e2c58a1332d0f988c2f271a65..238d7dd12fa040dae11508b8e2a9d9a0324fad18 100644 --- a/gio/gdbus-2.0/codegen/codegen_main.py +++ b/gio/gdbus-2.0/codegen/codegen_main.py @@ -32,30 +32,35 @@ from . import codegen from . import codegen_docbook from .utils import print_error, print_warning + def find_arg(arg_list, arg_name): for a in arg_list: if a.name == arg_name: return a return None + def find_method(iface, method): for m in iface.methods: if m.name == method: return m return None + def find_signal(iface, signal): for m in iface.signals: if m.name == signal: return m return None + def find_prop(iface, prop): for m in iface.properties: if m.name == prop: return m return None + def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value): iface_obj = None for i in iface_list: @@ -74,10 +79,14 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value): print_error('No method "{}" on interface "{}"'.format(method, iface)) if arg: arg_obj = find_arg(method_obj.in_args, arg) - if (arg_obj is None): + if arg_obj is None: arg_obj = find_arg(method_obj.out_args, arg) - if (arg_obj is None): - print_error('No arg "{}" on method "{}" on interface "{}"'.format(arg, method, iface)) + if arg_obj is None: + print_error( + 'No arg "{}" on method "{}" on interface "{}"'.format( + arg, method, iface + ) + ) target_obj = arg_obj else: target_obj = method_obj @@ -87,8 +96,12 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value): print_error('No signal "{}" on interface "{}"'.format(signal, iface)) if arg: arg_obj = find_arg(signal_obj.args, arg) - if (arg_obj is None): - print_error('No arg "{}" on signal "{}" on interface "{}"'.format(arg, signal, iface)) + if arg_obj is None: + print_error( + 'No arg "{}" on signal "{}" on interface "{}"'.format( + arg, signal, iface + ) + ) target_obj = arg_obj else: target_obj = signal_obj @@ -105,140 +118,294 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value): def apply_annotations(iface_list, annotation_list): # apply annotations given on the command line for (what, key, value) in annotation_list: - pos = what.find('::') + pos = what.find("::") if pos != -1: # signal - iface = what[0:pos]; - signal = what[pos + 2:] - pos = signal.find('[') + iface = what[0:pos] + signal = what[pos + 2 :] + pos = signal.find("[") if pos != -1: - arg = signal[pos + 1:] + arg = signal[pos + 1 :] signal = signal[0:pos] - pos = arg.find(']') + pos = arg.find("]") arg = arg[0:pos] apply_annotation(iface_list, iface, None, signal, None, arg, key, value) else: - apply_annotation(iface_list, iface, None, signal, None, None, key, value) + apply_annotation( + iface_list, iface, None, signal, None, None, key, value + ) else: - pos = what.find(':') + pos = what.find(":") if pos != -1: # property - iface = what[0:pos]; - prop = what[pos + 1:] + iface = what[0:pos] + prop = what[pos + 1 :] apply_annotation(iface_list, iface, None, None, prop, None, key, value) else: - pos = what.find('()') + pos = what.find("()") if pos != -1: # method combined = what[0:pos] - pos = combined.rfind('.') + pos = combined.rfind(".") iface = combined[0:pos] - method = combined[pos + 1:] - pos = what.find('[') + method = combined[pos + 1 :] + pos = what.find("[") if pos != -1: - arg = what[pos + 1:] - pos = arg.find(']') + arg = what[pos + 1 :] + pos = arg.find("]") arg = arg[0:pos] - apply_annotation(iface_list, iface, method, None, None, arg, key, value) + apply_annotation( + iface_list, iface, method, None, None, arg, key, value + ) else: - apply_annotation(iface_list, iface, method, None, None, None, key, value) + apply_annotation( + iface_list, iface, method, None, None, None, key, value + ) else: # must be an interface iface = what - apply_annotation(iface_list, iface, None, None, None, None, key, value) + apply_annotation( + iface_list, iface, None, None, None, None, key, value + ) + def codegen_main(): - arg_parser = argparse.ArgumentParser(description='D-Bus code and documentation generator') - arg_parser.add_argument('files', metavar='FILE', nargs='*', - help='D-Bus introspection XML file') - arg_parser.add_argument('--xml-files', metavar='FILE', action='append', default=[], - help=argparse.SUPPRESS) - arg_parser.add_argument('--interface-prefix', metavar='PREFIX', default='', - help='String to strip from D-Bus interface names for code and docs') - arg_parser.add_argument('--c-namespace', metavar='NAMESPACE', default='', - help='The namespace to use for generated C code') - arg_parser.add_argument('--c-generate-object-manager', action='store_true', - help='Generate a GDBusObjectManagerClient subclass when generating C code') - arg_parser.add_argument('--c-generate-autocleanup', choices=['none', 'objects', 'all'], default='objects', - help='Generate autocleanup support') - arg_parser.add_argument('--generate-docbook', metavar='OUTFILES', - help='Generate Docbook in OUTFILES-org.Project.IFace.xml') - arg_parser.add_argument('--pragma-once', action='store_true', - help='Use "pragma once" as the inclusion guard') - arg_parser.add_argument('--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE', - help='Add annotation (may be used several times)') + arg_parser = argparse.ArgumentParser( + description="D-Bus code and documentation generator" + ) + arg_parser.add_argument( + "files", metavar="FILE", nargs="+", help="D-Bus introspection XML file" + ) + arg_parser.add_argument( + "--xml-files", + metavar="FILE", + action="append", + default=[], + help=argparse.SUPPRESS, + ) + arg_parser.add_argument( + "--interface-prefix", + metavar="PREFIX", + default="", + help="String to strip from D-Bus interface names for code and docs", + ) + arg_parser.add_argument( + "--c-namespace", + metavar="NAMESPACE", + default="", + help="The namespace to use for generated C code", + ) + arg_parser.add_argument( + "--c-generate-object-manager", + action="store_true", + help="Generate a GDBusObjectManagerClient subclass when generating C code", + ) + arg_parser.add_argument( + "--c-generate-autocleanup", + choices=["none", "objects", "all"], + default="objects", + help="Generate autocleanup support", + ) + arg_parser.add_argument( + "--generate-docbook", + metavar="OUTFILES", + help="Generate Docbook in OUTFILES-org.Project.IFace.xml", + ) + arg_parser.add_argument( + "--pragma-once", + action="store_true", + help='Use "pragma once" as the inclusion guard', + ) + arg_parser.add_argument( + "--annotate", + nargs=3, + action="append", + metavar="WHAT KEY VALUE", + help="Add annotation (may be used several times)", + ) + arg_parser.add_argument( + "--glib-min-required", + metavar="VERSION", + help="Minimum version of GLib to be supported by the outputted code " + "(default: 2.30)", + ) + arg_parser.add_argument( + "--glib-max-allowed", + metavar="VERSION", + help="Maximum version of GLib to be used by the outputted code " + "(default: current GLib version)", + ) + arg_parser.add_argument( + "--symbol-decorator", + help="Macro used to decorate a symbol in the outputted header, " + "possibly to export symbols", + ) + arg_parser.add_argument( + "--symbol-decorator-header", + help="Additional header required for decorator specified by " + "--symbol-decorator", + ) + arg_parser.add_argument( + "--symbol-decorator-define", + help="Additional define required for decorator specified by " + "--symbol-decorator", + ) group = arg_parser.add_mutually_exclusive_group() - group.add_argument('--generate-c-code', metavar='OUTFILES', - help='Generate C code in OUTFILES.[ch]') - group.add_argument('--header', action='store_true', - help='Generate C headers') - group.add_argument('--body', action='store_true', - help='Generate C code') - group.add_argument('--interface-info-header', action='store_true', - help='Generate GDBusInterfaceInfo C header') - group.add_argument('--interface-info-body', action='store_true', - help='Generate GDBusInterfaceInfo C code') + group.add_argument( + "--generate-c-code", metavar="OUTFILES", help="Generate C code in OUTFILES.[ch]" + ) + group.add_argument("--header", action="store_true", help="Generate C headers") + group.add_argument("--body", action="store_true", help="Generate C code") + group.add_argument( + "--interface-info-header", + action="store_true", + help="Generate GDBusInterfaceInfo C header", + ) + group.add_argument( + "--interface-info-body", + action="store_true", + help="Generate GDBusInterfaceInfo C code", + ) group = arg_parser.add_mutually_exclusive_group() - group.add_argument('--output', metavar='FILE', - help='Write output into the specified file') - group.add_argument('--output-directory', metavar='OUTDIR', default='', - help='Location to output generated files') - - args = arg_parser.parse_args(); + group.add_argument( + "--output", metavar="FILE", help="Write output into the specified file" + ) + group.add_argument( + "--output-directory", + metavar="OUTDIR", + default="", + help="Location to output generated files", + ) + + args = arg_parser.parse_args() if len(args.xml_files) > 0: - print_warning('The "--xml-files" option is deprecated; use positional arguments instead') - - if ((args.generate_c_code is not None or args.generate_docbook is not None) and - args.output is not None): - print_error('Using --generate-c-code or --generate-docbook and ' - '--output at the same time is not allowed') + print_warning( + 'The "--xml-files" option is deprecated; use positional arguments instead' + ) + + if ( + args.generate_c_code is not None or args.generate_docbook is not None + ) and args.output is not None: + print_error( + "Using --generate-c-code or --generate-docbook and " + "--output at the same time is not allowed" + ) if args.generate_c_code: - header_name = args.generate_c_code + '.h' + header_name = args.generate_c_code + ".h" h_file = os.path.join(args.output_directory, header_name) args.header = True - c_file = os.path.join(args.output_directory, args.generate_c_code + '.c') + c_file = os.path.join(args.output_directory, args.generate_c_code + ".c") args.body = True elif args.header: if args.output is None: - print_error('Using --header requires --output') + print_error("Using --header requires --output") h_file = args.output header_name = os.path.basename(h_file) elif args.body: if args.output is None: - print_error('Using --body requires --output') + print_error("Using --body requires --output") c_file = args.output - header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' + header_name = os.path.splitext(os.path.basename(c_file))[0] + ".h" elif args.interface_info_header: if args.output is None: - print_error('Using --interface-info-header requires --output') + print_error("Using --interface-info-header requires --output") if args.c_generate_object_manager: - print_error('--c-generate-object-manager is incompatible with ' - '--interface-info-header') + print_error( + "--c-generate-object-manager is incompatible with " + "--interface-info-header" + ) h_file = args.output header_name = os.path.basename(h_file) elif args.interface_info_body: if args.output is None: - print_error('Using --interface-info-body requires --output') + print_error("Using --interface-info-body requires --output") if args.c_generate_object_manager: - print_error('--c-generate-object-manager is incompatible with ' - '--interface-info-body') + print_error( + "--c-generate-object-manager is incompatible with " + "--interface-info-body" + ) c_file = args.output - header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' + header_name = os.path.splitext(os.path.basename(c_file))[0] + ".h" + + # Check the minimum GLib version. The minimum --glib-min-required is 2.30, + # because that’s when gdbus-codegen was introduced. Support 1, 2 or 3 + # component versions, but ignore the micro component if it’s present. + if args.glib_min_required: + try: + parts = args.glib_min_required.split(".", 3) + glib_min_required = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0)) + # Ignore micro component, but still validate it: + _ = int(parts[2] if len(parts) > 2 else 0) # noqa: F841 + except (ValueError, IndexError): + print_error( + "Unrecognized --glib-min-required string ‘{}’".format( + args.glib_min_required + ) + ) + + if glib_min_required < (2, 30): + print_error( + "Invalid --glib-min-required string ‘{}’: minimum " + "version is 2.30".format(args.glib_min_required) + ) + else: + glib_min_required = (2, 30) + + # And the maximum GLib version. + if args.glib_max_allowed: + try: + parts = args.glib_max_allowed.split(".", 3) + glib_max_allowed = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0)) + # Ignore micro component, but still validate it: + _ = int(parts[2] if len(parts) > 2 else 0) # noqa: F841 + except (ValueError, IndexError): + print_error( + "Unrecognized --glib-max-allowed string ‘{}’".format( + args.glib_max_allowed + ) + ) + else: + glib_max_allowed = (config.MAJOR_VERSION, config.MINOR_VERSION) + + # Only allow --symbol-decorator-define and --symbol-decorator-header if + # --symbol-decorator is used + if args.symbol_decorator is None: + if args.symbol_decorator_header or args.symbol_decorator_define: + print_error( + "--symbol-decorator-define and --symbol-decorator-header must " + "be used with --symbol-decorator" + ) + + # Round --glib-max-allowed up to the next stable release. + glib_max_allowed = ( + glib_max_allowed[0], + glib_max_allowed[1] + (glib_max_allowed[1] % 2), + ) + + if glib_max_allowed < glib_min_required: + print_error( + "Invalid versions: --glib-min-required ({}) must be " + "less than or equal to --glib-max-allowed ({})".format( + glib_min_required, glib_max_allowed + ) + ) all_ifaces = [] input_files_basenames = [] for fname in sorted(args.files + args.xml_files): - with open(fname, 'rb') as f: + with open(fname, "rb") as f: xml_data = f.read() - parsed_ifaces = parser.parse_dbus_xml(xml_data) + parsed_ifaces = parser.parse_dbus_xml( + xml_data, h_type_implies_unix_fd=(glib_min_required >= (2, 64)) + ) all_ifaces.extend(parsed_ifaces) input_files_basenames.append(os.path.basename(fname)) @@ -249,53 +416,72 @@ def codegen_main(): i.post_process(args.interface_prefix, args.c_namespace) docbook = args.generate_docbook - docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces); + docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces) if docbook: - ret = docbook_gen.generate(docbook, args.output_directory) + docbook_gen.generate(docbook, args.output_directory) if args.header: - with open(h_file, 'w') as outfile: - gen = codegen.HeaderCodeGenerator(all_ifaces, - args.c_namespace, - args.c_generate_object_manager, - args.c_generate_autocleanup, - header_name, - input_files_basenames, - args.pragma_once, - outfile) + with open(h_file, "w") as outfile: + gen = codegen.HeaderCodeGenerator( + all_ifaces, + args.c_namespace, + args.c_generate_object_manager, + args.c_generate_autocleanup, + header_name, + input_files_basenames, + args.pragma_once, + glib_min_required, + args.symbol_decorator, + args.symbol_decorator_header, + outfile, + ) gen.generate() if args.body: - with open(c_file, 'w') as outfile: - gen = codegen.CodeGenerator(all_ifaces, - args.c_namespace, - args.c_generate_object_manager, - header_name, - input_files_basenames, - docbook_gen, - outfile) + with open(c_file, "w") as outfile: + gen = codegen.CodeGenerator( + all_ifaces, + args.c_namespace, + args.c_generate_object_manager, + header_name, + input_files_basenames, + docbook_gen, + glib_min_required, + args.symbol_decorator_define, + outfile, + ) gen.generate() if args.interface_info_header: - with open(h_file, 'w') as outfile: - gen = codegen.InterfaceInfoHeaderCodeGenerator(all_ifaces, - args.c_namespace, - header_name, - input_files_basenames, - args.pragma_once, - outfile) + with open(h_file, "w") as outfile: + gen = codegen.InterfaceInfoHeaderCodeGenerator( + all_ifaces, + args.c_namespace, + header_name, + input_files_basenames, + args.pragma_once, + glib_min_required, + args.symbol_decorator, + args.symbol_decorator_header, + outfile, + ) gen.generate() if args.interface_info_body: - with open(c_file, 'w') as outfile: - gen = codegen.InterfaceInfoBodyCodeGenerator(all_ifaces, - args.c_namespace, - header_name, - input_files_basenames, - outfile) + with open(c_file, "w") as outfile: + gen = codegen.InterfaceInfoBodyCodeGenerator( + all_ifaces, + args.c_namespace, + header_name, + input_files_basenames, + glib_min_required, + args.symbol_decorator_define, + outfile, + ) gen.generate() sys.exit(0) + if __name__ == "__main__": codegen_main() diff --git a/gio/gdbus-2.0/codegen/config.py.in b/gio/gdbus-2.0/codegen/config.py.in index a91178a955d4b1ac31f12954d1af82ebf9904cf5..4e6df5a09e3a162cdc243a690fc29fb1c85a16af 100644 --- a/gio/gdbus-2.0/codegen/config.py.in +++ b/gio/gdbus-2.0/codegen/config.py.in @@ -20,3 +20,5 @@ # Author: David Zeuthen VERSION = "@VERSION@" +MAJOR_VERSION = @MAJOR_VERSION@ +MINOR_VERSION = @MINOR_VERSION@ diff --git a/gio/gdbus-2.0/codegen/dbustypes.py b/gio/gdbus-2.0/codegen/dbustypes.py index 60c53c4be04614157c359724729e56b2ca7ca223..bbe5c4e1ee482511b93c16f23c315a310f715979 100644 --- a/gio/gdbus-2.0/codegen/dbustypes.py +++ b/gio/gdbus-2.0/codegen/dbustypes.py @@ -22,22 +22,30 @@ from . import utils from .utils import print_error + class Annotation: def __init__(self, key, value): self.key = key self.value = value self.annotations = [] - self.since = '' + self.since = "" def post_process(self, interface_prefix, cns, cns_upper, cns_lower, container): key = self.key - overridden_key = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') + overridden_key = utils.lookup_annotation( + self.annotations, "org.gtk.GDBus.C.Name" + ) if utils.is_ugly_case(overridden_key): self.key_lower = overridden_key.lower() else: if overridden_key: key = overridden_key - self.key_lower = utils.camel_case_to_uscore(key).lower().replace('-', '_').replace('.', '_') + self.key_lower = ( + utils.camel_case_to_uscore(key) + .lower() + .replace("-", "_") + .replace(".", "_") + ) if len(self.since) == 0: self.since = utils.lookup_since(self.annotations) @@ -47,13 +55,14 @@ class Annotation: for a in self.annotations: a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Arg: def __init__(self, name, signature): self.name = name self.signature = signature self.annotations = [] - self.doc_string = '' - self.since = '' + self.doc_string = "" + self.since = "" def post_process(self, interface_prefix, cns, cns_upper, cns_lower, arg_number): if len(self.doc_string) == 0: @@ -62,206 +71,213 @@ class Arg: self.since = utils.lookup_since(self.annotations) if self.name is None: - self.name = 'unnamed_arg%d'%arg_number + self.name = "unnamed_arg%d" % arg_number # default to GVariant - self.ctype_in_g = 'GVariant *' - self.ctype_in = 'GVariant *' - self.ctype_in_dup = 'GVariant *' - self.ctype_out = 'GVariant **' - self.gtype = 'G_TYPE_VARIANT' - self.free_func = 'g_variant_unref' - self.format_in = '@' + self.signature - self.format_out = '@' + self.signature - self.gvariant_get = 'XXX' - self.gvalue_get = 'g_value_get_variant' - self.array_annotation = '' - - if not utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.ForceGVariant'): - if self.signature == 'b': - self.ctype_in_g = 'gboolean ' - self.ctype_in = 'gboolean ' - self.ctype_out = 'gboolean *' - self.gtype = 'G_TYPE_BOOLEAN' + self.ctype_in_g = "GVariant *" + self.ctype_in = "GVariant *" + self.ctype_in_dup = "GVariant *" + self.ctype_out = "GVariant **" + self.gtype = "G_TYPE_VARIANT" + self.free_func = "g_variant_unref" + self.format_in = "@" + self.signature + self.format_out = "@" + self.signature + self.gvariant_get = "XXX" + self.gvalue_get = "g_value_get_variant" + self.array_annotation = "" + + if not utils.lookup_annotation( + self.annotations, "org.gtk.GDBus.C.ForceGVariant" + ): + if self.signature == "b": + self.ctype_in_g = "gboolean " + self.ctype_in = "gboolean " + self.ctype_out = "gboolean *" + self.gtype = "G_TYPE_BOOLEAN" self.free_func = None - self.format_in = 'b' - self.format_out = 'b' - self.gvariant_get = 'g_variant_get_boolean' - self.gvalue_get = 'g_value_get_boolean' - elif self.signature == 'y': - self.ctype_in_g = 'guchar ' - self.ctype_in = 'guchar ' - self.ctype_out = 'guchar *' - self.gtype = 'G_TYPE_UCHAR' + self.format_in = "b" + self.format_out = "b" + self.gvariant_get = "g_variant_get_boolean" + self.gvalue_get = "g_value_get_boolean" + elif self.signature == "y": + self.ctype_in_g = "guchar " + self.ctype_in = "guchar " + self.ctype_out = "guchar *" + self.gtype = "G_TYPE_UCHAR" self.free_func = None - self.format_in = 'y' - self.format_out = 'y' - self.gvariant_get = 'g_variant_get_byte' - self.gvalue_get = 'g_value_get_uchar' - elif self.signature == 'n': - self.ctype_in_g = 'gint ' - self.ctype_in = 'gint16 ' - self.ctype_out = 'gint16 *' - self.gtype = 'G_TYPE_INT' + self.format_in = "y" + self.format_out = "y" + self.gvariant_get = "g_variant_get_byte" + self.gvalue_get = "g_value_get_uchar" + elif self.signature == "n": + self.ctype_in_g = "gint " + self.ctype_in = "gint16 " + self.ctype_out = "gint16 *" + self.gtype = "G_TYPE_INT" self.free_func = None - self.format_in = 'n' - self.format_out = 'n' - self.gvariant_get = 'g_variant_get_int16' - self.gvalue_get = 'g_value_get_int' - elif self.signature == 'q': - self.ctype_in_g = 'guint ' - self.ctype_in = 'guint16 ' - self.ctype_out = 'guint16 *' - self.gtype = 'G_TYPE_UINT' + self.format_in = "n" + self.format_out = "n" + self.gvariant_get = "g_variant_get_int16" + self.gvalue_get = "g_value_get_int" + elif self.signature == "q": + self.ctype_in_g = "guint " + self.ctype_in = "guint16 " + self.ctype_out = "guint16 *" + self.gtype = "G_TYPE_UINT" self.free_func = None - self.format_in = 'q' - self.format_out = 'q' - self.gvariant_get = 'g_variant_get_uint16' - self.gvalue_get = 'g_value_get_uint' - elif self.signature == 'i': - self.ctype_in_g = 'gint ' - self.ctype_in = 'gint ' - self.ctype_out = 'gint *' - self.gtype = 'G_TYPE_INT' + self.format_in = "q" + self.format_out = "q" + self.gvariant_get = "g_variant_get_uint16" + self.gvalue_get = "g_value_get_uint" + elif self.signature == "i": + self.ctype_in_g = "gint " + self.ctype_in = "gint " + self.ctype_out = "gint *" + self.gtype = "G_TYPE_INT" self.free_func = None - self.format_in = 'i' - self.format_out = 'i' - self.gvariant_get = 'g_variant_get_int32' - self.gvalue_get = 'g_value_get_int' - elif self.signature == 'u': - self.ctype_in_g = 'guint ' - self.ctype_in = 'guint ' - self.ctype_out = 'guint *' - self.gtype = 'G_TYPE_UINT' + self.format_in = "i" + self.format_out = "i" + self.gvariant_get = "g_variant_get_int32" + self.gvalue_get = "g_value_get_int" + elif self.signature == "u": + self.ctype_in_g = "guint " + self.ctype_in = "guint " + self.ctype_out = "guint *" + self.gtype = "G_TYPE_UINT" self.free_func = None - self.format_in = 'u' - self.format_out = 'u' - self.gvariant_get = 'g_variant_get_uint32' - self.gvalue_get = 'g_value_get_uint' - elif self.signature == 'x': - self.ctype_in_g = 'gint64 ' - self.ctype_in = 'gint64 ' - self.ctype_out = 'gint64 *' - self.gtype = 'G_TYPE_INT64' + self.format_in = "u" + self.format_out = "u" + self.gvariant_get = "g_variant_get_uint32" + self.gvalue_get = "g_value_get_uint" + elif self.signature == "x": + self.ctype_in_g = "gint64 " + self.ctype_in = "gint64 " + self.ctype_out = "gint64 *" + self.gtype = "G_TYPE_INT64" self.free_func = None - self.format_in = 'x' - self.format_out = 'x' - self.gvariant_get = 'g_variant_get_int64' - self.gvalue_get = 'g_value_get_int64' - elif self.signature == 't': - self.ctype_in_g = 'guint64 ' - self.ctype_in = 'guint64 ' - self.ctype_out = 'guint64 *' - self.gtype = 'G_TYPE_UINT64' + self.format_in = "x" + self.format_out = "x" + self.gvariant_get = "g_variant_get_int64" + self.gvalue_get = "g_value_get_int64" + elif self.signature == "t": + self.ctype_in_g = "guint64 " + self.ctype_in = "guint64 " + self.ctype_out = "guint64 *" + self.gtype = "G_TYPE_UINT64" self.free_func = None - self.format_in = 't' - self.format_out = 't' - self.gvariant_get = 'g_variant_get_uint64' - self.gvalue_get = 'g_value_get_uint64' - elif self.signature == 'd': - self.ctype_in_g = 'gdouble ' - self.ctype_in = 'gdouble ' - self.ctype_out = 'gdouble *' - self.gtype = 'G_TYPE_DOUBLE' + self.format_in = "t" + self.format_out = "t" + self.gvariant_get = "g_variant_get_uint64" + self.gvalue_get = "g_value_get_uint64" + elif self.signature == "d": + self.ctype_in_g = "gdouble " + self.ctype_in = "gdouble " + self.ctype_out = "gdouble *" + self.gtype = "G_TYPE_DOUBLE" self.free_func = None - self.format_in = 'd' - self.format_out = 'd' - self.gvariant_get = 'g_variant_get_double' - self.gvalue_get = 'g_value_get_double' - elif self.signature == 's': - self.ctype_in_g = 'const gchar *' - self.ctype_in = 'const gchar *' - self.ctype_in_dup = 'gchar *' - self.ctype_out = 'gchar **' - self.gtype = 'G_TYPE_STRING' - self.free_func = 'g_free' - self.format_in = 's' - self.format_out = 's' - self.gvariant_get = 'g_variant_get_string' - self.gvalue_get = 'g_value_get_string' - elif self.signature == 'o': - self.ctype_in_g = 'const gchar *' - self.ctype_in = 'const gchar *' - self.ctype_in_dup = 'gchar *' - self.ctype_out = 'gchar **' - self.gtype = 'G_TYPE_STRING' - self.free_func = 'g_free' - self.format_in = 'o' - self.format_out = 'o' - self.gvariant_get = 'g_variant_get_string' - self.gvalue_get = 'g_value_get_string' - elif self.signature == 'g': - self.ctype_in_g = 'const gchar *' - self.ctype_in = 'const gchar *' - self.ctype_in_dup = 'gchar *' - self.ctype_out = 'gchar **' - self.gtype = 'G_TYPE_STRING' - self.free_func = 'g_free' - self.format_in = 'g' - self.format_out = 'g' - self.gvariant_get = 'g_variant_get_string' - self.gvalue_get = 'g_value_get_string' - elif self.signature == 'ay': - self.ctype_in_g = 'const gchar *' - self.ctype_in = 'const gchar *' - self.ctype_in_dup = 'gchar *' - self.ctype_out = 'gchar **' - self.gtype = 'G_TYPE_STRING' - self.free_func = 'g_free' - self.format_in = '^ay' - self.format_out = '^ay' - self.gvariant_get = 'g_variant_get_bytestring' - self.gvalue_get = 'g_value_get_string' - elif self.signature == 'as': - self.ctype_in_g = 'const gchar *const *' - self.ctype_in = 'const gchar *const *' - self.ctype_in_dup = 'gchar **' - self.ctype_out = 'gchar ***' - self.gtype = 'G_TYPE_STRV' - self.free_func = 'g_strfreev' - self.format_in = '^as' - self.format_out = '^as' - self.gvariant_get = 'g_variant_get_strv' - self.gvalue_get = 'g_value_get_boxed' - self.array_annotation = '(array zero-terminated=1)' - elif self.signature == 'ao': - self.ctype_in_g = 'const gchar *const *' - self.ctype_in = 'const gchar *const *' - self.ctype_in_dup = 'gchar **' - self.ctype_out = 'gchar ***' - self.gtype = 'G_TYPE_STRV' - self.free_func = 'g_strfreev' - self.format_in = '^ao' - self.format_out = '^ao' - self.gvariant_get = 'g_variant_get_objv' - self.gvalue_get = 'g_value_get_boxed' - self.array_annotation = '(array zero-terminated=1)' - elif self.signature == 'aay': - self.ctype_in_g = 'const gchar *const *' - self.ctype_in = 'const gchar *const *' - self.ctype_in_dup = 'gchar **' - self.ctype_out = 'gchar ***' - self.gtype = 'G_TYPE_STRV' - self.free_func = 'g_strfreev' - self.format_in = '^aay' - self.format_out = '^aay' - self.gvariant_get = 'g_variant_get_bytestring_array' - self.gvalue_get = 'g_value_get_boxed' - self.array_annotation = '(array zero-terminated=1)' + self.format_in = "d" + self.format_out = "d" + self.gvariant_get = "g_variant_get_double" + self.gvalue_get = "g_value_get_double" + elif self.signature == "s": + self.ctype_in_g = "const gchar *" + self.ctype_in = "const gchar *" + self.ctype_in_dup = "gchar *" + self.ctype_out = "gchar **" + self.gtype = "G_TYPE_STRING" + self.free_func = "g_free" + self.format_in = "s" + self.format_out = "s" + self.gvariant_get = "g_variant_get_string" + self.gvalue_get = "g_value_get_string" + elif self.signature == "o": + self.ctype_in_g = "const gchar *" + self.ctype_in = "const gchar *" + self.ctype_in_dup = "gchar *" + self.ctype_out = "gchar **" + self.gtype = "G_TYPE_STRING" + self.free_func = "g_free" + self.format_in = "o" + self.format_out = "o" + self.gvariant_get = "g_variant_get_string" + self.gvalue_get = "g_value_get_string" + elif self.signature == "g": + self.ctype_in_g = "const gchar *" + self.ctype_in = "const gchar *" + self.ctype_in_dup = "gchar *" + self.ctype_out = "gchar **" + self.gtype = "G_TYPE_STRING" + self.free_func = "g_free" + self.format_in = "g" + self.format_out = "g" + self.gvariant_get = "g_variant_get_string" + self.gvalue_get = "g_value_get_string" + elif self.signature == "ay": + self.ctype_in_g = "const gchar *" + self.ctype_in = "const gchar *" + self.ctype_in_dup = "gchar *" + self.ctype_out = "gchar **" + self.gtype = "G_TYPE_STRING" + self.free_func = "g_free" + self.format_in = "^ay" + self.format_out = "^ay" + self.gvariant_get = "g_variant_get_bytestring" + self.gvalue_get = "g_value_get_string" + elif self.signature == "as": + self.ctype_in_g = "const gchar *const *" + self.ctype_in = "const gchar *const *" + self.ctype_in_dup = "gchar **" + self.ctype_out = "gchar ***" + self.gtype = "G_TYPE_STRV" + self.free_func = "g_strfreev" + self.format_in = "^as" + self.format_out = "^as" + self.gvariant_get = "g_variant_get_strv" + self.gvalue_get = "g_value_get_boxed" + self.array_annotation = "(array zero-terminated=1)" + elif self.signature == "ao": + self.ctype_in_g = "const gchar *const *" + self.ctype_in = "const gchar *const *" + self.ctype_in_dup = "gchar **" + self.ctype_out = "gchar ***" + self.gtype = "G_TYPE_STRV" + self.free_func = "g_strfreev" + self.format_in = "^ao" + self.format_out = "^ao" + self.gvariant_get = "g_variant_get_objv" + self.gvalue_get = "g_value_get_boxed" + self.array_annotation = "(array zero-terminated=1)" + elif self.signature == "aay": + self.ctype_in_g = "const gchar *const *" + self.ctype_in = "const gchar *const *" + self.ctype_in_dup = "gchar **" + self.ctype_out = "gchar ***" + self.gtype = "G_TYPE_STRV" + self.free_func = "g_strfreev" + self.format_in = "^aay" + self.format_out = "^aay" + self.gvariant_get = "g_variant_get_bytestring_array" + self.gvalue_get = "g_value_get_boxed" + self.array_annotation = "(array zero-terminated=1)" for a in self.annotations: a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Method: - def __init__(self, name): + def __init__(self, name, h_type_implies_unix_fd=True): self.name = name + self.h_type_implies_unix_fd = h_type_implies_unix_fd self.in_args = [] self.out_args = [] self.annotations = [] - self.doc_string = '' - self.since = '' + self.doc_string = "" + self.since = "" self.deprecated = False + self.unix_fd = False - def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface): + def post_process( + self, interface_prefix, cns, cns_upper, cns_lower, containing_iface + ): if len(self.doc_string) == 0: self.doc_string = utils.lookup_docs(self.annotations) if len(self.since) == 0: @@ -270,40 +286,55 @@ class Method: self.since = containing_iface.since name = self.name - overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') + overridden_name = utils.lookup_annotation( + self.annotations, "org.gtk.GDBus.C.Name" + ) if utils.is_ugly_case(overridden_name): self.name_lower = overridden_name.lower() else: if overridden_name: name = overridden_name - self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_') - self.name_hyphen = self.name_lower.replace('_', '-') + self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_") + self.name_hyphen = self.name_lower.replace("_", "-") arg_count = 0 for a in self.in_args: a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count) arg_count += 1 + if self.h_type_implies_unix_fd and "h" in a.signature: + self.unix_fd = True for a in self.out_args: a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count) arg_count += 1 + if self.h_type_implies_unix_fd and "h" in a.signature: + self.unix_fd = True - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': + if ( + utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated") + == "true" + ): self.deprecated = True + if utils.lookup_annotation(self.annotations, "org.gtk.GDBus.C.UnixFD"): + self.unix_fd = True + for a in self.annotations: a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Signal: def __init__(self, name): self.name = name self.args = [] self.annotations = [] - self.doc_string = '' - self.since = '' + self.doc_string = "" + self.since = "" self.deprecated = False - def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface): + def post_process( + self, interface_prefix, cns, cns_upper, cns_lower, containing_iface + ): if len(self.doc_string) == 0: self.doc_string = utils.lookup_docs(self.annotations) if len(self.since) == 0: @@ -312,51 +343,59 @@ class Signal: self.since = containing_iface.since name = self.name - overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') + overridden_name = utils.lookup_annotation( + self.annotations, "org.gtk.GDBus.C.Name" + ) if utils.is_ugly_case(overridden_name): self.name_lower = overridden_name.lower() else: if overridden_name: name = overridden_name - self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_') - self.name_hyphen = self.name_lower.replace('_', '-') + self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_") + self.name_hyphen = self.name_lower.replace("_", "-") arg_count = 0 for a in self.args: a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count) arg_count += 1 - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': + if ( + utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated") + == "true" + ): self.deprecated = True for a in self.annotations: a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Property: def __init__(self, name, signature, access): self.name = name self.signature = signature self.access = access self.annotations = [] - self.arg = Arg('value', self.signature) + self.arg = Arg("value", self.signature) self.arg.annotations = self.annotations self.readable = False self.writable = False - if self.access == 'readwrite': + if self.access == "readwrite": self.readable = True self.writable = True - elif self.access == 'read': + elif self.access == "read": self.readable = True - elif self.access == 'write': + elif self.access == "write": self.writable = True else: print_error('Invalid access type "{}"'.format(self.access)) - self.doc_string = '' - self.since = '' + self.doc_string = "" + self.since = "" self.deprecated = False self.emits_changed_signal = True - def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface): + def post_process( + self, interface_prefix, cns, cns_upper, cns_lower, containing_iface + ): if len(self.doc_string) == 0: self.doc_string = utils.lookup_docs(self.annotations) if len(self.since) == 0: @@ -365,34 +404,44 @@ class Property: self.since = containing_iface.since name = self.name - overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') + overridden_name = utils.lookup_annotation( + self.annotations, "org.gtk.GDBus.C.Name" + ) if utils.is_ugly_case(overridden_name): self.name_lower = overridden_name.lower() else: if overridden_name: name = overridden_name - self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_') - self.name_hyphen = self.name_lower.replace('_', '-') - # don't clash with the GType getter, e.g.: GType foo_bar_get_type (void); G_GNUC_CONST - if self.name_lower == 'type': - self.name_lower = 'type_' + self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_") + self.name_hyphen = self.name_lower.replace("_", "-") + # don't clash with the GType getter, e.g.: + # GType foo_bar_get_type (void); G_GNUC_CONST + if self.name_lower == "type": + self.name_lower = "type_" # recalculate arg self.arg.annotations = self.annotations self.arg.post_process(interface_prefix, cns, cns_upper, cns_lower, 0) - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': + if ( + utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated") + == "true" + ): self.deprecated = True for a in self.annotations: a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) - # FIXME: for now we only support 'false' and 'const' on the signal itself, see #674913 and + # FIXME: for now we only support 'false' and 'const' on the signal itself, + # see #674913 and # http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format # for details - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Property.EmitsChangedSignal') in ('false', 'const'): + if utils.lookup_annotation( + self.annotations, "org.freedesktop.DBus.Property.EmitsChangedSignal" + ) in ("false", "const"): self.emits_changed_signal = False + class Interface: def __init__(self, name): self.name = name @@ -400,9 +449,9 @@ class Interface: self.signals = [] self.properties = [] self.annotations = [] - self.doc_string = '' - self.doc_string_brief = '' - self.since = '' + self.doc_string = "" + self.doc_string_brief = "" + self.since = "" self.deprecated = False def post_process(self, interface_prefix, c_namespace): @@ -415,21 +464,23 @@ class Interface: if len(c_namespace) > 0: if utils.is_ugly_case(c_namespace): - cns = c_namespace.replace('_', '') - cns_upper = c_namespace.upper() + '_' - cns_lower = c_namespace.lower() + '_' + cns = c_namespace.replace("_", "") + cns_upper = c_namespace.upper() + "_" + cns_lower = c_namespace.lower() + "_" else: cns = c_namespace - cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + '_' - cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + '_' + cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + "_" + cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + "_" else: - cns = '' - cns_upper = '' - cns_lower = '' + cns = "" + cns_upper = "" + cns_lower = "" - overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') + overridden_name = utils.lookup_annotation( + self.annotations, "org.gtk.GDBus.C.Name" + ) if utils.is_ugly_case(overridden_name): - name = overridden_name.replace('_', '') + name = overridden_name.replace("_", "") name_with_ns = cns + name self.name_without_prefix = name self.camel_name = name_with_ns @@ -437,25 +488,28 @@ class Interface: self.name_lower = cns_lower + overridden_name.lower() self.name_upper = overridden_name.upper() - #print_error('handle Ugly_Case "{}"'.format(overridden_name)) + # print_error('handle Ugly_Case "{}"'.format(overridden_name)) else: if overridden_name: name = overridden_name else: name = self.name if name.startswith(interface_prefix): - name = name[len(interface_prefix):] + name = name[len(interface_prefix) :] self.name_without_prefix = name name = utils.strip_dots(name) - name_with_ns = utils.strip_dots(cns + '.' + name) + name_with_ns = utils.strip_dots(cns + "." + name) self.camel_name = name_with_ns self.ns_upper = cns_upper self.name_lower = cns_lower + utils.camel_case_to_uscore(name) self.name_upper = utils.camel_case_to_uscore(name).upper() - self.name_hyphen = self.name_upper.lower().replace('_', '-') + self.name_hyphen = self.name_upper.lower().replace("_", "-") - if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': + if ( + utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated") + == "true" + ): self.deprecated = True for m in self.methods: diff --git a/gio/gdbus-2.0/codegen/gdbus-codegen.in b/gio/gdbus-2.0/codegen/gdbus-codegen.in old mode 100755 new mode 100644 diff --git a/gio/gdbus-2.0/codegen/meson.build b/gio/gdbus-2.0/codegen/meson.build index 5ea6bae2fca98cfa4084d48212a04d62613ca973..c0caf0e50565de86dc9fefca96b8fef0101135b6 100644 --- a/gio/gdbus-2.0/codegen/meson.build +++ b/gio/gdbus-2.0/codegen/meson.build @@ -10,6 +10,8 @@ gdbus_codegen_files = [ gdbus_codegen_conf = configuration_data() gdbus_codegen_conf.set('VERSION', glib_version) +gdbus_codegen_conf.set('MAJOR_VERSION', major_version) +gdbus_codegen_conf.set('MINOR_VERSION', minor_version) gdbus_codegen_conf.set('PYTHON', python_name) gdbus_codegen_conf.set('DATADIR', glib_datadir) diff --git a/gio/gdbus-2.0/codegen/parser.py b/gio/gdbus-2.0/codegen/parser.py index f49136d6e5bfbf1ebc2bd08fb92521e151c2952e..45226d540858a3cd8f01f7cb39747febd91648d8 100644 --- a/gio/gdbus-2.0/codegen/parser.py +++ b/gio/gdbus-2.0/codegen/parser.py @@ -19,24 +19,24 @@ # # Author: David Zeuthen -import sys import xml.parsers.expat from . import dbustypes from .utils import print_error + class DBusXMLParser: - STATE_TOP = 'top' - STATE_NODE = 'node' - STATE_INTERFACE = 'interface' - STATE_METHOD = 'method' - STATE_SIGNAL = 'signal' - STATE_PROPERTY = 'property' - STATE_ARG = 'arg' - STATE_ANNOTATION = 'annotation' - STATE_IGNORED = 'ignored' + STATE_TOP = "top" + STATE_NODE = "node" + STATE_INTERFACE = "interface" + STATE_METHOD = "method" + STATE_SIGNAL = "signal" + STATE_PROPERTY = "property" + STATE_ARG = "arg" + STATE_ANNOTATION = "annotation" + STATE_IGNORED = "ignored" - def __init__(self, xml_data): + def __init__(self, xml_data, h_type_implies_unix_fd=True): self._parser = xml.parsers.expat.ParserCreate() self._parser.CommentHandler = self.handle_comment self._parser.CharacterDataHandler = self.handle_char_data @@ -51,19 +51,22 @@ class DBusXMLParser: self._cur_object = None self._cur_object_stack = [] - self.doc_comment_last_symbol = '' + self.doc_comment_last_symbol = "" + + self._h_type_implies_unix_fd = h_type_implies_unix_fd self._parser.Parse(xml_data) - COMMENT_STATE_BEGIN = 'begin' - COMMENT_STATE_PARAMS = 'params' - COMMENT_STATE_BODY = 'body' - COMMENT_STATE_SKIP = 'skip' + COMMENT_STATE_BEGIN = "begin" + COMMENT_STATE_PARAMS = "params" + COMMENT_STATE_BODY = "body" + COMMENT_STATE_SKIP = "skip" + def handle_comment(self, data): - comment_state = DBusXMLParser.COMMENT_STATE_BEGIN; - lines = data.split('\n') - symbol = '' - body = '' + comment_state = DBusXMLParser.COMMENT_STATE_BEGIN + lines = data.split("\n") + symbol = "" + body = "" in_para = False params = {} for line in lines: @@ -71,59 +74,59 @@ class DBusXMLParser: line = line.lstrip() if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN: if len(line) > 0: - colon_index = line.find(': ') + colon_index = line.find(": ") if colon_index == -1: - if line.endswith(':'): - symbol = line[0:len(line)-1] + if line.endswith(":"): + symbol = line[0 : len(line) - 1] comment_state = DBusXMLParser.COMMENT_STATE_PARAMS else: comment_state = DBusXMLParser.COMMENT_STATE_SKIP else: symbol = line[0:colon_index] - rest_of_line = line[colon_index+2:].strip() + rest_of_line = line[colon_index + 2 :].strip() if len(rest_of_line) > 0: - body += '' + rest_of_line + '' + body += "" + rest_of_line + "" comment_state = DBusXMLParser.COMMENT_STATE_PARAMS elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS: - if line.startswith('@'): - colon_index = line.find(': ') + if line.startswith("@"): + colon_index = line.find(": ") if colon_index == -1: comment_state = DBusXMLParser.COMMENT_STATE_BODY if not in_para: - body += '' + body += "" in_para = True - body += orig_line + '\n' + body += orig_line + "\n" else: param = line[1:colon_index] - docs = line[colon_index + 2:] + docs = line[colon_index + 2 :] params[param] = docs else: comment_state = DBusXMLParser.COMMENT_STATE_BODY if len(line) > 0: if not in_para: - body += '' + body += "" in_para = True - body += orig_line + '\n' + body += orig_line + "\n" elif comment_state == DBusXMLParser.COMMENT_STATE_BODY: if len(line) > 0: if not in_para: - body += '' + body += "" in_para = True - body += orig_line + '\n' + body += orig_line + "\n" else: if in_para: - body += '' + body += "" in_para = False if in_para: - body += '' + body += "" - if symbol != '': + if symbol != "": self.doc_comment_last_symbol = symbol self.doc_comment_params = params self.doc_comment_body = body def handle_char_data(self, data): - #print 'char_data=%s'%data + # print 'char_data=%s'%data pass def handle_start_element(self, name, attrs): @@ -139,76 +142,76 @@ class DBusXMLParser: elif self.state == DBusXMLParser.STATE_NODE: if name == DBusXMLParser.STATE_INTERFACE: self.state = DBusXMLParser.STATE_INTERFACE - iface = dbustypes.Interface(attrs['name']) + iface = dbustypes.Interface(attrs["name"]) self._cur_object = iface self.parsed_interfaces.append(iface) elif name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: self.state = DBusXMLParser.STATE_IGNORED # assign docs, if any - if 'name' in attrs and self.doc_comment_last_symbol == attrs['name']: + if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]: self._cur_object.doc_string = self.doc_comment_body - if 'short_description' in self.doc_comment_params: - short_description = self.doc_comment_params['short_description'] + if "short_description" in self.doc_comment_params: + short_description = self.doc_comment_params["short_description"] self._cur_object.doc_string_brief = short_description - if 'since' in self.doc_comment_params: - self._cur_object.since = \ - self.doc_comment_params['since'].strip() + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params["since"].strip() elif self.state == DBusXMLParser.STATE_INTERFACE: if name == DBusXMLParser.STATE_METHOD: self.state = DBusXMLParser.STATE_METHOD - method = dbustypes.Method(attrs['name']) + method = dbustypes.Method( + attrs["name"], h_type_implies_unix_fd=self._h_type_implies_unix_fd + ) self._cur_object.methods.append(method) self._cur_object = method elif name == DBusXMLParser.STATE_SIGNAL: self.state = DBusXMLParser.STATE_SIGNAL - signal = dbustypes.Signal(attrs['name']) + signal = dbustypes.Signal(attrs["name"]) self._cur_object.signals.append(signal) self._cur_object = signal elif name == DBusXMLParser.STATE_PROPERTY: self.state = DBusXMLParser.STATE_PROPERTY - prop = dbustypes.Property(attrs['name'], attrs['type'], attrs['access']) + prop = dbustypes.Property(attrs["name"], attrs["type"], attrs["access"]) self._cur_object.properties.append(prop) self._cur_object = prop elif name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: self.state = DBusXMLParser.STATE_IGNORED # assign docs, if any - if 'name' in attrs and self.doc_comment_last_symbol == attrs['name']: + if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]: self._cur_object.doc_string = self.doc_comment_body - if 'since' in self.doc_comment_params: - self._cur_object.since = \ - self.doc_comment_params['since'].strip() + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params["since"].strip() elif self.state == DBusXMLParser.STATE_METHOD: if name == DBusXMLParser.STATE_ARG: self.state = DBusXMLParser.STATE_ARG arg_name = None - if 'name' in attrs: - arg_name = attrs['name'] - arg = dbustypes.Arg(arg_name, attrs['type']) - direction = attrs.get('direction', 'in') - if direction == 'in': + if "name" in attrs: + arg_name = attrs["name"] + arg = dbustypes.Arg(arg_name, attrs["type"]) + direction = attrs.get("direction", "in") + if direction == "in": self._cur_object.in_args.append(arg) - elif direction == 'out': + elif direction == "out": self._cur_object.out_args.append(arg) else: print_error('Invalid direction "{}"'.format(direction)) self._cur_object = arg elif name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: @@ -216,26 +219,27 @@ class DBusXMLParser: # assign docs, if any if self.doc_comment_last_symbol == old_cur_object.name: - if 'name' in attrs and attrs['name'] in self.doc_comment_params: - doc_string = self.doc_comment_params[attrs['name']] - if doc_string != None: + if "name" in attrs and attrs["name"] in self.doc_comment_params: + doc_string = self.doc_comment_params[attrs["name"]] + if doc_string is not None: self._cur_object.doc_string = doc_string - if 'since' in self.doc_comment_params: - self._cur_object.since = \ - self.doc_comment_params['since'].strip() + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params[ + "since" + ].strip() elif self.state == DBusXMLParser.STATE_SIGNAL: if name == DBusXMLParser.STATE_ARG: self.state = DBusXMLParser.STATE_ARG arg_name = None - if 'name' in attrs: - arg_name = attrs['name'] - arg = dbustypes.Arg(arg_name, attrs['type']) + if "name" in attrs: + arg_name = attrs["name"] + arg = dbustypes.Arg(arg_name, attrs["type"]) self._cur_object.args.append(arg) self._cur_object = arg elif name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: @@ -243,18 +247,19 @@ class DBusXMLParser: # assign docs, if any if self.doc_comment_last_symbol == old_cur_object.name: - if 'name' in attrs and attrs['name'] in self.doc_comment_params: - doc_string = self.doc_comment_params[attrs['name']] - if doc_string != None: + if "name" in attrs and attrs["name"] in self.doc_comment_params: + doc_string = self.doc_comment_params[attrs["name"]] + if doc_string is not None: self._cur_object.doc_string = doc_string - if 'since' in self.doc_comment_params: - self._cur_object.since = \ - self.doc_comment_params['since'].strip() + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params[ + "since" + ].strip() elif self.state == DBusXMLParser.STATE_PROPERTY: if name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: @@ -263,7 +268,7 @@ class DBusXMLParser: elif self.state == DBusXMLParser.STATE_ARG: if name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: @@ -272,14 +277,18 @@ class DBusXMLParser: elif self.state == DBusXMLParser.STATE_ANNOTATION: if name == DBusXMLParser.STATE_ANNOTATION: self.state = DBusXMLParser.STATE_ANNOTATION - anno = dbustypes.Annotation(attrs['name'], attrs['value']) + anno = dbustypes.Annotation(attrs["name"], attrs["value"]) self._cur_object.annotations.append(anno) self._cur_object = anno else: self.state = DBusXMLParser.STATE_IGNORED else: - print_error('Unhandled state "{}" while entering element with name "{}"'.format(self.state, name)) + print_error( + 'Unhandled state "{}" while entering element with name "{}"'.format( + self.state, name + ) + ) self.state_stack.append(old_state) self._cur_object_stack.append(old_cur_object) @@ -288,6 +297,7 @@ class DBusXMLParser: self.state = self.state_stack.pop() self._cur_object = self._cur_object_stack.pop() -def parse_dbus_xml(xml_data): - parser = DBusXMLParser(xml_data) + +def parse_dbus_xml(xml_data, h_type_implies_unix_fd): + parser = DBusXMLParser(xml_data, h_type_implies_unix_fd) return parser.parsed_interfaces diff --git a/gio/gdbus-2.0/codegen/utils.py b/gio/gdbus-2.0/codegen/utils.py index 95ba107d372785ecbde25f42c0dc226fbe6a4b73..95559d37c27cc646ec28178a682c41e994593ff0 100644 --- a/gio/gdbus-2.0/codegen/utils.py +++ b/gio/gdbus-2.0/codegen/utils.py @@ -23,49 +23,58 @@ import distutils.version import os import sys + # pylint: disable=too-few-public-methods class Color: - '''ANSI Terminal colors''' - GREEN = '\033[1;32m' - BLUE = '\033[1;34m' - YELLOW = '\033[1;33m' - RED = '\033[1;31m' - END = '\033[0m' - -def print_color(msg, color=Color.END, prefix='MESSAGE'): - '''Print a string with a color prefix''' + """ANSI Terminal colors""" + + GREEN = "\033[1;32m" + BLUE = "\033[1;34m" + YELLOW = "\033[1;33m" + RED = "\033[1;31m" + END = "\033[0m" + + +def print_color(msg, color=Color.END, prefix="MESSAGE"): + """Print a string with a color prefix""" if os.isatty(sys.stderr.fileno()): - real_prefix = '{start}{prefix}{end}'.format(start=color, prefix=prefix, end=Color.END) + real_prefix = "{start}{prefix}{end}".format( + start=color, prefix=prefix, end=Color.END + ) else: real_prefix = prefix - sys.stderr.write('{prefix}: {msg}\n'.format(prefix=real_prefix, msg=msg)) + sys.stderr.write("{prefix}: {msg}\n".format(prefix=real_prefix, msg=msg)) + def print_error(msg): - '''Print an error, and terminate''' - print_color(msg, color=Color.RED, prefix='ERROR') + """Print an error, and terminate""" + print_color(msg, color=Color.RED, prefix="ERROR") sys.exit(1) + def print_warning(msg, fatal=False): - '''Print a warning, and optionally terminate''' + """Print a warning, and optionally terminate""" if fatal: color = Color.RED - prefix = 'ERROR' + prefix = "ERROR" else: color = Color.YELLOW - prefix = 'WARNING' + prefix = "WARNING" print_color(msg, color, prefix) if fatal: sys.exit(1) + def print_info(msg): - '''Print a message''' - print_color(msg, color=Color.GREEN, prefix='INFO') + """Print a message""" + print_color(msg, color=Color.GREEN, prefix="INFO") + def strip_dots(s): - ret = '' + ret = "" force_upper = False for c in s: - if c == '.': + if c == ".": force_upper = True else: if force_upper: @@ -75,19 +84,21 @@ def strip_dots(s): ret += c return ret + def dots_to_hyphens(s): - return s.replace('.', '-') + return s.replace(".", "-") + def camel_case_to_uscore(s): - ret = '' + ret = "" insert_uscore = False prev_was_lower = False - initial = True; + initial = True for c in s: # Keep initial underscores in camel case - if initial and c == '_': - ret += '_' - continue; + if initial and c == "_": + ret += "_" + continue initial = False if c.isupper(): @@ -97,16 +108,18 @@ def camel_case_to_uscore(s): else: prev_was_lower = True if insert_uscore: - ret += '_' + ret += "_" ret += c.lower() insert_uscore = False return ret + def is_ugly_case(s): - if s and s.find('_') > 0: + if s and s.find("_") > 0: return True return False + def lookup_annotation(annotations, key): if annotations: for a in annotations: @@ -114,35 +127,39 @@ def lookup_annotation(annotations, key): return a.value return None + def lookup_docs(annotations): - s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString') + s = lookup_annotation(annotations, "org.gtk.GDBus.DocString") if s is None: - return '' + return "" else: return s + def lookup_since(annotations): - s = lookup_annotation(annotations, 'org.gtk.GDBus.Since') + s = lookup_annotation(annotations, "org.gtk.GDBus.Since") if s is None: - return '' + return "" else: return s + def lookup_brief_docs(annotations): - s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString.Short') + s = lookup_annotation(annotations, "org.gtk.GDBus.DocString.Short") if s is None: - return '' + return "" else: return s + def version_cmp_key(key): # If the 'since' version is 'UNRELEASED', compare higher than anything else # If it is empty put a 0 in its place as this will # allow LooseVersion to work and will always compare lower. - if key[0] == 'UNRELEASED': - v = '9999' + if key[0] == "UNRELEASED": + v = "9999" elif key[0]: v = str(key[0]) else: - v = '0' + v = "0" return (distutils.version.LooseVersion(v), key[1]) diff --git a/gio/gdbus-daemon-generated.c b/gio/gdbus-daemon-generated.c index c1deefb886a90712c68cb6a7f3e76c81aaa438db..bbdf7ff825d88d3b003b3fe32ae4cfdcc5fb3149 100644 --- a/gio/gdbus-daemon-generated.c +++ b/gio/gdbus-daemon-generated.c @@ -1,4338 +1,4339 @@ -/* - * Generated by gdbus-codegen 2.62.5 from dbus-daemon.xml. DO NOT EDIT. - * - * The license of this code is the same as for the D-Bus interface description - * it was derived from. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "gdbus-daemon-generated.h" - -#include -#ifdef G_OS_UNIX -# include -#endif - -typedef struct -{ - GDBusArgInfo parent_struct; - gboolean use_gvariant; -} _ExtendedGDBusArgInfo; - -typedef struct -{ - GDBusMethodInfo parent_struct; - const gchar *signal_name; - gboolean pass_fdlist; -} _ExtendedGDBusMethodInfo; - -typedef struct -{ - GDBusSignalInfo parent_struct; - const gchar *signal_name; -} _ExtendedGDBusSignalInfo; - -typedef struct -{ - GDBusPropertyInfo parent_struct; - const gchar *hyphen_name; - guint use_gvariant : 1; - guint emits_changed_signal : 1; -} _ExtendedGDBusPropertyInfo; - -typedef struct -{ - GDBusInterfaceInfo parent_struct; - const gchar *hyphen_name; -} _ExtendedGDBusInterfaceInfo; - -typedef struct -{ - const _ExtendedGDBusPropertyInfo *info; - guint prop_id; - GValue orig_value; /* the value before the change */ -} ChangedProperty; - -static void -_changed_property_free (ChangedProperty *data) -{ - g_value_unset (&data->orig_value); - g_free (data); -} - -static gboolean -_g_strv_equal0 (gchar **a, gchar **b) -{ - gboolean ret = FALSE; - guint n; - if (a == NULL && b == NULL) - { - ret = TRUE; - goto out; - } - if (a == NULL || b == NULL) - goto out; - if (g_strv_length (a) != g_strv_length (b)) - goto out; - for (n = 0; a[n] != NULL; n++) - if (g_strcmp0 (a[n], b[n]) != 0) - goto out; - ret = TRUE; -out: - return ret; -} - -static gboolean -_g_variant_equal0 (GVariant *a, GVariant *b) -{ - gboolean ret = FALSE; - if (a == NULL && b == NULL) - { - ret = TRUE; - goto out; - } - if (a == NULL || b == NULL) - goto out; - ret = g_variant_equal (a, b); -out: - return ret; -} - -G_GNUC_UNUSED static gboolean -_g_value_equal (const GValue *a, const GValue *b) -{ - gboolean ret = FALSE; - g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b)); - switch (G_VALUE_TYPE (a)) - { - case G_TYPE_BOOLEAN: - ret = (g_value_get_boolean (a) == g_value_get_boolean (b)); - break; - case G_TYPE_UCHAR: - ret = (g_value_get_uchar (a) == g_value_get_uchar (b)); - break; - case G_TYPE_INT: - ret = (g_value_get_int (a) == g_value_get_int (b)); - break; - case G_TYPE_UINT: - ret = (g_value_get_uint (a) == g_value_get_uint (b)); - break; - case G_TYPE_INT64: - ret = (g_value_get_int64 (a) == g_value_get_int64 (b)); - break; - case G_TYPE_UINT64: - ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b)); - break; - case G_TYPE_DOUBLE: - { - /* Avoid -Wfloat-equal warnings by doing a direct bit compare */ - gdouble da = g_value_get_double (a); - gdouble db = g_value_get_double (b); - ret = memcmp (&da, &db, sizeof (gdouble)) == 0; - } - break; - case G_TYPE_STRING: - ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0); - break; - case G_TYPE_VARIANT: - ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b)); - break; - default: - if (G_VALUE_TYPE (a) == G_TYPE_STRV) - ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b)); - else - g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a))); - break; - } - return ret; -} - -/* ------------------------------------------------------------------------ - * Code for interface org.freedesktop.DBus - * ------------------------------------------------------------------------ - */ - -/** - * SECTION:_GFreedesktopDBus - * @title: _GFreedesktopDBus - * @short_description: Generated C code for the org.freedesktop.DBus D-Bus interface - * - * This section contains code for working with the org.freedesktop.DBus D-Bus interface in C. - */ - -/* ---- Introspection data for org.freedesktop.DBus ---- */ - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_hello_OUT_ARG_assigned_name = -{ - { - -1, - (gchar *) "assigned_name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_hello_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_hello_OUT_ARG_assigned_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_hello = -{ - { - -1, - (gchar *) "Hello", - NULL, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_hello_OUT_ARG_pointers, - NULL - }, - "handle-hello", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_request_name_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_request_name_IN_ARG_flags = -{ - { - -1, - (gchar *) "flags", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_request_name_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_request_name_IN_ARG_name.parent_struct, - &__g_freedesktop_dbus_method_info_request_name_IN_ARG_flags.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_request_name_OUT_ARG_value = -{ - { - -1, - (gchar *) "value", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_request_name_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_request_name_OUT_ARG_value.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_request_name = -{ - { - -1, - (gchar *) "RequestName", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_request_name_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_request_name_OUT_ARG_pointers, - NULL - }, - "handle-request-name", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_release_name_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_release_name_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_release_name_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_release_name_OUT_ARG_value = -{ - { - -1, - (gchar *) "value", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_release_name_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_release_name_OUT_ARG_value.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_release_name = -{ - { - -1, - (gchar *) "ReleaseName", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_release_name_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_release_name_OUT_ARG_pointers, - NULL - }, - "handle-release-name", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_flags = -{ - { - -1, - (gchar *) "flags", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_name.parent_struct, - &__g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_flags.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_value = -{ - { - -1, - (gchar *) "value", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_value.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_start_service_by_name = -{ - { - -1, - (gchar *) "StartServiceByName", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_pointers, - NULL - }, - "handle-start-service-by-name", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_has_owner = -{ - { - -1, - (gchar *) "has_owner", - (gchar *) "b", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_has_owner.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_name_has_owner = -{ - { - -1, - (gchar *) "NameHasOwner", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_pointers, - NULL - }, - "handle-name-has-owner", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_names_OUT_ARG_names = -{ - { - -1, - (gchar *) "names", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_names_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_list_names_OUT_ARG_names.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_list_names = -{ - { - -1, - (gchar *) "ListNames", - NULL, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_names_OUT_ARG_pointers, - NULL - }, - "handle-list-names", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_activatable_names = -{ - { - -1, - (gchar *) "activatable_names", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_activatable_names.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_list_activatable_names = -{ - { - -1, - (gchar *) "ListActivatableNames", - NULL, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_pointers, - NULL - }, - "handle-list-activatable-names", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_add_match_IN_ARG_rule = -{ - { - -1, - (gchar *) "rule", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_add_match_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_add_match_IN_ARG_rule.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_add_match = -{ - { - -1, - (gchar *) "AddMatch", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_add_match_IN_ARG_pointers, - NULL, - NULL - }, - "handle-add-match", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_remove_match_IN_ARG_rule = -{ - { - -1, - (gchar *) "rule", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_remove_match_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_remove_match_IN_ARG_rule.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_remove_match = -{ - { - -1, - (gchar *) "RemoveMatch", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_remove_match_IN_ARG_pointers, - NULL, - NULL - }, - "handle-remove-match", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_unique_name = -{ - { - -1, - (gchar *) "unique_name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_unique_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_name_owner = -{ - { - -1, - (gchar *) "GetNameOwner", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_pointers, - NULL - }, - "handle-get-name-owner", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_queued_owners = -{ - { - -1, - (gchar *) "queued_owners", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_queued_owners.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_list_queued_owners = -{ - { - -1, - (gchar *) "ListQueuedOwners", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_pointers, - NULL - }, - "handle-list-queued-owners", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_uid = -{ - { - -1, - (gchar *) "uid", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_uid.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_connection_unix_user = -{ - { - -1, - (gchar *) "GetConnectionUnixUser", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_pointers, - NULL - }, - "handle-get-connection-unix-user", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pid = -{ - { - -1, - (gchar *) "pid", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pid.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_connection_unix_process_id = -{ - { - -1, - (gchar *) "GetConnectionUnixProcessID", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pointers, - NULL - }, - "handle-get-connection-unix-process-id", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_security_context = -{ - { - -1, - (gchar *) "security_context", - (gchar *) "ay", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_security_context.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_connection_selinux_security_context = -{ - { - -1, - (gchar *) "GetConnectionSELinuxSecurityContext", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_pointers, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_pointers, - NULL - }, - "handle-get-connection-selinux-security-context", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_environment = -{ - { - -1, - (gchar *) "environment", - (gchar *) "a{ss}", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_environment.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_update_activation_environment = -{ - { - -1, - (gchar *) "UpdateActivationEnvironment", - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_pointers, - NULL, - NULL - }, - "handle-update-activation-environment", - FALSE -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_reload_config = -{ - { - -1, - (gchar *) "ReloadConfig", - NULL, - NULL, - NULL - }, - "handle-reload-config", - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_id_OUT_ARG_unique_id = -{ - { - -1, - (gchar *) "unique_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_id_OUT_ARG_pointers[] = -{ - &__g_freedesktop_dbus_method_info_get_id_OUT_ARG_unique_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_id = -{ - { - -1, - (gchar *) "GetId", - NULL, - (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_id_OUT_ARG_pointers, - NULL - }, - "handle-get-id", - FALSE -}; - -static const GDBusMethodInfo * const __g_freedesktop_dbus_method_info_pointers[] = -{ - &__g_freedesktop_dbus_method_info_hello.parent_struct, - &__g_freedesktop_dbus_method_info_request_name.parent_struct, - &__g_freedesktop_dbus_method_info_release_name.parent_struct, - &__g_freedesktop_dbus_method_info_start_service_by_name.parent_struct, - &__g_freedesktop_dbus_method_info_name_has_owner.parent_struct, - &__g_freedesktop_dbus_method_info_list_names.parent_struct, - &__g_freedesktop_dbus_method_info_list_activatable_names.parent_struct, - &__g_freedesktop_dbus_method_info_add_match.parent_struct, - &__g_freedesktop_dbus_method_info_remove_match.parent_struct, - &__g_freedesktop_dbus_method_info_get_name_owner.parent_struct, - &__g_freedesktop_dbus_method_info_list_queued_owners.parent_struct, - &__g_freedesktop_dbus_method_info_get_connection_unix_user.parent_struct, - &__g_freedesktop_dbus_method_info_get_connection_unix_process_id.parent_struct, - &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context.parent_struct, - &__g_freedesktop_dbus_method_info_update_activation_environment.parent_struct, - &__g_freedesktop_dbus_method_info_reload_config.parent_struct, - &__g_freedesktop_dbus_method_info_get_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_old_owner = -{ - { - -1, - (gchar *) "old_owner", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_new_owner = -{ - { - -1, - (gchar *) "new_owner", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_pointers[] = -{ - &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_name.parent_struct, - &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_old_owner.parent_struct, - &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_new_owner.parent_struct, - NULL -}; - -static const _ExtendedGDBusSignalInfo __g_freedesktop_dbus_signal_info_name_owner_changed = -{ - { - -1, - (gchar *) "NameOwnerChanged", - (GDBusArgInfo **) &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_pointers, - NULL - }, - "name-owner-changed" -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_lost_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_signal_info_name_lost_ARG_pointers[] = -{ - &__g_freedesktop_dbus_signal_info_name_lost_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusSignalInfo __g_freedesktop_dbus_signal_info_name_lost = -{ - { - -1, - (gchar *) "NameLost", - (GDBusArgInfo **) &__g_freedesktop_dbus_signal_info_name_lost_ARG_pointers, - NULL - }, - "name-lost" -}; - -static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_acquired_ARG_name = -{ - { - -1, - (gchar *) "name", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const __g_freedesktop_dbus_signal_info_name_acquired_ARG_pointers[] = -{ - &__g_freedesktop_dbus_signal_info_name_acquired_ARG_name.parent_struct, - NULL -}; - -static const _ExtendedGDBusSignalInfo __g_freedesktop_dbus_signal_info_name_acquired = -{ - { - -1, - (gchar *) "NameAcquired", - (GDBusArgInfo **) &__g_freedesktop_dbus_signal_info_name_acquired_ARG_pointers, - NULL - }, - "name-acquired" -}; - -static const GDBusSignalInfo * const __g_freedesktop_dbus_signal_info_pointers[] = -{ - &__g_freedesktop_dbus_signal_info_name_owner_changed.parent_struct, - &__g_freedesktop_dbus_signal_info_name_lost.parent_struct, - &__g_freedesktop_dbus_signal_info_name_acquired.parent_struct, - NULL -}; - -static const _ExtendedGDBusInterfaceInfo __g_freedesktop_dbus_interface_info = -{ - { - -1, - (gchar *) "org.freedesktop.DBus", - (GDBusMethodInfo **) &__g_freedesktop_dbus_method_info_pointers, - (GDBusSignalInfo **) &__g_freedesktop_dbus_signal_info_pointers, - NULL, - NULL - }, - "freedesktop-dbus", -}; - - -/** - * _g_freedesktop_dbus_interface_info: - * - * Gets a machine-readable description of the org.freedesktop.DBus D-Bus interface. - * - * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. - */ -GDBusInterfaceInfo * -_g_freedesktop_dbus_interface_info (void) -{ - return (GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct; -} - -/** - * _g_freedesktop_dbus_override_properties: - * @klass: The class structure for a #GObject derived class. - * @property_id_begin: The property id to assign to the first overridden property. - * - * Overrides all #GObject properties in the #_GFreedesktopDBus interface for a concrete class. - * The properties are overridden in the order they are defined. - * - * Returns: The last property id. - */ -guint -_g_freedesktop_dbus_override_properties (GObjectClass *klass, guint property_id_begin) -{ - return property_id_begin - 1; -} - - - -/** - * _GFreedesktopDBus: - * - * Abstract interface type for the D-Bus interface org.freedesktop.DBus. - */ - -/** - * _GFreedesktopDBusIface: - * @parent_iface: The parent interface. - * @handle_add_match: Handler for the #_GFreedesktopDBus::handle-add-match signal. - * @handle_get_connection_selinux_security_context: Handler for the #_GFreedesktopDBus::handle-get-connection-selinux-security-context signal. - * @handle_get_connection_unix_process_id: Handler for the #_GFreedesktopDBus::handle-get-connection-unix-process-id signal. - * @handle_get_connection_unix_user: Handler for the #_GFreedesktopDBus::handle-get-connection-unix-user signal. - * @handle_get_id: Handler for the #_GFreedesktopDBus::handle-get-id signal. - * @handle_get_name_owner: Handler for the #_GFreedesktopDBus::handle-get-name-owner signal. - * @handle_hello: Handler for the #_GFreedesktopDBus::handle-hello signal. - * @handle_list_activatable_names: Handler for the #_GFreedesktopDBus::handle-list-activatable-names signal. - * @handle_list_names: Handler for the #_GFreedesktopDBus::handle-list-names signal. - * @handle_list_queued_owners: Handler for the #_GFreedesktopDBus::handle-list-queued-owners signal. - * @handle_name_has_owner: Handler for the #_GFreedesktopDBus::handle-name-has-owner signal. - * @handle_release_name: Handler for the #_GFreedesktopDBus::handle-release-name signal. - * @handle_reload_config: Handler for the #_GFreedesktopDBus::handle-reload-config signal. - * @handle_remove_match: Handler for the #_GFreedesktopDBus::handle-remove-match signal. - * @handle_request_name: Handler for the #_GFreedesktopDBus::handle-request-name signal. - * @handle_start_service_by_name: Handler for the #_GFreedesktopDBus::handle-start-service-by-name signal. - * @handle_update_activation_environment: Handler for the #_GFreedesktopDBus::handle-update-activation-environment signal. - * @name_acquired: Handler for the #_GFreedesktopDBus::name-acquired signal. - * @name_lost: Handler for the #_GFreedesktopDBus::name-lost signal. - * @name_owner_changed: Handler for the #_GFreedesktopDBus::name-owner-changed signal. - * - * Virtual table for the D-Bus interface org.freedesktop.DBus. - */ - -typedef _GFreedesktopDBusIface _GFreedesktopDBusInterface; -G_DEFINE_INTERFACE (_GFreedesktopDBus, _g_freedesktop_dbus, G_TYPE_OBJECT) - -static void -_g_freedesktop_dbus_default_init (_GFreedesktopDBusIface *iface) -{ - /* GObject signals for incoming D-Bus method calls: */ - /** - * _GFreedesktopDBus::handle-hello: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * - * Signal emitted when a remote caller is invoking the Hello() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_hello() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-hello", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_hello), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 1, - G_TYPE_DBUS_METHOD_INVOCATION); - - /** - * _GFreedesktopDBus::handle-request-name: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * @arg_flags: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the RequestName() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_request_name() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-request-name", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_request_name), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 3, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_UINT); - - /** - * _GFreedesktopDBus::handle-release-name: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the ReleaseName() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_release_name() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-release-name", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_release_name), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-start-service-by-name: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * @arg_flags: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the StartServiceByName() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_start_service_by_name() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-start-service-by-name", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_start_service_by_name), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 3, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_UINT); - - /** - * _GFreedesktopDBus::handle-name-has-owner: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the NameHasOwner() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_name_has_owner() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-name-has-owner", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_name_has_owner), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-list-names: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * - * Signal emitted when a remote caller is invoking the ListNames() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_list_names() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-list-names", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_list_names), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 1, - G_TYPE_DBUS_METHOD_INVOCATION); - - /** - * _GFreedesktopDBus::handle-list-activatable-names: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * - * Signal emitted when a remote caller is invoking the ListActivatableNames() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_list_activatable_names() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-list-activatable-names", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_list_activatable_names), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 1, - G_TYPE_DBUS_METHOD_INVOCATION); - - /** - * _GFreedesktopDBus::handle-add-match: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_rule: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the AddMatch() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_add_match() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-add-match", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_add_match), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-remove-match: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_rule: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the RemoveMatch() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_remove_match() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-remove-match", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_remove_match), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-get-name-owner: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the GetNameOwner() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_name_owner() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-get-name-owner", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_name_owner), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-list-queued-owners: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the ListQueuedOwners() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_list_queued_owners() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-list-queued-owners", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_list_queued_owners), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-get-connection-unix-user: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the GetConnectionUnixUser() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_connection_unix_user() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-get-connection-unix-user", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_connection_unix_user), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-get-connection-unix-process-id: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the GetConnectionUnixProcessID() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_connection_unix_process_id() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-get-connection-unix-process-id", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_connection_unix_process_id), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-get-connection-selinux-security-context: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_name: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the GetConnectionSELinuxSecurityContext() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_connection_selinux_security_context() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-get-connection-selinux-security-context", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_connection_selinux_security_context), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::handle-update-activation-environment: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * @arg_environment: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the UpdateActivationEnvironment() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_update_activation_environment() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-update-activation-environment", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_update_activation_environment), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_VARIANT); - - /** - * _GFreedesktopDBus::handle-reload-config: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * - * Signal emitted when a remote caller is invoking the ReloadConfig() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_reload_config() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-reload-config", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_reload_config), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 1, - G_TYPE_DBUS_METHOD_INVOCATION); - - /** - * _GFreedesktopDBus::handle-get-id: - * @object: A #_GFreedesktopDBus. - * @invocation: A #GDBusMethodInvocation. - * - * Signal emitted when a remote caller is invoking the GetId() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_id() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-get-id", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_id), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 1, - G_TYPE_DBUS_METHOD_INVOCATION); - - /* GObject signals for received D-Bus signals: */ - /** - * _GFreedesktopDBus::name-owner-changed: - * @object: A #_GFreedesktopDBus. - * @arg_name: Argument. - * @arg_old_owner: Argument. - * @arg_new_owner: Argument. - * - * On the client-side, this signal is emitted whenever the D-Bus signal "NameOwnerChanged" is received. - * - * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. - */ - g_signal_new ("name-owner-changed", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, name_owner_changed), - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::name-lost: - * @object: A #_GFreedesktopDBus. - * @arg_name: Argument. - * - * On the client-side, this signal is emitted whenever the D-Bus signal "NameLost" is received. - * - * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. - */ - g_signal_new ("name-lost", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, name_lost), - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, G_TYPE_STRING); - - /** - * _GFreedesktopDBus::name-acquired: - * @object: A #_GFreedesktopDBus. - * @arg_name: Argument. - * - * On the client-side, this signal is emitted whenever the D-Bus signal "NameAcquired" is received. - * - * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. - */ - g_signal_new ("name-acquired", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (_GFreedesktopDBusIface, name_acquired), - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, G_TYPE_STRING); - -} - -/** - * _g_freedesktop_dbus_emit_name_owner_changed: - * @object: A #_GFreedesktopDBus. - * @arg_name: Argument to pass with the signal. - * @arg_old_owner: Argument to pass with the signal. - * @arg_new_owner: Argument to pass with the signal. - * - * Emits the "NameOwnerChanged" D-Bus signal. - */ -void -_g_freedesktop_dbus_emit_name_owner_changed ( - _GFreedesktopDBus *object, - const gchar *arg_name, - const gchar *arg_old_owner, - const gchar *arg_new_owner) -{ - g_signal_emit_by_name (object, "name-owner-changed", arg_name, arg_old_owner, arg_new_owner); -} - -/** - * _g_freedesktop_dbus_emit_name_lost: - * @object: A #_GFreedesktopDBus. - * @arg_name: Argument to pass with the signal. - * - * Emits the "NameLost" D-Bus signal. - */ -void -_g_freedesktop_dbus_emit_name_lost ( - _GFreedesktopDBus *object, - const gchar *arg_name) -{ - g_signal_emit_by_name (object, "name-lost", arg_name); -} - -/** - * _g_freedesktop_dbus_emit_name_acquired: - * @object: A #_GFreedesktopDBus. - * @arg_name: Argument to pass with the signal. - * - * Emits the "NameAcquired" D-Bus signal. - */ -void -_g_freedesktop_dbus_emit_name_acquired ( - _GFreedesktopDBus *object, - const gchar *arg_name) -{ - g_signal_emit_by_name (object, "name-acquired", arg_name); -} - -/** - * _g_freedesktop_dbus_call_hello: - * @proxy: A #_GFreedesktopDBusProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the Hello() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_hello_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_hello_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_hello ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "Hello", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_hello_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_assigned_name: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_hello(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_hello(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_hello_finish ( - _GFreedesktopDBus *proxy, - gchar **out_assigned_name, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_assigned_name); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_hello_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_assigned_name: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the Hello() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_hello() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_hello_sync ( - _GFreedesktopDBus *proxy, - gchar **out_assigned_name, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "Hello", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_assigned_name); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_request_name: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @arg_flags: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the RequestName() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_request_name_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_request_name_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_request_name ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "RequestName", - g_variant_new ("(su)", - arg_name, - arg_flags), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_request_name_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_request_name(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_request_name(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_request_name_finish ( - _GFreedesktopDBus *proxy, - guint *out_value, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_value); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_request_name_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @arg_flags: Argument to pass with the method invocation. - * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the RequestName() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_request_name() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_request_name_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - guint *out_value, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "RequestName", - g_variant_new ("(su)", - arg_name, - arg_flags), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_value); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_release_name: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the ReleaseName() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_release_name_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_release_name_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_release_name ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "ReleaseName", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_release_name_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_release_name(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_release_name(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_release_name_finish ( - _GFreedesktopDBus *proxy, - guint *out_value, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_value); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_release_name_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the ReleaseName() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_release_name() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_release_name_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint *out_value, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "ReleaseName", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_value); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_start_service_by_name: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @arg_flags: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the StartServiceByName() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_start_service_by_name_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_start_service_by_name_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_start_service_by_name ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "StartServiceByName", - g_variant_new ("(su)", - arg_name, - arg_flags), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_start_service_by_name_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_start_service_by_name(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_start_service_by_name(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_start_service_by_name_finish ( - _GFreedesktopDBus *proxy, - guint *out_value, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_value); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_start_service_by_name_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @arg_flags: Argument to pass with the method invocation. - * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the StartServiceByName() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_start_service_by_name() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_start_service_by_name_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - guint *out_value, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "StartServiceByName", - g_variant_new ("(su)", - arg_name, - arg_flags), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_value); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_name_has_owner: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the NameHasOwner() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_name_has_owner_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_name_has_owner_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_name_has_owner ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "NameHasOwner", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_name_has_owner_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_has_owner: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_name_has_owner(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_name_has_owner(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_name_has_owner_finish ( - _GFreedesktopDBus *proxy, - gboolean *out_has_owner, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(b)", - out_has_owner); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_name_has_owner_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_has_owner: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the NameHasOwner() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_name_has_owner() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_name_has_owner_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gboolean *out_has_owner, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "NameHasOwner", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(b)", - out_has_owner); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_list_names: - * @proxy: A #_GFreedesktopDBusProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the ListNames() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_list_names_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_list_names_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_list_names ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "ListNames", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_list_names_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_list_names(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_list_names(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_list_names_finish ( - _GFreedesktopDBus *proxy, - gchar ***out_names, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_names); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_list_names_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the ListNames() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_list_names() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_list_names_sync ( - _GFreedesktopDBus *proxy, - gchar ***out_names, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "ListNames", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_names); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_list_activatable_names: - * @proxy: A #_GFreedesktopDBusProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the ListActivatableNames() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_list_activatable_names_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_list_activatable_names_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_list_activatable_names ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "ListActivatableNames", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_list_activatable_names_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_activatable_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_list_activatable_names(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_list_activatable_names(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_list_activatable_names_finish ( - _GFreedesktopDBus *proxy, - gchar ***out_activatable_names, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_activatable_names); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_list_activatable_names_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_activatable_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the ListActivatableNames() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_list_activatable_names() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_list_activatable_names_sync ( - _GFreedesktopDBus *proxy, - gchar ***out_activatable_names, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "ListActivatableNames", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_activatable_names); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_add_match: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_rule: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the AddMatch() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_add_match_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_add_match_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_add_match ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "AddMatch", - g_variant_new ("(s)", - arg_rule), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_add_match_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_add_match(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_add_match(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_add_match_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_add_match_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_rule: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the AddMatch() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_add_match() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_add_match_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "AddMatch", - g_variant_new ("(s)", - arg_rule), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_remove_match: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_rule: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the RemoveMatch() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_remove_match_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_remove_match_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_remove_match ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "RemoveMatch", - g_variant_new ("(s)", - arg_rule), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_remove_match_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_remove_match(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_remove_match(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_remove_match_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_remove_match_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_rule: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the RemoveMatch() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_remove_match() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_remove_match_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "RemoveMatch", - g_variant_new ("(s)", - arg_rule), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_name_owner: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GetNameOwner() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_get_name_owner_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_get_name_owner_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_get_name_owner ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GetNameOwner", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_get_name_owner_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_unique_name: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_name_owner(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_get_name_owner(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_name_owner_finish ( - _GFreedesktopDBus *proxy, - gchar **out_unique_name, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_unique_name); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_name_owner_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_unique_name: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GetNameOwner() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_get_name_owner() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_name_owner_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gchar **out_unique_name, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetNameOwner", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_unique_name); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_list_queued_owners: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the ListQueuedOwners() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_list_queued_owners_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_list_queued_owners_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_list_queued_owners ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "ListQueuedOwners", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_list_queued_owners_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_queued_owners: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_list_queued_owners(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_list_queued_owners(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_list_queued_owners_finish ( - _GFreedesktopDBus *proxy, - gchar ***out_queued_owners, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_queued_owners); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_list_queued_owners_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_queued_owners: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the ListQueuedOwners() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_list_queued_owners() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_list_queued_owners_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gchar ***out_queued_owners, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "ListQueuedOwners", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_queued_owners); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_connection_unix_user: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GetConnectionUnixUser() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_get_connection_unix_user_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_get_connection_unix_user_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_get_connection_unix_user ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GetConnectionUnixUser", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_get_connection_unix_user_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_uid: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_connection_unix_user(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_get_connection_unix_user(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_connection_unix_user_finish ( - _GFreedesktopDBus *proxy, - guint *out_uid, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_uid); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_connection_unix_user_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_uid: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GetConnectionUnixUser() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_get_connection_unix_user() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_connection_unix_user_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint *out_uid, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetConnectionUnixUser", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_uid); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_connection_unix_process_id: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GetConnectionUnixProcessID() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_get_connection_unix_process_id_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_get_connection_unix_process_id_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_get_connection_unix_process_id ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GetConnectionUnixProcessID", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_get_connection_unix_process_id_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_pid: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_connection_unix_process_id(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_get_connection_unix_process_id(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_connection_unix_process_id_finish ( - _GFreedesktopDBus *proxy, - guint *out_pid, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_pid); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_connection_unix_process_id_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_pid: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GetConnectionUnixProcessID() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_get_connection_unix_process_id() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_connection_unix_process_id_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint *out_pid, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetConnectionUnixProcessID", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_pid); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_connection_selinux_security_context: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GetConnectionSELinuxSecurityContext() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_get_connection_selinux_security_context_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_get_connection_selinux_security_context_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_get_connection_selinux_security_context ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GetConnectionSELinuxSecurityContext", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_get_connection_selinux_security_context_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_security_context: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_connection_selinux_security_context(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_get_connection_selinux_security_context(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_connection_selinux_security_context_finish ( - _GFreedesktopDBus *proxy, - gchar **out_security_context, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^ay)", - out_security_context); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_connection_selinux_security_context_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_name: Argument to pass with the method invocation. - * @out_security_context: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GetConnectionSELinuxSecurityContext() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_get_connection_selinux_security_context() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_connection_selinux_security_context_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gchar **out_security_context, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetConnectionSELinuxSecurityContext", - g_variant_new ("(s)", - arg_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^ay)", - out_security_context); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_update_activation_environment: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_environment: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the UpdateActivationEnvironment() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_update_activation_environment_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_update_activation_environment_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_update_activation_environment ( - _GFreedesktopDBus *proxy, - GVariant *arg_environment, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "UpdateActivationEnvironment", - g_variant_new ("(@a{ss})", - arg_environment), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_update_activation_environment_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_update_activation_environment(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_update_activation_environment(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_update_activation_environment_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_update_activation_environment_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @arg_environment: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the UpdateActivationEnvironment() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_update_activation_environment() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_update_activation_environment_sync ( - _GFreedesktopDBus *proxy, - GVariant *arg_environment, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "UpdateActivationEnvironment", - g_variant_new ("(@a{ss})", - arg_environment), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_reload_config: - * @proxy: A #_GFreedesktopDBusProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the ReloadConfig() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_reload_config_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_reload_config_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_reload_config ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "ReloadConfig", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_reload_config_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_reload_config(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_reload_config(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_reload_config_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_reload_config_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the ReloadConfig() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_reload_config() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_reload_config_sync ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "ReloadConfig", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_id: - * @proxy: A #_GFreedesktopDBusProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GetId() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_call_get_id_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_call_get_id_sync() for the synchronous, blocking version of this method. - */ -void -_g_freedesktop_dbus_call_get_id ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GetId", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * _g_freedesktop_dbus_call_get_id_finish: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_unique_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_id(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with _g_freedesktop_dbus_call_get_id(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_id_finish ( - _GFreedesktopDBus *proxy, - gchar **out_unique_id, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_unique_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_call_get_id_sync: - * @proxy: A #_GFreedesktopDBusProxy. - * @out_unique_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GetId() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_call_get_id() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -_g_freedesktop_dbus_call_get_id_sync ( - _GFreedesktopDBus *proxy, - gchar **out_unique_id, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetId", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_unique_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * _g_freedesktop_dbus_complete_hello: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @assigned_name: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the Hello() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_hello ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *assigned_name) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", - assigned_name)); -} - -/** - * _g_freedesktop_dbus_complete_request_name: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @value: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the RequestName() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_request_name ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint value) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(u)", - value)); -} - -/** - * _g_freedesktop_dbus_complete_release_name: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @value: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the ReleaseName() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_release_name ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint value) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(u)", - value)); -} - -/** - * _g_freedesktop_dbus_complete_start_service_by_name: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @value: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the StartServiceByName() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_start_service_by_name ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint value) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(u)", - value)); -} - -/** - * _g_freedesktop_dbus_complete_name_has_owner: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @has_owner: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the NameHasOwner() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_name_has_owner ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - gboolean has_owner) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(b)", - has_owner)); -} - -/** - * _g_freedesktop_dbus_complete_list_names: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @names: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the ListNames() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_list_names ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *const *names) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^as)", - names)); -} - -/** - * _g_freedesktop_dbus_complete_list_activatable_names: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @activatable_names: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the ListActivatableNames() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_list_activatable_names ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *const *activatable_names) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^as)", - activatable_names)); -} - -/** - * _g_freedesktop_dbus_complete_add_match: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the AddMatch() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_add_match ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * _g_freedesktop_dbus_complete_remove_match: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the RemoveMatch() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_remove_match ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * _g_freedesktop_dbus_complete_get_name_owner: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @unique_name: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the GetNameOwner() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_get_name_owner ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *unique_name) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", - unique_name)); -} - -/** - * _g_freedesktop_dbus_complete_list_queued_owners: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @queued_owners: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the ListQueuedOwners() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_list_queued_owners ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *const *queued_owners) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^as)", - queued_owners)); -} - -/** - * _g_freedesktop_dbus_complete_get_connection_unix_user: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @uid: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the GetConnectionUnixUser() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_get_connection_unix_user ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint uid) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(u)", - uid)); -} - -/** - * _g_freedesktop_dbus_complete_get_connection_unix_process_id: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @pid: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the GetConnectionUnixProcessID() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_get_connection_unix_process_id ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint pid) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(u)", - pid)); -} - -/** - * _g_freedesktop_dbus_complete_get_connection_selinux_security_context: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @security_context: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the GetConnectionSELinuxSecurityContext() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_get_connection_selinux_security_context ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *security_context) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^ay)", - security_context)); -} - -/** - * _g_freedesktop_dbus_complete_update_activation_environment: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the UpdateActivationEnvironment() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_update_activation_environment ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * _g_freedesktop_dbus_complete_reload_config: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the ReloadConfig() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_reload_config ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * _g_freedesktop_dbus_complete_get_id: - * @object: A #_GFreedesktopDBus. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @unique_id: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the GetId() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -_g_freedesktop_dbus_complete_get_id ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *unique_id) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", - unique_id)); -} - -/* ------------------------------------------------------------------------ */ - -/** - * _GFreedesktopDBusProxy: - * - * The #_GFreedesktopDBusProxy structure contains only private data and should only be accessed using the provided API. - */ - -/** - * _GFreedesktopDBusProxyClass: - * @parent_class: The parent class. - * - * Class structure for #_GFreedesktopDBusProxy. - */ - -struct __GFreedesktopDBusProxyPrivate -{ - GData *qdata; -}; - -static void _g_freedesktop_dbus_proxy_iface_init (_GFreedesktopDBusIface *iface); - -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusProxy, _g_freedesktop_dbus_proxy, G_TYPE_DBUS_PROXY, - G_ADD_PRIVATE (_GFreedesktopDBusProxy) - G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_proxy_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusProxy, _g_freedesktop_dbus_proxy, G_TYPE_DBUS_PROXY, - G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_proxy_iface_init)) - -#endif -static void -_g_freedesktop_dbus_proxy_finalize (GObject *object) -{ - _GFreedesktopDBusProxy *proxy = _G_FREEDESKTOP_DBUS_PROXY (object); - g_datalist_clear (&proxy->priv->qdata); - G_OBJECT_CLASS (_g_freedesktop_dbus_proxy_parent_class)->finalize (object); -} - -static void -_g_freedesktop_dbus_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ -} - -static void -_g_freedesktop_dbus_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ -} - -static void -_g_freedesktop_dbus_proxy_g_signal (GDBusProxy *proxy, - const gchar *sender_name G_GNUC_UNUSED, - const gchar *signal_name, - GVariant *parameters) -{ - _ExtendedGDBusSignalInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - gsize n; - guint signal_id; - info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, signal_name); - if (info == NULL) - return; - num_params = g_variant_n_children (parameters); - paramv = g_new0 (GValue, num_params + 1); - g_value_init (¶mv[0], _G_TYPE_FREEDESKTOP_DBUS); - g_value_set_object (¶mv[0], proxy); - g_variant_iter_init (&iter, parameters); - n = 1; - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, _G_TYPE_FREEDESKTOP_DBUS); - g_signal_emitv (paramv, signal_id, 0, NULL); - for (n = 0; n < num_params + 1; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static void -_g_freedesktop_dbus_proxy_g_properties_changed (GDBusProxy *_proxy, - GVariant *changed_properties, - const gchar *const *invalidated_properties) -{ - _GFreedesktopDBusProxy *proxy = _G_FREEDESKTOP_DBUS_PROXY (_proxy); - guint n; - const gchar *key; - GVariantIter *iter; - _ExtendedGDBusPropertyInfo *info; - g_variant_get (changed_properties, "a{sv}", &iter); - while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, key); - g_datalist_remove_data (&proxy->priv->qdata, key); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } - g_variant_iter_free (iter); - for (n = 0; invalidated_properties[n] != NULL; n++) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, invalidated_properties[n]); - g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } -} - -static void -_g_freedesktop_dbus_proxy_init (_GFreedesktopDBusProxy *proxy) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - proxy->priv = _g_freedesktop_dbus_proxy_get_instance_private (proxy); -#else - proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxyPrivate); -#endif - - g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), _g_freedesktop_dbus_interface_info ()); -} - -static void -_g_freedesktop_dbus_proxy_class_init (_GFreedesktopDBusProxyClass *klass) -{ - GObjectClass *gobject_class; - GDBusProxyClass *proxy_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = _g_freedesktop_dbus_proxy_finalize; - gobject_class->get_property = _g_freedesktop_dbus_proxy_get_property; - gobject_class->set_property = _g_freedesktop_dbus_proxy_set_property; - - proxy_class = G_DBUS_PROXY_CLASS (klass); - proxy_class->g_signal = _g_freedesktop_dbus_proxy_g_signal; - proxy_class->g_properties_changed = _g_freedesktop_dbus_proxy_g_properties_changed; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (_GFreedesktopDBusProxyPrivate)); -#endif -} - -static void -_g_freedesktop_dbus_proxy_iface_init (_GFreedesktopDBusIface *iface) -{ -} - -/** - * _g_freedesktop_dbus_proxy_new: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.DBus. See g_dbus_proxy_new() for more details. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_proxy_new_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_proxy_new_sync() for the synchronous, blocking version of this constructor. - */ -void -_g_freedesktop_dbus_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (_G_TYPE_FREEDESKTOP_DBUS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); -} - -/** - * _g_freedesktop_dbus_proxy_new_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_proxy_new(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with _g_freedesktop_dbus_proxy_new(). - * - * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. - */ -_GFreedesktopDBus * -_g_freedesktop_dbus_proxy_new_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return _G_FREEDESKTOP_DBUS (ret); - else - return NULL; -} - -/** - * _g_freedesktop_dbus_proxy_new_sync: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Synchronously creates a proxy for the D-Bus interface org.freedesktop.DBus. See g_dbus_proxy_new_sync() for more details. - * - * The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_proxy_new() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. - */ -_GFreedesktopDBus * -_g_freedesktop_dbus_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (_G_TYPE_FREEDESKTOP_DBUS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); - if (ret != NULL) - return _G_FREEDESKTOP_DBUS (ret); - else - return NULL; -} - - -/** - * _g_freedesktop_dbus_proxy_new_for_bus: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Like _g_freedesktop_dbus_proxy_new() but takes a #GBusType instead of a #GDBusConnection. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call _g_freedesktop_dbus_proxy_new_for_bus_finish() to get the result of the operation. - * - * See _g_freedesktop_dbus_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. - */ -void -_g_freedesktop_dbus_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (_G_TYPE_FREEDESKTOP_DBUS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); -} - -/** - * _g_freedesktop_dbus_proxy_new_for_bus_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_proxy_new_for_bus(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with _g_freedesktop_dbus_proxy_new_for_bus(). - * - * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. - */ -_GFreedesktopDBus * -_g_freedesktop_dbus_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return _G_FREEDESKTOP_DBUS (ret); - else - return NULL; -} - -/** - * _g_freedesktop_dbus_proxy_new_for_bus_sync: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Like _g_freedesktop_dbus_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. - * - * The calling thread is blocked until a reply is received. - * - * See _g_freedesktop_dbus_proxy_new_for_bus() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. - */ -_GFreedesktopDBus * -_g_freedesktop_dbus_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (_G_TYPE_FREEDESKTOP_DBUS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); - if (ret != NULL) - return _G_FREEDESKTOP_DBUS (ret); - else - return NULL; -} - - -/* ------------------------------------------------------------------------ */ - -/** - * _GFreedesktopDBusSkeleton: - * - * The #_GFreedesktopDBusSkeleton structure contains only private data and should only be accessed using the provided API. - */ - -/** - * _GFreedesktopDBusSkeletonClass: - * @parent_class: The parent class. - * - * Class structure for #_GFreedesktopDBusSkeleton. - */ - -struct __GFreedesktopDBusSkeletonPrivate -{ - GValue *properties; - GList *changed_properties; - GSource *changed_properties_idle_source; - GMainContext *context; - GMutex lock; -}; - -static void -__g_freedesktop_dbus_skeleton_handle_method_call ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (user_data); - _ExtendedGDBusMethodInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - guint num_extra; - gsize n; - guint signal_id; - GValue return_value = G_VALUE_INIT; - info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); - g_assert (info != NULL); - num_params = g_variant_n_children (parameters); - num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); - n = 0; - g_value_init (¶mv[n], _G_TYPE_FREEDESKTOP_DBUS); - g_value_set_object (¶mv[n++], skeleton); - g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); - g_value_set_object (¶mv[n++], invocation); - if (info->pass_fdlist) - { -#ifdef G_OS_UNIX - g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); - g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); -#else - g_assert_not_reached (); -#endif - } - g_variant_iter_init (&iter, parameters); - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, _G_TYPE_FREEDESKTOP_DBUS); - g_value_init (&return_value, G_TYPE_BOOLEAN); - g_signal_emitv (paramv, signal_id, 0, &return_value); - if (!g_value_get_boolean (&return_value)) - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); - g_value_unset (&return_value); - for (n = 0; n < num_params + num_extra; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static GVariant * -__g_freedesktop_dbus_skeleton_handle_get_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - GVariant *ret; - ret = NULL; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); - ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_value_unset (&value); - } - return ret; -} - -static gboolean -__g_freedesktop_dbus_skeleton_handle_set_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GVariant *variant, - GError **error, - gpointer user_data) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - gboolean ret; - ret = FALSE; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - if (info->use_gvariant) - g_value_set_variant (&value, variant); - else - g_dbus_gvariant_to_gvalue (variant, &value); - g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); - g_value_unset (&value); - ret = TRUE; - } - return ret; -} - -static const GDBusInterfaceVTable __g_freedesktop_dbus_skeleton_vtable = -{ - __g_freedesktop_dbus_skeleton_handle_method_call, - __g_freedesktop_dbus_skeleton_handle_get_property, - __g_freedesktop_dbus_skeleton_handle_set_property, - {NULL} -}; - -static GDBusInterfaceInfo * -_g_freedesktop_dbus_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return _g_freedesktop_dbus_interface_info (); -} - -static GDBusInterfaceVTable * -_g_freedesktop_dbus_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return (GDBusInterfaceVTable *) &__g_freedesktop_dbus_skeleton_vtable; -} - -static GVariant * -_g_freedesktop_dbus_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (_skeleton); - - GVariantBuilder builder; - guint n; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - if (__g_freedesktop_dbus_interface_info.parent_struct.properties == NULL) - goto out; - for (n = 0; __g_freedesktop_dbus_interface_info.parent_struct.properties[n] != NULL; n++) - { - GDBusPropertyInfo *info = __g_freedesktop_dbus_interface_info.parent_struct.properties[n]; - if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) - { - GVariant *value; - value = __g_freedesktop_dbus_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", info->name, NULL, skeleton); - if (value != NULL) - { - g_variant_take_ref (value); - g_variant_builder_add (&builder, "{sv}", info->name, value); - g_variant_unref (value); - } - } - } -out: - return g_variant_builder_end (&builder); -} - -static void -_g_freedesktop_dbus_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) -{ -} - -static void -__g_freedesktop_dbus_on_signal_name_owner_changed ( - _GFreedesktopDBus *object, - const gchar *arg_name, - const gchar *arg_old_owner, - const gchar *arg_new_owner) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); - - GList *connections, *l; - GVariant *signal_variant; - connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); - - signal_variant = g_variant_ref_sink (g_variant_new ("(sss)", - arg_name, - arg_old_owner, - arg_new_owner)); - for (l = connections; l != NULL; l = l->next) - { - GDBusConnection *connection = l->data; - g_dbus_connection_emit_signal (connection, - NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", "NameOwnerChanged", - signal_variant, NULL); - } - g_variant_unref (signal_variant); - g_list_free_full (connections, g_object_unref); -} - -static void -__g_freedesktop_dbus_on_signal_name_lost ( - _GFreedesktopDBus *object, - const gchar *arg_name) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); - - GList *connections, *l; - GVariant *signal_variant; - connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); - - signal_variant = g_variant_ref_sink (g_variant_new ("(s)", - arg_name)); - for (l = connections; l != NULL; l = l->next) - { - GDBusConnection *connection = l->data; - g_dbus_connection_emit_signal (connection, - NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", "NameLost", - signal_variant, NULL); - } - g_variant_unref (signal_variant); - g_list_free_full (connections, g_object_unref); -} - -static void -__g_freedesktop_dbus_on_signal_name_acquired ( - _GFreedesktopDBus *object, - const gchar *arg_name) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); - - GList *connections, *l; - GVariant *signal_variant; - connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); - - signal_variant = g_variant_ref_sink (g_variant_new ("(s)", - arg_name)); - for (l = connections; l != NULL; l = l->next) - { - GDBusConnection *connection = l->data; - g_dbus_connection_emit_signal (connection, - NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", "NameAcquired", - signal_variant, NULL); - } - g_variant_unref (signal_variant); - g_list_free_full (connections, g_object_unref); -} - -static void _g_freedesktop_dbus_skeleton_iface_init (_GFreedesktopDBusIface *iface); -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusSkeleton, _g_freedesktop_dbus_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_ADD_PRIVATE (_GFreedesktopDBusSkeleton) - G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_skeleton_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusSkeleton, _g_freedesktop_dbus_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_skeleton_iface_init)) - -#endif -static void -_g_freedesktop_dbus_skeleton_finalize (GObject *object) -{ - _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - if (skeleton->priv->changed_properties_idle_source != NULL) - g_source_destroy (skeleton->priv->changed_properties_idle_source); - g_main_context_unref (skeleton->priv->context); - g_mutex_clear (&skeleton->priv->lock); - G_OBJECT_CLASS (_g_freedesktop_dbus_skeleton_parent_class)->finalize (object); -} - -static void -_g_freedesktop_dbus_skeleton_init (_GFreedesktopDBusSkeleton *skeleton) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - skeleton->priv = _g_freedesktop_dbus_skeleton_get_instance_private (skeleton); -#else - skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeletonPrivate); -#endif - - g_mutex_init (&skeleton->priv->lock); - skeleton->priv->context = g_main_context_ref_thread_default (); -} - -static void -_g_freedesktop_dbus_skeleton_class_init (_GFreedesktopDBusSkeletonClass *klass) -{ - GObjectClass *gobject_class; - GDBusInterfaceSkeletonClass *skeleton_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = _g_freedesktop_dbus_skeleton_finalize; - - skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); - skeleton_class->get_info = _g_freedesktop_dbus_skeleton_dbus_interface_get_info; - skeleton_class->get_properties = _g_freedesktop_dbus_skeleton_dbus_interface_get_properties; - skeleton_class->flush = _g_freedesktop_dbus_skeleton_dbus_interface_flush; - skeleton_class->get_vtable = _g_freedesktop_dbus_skeleton_dbus_interface_get_vtable; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (_GFreedesktopDBusSkeletonPrivate)); -#endif -} - -static void -_g_freedesktop_dbus_skeleton_iface_init (_GFreedesktopDBusIface *iface) -{ - iface->name_owner_changed = __g_freedesktop_dbus_on_signal_name_owner_changed; - iface->name_lost = __g_freedesktop_dbus_on_signal_name_lost; - iface->name_acquired = __g_freedesktop_dbus_on_signal_name_acquired; -} - -/** - * _g_freedesktop_dbus_skeleton_new: - * - * Creates a skeleton object for the D-Bus interface org.freedesktop.DBus. - * - * Returns: (transfer full) (type _GFreedesktopDBusSkeleton): The skeleton object. - */ -_GFreedesktopDBus * -_g_freedesktop_dbus_skeleton_new (void) -{ - return _G_FREEDESKTOP_DBUS (g_object_new (_G_TYPE_FREEDESKTOP_DBUS_SKELETON, NULL)); -} - +/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gdbus-daemon-generated.h" + +#include +#ifdef G_OS_UNIX +# include +#endif + +typedef struct +{ + GDBusArgInfo parent_struct; + gboolean use_gvariant; +} _ExtendedGDBusArgInfo; + +typedef struct +{ + GDBusMethodInfo parent_struct; + const gchar *signal_name; + gboolean pass_fdlist; +} _ExtendedGDBusMethodInfo; + +typedef struct +{ + GDBusSignalInfo parent_struct; + const gchar *signal_name; +} _ExtendedGDBusSignalInfo; + +typedef struct +{ + GDBusPropertyInfo parent_struct; + const gchar *hyphen_name; + guint use_gvariant : 1; + guint emits_changed_signal : 1; +} _ExtendedGDBusPropertyInfo; + +typedef struct +{ + GDBusInterfaceInfo parent_struct; + const gchar *hyphen_name; +} _ExtendedGDBusInterfaceInfo; + +typedef struct +{ + const _ExtendedGDBusPropertyInfo *info; + guint prop_id; + GValue orig_value; /* the value before the change */ +} ChangedProperty; + +static void +_changed_property_free (ChangedProperty *data) +{ + g_value_unset (&data->orig_value); + g_free (data); +} + +static gboolean +_g_strv_equal0 (gchar **a, gchar **b) +{ + gboolean ret = FALSE; + guint n; + if (a == NULL && b == NULL) + { + ret = TRUE; + goto out; + } + if (a == NULL || b == NULL) + goto out; + if (g_strv_length (a) != g_strv_length (b)) + goto out; + for (n = 0; a[n] != NULL; n++) + if (g_strcmp0 (a[n], b[n]) != 0) + goto out; + ret = TRUE; +out: + return ret; +} + +static gboolean +_g_variant_equal0 (GVariant *a, GVariant *b) +{ + gboolean ret = FALSE; + if (a == NULL && b == NULL) + { + ret = TRUE; + goto out; + } + if (a == NULL || b == NULL) + goto out; + ret = g_variant_equal (a, b); +out: + return ret; +} + +G_GNUC_UNUSED static gboolean +_g_value_equal (const GValue *a, const GValue *b) +{ + gboolean ret = FALSE; + g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b)); + switch (G_VALUE_TYPE (a)) + { + case G_TYPE_BOOLEAN: + ret = (g_value_get_boolean (a) == g_value_get_boolean (b)); + break; + case G_TYPE_UCHAR: + ret = (g_value_get_uchar (a) == g_value_get_uchar (b)); + break; + case G_TYPE_INT: + ret = (g_value_get_int (a) == g_value_get_int (b)); + break; + case G_TYPE_UINT: + ret = (g_value_get_uint (a) == g_value_get_uint (b)); + break; + case G_TYPE_INT64: + ret = (g_value_get_int64 (a) == g_value_get_int64 (b)); + break; + case G_TYPE_UINT64: + ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b)); + break; + case G_TYPE_DOUBLE: + { + /* Avoid -Wfloat-equal warnings by doing a direct bit compare */ + gdouble da = g_value_get_double (a); + gdouble db = g_value_get_double (b); + ret = memcmp (&da, &db, sizeof (gdouble)) == 0; + } + break; + case G_TYPE_STRING: + ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0); + break; + case G_TYPE_VARIANT: + ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b)); + break; + default: + if (G_VALUE_TYPE (a) == G_TYPE_STRV) + ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b)); + else + g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a))); + break; + } + return ret; +} + +/* ------------------------------------------------------------------------ + * Code for interface org.freedesktop.DBus + * ------------------------------------------------------------------------ + */ + +/** + * SECTION:_GFreedesktopDBus + * @title: _GFreedesktopDBus + * @short_description: Generated C code for the org.freedesktop.DBus D-Bus interface + * + * This section contains code for working with the org.freedesktop.DBus D-Bus interface in C. + */ + +/* ---- Introspection data for org.freedesktop.DBus ---- */ + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_hello_OUT_ARG_assigned_name = +{ + { + -1, + (gchar *) "assigned_name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_hello_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_hello_OUT_ARG_assigned_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_hello = +{ + { + -1, + (gchar *) "Hello", + NULL, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_hello_OUT_ARG_pointers, + NULL + }, + "handle-hello", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_request_name_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_request_name_IN_ARG_flags = +{ + { + -1, + (gchar *) "flags", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_request_name_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_request_name_IN_ARG_name.parent_struct, + &__g_freedesktop_dbus_method_info_request_name_IN_ARG_flags.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_request_name_OUT_ARG_value = +{ + { + -1, + (gchar *) "value", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_request_name_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_request_name_OUT_ARG_value.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_request_name = +{ + { + -1, + (gchar *) "RequestName", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_request_name_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_request_name_OUT_ARG_pointers, + NULL + }, + "handle-request-name", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_release_name_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_release_name_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_release_name_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_release_name_OUT_ARG_value = +{ + { + -1, + (gchar *) "value", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_release_name_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_release_name_OUT_ARG_value.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_release_name = +{ + { + -1, + (gchar *) "ReleaseName", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_release_name_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_release_name_OUT_ARG_pointers, + NULL + }, + "handle-release-name", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_flags = +{ + { + -1, + (gchar *) "flags", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_name.parent_struct, + &__g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_flags.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_value = +{ + { + -1, + (gchar *) "value", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_value.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_start_service_by_name = +{ + { + -1, + (gchar *) "StartServiceByName", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_start_service_by_name_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_start_service_by_name_OUT_ARG_pointers, + NULL + }, + "handle-start-service-by-name", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_has_owner = +{ + { + -1, + (gchar *) "has_owner", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_has_owner.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_name_has_owner = +{ + { + -1, + (gchar *) "NameHasOwner", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_name_has_owner_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_name_has_owner_OUT_ARG_pointers, + NULL + }, + "handle-name-has-owner", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_names_OUT_ARG_names = +{ + { + -1, + (gchar *) "names", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_names_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_list_names_OUT_ARG_names.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_list_names = +{ + { + -1, + (gchar *) "ListNames", + NULL, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_names_OUT_ARG_pointers, + NULL + }, + "handle-list-names", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_activatable_names = +{ + { + -1, + (gchar *) "activatable_names", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_activatable_names.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_list_activatable_names = +{ + { + -1, + (gchar *) "ListActivatableNames", + NULL, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_activatable_names_OUT_ARG_pointers, + NULL + }, + "handle-list-activatable-names", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_add_match_IN_ARG_rule = +{ + { + -1, + (gchar *) "rule", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_add_match_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_add_match_IN_ARG_rule.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_add_match = +{ + { + -1, + (gchar *) "AddMatch", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_add_match_IN_ARG_pointers, + NULL, + NULL + }, + "handle-add-match", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_remove_match_IN_ARG_rule = +{ + { + -1, + (gchar *) "rule", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_remove_match_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_remove_match_IN_ARG_rule.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_remove_match = +{ + { + -1, + (gchar *) "RemoveMatch", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_remove_match_IN_ARG_pointers, + NULL, + NULL + }, + "handle-remove-match", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_unique_name = +{ + { + -1, + (gchar *) "unique_name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_unique_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_name_owner = +{ + { + -1, + (gchar *) "GetNameOwner", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_name_owner_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_name_owner_OUT_ARG_pointers, + NULL + }, + "handle-get-name-owner", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_queued_owners = +{ + { + -1, + (gchar *) "queued_owners", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_queued_owners.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_list_queued_owners = +{ + { + -1, + (gchar *) "ListQueuedOwners", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_queued_owners_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_list_queued_owners_OUT_ARG_pointers, + NULL + }, + "handle-list-queued-owners", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_uid = +{ + { + -1, + (gchar *) "uid", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_uid.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_connection_unix_user = +{ + { + -1, + (gchar *) "GetConnectionUnixUser", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_user_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_user_OUT_ARG_pointers, + NULL + }, + "handle-get-connection-unix-user", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pid = +{ + { + -1, + (gchar *) "pid", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pid.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_connection_unix_process_id = +{ + { + -1, + (gchar *) "GetConnectionUnixProcessID", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_unix_process_id_OUT_ARG_pointers, + NULL + }, + "handle-get-connection-unix-process-id", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_security_context = +{ + { + -1, + (gchar *) "security_context", + (gchar *) "ay", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_security_context.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_connection_selinux_security_context = +{ + { + -1, + (gchar *) "GetConnectionSELinuxSecurityContext", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_IN_ARG_pointers, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context_OUT_ARG_pointers, + NULL + }, + "handle-get-connection-selinux-security-context", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_environment = +{ + { + -1, + (gchar *) "environment", + (gchar *) "a{ss}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_environment.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_update_activation_environment = +{ + { + -1, + (gchar *) "UpdateActivationEnvironment", + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_update_activation_environment_IN_ARG_pointers, + NULL, + NULL + }, + "handle-update-activation-environment", + FALSE +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_reload_config = +{ + { + -1, + (gchar *) "ReloadConfig", + NULL, + NULL, + NULL + }, + "handle-reload-config", + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_method_info_get_id_OUT_ARG_unique_id = +{ + { + -1, + (gchar *) "unique_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_method_info_get_id_OUT_ARG_pointers[] = +{ + &__g_freedesktop_dbus_method_info_get_id_OUT_ARG_unique_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo __g_freedesktop_dbus_method_info_get_id = +{ + { + -1, + (gchar *) "GetId", + NULL, + (GDBusArgInfo **) &__g_freedesktop_dbus_method_info_get_id_OUT_ARG_pointers, + NULL + }, + "handle-get-id", + FALSE +}; + +static const GDBusMethodInfo * const __g_freedesktop_dbus_method_info_pointers[] = +{ + &__g_freedesktop_dbus_method_info_hello.parent_struct, + &__g_freedesktop_dbus_method_info_request_name.parent_struct, + &__g_freedesktop_dbus_method_info_release_name.parent_struct, + &__g_freedesktop_dbus_method_info_start_service_by_name.parent_struct, + &__g_freedesktop_dbus_method_info_name_has_owner.parent_struct, + &__g_freedesktop_dbus_method_info_list_names.parent_struct, + &__g_freedesktop_dbus_method_info_list_activatable_names.parent_struct, + &__g_freedesktop_dbus_method_info_add_match.parent_struct, + &__g_freedesktop_dbus_method_info_remove_match.parent_struct, + &__g_freedesktop_dbus_method_info_get_name_owner.parent_struct, + &__g_freedesktop_dbus_method_info_list_queued_owners.parent_struct, + &__g_freedesktop_dbus_method_info_get_connection_unix_user.parent_struct, + &__g_freedesktop_dbus_method_info_get_connection_unix_process_id.parent_struct, + &__g_freedesktop_dbus_method_info_get_connection_selinux_security_context.parent_struct, + &__g_freedesktop_dbus_method_info_update_activation_environment.parent_struct, + &__g_freedesktop_dbus_method_info_reload_config.parent_struct, + &__g_freedesktop_dbus_method_info_get_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_old_owner = +{ + { + -1, + (gchar *) "old_owner", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_new_owner = +{ + { + -1, + (gchar *) "new_owner", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_signal_info_name_owner_changed_ARG_pointers[] = +{ + &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_name.parent_struct, + &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_old_owner.parent_struct, + &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_new_owner.parent_struct, + NULL +}; + +static const _ExtendedGDBusSignalInfo __g_freedesktop_dbus_signal_info_name_owner_changed = +{ + { + -1, + (gchar *) "NameOwnerChanged", + (GDBusArgInfo **) &__g_freedesktop_dbus_signal_info_name_owner_changed_ARG_pointers, + NULL + }, + "name-owner-changed" +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_lost_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_signal_info_name_lost_ARG_pointers[] = +{ + &__g_freedesktop_dbus_signal_info_name_lost_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusSignalInfo __g_freedesktop_dbus_signal_info_name_lost = +{ + { + -1, + (gchar *) "NameLost", + (GDBusArgInfo **) &__g_freedesktop_dbus_signal_info_name_lost_ARG_pointers, + NULL + }, + "name-lost" +}; + +static const _ExtendedGDBusArgInfo __g_freedesktop_dbus_signal_info_name_acquired_ARG_name = +{ + { + -1, + (gchar *) "name", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const __g_freedesktop_dbus_signal_info_name_acquired_ARG_pointers[] = +{ + &__g_freedesktop_dbus_signal_info_name_acquired_ARG_name.parent_struct, + NULL +}; + +static const _ExtendedGDBusSignalInfo __g_freedesktop_dbus_signal_info_name_acquired = +{ + { + -1, + (gchar *) "NameAcquired", + (GDBusArgInfo **) &__g_freedesktop_dbus_signal_info_name_acquired_ARG_pointers, + NULL + }, + "name-acquired" +}; + +static const GDBusSignalInfo * const __g_freedesktop_dbus_signal_info_pointers[] = +{ + &__g_freedesktop_dbus_signal_info_name_owner_changed.parent_struct, + &__g_freedesktop_dbus_signal_info_name_lost.parent_struct, + &__g_freedesktop_dbus_signal_info_name_acquired.parent_struct, + NULL +}; + +static const _ExtendedGDBusInterfaceInfo __g_freedesktop_dbus_interface_info = +{ + { + -1, + (gchar *) "org.freedesktop.DBus", + (GDBusMethodInfo **) &__g_freedesktop_dbus_method_info_pointers, + (GDBusSignalInfo **) &__g_freedesktop_dbus_signal_info_pointers, + NULL, + NULL + }, + "freedesktop-dbus", +}; + + +/** + * _g_freedesktop_dbus_interface_info: + * + * Gets a machine-readable description of the org.freedesktop.DBus D-Bus interface. + * + * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. + */ +GDBusInterfaceInfo * +_g_freedesktop_dbus_interface_info (void) +{ + return (GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct; +} + +/** + * _g_freedesktop_dbus_override_properties: + * @klass: The class structure for a #GObject derived class. + * @property_id_begin: The property id to assign to the first overridden property. + * + * Overrides all #GObject properties in the #_GFreedesktopDBus interface for a concrete class. + * The properties are overridden in the order they are defined. + * + * Returns: The last property id. + */ +guint +_g_freedesktop_dbus_override_properties (GObjectClass *klass G_GNUC_UNUSED, guint property_id_begin) +{ + return property_id_begin - 1; +} + + + +/** + * _GFreedesktopDBus: + * + * Abstract interface type for the D-Bus interface org.freedesktop.DBus. + */ + +/** + * _GFreedesktopDBusIface: + * @parent_iface: The parent interface. + * @handle_add_match: Handler for the #_GFreedesktopDBus::handle-add-match signal. + * @handle_get_connection_selinux_security_context: Handler for the #_GFreedesktopDBus::handle-get-connection-selinux-security-context signal. + * @handle_get_connection_unix_process_id: Handler for the #_GFreedesktopDBus::handle-get-connection-unix-process-id signal. + * @handle_get_connection_unix_user: Handler for the #_GFreedesktopDBus::handle-get-connection-unix-user signal. + * @handle_get_id: Handler for the #_GFreedesktopDBus::handle-get-id signal. + * @handle_get_name_owner: Handler for the #_GFreedesktopDBus::handle-get-name-owner signal. + * @handle_hello: Handler for the #_GFreedesktopDBus::handle-hello signal. + * @handle_list_activatable_names: Handler for the #_GFreedesktopDBus::handle-list-activatable-names signal. + * @handle_list_names: Handler for the #_GFreedesktopDBus::handle-list-names signal. + * @handle_list_queued_owners: Handler for the #_GFreedesktopDBus::handle-list-queued-owners signal. + * @handle_name_has_owner: Handler for the #_GFreedesktopDBus::handle-name-has-owner signal. + * @handle_release_name: Handler for the #_GFreedesktopDBus::handle-release-name signal. + * @handle_reload_config: Handler for the #_GFreedesktopDBus::handle-reload-config signal. + * @handle_remove_match: Handler for the #_GFreedesktopDBus::handle-remove-match signal. + * @handle_request_name: Handler for the #_GFreedesktopDBus::handle-request-name signal. + * @handle_start_service_by_name: Handler for the #_GFreedesktopDBus::handle-start-service-by-name signal. + * @handle_update_activation_environment: Handler for the #_GFreedesktopDBus::handle-update-activation-environment signal. + * @name_acquired: Handler for the #_GFreedesktopDBus::name-acquired signal. + * @name_lost: Handler for the #_GFreedesktopDBus::name-lost signal. + * @name_owner_changed: Handler for the #_GFreedesktopDBus::name-owner-changed signal. + * + * Virtual table for the D-Bus interface org.freedesktop.DBus. + */ + +typedef _GFreedesktopDBusIface _GFreedesktopDBusInterface; +G_DEFINE_INTERFACE (_GFreedesktopDBus, _g_freedesktop_dbus, G_TYPE_OBJECT) + +static void +_g_freedesktop_dbus_default_init (_GFreedesktopDBusIface *iface) +{ + /* GObject signals for incoming D-Bus method calls: */ + /** + * _GFreedesktopDBus::handle-hello: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * + * Signal emitted when a remote caller is invoking the Hello() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_hello() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-hello", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_hello), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + + /** + * _GFreedesktopDBus::handle-request-name: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * @arg_flags: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the RequestName() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_request_name() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-request-name", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_request_name), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 3, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_UINT); + + /** + * _GFreedesktopDBus::handle-release-name: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the ReleaseName() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_release_name() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-release-name", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_release_name), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-start-service-by-name: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * @arg_flags: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the StartServiceByName() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_start_service_by_name() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-start-service-by-name", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_start_service_by_name), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 3, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_UINT); + + /** + * _GFreedesktopDBus::handle-name-has-owner: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the NameHasOwner() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_name_has_owner() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-name-has-owner", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_name_has_owner), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-list-names: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * + * Signal emitted when a remote caller is invoking the ListNames() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_list_names() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-list-names", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_list_names), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + + /** + * _GFreedesktopDBus::handle-list-activatable-names: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * + * Signal emitted when a remote caller is invoking the ListActivatableNames() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_list_activatable_names() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-list-activatable-names", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_list_activatable_names), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + + /** + * _GFreedesktopDBus::handle-add-match: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_rule: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the AddMatch() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_add_match() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-add-match", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_add_match), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-remove-match: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_rule: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the RemoveMatch() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_remove_match() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-remove-match", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_remove_match), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-get-name-owner: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the GetNameOwner() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_name_owner() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-get-name-owner", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_name_owner), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-list-queued-owners: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the ListQueuedOwners() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_list_queued_owners() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-list-queued-owners", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_list_queued_owners), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-get-connection-unix-user: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the GetConnectionUnixUser() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_connection_unix_user() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-get-connection-unix-user", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_connection_unix_user), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-get-connection-unix-process-id: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the GetConnectionUnixProcessID() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_connection_unix_process_id() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-get-connection-unix-process-id", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_connection_unix_process_id), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-get-connection-selinux-security-context: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_name: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the GetConnectionSELinuxSecurityContext() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_connection_selinux_security_context() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-get-connection-selinux-security-context", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_connection_selinux_security_context), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::handle-update-activation-environment: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * @arg_environment: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the UpdateActivationEnvironment() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_update_activation_environment() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-update-activation-environment", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_update_activation_environment), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_VARIANT); + + /** + * _GFreedesktopDBus::handle-reload-config: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * + * Signal emitted when a remote caller is invoking the ReloadConfig() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_reload_config() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-reload-config", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_reload_config), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + + /** + * _GFreedesktopDBus::handle-get-id: + * @object: A #_GFreedesktopDBus. + * @invocation: A #GDBusMethodInvocation. + * + * Signal emitted when a remote caller is invoking the GetId() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call _g_freedesktop_dbus_complete_get_id() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-get-id", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, handle_get_id), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + + /* GObject signals for received D-Bus signals: */ + /** + * _GFreedesktopDBus::name-owner-changed: + * @object: A #_GFreedesktopDBus. + * @arg_name: Argument. + * @arg_old_owner: Argument. + * @arg_new_owner: Argument. + * + * On the client-side, this signal is emitted whenever the D-Bus signal "NameOwnerChanged" is received. + * + * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. + */ + g_signal_new ("name-owner-changed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, name_owner_changed), + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::name-lost: + * @object: A #_GFreedesktopDBus. + * @arg_name: Argument. + * + * On the client-side, this signal is emitted whenever the D-Bus signal "NameLost" is received. + * + * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. + */ + g_signal_new ("name-lost", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, name_lost), + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 1, G_TYPE_STRING); + + /** + * _GFreedesktopDBus::name-acquired: + * @object: A #_GFreedesktopDBus. + * @arg_name: Argument. + * + * On the client-side, this signal is emitted whenever the D-Bus signal "NameAcquired" is received. + * + * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. + */ + g_signal_new ("name-acquired", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (_GFreedesktopDBusIface, name_acquired), + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 1, G_TYPE_STRING); + +} + +/** + * _g_freedesktop_dbus_emit_name_owner_changed: + * @object: A #_GFreedesktopDBus. + * @arg_name: Argument to pass with the signal. + * @arg_old_owner: Argument to pass with the signal. + * @arg_new_owner: Argument to pass with the signal. + * + * Emits the "NameOwnerChanged" D-Bus signal. + */ +void +_g_freedesktop_dbus_emit_name_owner_changed ( + _GFreedesktopDBus *object, + const gchar *arg_name, + const gchar *arg_old_owner, + const gchar *arg_new_owner) +{ + g_signal_emit_by_name (object, "name-owner-changed", arg_name, arg_old_owner, arg_new_owner); +} + +/** + * _g_freedesktop_dbus_emit_name_lost: + * @object: A #_GFreedesktopDBus. + * @arg_name: Argument to pass with the signal. + * + * Emits the "NameLost" D-Bus signal. + */ +void +_g_freedesktop_dbus_emit_name_lost ( + _GFreedesktopDBus *object, + const gchar *arg_name) +{ + g_signal_emit_by_name (object, "name-lost", arg_name); +} + +/** + * _g_freedesktop_dbus_emit_name_acquired: + * @object: A #_GFreedesktopDBus. + * @arg_name: Argument to pass with the signal. + * + * Emits the "NameAcquired" D-Bus signal. + */ +void +_g_freedesktop_dbus_emit_name_acquired ( + _GFreedesktopDBus *object, + const gchar *arg_name) +{ + g_signal_emit_by_name (object, "name-acquired", arg_name); +} + +/** + * _g_freedesktop_dbus_call_hello: + * @proxy: A #_GFreedesktopDBusProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the Hello() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_hello_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_hello_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_hello ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "Hello", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_hello_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_assigned_name: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_hello(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_hello(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_hello_finish ( + _GFreedesktopDBus *proxy, + gchar **out_assigned_name, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_assigned_name); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_hello_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_assigned_name: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the Hello() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_hello() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_hello_sync ( + _GFreedesktopDBus *proxy, + gchar **out_assigned_name, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "Hello", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_assigned_name); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_request_name: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the RequestName() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_request_name_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_request_name_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_request_name ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "RequestName", + g_variant_new ("(su)", + arg_name, + arg_flags), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_request_name_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_request_name(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_request_name(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_request_name_finish ( + _GFreedesktopDBus *proxy, + guint *out_value, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_value); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_request_name_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the RequestName() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_request_name() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_request_name_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + guint *out_value, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "RequestName", + g_variant_new ("(su)", + arg_name, + arg_flags), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_value); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_release_name: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the ReleaseName() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_release_name_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_release_name_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_release_name ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "ReleaseName", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_release_name_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_release_name(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_release_name(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_release_name_finish ( + _GFreedesktopDBus *proxy, + guint *out_value, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_value); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_release_name_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the ReleaseName() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_release_name() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_release_name_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint *out_value, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "ReleaseName", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_value); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_start_service_by_name: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the StartServiceByName() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_start_service_by_name_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_start_service_by_name_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_start_service_by_name ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "StartServiceByName", + g_variant_new ("(su)", + arg_name, + arg_flags), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_start_service_by_name_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_start_service_by_name(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_start_service_by_name(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_start_service_by_name_finish ( + _GFreedesktopDBus *proxy, + guint *out_value, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_value); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_start_service_by_name_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @out_value: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the StartServiceByName() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_start_service_by_name() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_start_service_by_name_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + guint *out_value, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "StartServiceByName", + g_variant_new ("(su)", + arg_name, + arg_flags), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_value); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_name_has_owner: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the NameHasOwner() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_name_has_owner_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_name_has_owner_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_name_has_owner ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "NameHasOwner", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_name_has_owner_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_has_owner: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_name_has_owner(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_name_has_owner(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_name_has_owner_finish ( + _GFreedesktopDBus *proxy, + gboolean *out_has_owner, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(b)", + out_has_owner); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_name_has_owner_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_has_owner: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the NameHasOwner() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_name_has_owner() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_name_has_owner_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gboolean *out_has_owner, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "NameHasOwner", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(b)", + out_has_owner); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_list_names: + * @proxy: A #_GFreedesktopDBusProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the ListNames() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_list_names_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_list_names_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_list_names ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "ListNames", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_list_names_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_list_names(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_list_names(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_list_names_finish ( + _GFreedesktopDBus *proxy, + gchar ***out_names, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_names); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_list_names_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the ListNames() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_list_names() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_list_names_sync ( + _GFreedesktopDBus *proxy, + gchar ***out_names, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "ListNames", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_names); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_list_activatable_names: + * @proxy: A #_GFreedesktopDBusProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the ListActivatableNames() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_list_activatable_names_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_list_activatable_names_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_list_activatable_names ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "ListActivatableNames", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_list_activatable_names_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_activatable_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_list_activatable_names(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_list_activatable_names(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_list_activatable_names_finish ( + _GFreedesktopDBus *proxy, + gchar ***out_activatable_names, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_activatable_names); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_list_activatable_names_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_activatable_names: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the ListActivatableNames() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_list_activatable_names() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_list_activatable_names_sync ( + _GFreedesktopDBus *proxy, + gchar ***out_activatable_names, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "ListActivatableNames", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_activatable_names); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_add_match: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_rule: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the AddMatch() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_add_match_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_add_match_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_add_match ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "AddMatch", + g_variant_new ("(s)", + arg_rule), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_add_match_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_add_match(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_add_match(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_add_match_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_add_match_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_rule: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the AddMatch() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_add_match() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_add_match_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "AddMatch", + g_variant_new ("(s)", + arg_rule), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_remove_match: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_rule: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the RemoveMatch() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_remove_match_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_remove_match_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_remove_match ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "RemoveMatch", + g_variant_new ("(s)", + arg_rule), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_remove_match_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_remove_match(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_remove_match(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_remove_match_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_remove_match_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_rule: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the RemoveMatch() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_remove_match() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_remove_match_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "RemoveMatch", + g_variant_new ("(s)", + arg_rule), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_name_owner: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GetNameOwner() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_get_name_owner_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_get_name_owner_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_get_name_owner ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GetNameOwner", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_get_name_owner_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_unique_name: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_name_owner(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_get_name_owner(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_name_owner_finish ( + _GFreedesktopDBus *proxy, + gchar **out_unique_name, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_unique_name); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_name_owner_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_unique_name: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GetNameOwner() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_get_name_owner() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_name_owner_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gchar **out_unique_name, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetNameOwner", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_unique_name); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_list_queued_owners: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the ListQueuedOwners() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_list_queued_owners_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_list_queued_owners_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_list_queued_owners ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "ListQueuedOwners", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_list_queued_owners_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_queued_owners: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_list_queued_owners(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_list_queued_owners(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_list_queued_owners_finish ( + _GFreedesktopDBus *proxy, + gchar ***out_queued_owners, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_queued_owners); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_list_queued_owners_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_queued_owners: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the ListQueuedOwners() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_list_queued_owners() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_list_queued_owners_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gchar ***out_queued_owners, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "ListQueuedOwners", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_queued_owners); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_connection_unix_user: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GetConnectionUnixUser() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_get_connection_unix_user_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_get_connection_unix_user_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_get_connection_unix_user ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GetConnectionUnixUser", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_get_connection_unix_user_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_uid: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_connection_unix_user(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_get_connection_unix_user(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_connection_unix_user_finish ( + _GFreedesktopDBus *proxy, + guint *out_uid, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_uid); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_connection_unix_user_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_uid: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GetConnectionUnixUser() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_get_connection_unix_user() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_connection_unix_user_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint *out_uid, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetConnectionUnixUser", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_uid); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_connection_unix_process_id: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GetConnectionUnixProcessID() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_get_connection_unix_process_id_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_get_connection_unix_process_id_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_get_connection_unix_process_id ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GetConnectionUnixProcessID", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_get_connection_unix_process_id_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_pid: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_connection_unix_process_id(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_get_connection_unix_process_id(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_connection_unix_process_id_finish ( + _GFreedesktopDBus *proxy, + guint *out_pid, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_pid); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_connection_unix_process_id_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_pid: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GetConnectionUnixProcessID() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_get_connection_unix_process_id() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_connection_unix_process_id_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint *out_pid, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetConnectionUnixProcessID", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_pid); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_connection_selinux_security_context: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GetConnectionSELinuxSecurityContext() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_get_connection_selinux_security_context_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_get_connection_selinux_security_context_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_get_connection_selinux_security_context ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GetConnectionSELinuxSecurityContext", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_get_connection_selinux_security_context_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_security_context: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_connection_selinux_security_context(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_get_connection_selinux_security_context(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_connection_selinux_security_context_finish ( + _GFreedesktopDBus *proxy, + gchar **out_security_context, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^ay)", + out_security_context); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_connection_selinux_security_context_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_name: Argument to pass with the method invocation. + * @out_security_context: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GetConnectionSELinuxSecurityContext() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_get_connection_selinux_security_context() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_connection_selinux_security_context_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gchar **out_security_context, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetConnectionSELinuxSecurityContext", + g_variant_new ("(s)", + arg_name), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^ay)", + out_security_context); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_update_activation_environment: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_environment: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the UpdateActivationEnvironment() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_update_activation_environment_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_update_activation_environment_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_update_activation_environment ( + _GFreedesktopDBus *proxy, + GVariant *arg_environment, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "UpdateActivationEnvironment", + g_variant_new ("(@a{ss})", + arg_environment), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_update_activation_environment_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_update_activation_environment(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_update_activation_environment(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_update_activation_environment_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_update_activation_environment_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @arg_environment: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the UpdateActivationEnvironment() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_update_activation_environment() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_update_activation_environment_sync ( + _GFreedesktopDBus *proxy, + GVariant *arg_environment, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "UpdateActivationEnvironment", + g_variant_new ("(@a{ss})", + arg_environment), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_reload_config: + * @proxy: A #_GFreedesktopDBusProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the ReloadConfig() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_reload_config_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_reload_config_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_reload_config ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "ReloadConfig", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_reload_config_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_reload_config(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_reload_config(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_reload_config_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_reload_config_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the ReloadConfig() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_reload_config() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_reload_config_sync ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "ReloadConfig", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_id: + * @proxy: A #_GFreedesktopDBusProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GetId() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_call_get_id_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_call_get_id_sync() for the synchronous, blocking version of this method. + */ +void +_g_freedesktop_dbus_call_get_id ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GetId", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * _g_freedesktop_dbus_call_get_id_finish: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_unique_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_call_get_id(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with _g_freedesktop_dbus_call_get_id(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_id_finish ( + _GFreedesktopDBus *proxy, + gchar **out_unique_id, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_unique_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_call_get_id_sync: + * @proxy: A #_GFreedesktopDBusProxy. + * @out_unique_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GetId() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_call_get_id() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +_g_freedesktop_dbus_call_get_id_sync ( + _GFreedesktopDBus *proxy, + gchar **out_unique_id, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetId", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_unique_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * _g_freedesktop_dbus_complete_hello: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @assigned_name: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the Hello() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_hello ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *assigned_name) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", + assigned_name)); +} + +/** + * _g_freedesktop_dbus_complete_request_name: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @value: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the RequestName() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_request_name ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + guint value) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(u)", + value)); +} + +/** + * _g_freedesktop_dbus_complete_release_name: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @value: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the ReleaseName() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_release_name ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + guint value) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(u)", + value)); +} + +/** + * _g_freedesktop_dbus_complete_start_service_by_name: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @value: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the StartServiceByName() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_start_service_by_name ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + guint value) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(u)", + value)); +} + +/** + * _g_freedesktop_dbus_complete_name_has_owner: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @has_owner: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the NameHasOwner() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_name_has_owner ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + gboolean has_owner) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(b)", + has_owner)); +} + +/** + * _g_freedesktop_dbus_complete_list_names: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @names: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the ListNames() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_list_names ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *const *names) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^as)", + names)); +} + +/** + * _g_freedesktop_dbus_complete_list_activatable_names: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @activatable_names: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the ListActivatableNames() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_list_activatable_names ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *const *activatable_names) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^as)", + activatable_names)); +} + +/** + * _g_freedesktop_dbus_complete_add_match: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the AddMatch() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_add_match ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * _g_freedesktop_dbus_complete_remove_match: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the RemoveMatch() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_remove_match ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * _g_freedesktop_dbus_complete_get_name_owner: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @unique_name: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the GetNameOwner() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_get_name_owner ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *unique_name) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", + unique_name)); +} + +/** + * _g_freedesktop_dbus_complete_list_queued_owners: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @queued_owners: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the ListQueuedOwners() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_list_queued_owners ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *const *queued_owners) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^as)", + queued_owners)); +} + +/** + * _g_freedesktop_dbus_complete_get_connection_unix_user: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @uid: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the GetConnectionUnixUser() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_get_connection_unix_user ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + guint uid) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(u)", + uid)); +} + +/** + * _g_freedesktop_dbus_complete_get_connection_unix_process_id: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @pid: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the GetConnectionUnixProcessID() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_get_connection_unix_process_id ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + guint pid) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(u)", + pid)); +} + +/** + * _g_freedesktop_dbus_complete_get_connection_selinux_security_context: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @security_context: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the GetConnectionSELinuxSecurityContext() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_get_connection_selinux_security_context ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *security_context) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^ay)", + security_context)); +} + +/** + * _g_freedesktop_dbus_complete_update_activation_environment: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the UpdateActivationEnvironment() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_update_activation_environment ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * _g_freedesktop_dbus_complete_reload_config: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the ReloadConfig() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_reload_config ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * _g_freedesktop_dbus_complete_get_id: + * @object: A #_GFreedesktopDBus. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @unique_id: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the GetId() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +_g_freedesktop_dbus_complete_get_id ( + _GFreedesktopDBus *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *unique_id) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", + unique_id)); +} + +/* ------------------------------------------------------------------------ */ + +/** + * _GFreedesktopDBusProxy: + * + * The #_GFreedesktopDBusProxy structure contains only private data and should only be accessed using the provided API. + */ + +/** + * _GFreedesktopDBusProxyClass: + * @parent_class: The parent class. + * + * Class structure for #_GFreedesktopDBusProxy. + */ + +struct __GFreedesktopDBusProxyPrivate +{ + GData *qdata; +}; + +static void _g_freedesktop_dbus_proxy_iface_init (_GFreedesktopDBusIface *iface); + +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusProxy, _g_freedesktop_dbus_proxy, G_TYPE_DBUS_PROXY, + G_ADD_PRIVATE (_GFreedesktopDBusProxy) + G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_proxy_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusProxy, _g_freedesktop_dbus_proxy, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_proxy_iface_init)) + +#endif +static void +_g_freedesktop_dbus_proxy_finalize (GObject *object) +{ + _GFreedesktopDBusProxy *proxy = _G_FREEDESKTOP_DBUS_PROXY (object); + g_datalist_clear (&proxy->priv->qdata); + G_OBJECT_CLASS (_g_freedesktop_dbus_proxy_parent_class)->finalize (object); +} + +static void +_g_freedesktop_dbus_proxy_get_property (GObject *object G_GNUC_UNUSED, + guint prop_id G_GNUC_UNUSED, + GValue *value G_GNUC_UNUSED, + GParamSpec *pspec G_GNUC_UNUSED) +{ +} + +static void +_g_freedesktop_dbus_proxy_set_property (GObject *object G_GNUC_UNUSED, + guint prop_id G_GNUC_UNUSED, + const GValue *value G_GNUC_UNUSED, + GParamSpec *pspec G_GNUC_UNUSED) +{ +} + +static void +_g_freedesktop_dbus_proxy_g_signal (GDBusProxy *proxy, + const gchar *sender_name G_GNUC_UNUSED, + const gchar *signal_name, + GVariant *parameters) +{ + _ExtendedGDBusSignalInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + gsize n; + guint signal_id; + info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, signal_name); + if (info == NULL) + return; + num_params = g_variant_n_children (parameters); + paramv = g_new0 (GValue, num_params + 1); + g_value_init (¶mv[0], _G_TYPE_FREEDESKTOP_DBUS); + g_value_set_object (¶mv[0], proxy); + g_variant_iter_init (&iter, parameters); + n = 1; + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, _G_TYPE_FREEDESKTOP_DBUS); + g_signal_emitv (paramv, signal_id, 0, NULL); + for (n = 0; n < num_params + 1; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static void +_g_freedesktop_dbus_proxy_g_properties_changed (GDBusProxy *_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties) +{ + _GFreedesktopDBusProxy *proxy = _G_FREEDESKTOP_DBUS_PROXY (_proxy); + guint n; + const gchar *key; + GVariantIter *iter; + _ExtendedGDBusPropertyInfo *info; + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, key); + g_datalist_remove_data (&proxy->priv->qdata, key); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } + g_variant_iter_free (iter); + for (n = 0; invalidated_properties[n] != NULL; n++) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, invalidated_properties[n]); + g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } +} + +static void +_g_freedesktop_dbus_proxy_init (_GFreedesktopDBusProxy *proxy) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + proxy->priv = _g_freedesktop_dbus_proxy_get_instance_private (proxy); +#else + proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxyPrivate); +#endif + + g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), _g_freedesktop_dbus_interface_info ()); +} + +static void +_g_freedesktop_dbus_proxy_class_init (_GFreedesktopDBusProxyClass *klass) +{ + GObjectClass *gobject_class; + GDBusProxyClass *proxy_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = _g_freedesktop_dbus_proxy_finalize; + gobject_class->get_property = _g_freedesktop_dbus_proxy_get_property; + gobject_class->set_property = _g_freedesktop_dbus_proxy_set_property; + + proxy_class = G_DBUS_PROXY_CLASS (klass); + proxy_class->g_signal = _g_freedesktop_dbus_proxy_g_signal; + proxy_class->g_properties_changed = _g_freedesktop_dbus_proxy_g_properties_changed; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (_GFreedesktopDBusProxyPrivate)); +#endif +} + +static void +_g_freedesktop_dbus_proxy_iface_init (_GFreedesktopDBusIface *iface G_GNUC_UNUSED) +{ +} + +/** + * _g_freedesktop_dbus_proxy_new: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.DBus. See g_dbus_proxy_new() for more details. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_proxy_new_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_proxy_new_sync() for the synchronous, blocking version of this constructor. + */ +void +_g_freedesktop_dbus_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (_G_TYPE_FREEDESKTOP_DBUS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); +} + +/** + * _g_freedesktop_dbus_proxy_new_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_proxy_new(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with _g_freedesktop_dbus_proxy_new(). + * + * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. + */ +_GFreedesktopDBus * +_g_freedesktop_dbus_proxy_new_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return _G_FREEDESKTOP_DBUS (ret); + else + return NULL; +} + +/** + * _g_freedesktop_dbus_proxy_new_sync: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Synchronously creates a proxy for the D-Bus interface org.freedesktop.DBus. See g_dbus_proxy_new_sync() for more details. + * + * The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_proxy_new() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. + */ +_GFreedesktopDBus * +_g_freedesktop_dbus_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (_G_TYPE_FREEDESKTOP_DBUS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); + if (ret != NULL) + return _G_FREEDESKTOP_DBUS (ret); + else + return NULL; +} + + +/** + * _g_freedesktop_dbus_proxy_new_for_bus: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Like _g_freedesktop_dbus_proxy_new() but takes a #GBusType instead of a #GDBusConnection. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call _g_freedesktop_dbus_proxy_new_for_bus_finish() to get the result of the operation. + * + * See _g_freedesktop_dbus_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. + */ +void +_g_freedesktop_dbus_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (_G_TYPE_FREEDESKTOP_DBUS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); +} + +/** + * _g_freedesktop_dbus_proxy_new_for_bus_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to _g_freedesktop_dbus_proxy_new_for_bus(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with _g_freedesktop_dbus_proxy_new_for_bus(). + * + * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. + */ +_GFreedesktopDBus * +_g_freedesktop_dbus_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return _G_FREEDESKTOP_DBUS (ret); + else + return NULL; +} + +/** + * _g_freedesktop_dbus_proxy_new_for_bus_sync: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Like _g_freedesktop_dbus_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. + * + * The calling thread is blocked until a reply is received. + * + * See _g_freedesktop_dbus_proxy_new_for_bus() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type _GFreedesktopDBusProxy): The constructed proxy object or %NULL if @error is set. + */ +_GFreedesktopDBus * +_g_freedesktop_dbus_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (_G_TYPE_FREEDESKTOP_DBUS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.DBus", NULL); + if (ret != NULL) + return _G_FREEDESKTOP_DBUS (ret); + else + return NULL; +} + + +/* ------------------------------------------------------------------------ */ + +/** + * _GFreedesktopDBusSkeleton: + * + * The #_GFreedesktopDBusSkeleton structure contains only private data and should only be accessed using the provided API. + */ + +/** + * _GFreedesktopDBusSkeletonClass: + * @parent_class: The parent class. + * + * Class structure for #_GFreedesktopDBusSkeleton. + */ + +struct __GFreedesktopDBusSkeletonPrivate +{ + GValue *properties; + GList *changed_properties; + GSource *changed_properties_idle_source; + GMainContext *context; + GMutex lock; +}; + +static void +__g_freedesktop_dbus_skeleton_handle_method_call ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (user_data); + _ExtendedGDBusMethodInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + guint num_extra; + gsize n; + guint signal_id; + GValue return_value = G_VALUE_INIT; + info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); + g_assert (info != NULL); + num_params = g_variant_n_children (parameters); + num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); + n = 0; + g_value_init (¶mv[n], _G_TYPE_FREEDESKTOP_DBUS); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); +#else + g_assert_not_reached (); +#endif + } + g_variant_iter_init (&iter, parameters); + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, _G_TYPE_FREEDESKTOP_DBUS); + g_value_init (&return_value, G_TYPE_BOOLEAN); + g_signal_emitv (paramv, signal_id, 0, &return_value); + if (!g_value_get_boolean (&return_value)) + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); + g_value_unset (&return_value); + for (n = 0; n < num_params + num_extra; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static GVariant * +__g_freedesktop_dbus_skeleton_handle_get_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + GVariant *ret; + ret = NULL; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); + ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_value_unset (&value); + } + return ret; +} + +static gboolean +__g_freedesktop_dbus_skeleton_handle_set_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GVariant *variant, + GError **error, + gpointer user_data) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + gboolean ret; + ret = FALSE; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &__g_freedesktop_dbus_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + if (info->use_gvariant) + g_value_set_variant (&value, variant); + else + g_dbus_gvariant_to_gvalue (variant, &value); + g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); + g_value_unset (&value); + ret = TRUE; + } + return ret; +} + +static const GDBusInterfaceVTable __g_freedesktop_dbus_skeleton_vtable = +{ + __g_freedesktop_dbus_skeleton_handle_method_call, + __g_freedesktop_dbus_skeleton_handle_get_property, + __g_freedesktop_dbus_skeleton_handle_set_property, + {NULL} +}; + +static GDBusInterfaceInfo * +_g_freedesktop_dbus_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return _g_freedesktop_dbus_interface_info (); +} + +static GDBusInterfaceVTable * +_g_freedesktop_dbus_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return (GDBusInterfaceVTable *) &__g_freedesktop_dbus_skeleton_vtable; +} + +static GVariant * +_g_freedesktop_dbus_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (_skeleton); + + GVariantBuilder builder; + guint n; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + if (__g_freedesktop_dbus_interface_info.parent_struct.properties == NULL) + goto out; + for (n = 0; __g_freedesktop_dbus_interface_info.parent_struct.properties[n] != NULL; n++) + { + GDBusPropertyInfo *info = __g_freedesktop_dbus_interface_info.parent_struct.properties[n]; + if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) + { + GVariant *value; + value = __g_freedesktop_dbus_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", info->name, NULL, skeleton); + if (value != NULL) + { + g_variant_take_ref (value); + g_variant_builder_add (&builder, "{sv}", info->name, value); + g_variant_unref (value); + } + } + } +out: + return g_variant_builder_end (&builder); +} + +static void +_g_freedesktop_dbus_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton G_GNUC_UNUSED) +{ +} + +static void +__g_freedesktop_dbus_on_signal_name_owner_changed ( + _GFreedesktopDBus *object, + const gchar *arg_name, + const gchar *arg_old_owner, + const gchar *arg_new_owner) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); + + GList *connections, *l; + GVariant *signal_variant; + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + + signal_variant = g_variant_ref_sink (g_variant_new ("(sss)", + arg_name, + arg_old_owner, + arg_new_owner)); + for (l = connections; l != NULL; l = l->next) + { + GDBusConnection *connection = l->data; + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", "NameOwnerChanged", + signal_variant, NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); +} + +static void +__g_freedesktop_dbus_on_signal_name_lost ( + _GFreedesktopDBus *object, + const gchar *arg_name) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); + + GList *connections, *l; + GVariant *signal_variant; + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + + signal_variant = g_variant_ref_sink (g_variant_new ("(s)", + arg_name)); + for (l = connections; l != NULL; l = l->next) + { + GDBusConnection *connection = l->data; + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", "NameLost", + signal_variant, NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); +} + +static void +__g_freedesktop_dbus_on_signal_name_acquired ( + _GFreedesktopDBus *object, + const gchar *arg_name) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); + + GList *connections, *l; + GVariant *signal_variant; + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + + signal_variant = g_variant_ref_sink (g_variant_new ("(s)", + arg_name)); + for (l = connections; l != NULL; l = l->next) + { + GDBusConnection *connection = l->data; + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.DBus", "NameAcquired", + signal_variant, NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); +} + +static void _g_freedesktop_dbus_skeleton_iface_init (_GFreedesktopDBusIface *iface); +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusSkeleton, _g_freedesktop_dbus_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_ADD_PRIVATE (_GFreedesktopDBusSkeleton) + G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_skeleton_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (_GFreedesktopDBusSkeleton, _g_freedesktop_dbus_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, _g_freedesktop_dbus_skeleton_iface_init)) + +#endif +static void +_g_freedesktop_dbus_skeleton_finalize (GObject *object) +{ + _GFreedesktopDBusSkeleton *skeleton = _G_FREEDESKTOP_DBUS_SKELETON (object); + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + if (skeleton->priv->changed_properties_idle_source != NULL) + g_source_destroy (skeleton->priv->changed_properties_idle_source); + g_main_context_unref (skeleton->priv->context); + g_mutex_clear (&skeleton->priv->lock); + G_OBJECT_CLASS (_g_freedesktop_dbus_skeleton_parent_class)->finalize (object); +} + +static void +_g_freedesktop_dbus_skeleton_init (_GFreedesktopDBusSkeleton *skeleton) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + skeleton->priv = _g_freedesktop_dbus_skeleton_get_instance_private (skeleton); +#else + skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeletonPrivate); +#endif + + g_mutex_init (&skeleton->priv->lock); + skeleton->priv->context = g_main_context_ref_thread_default (); +} + +static void +_g_freedesktop_dbus_skeleton_class_init (_GFreedesktopDBusSkeletonClass *klass) +{ + GObjectClass *gobject_class; + GDBusInterfaceSkeletonClass *skeleton_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = _g_freedesktop_dbus_skeleton_finalize; + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_info = _g_freedesktop_dbus_skeleton_dbus_interface_get_info; + skeleton_class->get_properties = _g_freedesktop_dbus_skeleton_dbus_interface_get_properties; + skeleton_class->flush = _g_freedesktop_dbus_skeleton_dbus_interface_flush; + skeleton_class->get_vtable = _g_freedesktop_dbus_skeleton_dbus_interface_get_vtable; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (_GFreedesktopDBusSkeletonPrivate)); +#endif +} + +static void +_g_freedesktop_dbus_skeleton_iface_init (_GFreedesktopDBusIface *iface) +{ + iface->name_owner_changed = __g_freedesktop_dbus_on_signal_name_owner_changed; + iface->name_lost = __g_freedesktop_dbus_on_signal_name_lost; + iface->name_acquired = __g_freedesktop_dbus_on_signal_name_acquired; +} + +/** + * _g_freedesktop_dbus_skeleton_new: + * + * Creates a skeleton object for the D-Bus interface org.freedesktop.DBus. + * + * Returns: (transfer full) (type _GFreedesktopDBusSkeleton): The skeleton object. + */ +_GFreedesktopDBus * +_g_freedesktop_dbus_skeleton_new (void) +{ + return _G_FREEDESKTOP_DBUS (g_object_new (_G_TYPE_FREEDESKTOP_DBUS_SKELETON, NULL)); +} + diff --git a/gio/gdbus-daemon-generated.h b/gio/gdbus-daemon-generated.h index d08a137a1ad215ec6946a4105740a7cb27fde7dc..8a996842be86bb5323202787263f723bd2565d9c 100644 --- a/gio/gdbus-daemon-generated.h +++ b/gio/gdbus-daemon-generated.h @@ -1,673 +1,674 @@ -/* - * Generated by gdbus-codegen 2.62.5 from dbus-daemon.xml. DO NOT EDIT. - * - * The license of this code is the same as for the D-Bus interface description - * it was derived from. - */ - -#ifndef __GDBUS_DAEMON_GENERATED_H__ -#define __GDBUS_DAEMON_GENERATED_H__ - -#include - -G_BEGIN_DECLS - - -/* ------------------------------------------------------------------------ */ -/* Declarations for org.freedesktop.DBus */ - -#define _G_TYPE_FREEDESKTOP_DBUS (_g_freedesktop_dbus_get_type ()) -#define _G_FREEDESKTOP_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), _G_TYPE_FREEDESKTOP_DBUS, _GFreedesktopDBus)) -#define _G_IS_FREEDESKTOP_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), _G_TYPE_FREEDESKTOP_DBUS)) -#define _G_FREEDESKTOP_DBUS_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), _G_TYPE_FREEDESKTOP_DBUS, _GFreedesktopDBusIface)) - -struct __GFreedesktopDBus; -typedef struct __GFreedesktopDBus _GFreedesktopDBus; -typedef struct __GFreedesktopDBusIface _GFreedesktopDBusIface; - -struct __GFreedesktopDBusIface -{ - GTypeInterface parent_iface; - - - gboolean (*handle_add_match) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_rule); - - gboolean (*handle_get_connection_selinux_security_context) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_get_connection_unix_process_id) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_get_connection_unix_user) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_get_id) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - - gboolean (*handle_get_name_owner) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_hello) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - - gboolean (*handle_list_activatable_names) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - - gboolean (*handle_list_names) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - - gboolean (*handle_list_queued_owners) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_name_has_owner) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_release_name) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name); - - gboolean (*handle_reload_config) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - - gboolean (*handle_remove_match) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_rule); - - gboolean (*handle_request_name) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name, - guint arg_flags); - - gboolean (*handle_start_service_by_name) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *arg_name, - guint arg_flags); - - gboolean (*handle_update_activation_environment) ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - GVariant *arg_environment); - - void (*name_acquired) ( - _GFreedesktopDBus *object, - const gchar *arg_name); - - void (*name_lost) ( - _GFreedesktopDBus *object, - const gchar *arg_name); - - void (*name_owner_changed) ( - _GFreedesktopDBus *object, - const gchar *arg_name, - const gchar *arg_old_owner, - const gchar *arg_new_owner); - -}; - -GType _g_freedesktop_dbus_get_type (void) G_GNUC_CONST; - -GDBusInterfaceInfo *_g_freedesktop_dbus_interface_info (void); -guint _g_freedesktop_dbus_override_properties (GObjectClass *klass, guint property_id_begin); - - -/* D-Bus method call completion functions: */ -void _g_freedesktop_dbus_complete_hello ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *assigned_name); - -void _g_freedesktop_dbus_complete_request_name ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint value); - -void _g_freedesktop_dbus_complete_release_name ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint value); - -void _g_freedesktop_dbus_complete_start_service_by_name ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint value); - -void _g_freedesktop_dbus_complete_name_has_owner ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - gboolean has_owner); - -void _g_freedesktop_dbus_complete_list_names ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *const *names); - -void _g_freedesktop_dbus_complete_list_activatable_names ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *const *activatable_names); - -void _g_freedesktop_dbus_complete_add_match ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - -void _g_freedesktop_dbus_complete_remove_match ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - -void _g_freedesktop_dbus_complete_get_name_owner ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *unique_name); - -void _g_freedesktop_dbus_complete_list_queued_owners ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *const *queued_owners); - -void _g_freedesktop_dbus_complete_get_connection_unix_user ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint uid); - -void _g_freedesktop_dbus_complete_get_connection_unix_process_id ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - guint pid); - -void _g_freedesktop_dbus_complete_get_connection_selinux_security_context ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *security_context); - -void _g_freedesktop_dbus_complete_update_activation_environment ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - -void _g_freedesktop_dbus_complete_reload_config ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation); - -void _g_freedesktop_dbus_complete_get_id ( - _GFreedesktopDBus *object, - GDBusMethodInvocation *invocation, - const gchar *unique_id); - - - -/* D-Bus signal emissions functions: */ -void _g_freedesktop_dbus_emit_name_owner_changed ( - _GFreedesktopDBus *object, - const gchar *arg_name, - const gchar *arg_old_owner, - const gchar *arg_new_owner); - -void _g_freedesktop_dbus_emit_name_lost ( - _GFreedesktopDBus *object, - const gchar *arg_name); - -void _g_freedesktop_dbus_emit_name_acquired ( - _GFreedesktopDBus *object, - const gchar *arg_name); - - - -/* D-Bus method calls: */ -void _g_freedesktop_dbus_call_hello ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_hello_finish ( - _GFreedesktopDBus *proxy, - gchar **out_assigned_name, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_hello_sync ( - _GFreedesktopDBus *proxy, - gchar **out_assigned_name, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_request_name ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_request_name_finish ( - _GFreedesktopDBus *proxy, - guint *out_value, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_request_name_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - guint *out_value, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_release_name ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_release_name_finish ( - _GFreedesktopDBus *proxy, - guint *out_value, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_release_name_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint *out_value, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_start_service_by_name ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_start_service_by_name_finish ( - _GFreedesktopDBus *proxy, - guint *out_value, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_start_service_by_name_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint arg_flags, - guint *out_value, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_name_has_owner ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_name_has_owner_finish ( - _GFreedesktopDBus *proxy, - gboolean *out_has_owner, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_name_has_owner_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gboolean *out_has_owner, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_list_names ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_list_names_finish ( - _GFreedesktopDBus *proxy, - gchar ***out_names, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_list_names_sync ( - _GFreedesktopDBus *proxy, - gchar ***out_names, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_list_activatable_names ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_list_activatable_names_finish ( - _GFreedesktopDBus *proxy, - gchar ***out_activatable_names, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_list_activatable_names_sync ( - _GFreedesktopDBus *proxy, - gchar ***out_activatable_names, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_add_match ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_add_match_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_add_match_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_remove_match ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_remove_match_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_remove_match_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_rule, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_get_name_owner ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_get_name_owner_finish ( - _GFreedesktopDBus *proxy, - gchar **out_unique_name, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_get_name_owner_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gchar **out_unique_name, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_list_queued_owners ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_list_queued_owners_finish ( - _GFreedesktopDBus *proxy, - gchar ***out_queued_owners, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_list_queued_owners_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gchar ***out_queued_owners, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_get_connection_unix_user ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_get_connection_unix_user_finish ( - _GFreedesktopDBus *proxy, - guint *out_uid, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_get_connection_unix_user_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint *out_uid, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_get_connection_unix_process_id ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_get_connection_unix_process_id_finish ( - _GFreedesktopDBus *proxy, - guint *out_pid, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_get_connection_unix_process_id_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - guint *out_pid, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_get_connection_selinux_security_context ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_get_connection_selinux_security_context_finish ( - _GFreedesktopDBus *proxy, - gchar **out_security_context, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_get_connection_selinux_security_context_sync ( - _GFreedesktopDBus *proxy, - const gchar *arg_name, - gchar **out_security_context, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_update_activation_environment ( - _GFreedesktopDBus *proxy, - GVariant *arg_environment, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_update_activation_environment_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_update_activation_environment_sync ( - _GFreedesktopDBus *proxy, - GVariant *arg_environment, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_reload_config ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_reload_config_finish ( - _GFreedesktopDBus *proxy, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_reload_config_sync ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_call_get_id ( - _GFreedesktopDBus *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _g_freedesktop_dbus_call_get_id_finish ( - _GFreedesktopDBus *proxy, - gchar **out_unique_id, - GAsyncResult *res, - GError **error); - -gboolean _g_freedesktop_dbus_call_get_id_sync ( - _GFreedesktopDBus *proxy, - gchar **out_unique_id, - GCancellable *cancellable, - GError **error); - - - -/* ---- */ - -#define _G_TYPE_FREEDESKTOP_DBUS_PROXY (_g_freedesktop_dbus_proxy_get_type ()) -#define _G_FREEDESKTOP_DBUS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxy)) -#define _G_FREEDESKTOP_DBUS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxyClass)) -#define _G_FREEDESKTOP_DBUS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxyClass)) -#define _G_IS_FREEDESKTOP_DBUS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), _G_TYPE_FREEDESKTOP_DBUS_PROXY)) -#define _G_IS_FREEDESKTOP_DBUS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), _G_TYPE_FREEDESKTOP_DBUS_PROXY)) - -typedef struct __GFreedesktopDBusProxy _GFreedesktopDBusProxy; -typedef struct __GFreedesktopDBusProxyClass _GFreedesktopDBusProxyClass; -typedef struct __GFreedesktopDBusProxyPrivate _GFreedesktopDBusProxyPrivate; - -struct __GFreedesktopDBusProxy -{ - /*< private >*/ - GDBusProxy parent_instance; - _GFreedesktopDBusProxyPrivate *priv; -}; - -struct __GFreedesktopDBusProxyClass -{ - GDBusProxyClass parent_class; -}; - -GType _g_freedesktop_dbus_proxy_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (_GFreedesktopDBusProxy, g_object_unref) -#endif - -void _g_freedesktop_dbus_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_finish ( - GAsyncResult *res, - GError **error); -_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - -void _g_freedesktop_dbus_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error); -_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - - -/* ---- */ - -#define _G_TYPE_FREEDESKTOP_DBUS_SKELETON (_g_freedesktop_dbus_skeleton_get_type ()) -#define _G_FREEDESKTOP_DBUS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeleton)) -#define _G_FREEDESKTOP_DBUS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeletonClass)) -#define _G_FREEDESKTOP_DBUS_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeletonClass)) -#define _G_IS_FREEDESKTOP_DBUS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), _G_TYPE_FREEDESKTOP_DBUS_SKELETON)) -#define _G_IS_FREEDESKTOP_DBUS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), _G_TYPE_FREEDESKTOP_DBUS_SKELETON)) - -typedef struct __GFreedesktopDBusSkeleton _GFreedesktopDBusSkeleton; -typedef struct __GFreedesktopDBusSkeletonClass _GFreedesktopDBusSkeletonClass; -typedef struct __GFreedesktopDBusSkeletonPrivate _GFreedesktopDBusSkeletonPrivate; - -struct __GFreedesktopDBusSkeleton -{ - /*< private >*/ - GDBusInterfaceSkeleton parent_instance; - _GFreedesktopDBusSkeletonPrivate *priv; -}; - -struct __GFreedesktopDBusSkeletonClass -{ - GDBusInterfaceSkeletonClass parent_class; -}; - -GType _g_freedesktop_dbus_skeleton_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (_GFreedesktopDBusSkeleton, g_object_unref) -#endif - -_GFreedesktopDBus *_g_freedesktop_dbus_skeleton_new (void); - - -G_END_DECLS - -#endif /* __GDBUS_DAEMON_GENERATED_H__ */ +/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */ + +#ifndef __GDBUS_DAEMON_GENERATED_H__ +#define __GDBUS_DAEMON_GENERATED_H__ + +#include + +G_BEGIN_DECLS + + +/* ------------------------------------------------------------------------ */ +/* Declarations for org.freedesktop.DBus */ + +#define _G_TYPE_FREEDESKTOP_DBUS (_g_freedesktop_dbus_get_type ()) +#define _G_FREEDESKTOP_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), _G_TYPE_FREEDESKTOP_DBUS, _GFreedesktopDBus)) +#define _G_IS_FREEDESKTOP_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), _G_TYPE_FREEDESKTOP_DBUS)) +#define _G_FREEDESKTOP_DBUS_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), _G_TYPE_FREEDESKTOP_DBUS, _GFreedesktopDBusIface)) + +struct __GFreedesktopDBus; +typedef struct __GFreedesktopDBus _GFreedesktopDBus; +typedef struct __GFreedesktopDBusIface _GFreedesktopDBusIface; + +struct __GFreedesktopDBusIface +{ + GTypeInterface parent_iface; + + + gboolean (*handle_add_match) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_rule); + + gboolean (*handle_get_connection_selinux_security_context) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_get_connection_unix_process_id) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_get_connection_unix_user) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_get_id) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + + gboolean (*handle_get_name_owner) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_hello) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + + gboolean (*handle_list_activatable_names) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + + gboolean (*handle_list_names) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + + gboolean (*handle_list_queued_owners) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_name_has_owner) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_release_name) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name); + + gboolean (*handle_reload_config) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + + gboolean (*handle_remove_match) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_rule); + + gboolean (*handle_request_name) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name, + guint arg_flags); + + gboolean (*handle_start_service_by_name) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *arg_name, + guint arg_flags); + + gboolean (*handle_update_activation_environment) ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + GVariant *arg_environment); + + void (*name_acquired) ( + _GFreedesktopDBus *object, + const gchar *arg_name); + + void (*name_lost) ( + _GFreedesktopDBus *object, + const gchar *arg_name); + + void (*name_owner_changed) ( + _GFreedesktopDBus *object, + const gchar *arg_name, + const gchar *arg_old_owner, + const gchar *arg_new_owner); + +}; + +GType _g_freedesktop_dbus_get_type (void) G_GNUC_CONST; + +GDBusInterfaceInfo *_g_freedesktop_dbus_interface_info (void); +guint _g_freedesktop_dbus_override_properties (GObjectClass *klass, guint property_id_begin); + + +/* D-Bus method call completion functions: */ +void _g_freedesktop_dbus_complete_hello ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *assigned_name); + +void _g_freedesktop_dbus_complete_request_name ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + guint value); + +void _g_freedesktop_dbus_complete_release_name ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + guint value); + +void _g_freedesktop_dbus_complete_start_service_by_name ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + guint value); + +void _g_freedesktop_dbus_complete_name_has_owner ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + gboolean has_owner); + +void _g_freedesktop_dbus_complete_list_names ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *const *names); + +void _g_freedesktop_dbus_complete_list_activatable_names ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *const *activatable_names); + +void _g_freedesktop_dbus_complete_add_match ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + +void _g_freedesktop_dbus_complete_remove_match ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + +void _g_freedesktop_dbus_complete_get_name_owner ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *unique_name); + +void _g_freedesktop_dbus_complete_list_queued_owners ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *const *queued_owners); + +void _g_freedesktop_dbus_complete_get_connection_unix_user ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + guint uid); + +void _g_freedesktop_dbus_complete_get_connection_unix_process_id ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + guint pid); + +void _g_freedesktop_dbus_complete_get_connection_selinux_security_context ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *security_context); + +void _g_freedesktop_dbus_complete_update_activation_environment ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + +void _g_freedesktop_dbus_complete_reload_config ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation); + +void _g_freedesktop_dbus_complete_get_id ( + _GFreedesktopDBus *object, + GDBusMethodInvocation *invocation, + const gchar *unique_id); + + + +/* D-Bus signal emissions functions: */ +void _g_freedesktop_dbus_emit_name_owner_changed ( + _GFreedesktopDBus *object, + const gchar *arg_name, + const gchar *arg_old_owner, + const gchar *arg_new_owner); + +void _g_freedesktop_dbus_emit_name_lost ( + _GFreedesktopDBus *object, + const gchar *arg_name); + +void _g_freedesktop_dbus_emit_name_acquired ( + _GFreedesktopDBus *object, + const gchar *arg_name); + + + +/* D-Bus method calls: */ +void _g_freedesktop_dbus_call_hello ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_hello_finish ( + _GFreedesktopDBus *proxy, + gchar **out_assigned_name, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_hello_sync ( + _GFreedesktopDBus *proxy, + gchar **out_assigned_name, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_request_name ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_request_name_finish ( + _GFreedesktopDBus *proxy, + guint *out_value, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_request_name_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + guint *out_value, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_release_name ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_release_name_finish ( + _GFreedesktopDBus *proxy, + guint *out_value, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_release_name_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint *out_value, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_start_service_by_name ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_start_service_by_name_finish ( + _GFreedesktopDBus *proxy, + guint *out_value, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_start_service_by_name_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint arg_flags, + guint *out_value, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_name_has_owner ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_name_has_owner_finish ( + _GFreedesktopDBus *proxy, + gboolean *out_has_owner, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_name_has_owner_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gboolean *out_has_owner, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_list_names ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_list_names_finish ( + _GFreedesktopDBus *proxy, + gchar ***out_names, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_list_names_sync ( + _GFreedesktopDBus *proxy, + gchar ***out_names, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_list_activatable_names ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_list_activatable_names_finish ( + _GFreedesktopDBus *proxy, + gchar ***out_activatable_names, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_list_activatable_names_sync ( + _GFreedesktopDBus *proxy, + gchar ***out_activatable_names, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_add_match ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_add_match_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_add_match_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_remove_match ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_remove_match_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_remove_match_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_rule, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_get_name_owner ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_get_name_owner_finish ( + _GFreedesktopDBus *proxy, + gchar **out_unique_name, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_get_name_owner_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gchar **out_unique_name, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_list_queued_owners ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_list_queued_owners_finish ( + _GFreedesktopDBus *proxy, + gchar ***out_queued_owners, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_list_queued_owners_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gchar ***out_queued_owners, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_get_connection_unix_user ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_get_connection_unix_user_finish ( + _GFreedesktopDBus *proxy, + guint *out_uid, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_get_connection_unix_user_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint *out_uid, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_get_connection_unix_process_id ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_get_connection_unix_process_id_finish ( + _GFreedesktopDBus *proxy, + guint *out_pid, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_get_connection_unix_process_id_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + guint *out_pid, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_get_connection_selinux_security_context ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_get_connection_selinux_security_context_finish ( + _GFreedesktopDBus *proxy, + gchar **out_security_context, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_get_connection_selinux_security_context_sync ( + _GFreedesktopDBus *proxy, + const gchar *arg_name, + gchar **out_security_context, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_update_activation_environment ( + _GFreedesktopDBus *proxy, + GVariant *arg_environment, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_update_activation_environment_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_update_activation_environment_sync ( + _GFreedesktopDBus *proxy, + GVariant *arg_environment, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_reload_config ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_reload_config_finish ( + _GFreedesktopDBus *proxy, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_reload_config_sync ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_call_get_id ( + _GFreedesktopDBus *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _g_freedesktop_dbus_call_get_id_finish ( + _GFreedesktopDBus *proxy, + gchar **out_unique_id, + GAsyncResult *res, + GError **error); + +gboolean _g_freedesktop_dbus_call_get_id_sync ( + _GFreedesktopDBus *proxy, + gchar **out_unique_id, + GCancellable *cancellable, + GError **error); + + + +/* ---- */ + +#define _G_TYPE_FREEDESKTOP_DBUS_PROXY (_g_freedesktop_dbus_proxy_get_type ()) +#define _G_FREEDESKTOP_DBUS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxy)) +#define _G_FREEDESKTOP_DBUS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxyClass)) +#define _G_FREEDESKTOP_DBUS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), _G_TYPE_FREEDESKTOP_DBUS_PROXY, _GFreedesktopDBusProxyClass)) +#define _G_IS_FREEDESKTOP_DBUS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), _G_TYPE_FREEDESKTOP_DBUS_PROXY)) +#define _G_IS_FREEDESKTOP_DBUS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), _G_TYPE_FREEDESKTOP_DBUS_PROXY)) + +typedef struct __GFreedesktopDBusProxy _GFreedesktopDBusProxy; +typedef struct __GFreedesktopDBusProxyClass _GFreedesktopDBusProxyClass; +typedef struct __GFreedesktopDBusProxyPrivate _GFreedesktopDBusProxyPrivate; + +struct __GFreedesktopDBusProxy +{ + /*< private >*/ + GDBusProxy parent_instance; + _GFreedesktopDBusProxyPrivate *priv; +}; + +struct __GFreedesktopDBusProxyClass +{ + GDBusProxyClass parent_class; +}; + +GType _g_freedesktop_dbus_proxy_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (_GFreedesktopDBusProxy, g_object_unref) +#endif + +void _g_freedesktop_dbus_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_finish ( + GAsyncResult *res, + GError **error); +_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + +void _g_freedesktop_dbus_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error); +_GFreedesktopDBus *_g_freedesktop_dbus_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + + +/* ---- */ + +#define _G_TYPE_FREEDESKTOP_DBUS_SKELETON (_g_freedesktop_dbus_skeleton_get_type ()) +#define _G_FREEDESKTOP_DBUS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeleton)) +#define _G_FREEDESKTOP_DBUS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeletonClass)) +#define _G_FREEDESKTOP_DBUS_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), _G_TYPE_FREEDESKTOP_DBUS_SKELETON, _GFreedesktopDBusSkeletonClass)) +#define _G_IS_FREEDESKTOP_DBUS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), _G_TYPE_FREEDESKTOP_DBUS_SKELETON)) +#define _G_IS_FREEDESKTOP_DBUS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), _G_TYPE_FREEDESKTOP_DBUS_SKELETON)) + +typedef struct __GFreedesktopDBusSkeleton _GFreedesktopDBusSkeleton; +typedef struct __GFreedesktopDBusSkeletonClass _GFreedesktopDBusSkeletonClass; +typedef struct __GFreedesktopDBusSkeletonPrivate _GFreedesktopDBusSkeletonPrivate; + +struct __GFreedesktopDBusSkeleton +{ + /*< private >*/ + GDBusInterfaceSkeleton parent_instance; + _GFreedesktopDBusSkeletonPrivate *priv; +}; + +struct __GFreedesktopDBusSkeletonClass +{ + GDBusInterfaceSkeletonClass parent_class; +}; + +GType _g_freedesktop_dbus_skeleton_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (_GFreedesktopDBusSkeleton, g_object_unref) +#endif + +_GFreedesktopDBus *_g_freedesktop_dbus_skeleton_new (void); + + +G_END_DECLS + +#endif /* __GDBUS_DAEMON_GENERATED_H__ */ diff --git a/gio/gdbus-tool.c b/gio/gdbus-tool.c index 57978f1c20abe22c0837847cd1dddbd982840abb..1f9e308d5164e7f2db615425047e0f972d47ccd6 100644 --- a/gio/gdbus-tool.c +++ b/gio/gdbus-tool.c @@ -27,6 +27,10 @@ #include +#ifdef G_OS_UNIX +#include +#endif + #include #ifdef G_OS_WIN32 @@ -246,6 +250,11 @@ print_paths (GDBusConnection *c, g_printerr (_("Error: %s is not a valid name\n"), name); goto out; } + if (!g_variant_is_object_path (path)) + { + g_printerr (_("Error: %s is not a valid object path\n"), path); + goto out; + } error = NULL; result = g_dbus_connection_call_sync (c, @@ -414,7 +423,8 @@ connection_get_group (void) } static GDBusConnection * -connection_get_dbus_connection (GError **error) +connection_get_dbus_connection (gboolean require_message_bus, + GError **error) { GDBusConnection *c; @@ -450,8 +460,11 @@ connection_get_dbus_connection (GError **error) } else if (opt_connection_address != NULL) { + GDBusConnectionFlags flags = G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT; + if (require_message_bus) + flags |= G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION; c = g_dbus_connection_new_for_address_sync (opt_connection_address, - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + flags, NULL, /* GDBusAuthObserver */ NULL, /* GCancellable */ error); @@ -649,7 +662,7 @@ handle_emit (gint *argc, } error = NULL; - c = connection_get_dbus_connection (&error); + c = connection_get_dbus_connection ((opt_emit_dest != NULL), &error); if (c == NULL) { if (request_completion) @@ -668,8 +681,8 @@ handle_emit (gint *argc, else { g_printerr (_("Error connecting: %s\n"), error->message); - g_error_free (error); } + g_error_free (error); goto out; } @@ -901,6 +914,10 @@ handle_call (gint *argc, gchar *method_name; GVariant *result; GPtrArray *in_signature_types; +#ifdef G_OS_UNIX + GUnixFDList *fd_list; + gint fd_id; +#endif gboolean complete_names; gboolean complete_paths; gboolean complete_methods; @@ -916,6 +933,9 @@ handle_call (gint *argc, method_name = NULL; result = NULL; in_signature_types = NULL; +#ifdef G_OS_UNIX + fd_list = NULL; +#endif modify_argv0_for_command (argc, argv, "call"); @@ -956,7 +976,7 @@ handle_call (gint *argc, } error = NULL; - c = connection_get_dbus_connection (&error); + c = connection_get_dbus_connection (TRUE, &error); if (c == NULL) { if (request_completion) @@ -975,8 +995,8 @@ handle_call (gint *argc, else { g_printerr (_("Error connecting: %s\n"), error->message); - g_error_free (error); } + g_error_free (error); goto out; } @@ -1160,6 +1180,23 @@ handle_call (gint *argc, } g_free (context); } +#ifdef G_OS_UNIX + if (g_variant_is_of_type (value, G_VARIANT_TYPE_HANDLE)) + { + if (!fd_list) + fd_list = g_unix_fd_list_new (); + if ((fd_id = g_unix_fd_list_append (fd_list, g_variant_get_handle (value), &error)) == -1) + { + g_printerr (_("Error adding handle %d: %s\n"), + g_variant_get_handle (value), error->message); + g_variant_builder_clear (&builder); + g_error_free (error); + goto out; + } + g_variant_unref (value); + value = g_variant_new_handle (fd_id); + } +#endif g_variant_builder_add_value (&builder, value); ++parm; } @@ -1167,17 +1204,33 @@ handle_call (gint *argc, if (parameters != NULL) parameters = g_variant_ref_sink (parameters); +#ifdef G_OS_UNIX + result = g_dbus_connection_call_with_unix_fd_list_sync (c, + opt_call_dest, + opt_call_object_path, + interface_name, + method_name, + parameters, + NULL, + G_DBUS_CALL_FLAGS_NONE, + opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout, + fd_list, + NULL, + NULL, + &error); +#else result = g_dbus_connection_call_sync (c, - opt_call_dest, - opt_call_object_path, - interface_name, - method_name, - parameters, - NULL, - G_DBUS_CALL_FLAGS_NONE, - opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout, - NULL, - &error); + opt_call_dest, + opt_call_object_path, + interface_name, + method_name, + parameters, + NULL, + G_DBUS_CALL_FLAGS_NONE, + opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout, + NULL, + &error); +#endif if (result == NULL) { g_printerr (_("Error: %s\n"), error->message); @@ -1226,6 +1279,9 @@ handle_call (gint *argc, g_free (interface_name); g_free (method_name); g_option_context_free (o); +#ifdef G_OS_UNIX + g_clear_object (&fd_list); +#endif return ret; } @@ -1750,7 +1806,7 @@ handle_introspect (gint *argc, } error = NULL; - c = connection_get_dbus_connection (&error); + c = connection_get_dbus_connection (TRUE, &error); if (c == NULL) { if (request_completion) @@ -1769,8 +1825,8 @@ handle_introspect (gint *argc, else { g_printerr (_("Error connecting: %s\n"), error->message); - g_error_free (error); } + g_error_free (error); goto out; } @@ -1982,7 +2038,7 @@ handle_monitor (gint *argc, } error = NULL; - c = connection_get_dbus_connection (&error); + c = connection_get_dbus_connection (TRUE, &error); if (c == NULL) { if (request_completion) @@ -2001,8 +2057,8 @@ handle_monitor (gint *argc, else { g_printerr (_("Error connecting: %s\n"), error->message); - g_error_free (error); } + g_error_free (error); goto out; } @@ -2202,7 +2258,7 @@ handle_wait (gint *argc, } error = NULL; - c = connection_get_dbus_connection (&error); + c = connection_get_dbus_connection (TRUE, &error); if (c == NULL) { if (request_completion) @@ -2221,8 +2277,8 @@ handle_wait (gint *argc, else { g_printerr (_("Error connecting: %s\n"), error->message); - g_error_free (error); } + g_error_free (error); goto out; } diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index 3015457a5479763237f9c93e80eb7694f0309410..a341023dfed72689b02ca73b1a2034cff94793fd 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -30,6 +30,7 @@ #include "gdbusaddress.h" #include "gdbuserror.h" #include "gioenumtypes.h" +#include "glib-private.h" #include "gnetworkaddress.h" #include "gsocketclient.h" #include "giostream.h" @@ -244,8 +245,8 @@ is_valid_nonce_tcp (const gchar *address_entry, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Error in address “%s” — the port attribute is malformed"), - address_entry); + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "port"); goto out; } } @@ -255,8 +256,8 @@ is_valid_nonce_tcp (const gchar *address_entry, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Error in address “%s” — the family attribute is malformed"), - address_entry); + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "family"); goto out; } @@ -265,9 +266,17 @@ is_valid_nonce_tcp (const gchar *address_entry, /* TODO: validate host */ } - nonce_file = nonce_file; /* To avoid -Wunused-but-set-variable */ + if (nonce_file != NULL && *nonce_file == '\0') + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "noncefile"); + goto out; + } - ret= TRUE; + ret = TRUE; out: g_list_free (keys); @@ -325,8 +334,8 @@ is_valid_tcp (const gchar *address_entry, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Error in address “%s” — the port attribute is malformed"), - address_entry); + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "port"); goto out; } } @@ -336,8 +345,8 @@ is_valid_tcp (const gchar *address_entry, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Error in address “%s” — the family attribute is malformed"), - address_entry); + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "family"); goto out; } @@ -895,11 +904,14 @@ g_dbus_address_get_stream (const gchar *address, /** * g_dbus_address_get_stream_finish: * @res: A #GAsyncResult obtained from the GAsyncReadyCallback passed to g_dbus_address_get_stream(). - * @out_guid: (optional) (out): %NULL or return location to store the GUID extracted from @address, if any. + * @out_guid: (optional) (out) (nullable): %NULL or return location to store the GUID extracted from @address, if any. * @error: Return location for error or %NULL. * * Finishes an operation started with g_dbus_address_get_stream(). * + * A server is not required to set a GUID, so @out_guid may be set to %NULL + * even on success. + * * Returns: (transfer full): A #GIOStream or %NULL if @error is set. * * Since: 2.26 @@ -932,7 +944,7 @@ g_dbus_address_get_stream_finish (GAsyncResult *res, /** * g_dbus_address_get_stream_sync: * @address: A valid D-Bus address. - * @out_guid: (optional) (out): %NULL or return location to store the GUID extracted from @address, if any. + * @out_guid: (optional) (out) (nullable): %NULL or return location to store the GUID extracted from @address, if any. * @cancellable: (nullable): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * @@ -941,6 +953,9 @@ g_dbus_address_get_stream_finish (GAsyncResult *res, * of the D-Bus authentication conversation. @address must be in the * [D-Bus address format](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses). * + * A server is not required to set a GUID, so @out_guid may be set to %NULL + * even on success. + * * This is a synchronous failable function. See * g_dbus_address_get_stream() for the asynchronous version. * @@ -974,7 +989,7 @@ g_dbus_address_get_stream_sync (const gchar *address, goto out; } - for (n = 0; addr_array != NULL && addr_array[n] != NULL; n++) + for (n = 0; addr_array[n] != NULL; n++) { const gchar *addr = addr_array[n]; GError *this_error; @@ -1271,6 +1286,7 @@ g_dbus_address_get_for_bus_sync (GBusType bus_type, GCancellable *cancellable, GError **error) { + gboolean has_elevated_privileges = GLIB_PRIVATE_CALL (g_check_setuid) (); gchar *ret, *s = NULL; const gchar *starter_bus; GError *local_error; @@ -1309,10 +1325,16 @@ g_dbus_address_get_for_bus_sync (GBusType bus_type, _g_dbus_debug_print_unlock (); } + /* Don’t load the addresses from the environment if running as setuid, as they + * come from an unprivileged caller. */ switch (bus_type) { case G_BUS_TYPE_SYSTEM: - ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS")); + if (has_elevated_privileges) + ret = NULL; + else + ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS")); + if (ret == NULL) { ret = g_strdup ("unix:path=/var/run/dbus/system_bus_socket"); @@ -1320,7 +1342,33 @@ g_dbus_address_get_for_bus_sync (GBusType bus_type, break; case G_BUS_TYPE_SESSION: - ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS")); + if (has_elevated_privileges) + { +#ifdef G_OS_UNIX + if (geteuid () == getuid ()) + { + /* Ideally we shouldn't do this, because setgid and + * filesystem capabilities are also elevated privileges + * with which we should not be trusting environment variables + * from the caller. Unfortunately, there are programs with + * elevated privileges that rely on the session bus being + * available. We already prevent the really dangerous + * transports like autolaunch: and unixexec: when our + * privileges are elevated, so this can only make us connect + * to the wrong AF_UNIX or TCP socket. */ + ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS")); + } + else +#endif + { + ret = NULL; + } + } + else + { + ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS")); + } + if (ret == NULL) { ret = get_session_address_platform_specific (&local_error); diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c index 14cc5d70e10c8281bf70d02853ecde03b574aec7..c430f0cf036026df00bbd433a8e2e60d16f15c43 100644 --- a/gio/gdbusauth.c +++ b/gio/gdbusauth.c @@ -924,6 +924,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth, GDBusAuthObserver *observer, const gchar *guid, gboolean allow_anonymous, + gboolean require_same_user, GDBusCapabilityFlags offered_capabilities, GDBusCapabilityFlags *out_negotiated_capabilities, GCredentials **out_received_credentials, @@ -941,6 +942,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth, gchar *s; GDBusCapabilityFlags negotiated_capabilities; GCredentials *credentials; + GCredentials *own_credentials = NULL; debug_print ("SERVER: initiating"); @@ -1039,6 +1041,8 @@ _g_dbus_auth_run_server (GDBusAuth *auth, debug_print ("SERVER: didn't receive any credentials"); } + own_credentials = g_credentials_new (); + state = SERVER_STATE_WAITING_FOR_AUTH; while (TRUE) { @@ -1155,10 +1159,21 @@ _g_dbus_auth_run_server (GDBusAuth *auth, switch (_g_dbus_auth_mechanism_server_get_state (mech)) { case G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED: - if (observer != NULL && - !g_dbus_auth_observer_authorize_authenticated_peer (observer, - auth->priv->stream, - credentials)) + if (require_same_user && + (credentials == NULL || + !g_credentials_is_same_user (credentials, own_credentials, NULL))) + { + /* disconnect */ + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("User IDs must be the same for peer and server")); + goto out; + } + else if (observer != NULL && + !g_dbus_auth_observer_authorize_authenticated_peer (observer, + auth->priv->stream, + credentials)) { /* disconnect */ g_set_error_literal (error, @@ -1348,12 +1363,10 @@ _g_dbus_auth_run_server (GDBusAuth *auth, "Not implemented (server)"); out: - if (mech != NULL) - g_object_unref (mech); - if (dis != NULL) - g_object_unref (dis); - if (dos != NULL) - g_object_unref (dos); + g_clear_object (&mech); + g_clear_object (&dis); + g_clear_object (&dos); + g_clear_object (&own_credentials); /* ensure return value is FALSE if error is set */ if (error != NULL && *error != NULL) diff --git a/gio/gdbusauth.h b/gio/gdbusauth.h index 2b4652beaef3078dc5d302b6fef6915ba537abd3..70b6a603906bc8dbb9ba75440530af07062b9d80 100644 --- a/gio/gdbusauth.h +++ b/gio/gdbusauth.h @@ -67,6 +67,7 @@ gboolean _g_dbus_auth_run_server (GDBusAuth *auth, GDBusAuthObserver *observer, const gchar *guid, gboolean allow_anonymous, + gboolean require_same_user, GDBusCapabilityFlags offered_capabilities, GDBusCapabilityFlags *out_negotiated_capabilities, GCredentials **out_received_credentials, diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c index 2754d3c2b8f3bca2ba3073676e5a011100b63c65..095a6663e3f1a98f0f1a46eb50ec9cb3853da7f2 100644 --- a/gio/gdbusauthmechanismsha1.c +++ b/gio/gdbusauthmechanismsha1.c @@ -40,9 +40,41 @@ #include "gioenumtypes.h" #include "gioerror.h" #include "gdbusprivate.h" +#include "glib-private.h" #include "glibintl.h" +/* + * Arbitrary timeouts for keys in the keyring. + * For interoperability, these match the reference implementation, libdbus. + * To make them easier to compare, their names also match libdbus + * (see dbus/dbus-keyring.c). + */ + +/* + * Maximum age of a key before we create a new key to use in challenges: + * 5 minutes. + */ +#define NEW_KEY_TIMEOUT_SECONDS (60*5) + +/* + * Time before we drop a key from the keyring: 7 minutes. + * Authentication will succeed if it takes less than + * EXPIRE_KEYS_TIMEOUT_SECONDS - NEW_KEY_TIMEOUT_SECONDS (2 minutes) + * to complete. + * The spec says "delete any cookies that are old (the timeout can be + * fairly short)". + */ +#define EXPIRE_KEYS_TIMEOUT_SECONDS (NEW_KEY_TIMEOUT_SECONDS + (60*2)) + +/* + * Maximum amount of time a key can be in the future due to clock skew + * with a shared home directory: 5 minutes. + * The spec says "a reasonable time in the future". + */ +#define MAX_TIME_TRAVEL_SECONDS (60*5) + + struct _GDBusAuthMechanismSha1Private { gboolean is_client; @@ -234,6 +266,10 @@ ensure_keyring_directory (GError **error) { gchar *path; const gchar *e; + gboolean is_setuid; +#ifdef G_OS_UNIX + struct stat statbuf; +#endif g_return_val_if_fail (error == NULL || *error == NULL, NULL); @@ -249,50 +285,59 @@ ensure_keyring_directory (GError **error) NULL); } - if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) +#ifdef G_OS_UNIX + if (stat (path, &statbuf) != 0) { - if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL) + int errsv = errno; + + if (errsv != ENOENT) { -#ifdef G_OS_UNIX - struct stat statbuf; - if (stat (path, &statbuf) != 0) - { - int errsv = errno; - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error when getting information for directory “%s”: %s"), - path, - g_strerror (errsv)); - g_free (path); - path = NULL; - goto out; - } - if ((statbuf.st_mode & 0777) != 0700) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - _("Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o"), - path, - (guint) (statbuf.st_mode & 0777)); - g_free (path); - path = NULL; - goto out; - } -#else + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error when getting information for directory “%s”: %s"), + path, + g_strerror (errsv)); + g_clear_pointer (&path, g_free); + return NULL; + } + } + else if (S_ISDIR (statbuf.st_mode)) + { + if (g_getenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION") == NULL && + (statbuf.st_mode & 0777) != 0700) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o"), + path, + (guint) (statbuf.st_mode & 0777)); + g_clear_pointer (&path, g_free); + return NULL; + } + + return g_steal_pointer (&path); + } +#else /* if !G_OS_UNIX */ + /* On non-Unix platforms, check that it exists as a directory, but don’t do + * permissions checks at the moment. */ + if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + { #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic warning "-Wcpp" #warning Please implement permission checking on this non-UNIX platform #pragma GCC diagnostic pop -#endif -#endif - } - goto out; +#endif /* __GNUC__ */ + return g_steal_pointer (&path); } +#endif /* if !G_OS_UNIX */ - if (g_mkdir_with_parents (path, 0700) != 0) + /* Only create the directory if not running as setuid */ + is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) (); + if (!is_setuid && + g_mkdir_with_parents (path, 0700) != 0) { int errsv = errno; g_set_error (error, @@ -301,13 +346,22 @@ ensure_keyring_directory (GError **error) _("Error creating directory “%s”: %s"), path, g_strerror (errsv)); - g_free (path); - path = NULL; - goto out; + g_clear_pointer (&path, g_free); + return NULL; + } + else if (is_setuid) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED, + _("Error creating directory “%s”: %s"), + path, + _("Operation not supported")); + g_clear_pointer (&path, g_free); + return NULL; } -out: - return path; + return g_steal_pointer (&path); } /* ---------------------------------------------------------------------------------------------------- */ @@ -450,25 +504,52 @@ _log (const gchar *message, g_free (s); } +/* Returns FD for lock file, if it was created exclusively (didn't exist already, + * and was created successfully) */ +static gint +create_lock_exclusive (const gchar *lock_path, + GError **error) +{ + int errsv; + gint ret; + + ret = g_open (lock_path, O_CREAT | O_EXCL, 0600); + errsv = errno; + if (ret < 0) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error creating lock file “%s”: %s"), + lock_path, + g_strerror (errsv)); + return -1; + } + + return ret; +} + static gint keyring_acquire_lock (const gchar *path, GError **error) { - gchar *lock; + gchar *lock = NULL; gint ret; guint num_tries; -#ifdef EEXISTS - guint num_create_tries; -#endif int errsv; - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + /* Total possible sleep period = max_tries * timeout_usec = 0.5s */ + const guint max_tries = 50; + const guint timeout_usec = 1000 * 10; + + g_return_val_if_fail (path != NULL, -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); ret = -1; - lock = g_strdup_printf ("%s.lock", path); + lock = g_strconcat (path, ".lock", NULL); /* This is what the D-Bus spec says + * (https://dbus.freedesktop.org/doc/dbus-specification.html#auth-mechanisms-sha) * * Create a lockfile name by appending ".lock" to the name of the * cookie file. The server should attempt to create this file using @@ -481,66 +562,43 @@ keyring_acquire_lock (const gchar *path, * real locking implementations are still flaky on network filesystems */ -#ifdef EEXISTS - num_create_tries = 0; - again: -#endif - num_tries = 0; - while (g_file_test (lock, G_FILE_TEST_EXISTS)) + for (num_tries = 0; num_tries < max_tries; num_tries++) { + /* Ignore the error until the final call. */ + ret = create_lock_exclusive (lock, NULL); + if (ret >= 0) + break; + /* sleep 10ms, then try again */ - g_usleep (1000*10); - num_tries++; - if (num_tries == 50) - { - /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be - * stale (nuke the it from orbit) - */ - if (g_unlink (lock) != 0) - { - errsv = errno; - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error deleting stale lock file “%s”: %s"), - lock, - g_strerror (errsv)); - goto out; - } - _log ("Deleted stale lock file '%s'", lock); - break; - } + g_usleep (timeout_usec); } - ret = g_open (lock, O_CREAT | -#ifdef O_EXCL - O_EXCL, -#else - 0, -#endif - 0700); - errsv = errno; - if (ret == -1) + if (num_tries == max_tries) { -#ifdef EEXISTS - /* EEXIST: pathname already exists and O_CREAT and O_EXCL were used. */ - if (errsv == EEXISTS) + /* ok, we slept 50*10ms = 0.5 seconds. Conclude that the lock file must be + * stale (nuke it from orbit) + */ + if (g_unlink (lock) != 0) { - num_create_tries++; - if (num_create_tries < 5) - goto again; + errsv = errno; + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error deleting stale lock file “%s”: %s"), + lock, + g_strerror (errsv)); + goto out; } -#endif - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error creating lock file “%s”: %s"), - lock, - g_strerror (errsv)); - goto out; + + _log ("Deleted stale lock file '%s'", lock); + + /* Try one last time to create it, now that we've deleted the stale one */ + ret = create_lock_exclusive (lock, error); + if (ret < 0) + goto out; } - out: +out: g_free (lock); return ret; } @@ -739,12 +797,8 @@ keyring_generate_entry (const gchar *cookie_context, { /* Oddball case: entry is more recent than our current wall-clock time.. * This is OK, it means that another server on another machine but with - * same $HOME wrote the entry. - * - * So discard the entry if it's more than 1 day in the future ("reasonable - * time in the future"). - */ - if (line_when - now > 24*60*60) + * same $HOME wrote the entry. */ + if (line_when - now > MAX_TIME_TRAVEL_SECONDS) { keep_entry = FALSE; _log ("Deleted SHA1 cookie from %" G_GUINT64_FORMAT " seconds in the future", line_when - now); @@ -752,8 +806,8 @@ keyring_generate_entry (const gchar *cookie_context, } else { - /* Discard entry if it's older than 15 minutes ("can be fairly short") */ - if (now - line_when > 15*60) + /* Discard entry if it's too old. */ + if (now - line_when > EXPIRE_KEYS_TIMEOUT_SECONDS) { keep_entry = FALSE; } @@ -771,13 +825,13 @@ keyring_generate_entry (const gchar *cookie_context, line_when, tokens[2]); max_line_id = MAX (line_id, max_line_id); - /* Only reuse entry if not older than 10 minutes. + /* Only reuse entry if not older than 5 minutes. * - * (We need a bit of grace time compared to 15 minutes above.. otherwise - * there's a race where we reuse the 14min59.9 secs old entry and a - * split-second later another server purges the now 15 minute old entry.) + * (We need a bit of grace time compared to 7 minutes above.. otherwise + * there's a race where we reuse the 6min59.9 secs old entry and a + * split-second later another server purges the now 7 minute old entry.) */ - if (now - line_when < 10 * 60) + if (now - line_when < NEW_KEY_TIMEOUT_SECONDS) { if (!have_id) { @@ -819,10 +873,12 @@ keyring_generate_entry (const gchar *cookie_context, /* and now actually write the cookie file if there are changes (this is atomic) */ if (changed_file) { - if (!g_file_set_contents (path, - new_contents->str, - -1, - error)) + if (!g_file_set_contents_full (path, + new_contents->str, + -1, + G_FILE_SET_CONTENTS_CONSISTENT, + 0600, + error)) { *out_id = 0; *out_cookie = 0; diff --git a/gio/gdbusauthobserver.c b/gio/gdbusauthobserver.c index be36c9dac41e48f6f9fe3b022e43f02fe413ce86..7bafa94ec8c0c2b05943f41f50e6ba83444372fd 100644 --- a/gio/gdbusauthobserver.c +++ b/gio/gdbusauthobserver.c @@ -70,7 +70,9 @@ * connections from any successfully authenticated user (but not from * anonymous connections using the `ANONYMOUS` mechanism). If you only * want to allow D-Bus connections from processes owned by the same uid - * as the server, you would use a signal handler like the following: + * as the server, since GLib 2.68, you should use the + * %G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flag. It’s equivalent + * to the following signal handler: * * |[ * static gboolean @@ -311,4 +313,3 @@ g_dbus_auth_observer_allow_mechanism (GDBusAuthObserver *observer, &ret); return ret; } - diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index 64a307e3dbcba091b4417fc4abfa7b874b96d4d6..a37611275435b25c6c8ccee9a7689f43782d6b23 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -120,6 +120,14 @@ #include "glibintl.h" +#define G_DBUS_CONNECTION_FLAGS_ALL \ + (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | \ + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | \ + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \ + G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | \ + G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING | \ + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER) + /** * SECTION:gdbusconnection * @short_description: D-Bus Connections @@ -222,7 +230,6 @@ typedef struct { GDestroyNotify callback; gpointer user_data; - GMainContext *context; } CallDestroyNotifyData; static gboolean @@ -236,8 +243,6 @@ call_destroy_notify_data_in_idle (gpointer user_data) static void call_destroy_notify_data_free (CallDestroyNotifyData *data) { - if (data->context != NULL) - g_main_context_unref (data->context); g_free (data); } @@ -258,14 +263,11 @@ call_destroy_notify (GMainContext *context, CallDestroyNotifyData *data; if (callback == NULL) - goto out; + return; data = g_new0 (CallDestroyNotifyData, 1); data->callback = callback; data->user_data = user_data; - data->context = context; - if (data->context != NULL) - g_main_context_ref (data->context); idle_source = g_idle_source_new (); g_source_set_priority (idle_source, G_PRIORITY_DEFAULT); @@ -274,11 +276,8 @@ call_destroy_notify (GMainContext *context, data, (GDestroyNotify) call_destroy_notify_data_free); g_source_set_name (idle_source, "[gio] call_destroy_notify_data_in_idle"); - g_source_attach (idle_source, data->context); + g_source_attach (idle_source, context); g_source_unref (idle_source); - - out: - ; } /* ---------------------------------------------------------------------------------------------------- */ @@ -402,7 +401,7 @@ struct _GDBusConnection * FLAG_CLOSED is the closed property. It may be read at any time, but * may only be written while holding @lock. */ - volatile gint atomic_flags; + gint atomic_flags; /* (atomic) */ /* If the connection could not be established during initable_init(), * this GError will be set. @@ -894,7 +893,7 @@ g_dbus_connection_class_init (GDBusConnectionClass *klass) * * If you are constructing a #GDBusConnection and pass * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER in the - * #GDBusConnection:flags property then you MUST also set this + * #GDBusConnection:flags property then you **must** also set this * property to a valid guid. * * If you are constructing a #GDBusConnection and pass @@ -1111,7 +1110,7 @@ g_dbus_connection_init (GDBusConnection *connection) * stream from a worker thread, so it is not safe to interact with * the stream directly. * - * Returns: (transfer none): the stream used for IO + * Returns: (transfer none) (not nullable): the stream used for IO * * Since: 2.26 */ @@ -1605,7 +1604,7 @@ static gboolean g_dbus_connection_send_message_unlocked (GDBusConnection *connection, GDBusMessage *message, GDBusSendMessageFlags flags, - volatile guint32 *out_serial, + guint32 *out_serial, GError **error) { guchar *blob; @@ -1717,7 +1716,9 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, * will be assigned by @connection and set on @message via * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the * serial number used will be written to this location prior to - * submitting the message to the underlying transport. + * submitting the message to the underlying transport. While it has a `volatile` + * qualifier, this is a historical artifact and the argument passed to it should + * not be `volatile`. * * If @connection is closed then the operation will fail with * %G_IO_ERROR_CLOSED. If @message is not well-formed, @@ -1750,7 +1751,7 @@ g_dbus_connection_send_message (GDBusConnection *connection, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); CONNECTION_LOCK (connection); - ret = g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, error); + ret = g_dbus_connection_send_message_unlocked (connection, message, flags, (guint32 *) out_serial, error); CONNECTION_UNLOCK (connection); return ret; } @@ -1910,7 +1911,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection *connect GDBusMessage *message, GDBusSendMessageFlags flags, gint timeout_msec, - volatile guint32 *out_serial, + guint32 *out_serial, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) @@ -1918,7 +1919,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection *connect GTask *task; SendMessageData *data; GError *error = NULL; - volatile guint32 serial; + guint32 serial; if (out_serial == NULL) out_serial = &serial; @@ -1988,7 +1989,9 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection *connect * will be assigned by @connection and set on @message via * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the * serial number used will be written to this location prior to - * submitting the message to the underlying transport. + * submitting the message to the underlying transport. While it has a `volatile` + * qualifier, this is a historical artifact and the argument passed to it should + * not be `volatile`. * * If @connection is closed then the operation will fail with * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will @@ -2031,7 +2034,7 @@ g_dbus_connection_send_message_with_reply (GDBusConnection *connection, message, flags, timeout_msec, - out_serial, + (guint32 *) out_serial, cancellable, callback, user_data); @@ -2114,7 +2117,9 @@ send_message_with_reply_sync_cb (GDBusConnection *connection, * will be assigned by @connection and set on @message via * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the * serial number used will be written to this location prior to - * submitting the message to the underlying transport. + * submitting the message to the underlying transport. While it has a `volatile` + * qualifier, this is a historical artifact and the argument passed to it should + * not be `volatile`. * * If @connection is closed then the operation will fail with * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will @@ -2514,7 +2519,8 @@ initable_init (GInitable *initable, g_assert (connection->stream == NULL); if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) || - (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS)) + (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) || + (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)) { g_set_error_literal (&connection->initialization_error, G_IO_ERROR, @@ -2549,6 +2555,7 @@ initable_init (GInitable *initable, connection->authentication_observer, connection->guid, (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS), + (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER), get_offered_capabilities_max (connection), &connection->capabilities, &connection->credentials, @@ -2714,6 +2721,7 @@ g_dbus_connection_new (GIOStream *stream, _g_dbus_initialize (); g_return_if_fail (G_IS_IO_STREAM (stream)); + g_return_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0); g_async_initable_new_async (G_TYPE_DBUS_CONNECTION, G_PRIORITY_DEFAULT, @@ -2735,7 +2743,7 @@ g_dbus_connection_new (GIOStream *stream, * * Finishes an operation started with g_dbus_connection_new(). * - * Returns: a #GDBusConnection or %NULL if @error is set. Free + * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set. Free * with g_object_unref(). * * Since: 2.26 @@ -2787,7 +2795,8 @@ g_dbus_connection_new_finish (GAsyncResult *res, * This is a synchronous failable constructor. See * g_dbus_connection_new() for the asynchronous version. * - * Returns: a #GDBusConnection or %NULL if @error is set. Free with g_object_unref(). + * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set. + * Free with g_object_unref(). * * Since: 2.26 */ @@ -2801,6 +2810,7 @@ g_dbus_connection_new_sync (GIOStream *stream, { _g_dbus_initialize (); g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL); + g_return_val_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); return g_initable_new (G_TYPE_DBUS_CONNECTION, cancellable, @@ -2831,8 +2841,9 @@ g_dbus_connection_new_sync (GIOStream *stream, * This constructor can only be used to initiate client-side * connections - use g_dbus_connection_new() if you need to act as the * server. In particular, @flags cannot contain the - * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or - * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags. + * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, + * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS or + * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flags. * * When the operation is finished, @callback will be invoked. You can * then call g_dbus_connection_new_for_address_finish() to get the result of @@ -2858,6 +2869,7 @@ g_dbus_connection_new_for_address (const gchar *address, _g_dbus_initialize (); g_return_if_fail (address != NULL); + g_return_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0); g_async_initable_new_async (G_TYPE_DBUS_CONNECTION, G_PRIORITY_DEFAULT, @@ -2878,8 +2890,8 @@ g_dbus_connection_new_for_address (const gchar *address, * * Finishes an operation started with g_dbus_connection_new_for_address(). * - * Returns: a #GDBusConnection or %NULL if @error is set. Free with - * g_object_unref(). + * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set. + * Free with g_object_unref(). * * Since: 2.26 */ @@ -2921,8 +2933,9 @@ g_dbus_connection_new_for_address_finish (GAsyncResult *res, * This constructor can only be used to initiate client-side * connections - use g_dbus_connection_new_sync() if you need to act * as the server. In particular, @flags cannot contain the - * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or - * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags. + * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, + * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS or + * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flags. * * This is a synchronous failable constructor. See * g_dbus_connection_new_for_address() for the asynchronous version. @@ -2930,8 +2943,8 @@ g_dbus_connection_new_for_address_finish (GAsyncResult *res, * If @observer is not %NULL it may be used to control the * authentication process. * - * Returns: a #GDBusConnection or %NULL if @error is set. Free with - * g_object_unref(). + * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set. + * Free with g_object_unref(). * * Since: 2.26 */ @@ -2945,6 +2958,7 @@ g_dbus_connection_new_for_address_sync (const gchar *address, _g_dbus_initialize (); g_return_val_if_fail (address != NULL, NULL); + g_return_val_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); return g_initable_new (G_TYPE_DBUS_CONNECTION, cancellable, @@ -3020,7 +3034,7 @@ g_dbus_connection_get_exit_on_close (GDBusConnection *connection) * The GUID of the peer performing the role of server when * authenticating. See #GDBusConnection:guid for more details. * - * Returns: The GUID. Do not free this string, it is owned by + * Returns: (not nullable): The GUID. Do not free this string, it is owned by * @connection. * * Since: 2.26 @@ -3091,7 +3105,7 @@ g_dbus_connection_get_peer_credentials (GDBusConnection *connection) /* ---------------------------------------------------------------------------------------------------- */ -static volatile guint _global_filter_id = 1; +static guint _global_filter_id = 1; /* (atomic) */ /** * g_dbus_connection_add_filter: @@ -3148,7 +3162,7 @@ g_dbus_connection_add_filter (GDBusConnection *connection, CONNECTION_LOCK (connection); data = g_new0 (FilterData, 1); - data->id = g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */ + data->id = (guint) g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */ data->ref_count = 1; data->filter_function = filter_function; data->user_data = user_data; @@ -3248,18 +3262,9 @@ typedef struct gchar *object_path; gchar *arg0; GDBusSignalFlags flags; - GArray *subscribers; + GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */ } SignalData; -typedef struct -{ - GDBusSignalCallback callback; - gpointer user_data; - GDestroyNotify user_data_free_func; - guint id; - GMainContext *context; -} SignalSubscriber; - static void signal_data_free (SignalData *signal_data) { @@ -3270,10 +3275,46 @@ signal_data_free (SignalData *signal_data) g_free (signal_data->member); g_free (signal_data->object_path); g_free (signal_data->arg0); - g_array_free (signal_data->subscribers, TRUE); + g_ptr_array_unref (signal_data->subscribers); g_free (signal_data); } +typedef struct +{ + /* All fields are immutable after construction. */ + gatomicrefcount ref_count; + GDBusSignalCallback callback; + gpointer user_data; + GDestroyNotify user_data_free_func; + guint id; + GMainContext *context; +} SignalSubscriber; + +static SignalSubscriber * +signal_subscriber_ref (SignalSubscriber *subscriber) +{ + g_atomic_ref_count_inc (&subscriber->ref_count); + return subscriber; +} + +static void +signal_subscriber_unref (SignalSubscriber *subscriber) +{ + if (g_atomic_ref_count_dec (&subscriber->ref_count)) + { + /* Destroy the user data. It doesn’t matter which thread + * signal_subscriber_unref() is called in (or whether it’s called with a + * lock held), as call_destroy_notify() always defers to the next + * #GMainContext iteration. */ + call_destroy_notify (subscriber->context, + subscriber->user_data_free_func, + subscriber->user_data); + + g_main_context_unref (subscriber->context); + g_free (subscriber); + } +} + static gchar * args_to_rule (const gchar *sender, const gchar *interface_name, @@ -3309,9 +3350,9 @@ args_to_rule (const gchar *sender, return g_string_free (rule, FALSE); } -static volatile guint _global_subscriber_id = 1; -static volatile guint _global_registration_id = 1; -static volatile guint _global_subtree_registration_id = 1; +static guint _global_subscriber_id = 1; /* (atomic) */ +static guint _global_registration_id = 1; /* (atomic) */ +static guint _global_subtree_registration_id = 1; /* (atomic) */ /* ---------------------------------------------------------------------------------------------------- */ @@ -3441,6 +3482,24 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data) * signal is unsubscribed from, and may be called after @connection * has been destroyed.) * + * As @callback is potentially invoked in a different thread from where it’s + * emitted, it’s possible for this to happen after + * g_dbus_connection_signal_unsubscribe() has been called in another thread. + * Due to this, @user_data should have a strong reference which is freed with + * @user_data_free_func, rather than pointing to data whose lifecycle is tied + * to the signal subscription. For example, if a #GObject is used to store the + * subscription ID from g_dbus_connection_signal_subscribe(), a strong reference + * to that #GObject must be passed to @user_data, and g_object_unref() passed to + * @user_data_free_func. You are responsible for breaking the resulting + * reference count cycle by explicitly unsubscribing from the signal when + * dropping the last external reference to the #GObject. Alternatively, a weak + * reference may be used. + * + * It is guaranteed that if you unsubscribe from a signal using + * g_dbus_connection_signal_unsubscribe() from the same thread which made the + * corresponding g_dbus_connection_signal_subscribe() call, @callback will not + * be invoked after g_dbus_connection_signal_unsubscribe() returns. + * * The returned subscription identifier is an opaque value which is guaranteed * to never be zero. * @@ -3464,7 +3523,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, { gchar *rule; SignalData *signal_data; - SignalSubscriber subscriber; + SignalSubscriber *subscriber; GPtrArray *signal_data_array; const gchar *sender_unique_name; @@ -3505,17 +3564,19 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, else sender_unique_name = ""; - subscriber.callback = callback; - subscriber.user_data = user_data; - subscriber.user_data_free_func = user_data_free_func; - subscriber.id = g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */ - subscriber.context = g_main_context_ref_thread_default (); + subscriber = g_new0 (SignalSubscriber, 1); + subscriber->ref_count = 1; + subscriber->callback = callback; + subscriber->user_data = user_data; + subscriber->user_data_free_func = user_data_free_func; + subscriber->id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */ + subscriber->context = g_main_context_ref_thread_default (); /* see if we've already have this rule */ signal_data = g_hash_table_lookup (connection->map_rule_to_signal_data, rule); if (signal_data != NULL) { - g_array_append_val (signal_data->subscribers, subscriber); + g_ptr_array_add (signal_data->subscribers, subscriber); g_free (rule); goto out; } @@ -3529,8 +3590,8 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, signal_data->object_path = g_strdup (object_path); signal_data->arg0 = g_strdup (arg0); signal_data->flags = flags; - signal_data->subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber)); - g_array_append_val (signal_data->subscribers, subscriber); + signal_data->subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref); + g_ptr_array_add (signal_data->subscribers, subscriber); g_hash_table_insert (connection->map_rule_to_signal_data, signal_data->rule, @@ -3560,26 +3621,27 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, out: g_hash_table_insert (connection->map_id_to_signal_data, - GUINT_TO_POINTER (subscriber.id), + GUINT_TO_POINTER (subscriber->id), signal_data); CONNECTION_UNLOCK (connection); - return subscriber.id; + return subscriber->id; } /* ---------------------------------------------------------------------------------------------------- */ /* called in any thread */ -/* must hold lock when calling this (except if connection->finalizing is TRUE) */ -static void +/* must hold lock when calling this (except if connection->finalizing is TRUE) + * returns the number of removed subscribers */ +static guint unsubscribe_id_internal (GDBusConnection *connection, - guint subscription_id, - GArray *out_removed_subscribers) + guint subscription_id) { SignalData *signal_data; GPtrArray *signal_data_array; guint n; + guint n_removed = 0; signal_data = g_hash_table_lookup (connection->map_id_to_signal_data, GUINT_TO_POINTER (subscription_id)); @@ -3591,16 +3653,19 @@ unsubscribe_id_internal (GDBusConnection *connection, for (n = 0; n < signal_data->subscribers->len; n++) { - SignalSubscriber *subscriber; + SignalSubscriber *subscriber = signal_data->subscribers->pdata[n]; - subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, n)); if (subscriber->id != subscription_id) continue; + /* It’s OK to rearrange the array order using the ‘fast’ #GPtrArray + * removal functions, since we’re going to exit the loop below anyway — we + * never move on to the next element. Secondly, subscription IDs are + * guaranteed to be unique. */ g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data, GUINT_TO_POINTER (subscription_id))); - g_array_append_val (out_removed_subscribers, *subscriber); - g_array_remove_index (signal_data->subscribers, n); + n_removed++; + g_ptr_array_remove_index_fast (signal_data->subscribers, n); if (signal_data->subscribers->len == 0) { @@ -3641,7 +3706,7 @@ unsubscribe_id_internal (GDBusConnection *connection, g_assert_not_reached (); out: - ; + return n_removed; } /** @@ -3652,53 +3717,41 @@ unsubscribe_id_internal (GDBusConnection *connection, * * Unsubscribes from signals. * + * Note that there may still be D-Bus traffic to process (relating to this + * signal subscription) in the current thread-default #GMainContext after this + * function has returned. You should continue to iterate the #GMainContext + * until the #GDestroyNotify function passed to + * g_dbus_connection_signal_subscribe() is called, in order to avoid memory + * leaks through callbacks queued on the #GMainContext after it’s stopped being + * iterated. + * * Since: 2.26 */ void g_dbus_connection_signal_unsubscribe (GDBusConnection *connection, guint subscription_id) { - GArray *subscribers; - guint n; + guint n_subscribers_removed G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */; g_return_if_fail (G_IS_DBUS_CONNECTION (connection)); g_return_if_fail (check_initialized (connection)); - subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber)); - CONNECTION_LOCK (connection); - unsubscribe_id_internal (connection, - subscription_id, - subscribers); + n_subscribers_removed = unsubscribe_id_internal (connection, subscription_id); CONNECTION_UNLOCK (connection); /* invariant */ - g_assert (subscribers->len == 0 || subscribers->len == 1); - - /* call GDestroyNotify without lock held */ - for (n = 0; n < subscribers->len; n++) - { - SignalSubscriber *subscriber; - subscriber = &(g_array_index (subscribers, SignalSubscriber, n)); - call_destroy_notify (subscriber->context, - subscriber->user_data_free_func, - subscriber->user_data); - g_main_context_unref (subscriber->context); - } - - g_array_free (subscribers, TRUE); + g_assert (n_subscribers_removed == 0 || n_subscribers_removed == 1); } /* ---------------------------------------------------------------------------------------------------- */ typedef struct { - guint subscription_id; - GDBusSignalCallback callback; - gpointer user_data; + SignalSubscriber *subscriber; /* (owned) */ GDBusMessage *message; GDBusConnection *connection; - const gchar *sender; + const gchar *sender; /* (nullable) for peer-to-peer connections */ const gchar *path; const gchar *interface; const gchar *member; @@ -3727,7 +3780,7 @@ emit_signal_instance_in_idle_cb (gpointer data) #if 0 g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n", - signal_instance->subscription_id, + signal_instance->subscriber->id, signal_instance->sender, signal_instance->path, signal_instance->interface, @@ -3739,18 +3792,18 @@ emit_signal_instance_in_idle_cb (gpointer data) CONNECTION_LOCK (signal_instance->connection); has_subscription = FALSE; if (g_hash_table_lookup (signal_instance->connection->map_id_to_signal_data, - GUINT_TO_POINTER (signal_instance->subscription_id)) != NULL) + GUINT_TO_POINTER (signal_instance->subscriber->id)) != NULL) has_subscription = TRUE; CONNECTION_UNLOCK (signal_instance->connection); if (has_subscription) - signal_instance->callback (signal_instance->connection, - signal_instance->sender, - signal_instance->path, - signal_instance->interface, - signal_instance->member, - parameters, - signal_instance->user_data); + signal_instance->subscriber->callback (signal_instance->connection, + signal_instance->sender, + signal_instance->path, + signal_instance->interface, + signal_instance->member, + parameters, + signal_instance->subscriber->user_data); g_variant_unref (parameters); @@ -3762,6 +3815,7 @@ signal_instance_free (SignalInstance *signal_instance) { g_object_unref (signal_instance->message); g_object_unref (signal_instance->connection); + signal_subscriber_unref (signal_instance->subscriber); g_free (signal_instance); } @@ -3802,7 +3856,9 @@ path_rule_matches (const gchar *path_a, return memcmp (path_a, path_b, MIN (len_a, len_b)) == 0; } -/* called in GDBusWorker thread WITH lock held */ +/* called in GDBusWorker thread WITH lock held + * + * @sender is (nullable) for peer-to-peer connections */ static void schedule_callbacks (GDBusConnection *connection, GPtrArray *signal_data_array, @@ -3876,16 +3932,12 @@ schedule_callbacks (GDBusConnection *connection, for (m = 0; m < signal_data->subscribers->len; m++) { - SignalSubscriber *subscriber; + SignalSubscriber *subscriber = signal_data->subscribers->pdata[m]; GSource *idle_source; SignalInstance *signal_instance; - subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, m)); - signal_instance = g_new0 (SignalInstance, 1); - signal_instance->subscription_id = subscriber->id; - signal_instance->callback = subscriber->callback; - signal_instance->user_data = subscriber->user_data; + signal_instance->subscriber = signal_subscriber_ref (subscriber); signal_instance->message = g_object_ref (message); signal_instance->connection = g_object_ref (connection); signal_instance->sender = sender; @@ -3954,7 +4006,6 @@ purge_all_signal_subscriptions (GDBusConnection *connection) GHashTableIter iter; gpointer key; GArray *ids; - GArray *subscribers; guint n; ids = g_array_new (FALSE, FALSE, sizeof (guint)); @@ -3965,28 +4016,12 @@ purge_all_signal_subscriptions (GDBusConnection *connection) g_array_append_val (ids, subscription_id); } - subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber)); for (n = 0; n < ids->len; n++) { guint subscription_id = g_array_index (ids, guint, n); - unsubscribe_id_internal (connection, - subscription_id, - subscribers); + unsubscribe_id_internal (connection, subscription_id); } g_array_free (ids, TRUE); - - /* call GDestroyNotify without lock held */ - for (n = 0; n < subscribers->len; n++) - { - SignalSubscriber *subscriber; - subscriber = &(g_array_index (subscribers, SignalSubscriber, n)); - call_destroy_notify (subscriber->context, - subscriber->user_data_free_func, - subscriber->user_data); - g_main_context_unref (subscriber->context); - } - - g_array_free (subscribers, TRUE); } /* ---------------------------------------------------------------------------------------------------- */ @@ -5198,7 +5233,7 @@ g_dbus_connection_register_object (GDBusConnection *connection, } ei = g_new0 (ExportedInterface, 1); - ei->id = g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */ + ei->id = (guint) g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */ ei->eo = eo; ei->user_data = user_data; ei->user_data_free_func = user_data_free_func; @@ -5492,7 +5527,7 @@ register_with_closures_on_set_property (GDBusConnection *connection, * Version of g_dbus_connection_register_object() using closures instead of a * #GDBusInterfaceVTable for easier binding in other languages. * - * Returns: 0 if @error is set, otherwise a registration id (never 0) + * Returns: 0 if @error is set, otherwise a registration ID (never 0) * that can be used with g_dbus_connection_unregister_object() . * * Since: 2.46 @@ -5511,7 +5546,8 @@ g_dbus_connection_register_object_with_closures (GDBusConnection *connection { method_call_closure != NULL ? register_with_closures_on_method_call : NULL, get_property_closure != NULL ? register_with_closures_on_get_property : NULL, - set_property_closure != NULL ? register_with_closures_on_set_property : NULL + set_property_closure != NULL ? register_with_closures_on_set_property : NULL, + { 0 } }; data = register_object_data_new (method_call_closure, get_property_closure, set_property_closure); @@ -5726,17 +5762,19 @@ g_dbus_connection_call_done (GObject *source, _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Call:\n" - " <<<< ASYNC COMPLETE %s() (serial %d)\n" - " ", - state->method_name, - g_dbus_message_get_reply_serial (reply)); + " <<<< ASYNC COMPLETE %s()", + state->method_name); + if (reply != NULL) { - g_print ("SUCCESS\n"); + g_print (" (serial %d)\n" + " SUCCESS\n", + g_dbus_message_get_reply_serial (reply)); } else { - g_print ("FAILED: %s\n", + g_print ("\n" + " FAILED: %s\n", error->message); } _g_dbus_debug_print_unlock (); @@ -5978,7 +6016,7 @@ g_dbus_connection_call_sync_internal (GDBusConnection *connection, message, send_flags, timeout_msec, - NULL, /* volatile guint32 *out_serial */ + NULL, /* guint32 *out_serial */ cancellable, &local_error); @@ -6119,8 +6157,8 @@ g_dbus_connection_call (GDBusConnection *connection, * * Finishes an operation started with g_dbus_connection_call(). * - * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with - * return values. Free with g_variant_unref(). + * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating + * #GVariant tuple with return values. Free with g_variant_unref(). * * Since: 2.26 */ @@ -6186,8 +6224,8 @@ g_dbus_connection_call_finish (GDBusConnection *connection, * g_dbus_connection_call() for the asynchronous version of * this method. * - * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with - * return values. Free with g_variant_unref(). + * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating + * #GVariant tuple with return values. Free with g_variant_unref(). * * Since: 2.26 */ @@ -6234,6 +6272,18 @@ g_dbus_connection_call_sync (GDBusConnection *connection, * * Like g_dbus_connection_call() but also takes a #GUnixFDList object. * + * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE + * values in the body of the message. For example, if a message contains + * two file descriptors, @fd_list would have length 2, and + * `g_variant_new_handle (0)` and `g_variant_new_handle (1)` would appear + * somewhere in the body of the message (not necessarily in that order!) + * to represent the file descriptors at indexes 0 and 1 respectively. + * + * When designing D-Bus APIs that are intended to be interoperable, + * please note that non-GDBus implementations of D-Bus can usually only + * access file descriptors if they are referenced in this way by a + * value of type %G_VARIANT_TYPE_HANDLE in the body of the message. + * * This method is only available on UNIX. * * Since: 2.30 @@ -6266,8 +6316,19 @@ g_dbus_connection_call_with_unix_fd_list (GDBusConnection *connection, * * Finishes an operation started with g_dbus_connection_call_with_unix_fd_list(). * - * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with - * return values. Free with g_variant_unref(). + * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE + * values in the body of the message. For example, + * if g_variant_get_handle() returns 5, that is intended to be a reference + * to the file descriptor that can be accessed by + * `g_unix_fd_list_get (*out_fd_list, 5, ...)`. + * + * When designing D-Bus APIs that are intended to be interoperable, + * please note that non-GDBus implementations of D-Bus can usually only + * access file descriptors if they are referenced in this way by a + * value of type %G_VARIANT_TYPE_HANDLE in the body of the message. + * + * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating + * #GVariant tuple with return values. Free with g_variant_unref(). * * Since: 2.30 */ @@ -6300,11 +6361,13 @@ g_dbus_connection_call_with_unix_fd_list_finish (GDBusConnection *connection, * @error: return location for error or %NULL * * Like g_dbus_connection_call_sync() but also takes and returns #GUnixFDList objects. + * See g_dbus_connection_call_with_unix_fd_list() and + * g_dbus_connection_call_with_unix_fd_list_finish() for more details. * * This method is only available on UNIX. * - * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with - * return values. Free with g_variant_unref(). + * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating + * #GVariant tuple with return values. Free with g_variant_unref(). * * Since: 2.30 */ @@ -6814,8 +6877,8 @@ subtree_message_func (GDBusConnection *connection, * See this [server][gdbus-subtree-server] for an example of how to use * this method. * - * Returns: 0 if @error is set, otherwise a subtree registration id (never 0) - * that can be used with g_dbus_connection_unregister_subtree() . + * Returns: 0 if @error is set, otherwise a subtree registration ID (never 0) + * that can be used with g_dbus_connection_unregister_subtree() * * Since: 2.26 */ @@ -6858,7 +6921,7 @@ g_dbus_connection_register_subtree (GDBusConnection *connection, es->vtable = _g_dbus_subtree_vtable_copy (vtable); es->flags = flags; - es->id = g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */ + es->id = (guint) g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */ es->user_data = user_data; es->user_data_free_func = user_data_free_func; es->context = g_main_context_ref_thread_default (); diff --git a/gio/gdbusconnection.h b/gio/gdbusconnection.h index c37363c0d1665176138c0943d4077d9f4f35ed96..4bd3e9a4b723263e696626c2100932d32328f779 100644 --- a/gio/gdbusconnection.h +++ b/gio/gdbusconnection.h @@ -432,11 +432,11 @@ gboolean g_dbus_connection_unregister_object (GDBusConnection * specified (ie: to verify that the object path is valid). * * Hierarchies are not supported; the items that you return should not - * contain the '/' character. + * contain the `/` character. * * The return value will be freed with g_strfreev(). * - * Returns: A newly allocated array of strings for node names that are children of @object_path. + * Returns: (array zero-terminated=1) (transfer full): A newly allocated array of strings for node names that are children of @object_path. * * Since: 2.26 */ @@ -472,7 +472,7 @@ typedef gchar** (*GDBusSubtreeEnumerateFunc) (GDBusConnection *connection, * remote introspector in the empty array case, but not in the %NULL * case. * - * Returns: A %NULL-terminated array of pointers to #GDBusInterfaceInfo, or %NULL. + * Returns: (array zero-terminated=1) (nullable) (transfer full): A %NULL-terminated array of pointers to #GDBusInterfaceInfo, or %NULL. * * Since: 2.26 */ @@ -489,7 +489,7 @@ typedef GDBusInterfaceInfo ** (*GDBusSubtreeIntrospectFunc) (GDBusConnection * @object_path: The object path that was registered with g_dbus_connection_register_subtree(). * @interface_name: The D-Bus interface name that the method call or property access is for. * @node: A node that is a child of @object_path (relative to @object_path) or %NULL for the root of the subtree. - * @out_user_data: (nullable) (not optional): Return location for user data to pass to functions in the returned #GDBusInterfaceVTable (never %NULL). + * @out_user_data: (nullable) (not optional): Return location for user data to pass to functions in the returned #GDBusInterfaceVTable. * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_subtree(). * * The type of the @dispatch function in #GDBusSubtreeVTable. @@ -497,7 +497,7 @@ typedef GDBusInterfaceInfo ** (*GDBusSubtreeIntrospectFunc) (GDBusConnection * Subtrees are flat. @node, if non-%NULL, is always exactly one * segment of the object path (ie: it never contains a slash). * - * Returns: A #GDBusInterfaceVTable or %NULL if you don't want to handle the methods. + * Returns: (nullable): A #GDBusInterfaceVTable or %NULL if you don't want to handle the methods. * * Since: 2.26 */ @@ -550,7 +550,8 @@ gboolean g_dbus_connection_unregister_subtree (GDBusConnection /** * GDBusSignalCallback: * @connection: A #GDBusConnection. - * @sender_name: The unique bus name of the sender of the signal. + * @sender_name: (nullable): The unique bus name of the sender of the signal, + or %NULL on a peer-to-peer D-Bus connection. * @object_path: The object path that the signal was emitted on. * @interface_name: The name of the interface. * @signal_name: The name of the signal. diff --git a/gio/gdbusdaemon.c b/gio/gdbusdaemon.c index 0d5058f703f1e5a015c44f6867bd5c52f44f451c..5dfe62cd3318f2a29e8bd168be83aacc79e2748d 100644 --- a/gio/gdbusdaemon.c +++ b/gio/gdbusdaemon.c @@ -170,6 +170,7 @@ name_new (GDBusDaemon *daemon, const char *str) static Name * name_ref (Name *name) { + g_assert (name->refcount > 0); name->refcount++; return name; } @@ -177,6 +178,7 @@ name_ref (Name *name) static void name_unref (Name *name) { + g_assert (name->refcount > 0); if (--name->refcount == 0) { g_hash_table_remove (name->daemon->names, name->name); @@ -208,7 +210,8 @@ is_key (const char *key_start, const char *key_end, const char *value) { gsize len = strlen (value); - if (len != key_end - key_start) + g_assert (key_end >= key_start); + if (len != (gsize) (key_end - key_start)) return FALSE; return strncmp (key_start, value, len) == 0; @@ -358,7 +361,7 @@ match_new (const char *str) MatchElement element; gboolean eavesdrop; GDBusMessageType type; - int i; + gsize i; eavesdrop = FALSE; type = G_DBUS_MESSAGE_TYPE_INVALID; @@ -1463,10 +1466,11 @@ filter_function (GDBusConnection *connection, gpointer user_data) { Client *client = user_data; - const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" }; if (0) - g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n", + { + const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" }; + g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n", client->id, incoming? "->" : "<-", types[g_dbus_message_get_message_type (message)], @@ -1477,6 +1481,7 @@ filter_function (GDBusConnection *connection, g_dbus_message_get_path (message), g_dbus_message_get_interface (message), g_dbus_message_get_member (message)); + } if (incoming) { @@ -1533,34 +1538,6 @@ on_new_connection (GDBusServer *server, return TRUE; } -static gboolean -on_authorize_authenticated_peer (GDBusAuthObserver *observer, - GIOStream *stream, - GCredentials *credentials, - gpointer user_data) -{ - gboolean authorized = FALSE; - - if (credentials != NULL) - { - GCredentials *own_credentials; - - own_credentials = g_credentials_new (); - authorized = g_credentials_is_same_user (credentials, own_credentials, NULL); - g_object_unref (own_credentials); - } -#ifdef G_OS_WIN32 - else - { - /* We allow ANONYMOUS authentication on Windows for now, in - * combination with the nonce-tcp transport. */ - authorized = TRUE; - } -#endif - - return authorized; -} - static void g_dbus_daemon_finalize (GObject *object) { @@ -1610,7 +1587,6 @@ initable_init (GInitable *initable, GError **error) { GDBusDaemon *daemon = G_DBUS_DAEMON (initable); - GDBusAuthObserver *observer; GDBusServerFlags flags; flags = G_DBUS_SERVER_FLAGS_NONE; @@ -1624,24 +1600,23 @@ initable_init (GInitable *initable, daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL); daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir); } + flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER; #else + /* Don’t require authentication on Windows as that hasn’t been + * implemented yet. */ daemon->address = g_strdup ("nonce-tcp:"); flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; #endif } - observer = g_dbus_auth_observer_new (); daemon->server = g_dbus_server_new_sync (daemon->address, flags, daemon->guid, - observer, + NULL, cancellable, error); if (daemon->server == NULL) - { - g_object_unref (observer); - return FALSE; - } + return FALSE; g_dbus_server_start (daemon->server); @@ -1649,12 +1624,6 @@ initable_init (GInitable *initable, g_signal_connect (daemon->server, "new-connection", G_CALLBACK (on_new_connection), daemon); - g_signal_connect (observer, - "authorize-authenticated-peer", - G_CALLBACK (on_authorize_authenticated_peer), - daemon); - - g_object_unref (observer); return TRUE; } diff --git a/gio/gdbuserror.c b/gio/gdbuserror.c index 6826773545c61666d803797ea283cb84cd0f1577..b3ea28f5a480fe994519c58b99bf7bfb9801da6a 100644 --- a/gio/gdbuserror.c +++ b/gio/gdbuserror.c @@ -84,12 +84,12 @@ * GQuark * foo_bar_error_quark (void) * { - * static volatile gsize quark_volatile = 0; + * static gsize quark = 0; * g_dbus_error_register_error_domain ("foo-bar-error-quark", - * &quark_volatile, + * &quark, * foo_bar_error_entries, * G_N_ELEMENTS (foo_bar_error_entries)); - * return (GQuark) quark_volatile; + * return (GQuark) quark; * } * ]| * With this setup, a D-Bus peer can transparently pass e.g. %FOO_BAR_ERROR_ANOTHER_ERROR and @@ -160,12 +160,12 @@ GQuark g_dbus_error_quark (void) { G_STATIC_ASSERT (G_N_ELEMENTS (g_dbus_error_entries) - 1 == G_DBUS_ERROR_PROPERTY_READ_ONLY); - static volatile gsize quark_volatile = 0; + static gsize quark = 0; g_dbus_error_register_error_domain ("g-dbus-error-quark", - &quark_volatile, + &quark, g_dbus_error_entries, G_N_ELEMENTS (g_dbus_error_entries)); - return (GQuark) quark_volatile; + return (GQuark) quark; } /** @@ -177,6 +177,9 @@ g_dbus_error_quark (void) * * Helper function for associating a #GError error domain with D-Bus error names. * + * While @quark_volatile has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. + * * Since: 2.26 */ void @@ -185,25 +188,31 @@ g_dbus_error_register_error_domain (const gchar *error_domain_quark_na const GDBusErrorEntry *entries, guint num_entries) { + gsize *quark; + g_return_if_fail (error_domain_quark_name != NULL); g_return_if_fail (quark_volatile != NULL); g_return_if_fail (entries != NULL); g_return_if_fail (num_entries > 0); - if (g_once_init_enter (quark_volatile)) + /* Drop the volatile qualifier, which should never have been on the argument + * in the first place. */ + quark = (gsize *) quark_volatile; + + if (g_once_init_enter (quark)) { guint n; - GQuark quark; + GQuark new_quark; - quark = g_quark_from_static_string (error_domain_quark_name); + new_quark = g_quark_from_static_string (error_domain_quark_name); for (n = 0; n < num_entries; n++) { - g_warn_if_fail (g_dbus_error_register_error (quark, + g_warn_if_fail (g_dbus_error_register_error (new_quark, entries[n].error_code, entries[n].dbus_error_name)); } - g_once_init_leave (quark_volatile, quark); + g_once_init_leave (quark, new_quark); } } @@ -503,8 +512,8 @@ g_dbus_error_is_remote_error (const GError *error) * (e.g. g_dbus_connection_call_finish()) unless * g_dbus_error_strip_remote_error() has been used on @error. * - * Returns: an allocated string or %NULL if the D-Bus error name - * could not be found. Free with g_free(). + * Returns: (nullable) (transfer full): an allocated string or %NULL if the + * D-Bus error name could not be found. Free with g_free(). * * Since: 2.26 */ @@ -591,7 +600,7 @@ g_dbus_error_get_remote_error (const GError *error) * #GError instances for applications. Regular applications should not use * it. * - * Returns: An allocated #GError. Free with g_error_free(). + * Returns: (transfer full): An allocated #GError. Free with g_error_free(). * * Since: 2.26 */ @@ -801,7 +810,8 @@ g_dbus_error_strip_remote_error (GError *error) * This function is typically only used in object mappings to put a * #GError on the wire. Regular applications should not use it. * - * Returns: A D-Bus error name (never %NULL). Free with g_free(). + * Returns: (transfer full) (not nullable): A D-Bus error name (never %NULL). + * Free with g_free(). * * Since: 2.26 */ diff --git a/gio/gdbusinterface.c b/gio/gdbusinterface.c index fa03115d2b1543a9060fda09b4582b4f8364f250..35fa8e460cc20618c3fc6653491f46d390489de6 100644 --- a/gio/gdbusinterface.c +++ b/gio/gdbusinterface.c @@ -73,7 +73,7 @@ g_dbus_interface_get_info (GDBusInterface *interface_) * the returned object is being used from other threads. See * g_dbus_interface_dup_object() for a thread-safe alternative. * - * Returns: (transfer none): A #GDBusObject or %NULL. The returned + * Returns: (nullable) (transfer none): A #GDBusObject or %NULL. The returned * reference belongs to @interface_ and should not be freed. * * Since: 2.30 @@ -91,7 +91,7 @@ g_dbus_interface_get_object (GDBusInterface *interface_) * * Gets the #GDBusObject that @interface_ belongs to, if any. * - * Returns: (transfer full): A #GDBusObject or %NULL. The returned + * Returns: (nullable) (transfer full): A #GDBusObject or %NULL. The returned * reference should be freed with g_object_unref(). * * Since: 2.32 diff --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c index 0e9157508951852cf0aabefab46dcca7f1dc97a9..878c1459940a59f98adc82b538755008631ada47 100644 --- a/gio/gdbusinterfaceskeleton.c +++ b/gio/gdbusinterfaceskeleton.c @@ -458,7 +458,7 @@ dbus_interface_interface_init (GDBusInterfaceIface *iface) typedef struct { - volatile gint ref_count; + gint ref_count; /* (atomic) */ GDBusInterfaceSkeleton *interface; GDBusInterfaceMethodCallFunc method_call_func; GDBusMethodInvocation *invocation; @@ -632,6 +632,7 @@ g_dbus_interface_method_dispatch_helper (GDBusInterfaceSkeleton *interface task = g_task_new (interface, NULL, NULL, NULL); g_task_set_source_tag (task, g_dbus_interface_method_dispatch_helper); + g_task_set_name (task, "[gio] D-Bus interface method dispatch"); g_task_set_task_data (task, data, (GDestroyNotify) dispatch_data_unref); g_task_run_in_thread (task, dispatch_in_thread_func); g_object_unref (task); @@ -766,7 +767,7 @@ set_object_path_locked (GDBusInterfaceSkeleton *interface_, * * Gets the first connection that @interface_ is exported on, if any. * - * Returns: (transfer none): A #GDBusConnection or %NULL if @interface_ is + * Returns: (nullable) (transfer none): A #GDBusConnection or %NULL if @interface_ is * not exported anywhere. Do not free, the object belongs to @interface_. * * Since: 2.30 @@ -875,7 +876,7 @@ g_dbus_interface_skeleton_has_connection (GDBusInterfaceSkeleton *interface_ * * Gets the object path that @interface_ is exported on, if any. * - * Returns: A string owned by @interface_ or %NULL if @interface_ is not exported + * Returns: (nullable): A string owned by @interface_ or %NULL if @interface_ is not exported * anywhere. Do not free, the string belongs to @interface_. * * Since: 2.30 diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c index dde06422ebfda3e81f1004759aaa4aa4042a7a3d..f35b2fb4434a7f370c23dcf06f17322b3e6013e1 100644 --- a/gio/gdbusintrospection.c +++ b/gio/gdbusintrospection.c @@ -1847,7 +1847,7 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data, * * The cost of this function is O(n) in number of annotations. * - * Returns: The value or %NULL if not found. Do not free, it is owned by @annotations. + * Returns: (nullable): The value or %NULL if not found. Do not free, it is owned by @annotations. * * Since: 2.26 */ @@ -1915,7 +1915,7 @@ static GHashTable *info_cache = NULL; * The cost of this function is O(n) in number of methods unless * g_dbus_interface_info_cache_build() has been used on @info. * - * Returns: (transfer none): A #GDBusMethodInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (nullable) (transfer none): A #GDBusMethodInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ @@ -1969,7 +1969,7 @@ g_dbus_interface_info_lookup_method (GDBusInterfaceInfo *info, * The cost of this function is O(n) in number of signals unless * g_dbus_interface_info_cache_build() has been used on @info. * - * Returns: (transfer none): A #GDBusSignalInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (nullable) (transfer none): A #GDBusSignalInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ @@ -2023,7 +2023,7 @@ g_dbus_interface_info_lookup_signal (GDBusInterfaceInfo *info, * The cost of this function is O(n) in number of properties unless * g_dbus_interface_info_cache_build() has been used on @info. * - * Returns: (transfer none): A #GDBusPropertyInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (nullable) (transfer none): A #GDBusPropertyInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ @@ -2165,7 +2165,7 @@ g_dbus_interface_info_cache_release (GDBusInterfaceInfo *info) * * The cost of this function is O(n) in number of interfaces. * - * Returns: (transfer none): A #GDBusInterfaceInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (nullable) (transfer none): A #GDBusInterfaceInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ diff --git a/gio/gdbusintrospection.h b/gio/gdbusintrospection.h index 14b171055e23936a3f92422c73cb3c5daaa2360a..f2e291787666b3703c69a544299da2a3bf32002f 100644 --- a/gio/gdbusintrospection.h +++ b/gio/gdbusintrospection.h @@ -43,7 +43,7 @@ G_BEGIN_DECLS struct _GDBusAnnotationInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *key; gchar *value; GDBusAnnotationInfo **annotations; @@ -63,7 +63,7 @@ struct _GDBusAnnotationInfo struct _GDBusArgInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *name; gchar *signature; GDBusAnnotationInfo **annotations; @@ -84,7 +84,7 @@ struct _GDBusArgInfo struct _GDBusMethodInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *name; GDBusArgInfo **in_args; GDBusArgInfo **out_args; @@ -105,7 +105,7 @@ struct _GDBusMethodInfo struct _GDBusSignalInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *name; GDBusArgInfo **args; GDBusAnnotationInfo **annotations; @@ -126,7 +126,7 @@ struct _GDBusSignalInfo struct _GDBusPropertyInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *name; gchar *signature; GDBusPropertyInfoFlags flags; @@ -149,7 +149,7 @@ struct _GDBusPropertyInfo struct _GDBusInterfaceInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *name; GDBusMethodInfo **methods; GDBusSignalInfo **signals; @@ -172,7 +172,7 @@ struct _GDBusInterfaceInfo struct _GDBusNodeInfo { /*< public >*/ - volatile gint ref_count; + gint ref_count; /* (atomic) */ gchar *path; GDBusInterfaceInfo **interfaces; GDBusNodeInfo **nodes; diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c index 6e3bd8bf40daf3dc0b4c4ec9bfe19f2c847b20e5..bc9386ee78e4276b50c24d847abb8b46054c075e 100644 --- a/gio/gdbusmessage.c +++ b/gio/gdbusmessage.c @@ -264,7 +264,7 @@ g_memory_buffer_write (GMemoryBuffer *mbuf, if (mbuf->pos + count > mbuf->len) { - /* At least enought to fit the write, rounded up + /* At least enough to fit the write, rounded up for greater than linear growth. TODO: This wastes a lot of memory at large buffer sizes. Figure out a more rational allocation strategy. */ @@ -877,7 +877,7 @@ g_dbus_message_set_message_type (GDBusMessage *message, GDBusMessageType type) { g_return_if_fail (G_IS_DBUS_MESSAGE (message)); - g_return_if_fail ((guint) type >= 0 && (guint) type < 256); + g_return_if_fail ((guint) type < 256); if (message->locked) { @@ -924,7 +924,7 @@ g_dbus_message_set_flags (GDBusMessage *message, GDBusMessageFlags flags) { g_return_if_fail (G_IS_DBUS_MESSAGE (message)); - g_return_if_fail ((guint) flags >= 0 && (guint) flags < 256); + g_return_if_fail ((guint) flags < 256); if (message->locked) { @@ -1002,7 +1002,7 @@ g_dbus_message_get_header (GDBusMessage *message, GDBusMessageHeaderField header_field) { g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL); - g_return_val_if_fail ((guint) header_field >= 0 && (guint) header_field < 256, NULL); + g_return_val_if_fail ((guint) header_field < 256, NULL); return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field)); } @@ -1024,7 +1024,7 @@ g_dbus_message_set_header (GDBusMessage *message, GVariant *value) { g_return_if_fail (G_IS_DBUS_MESSAGE (message)); - g_return_if_fail ((guint) header_field >= 0 && (guint) header_field < 256); + g_return_if_fail ((guint) header_field < 256); if (message->locked) { @@ -1085,7 +1085,7 @@ g_dbus_message_get_header_fields (GDBusMessage *message) * * Gets the body of a message. * - * Returns: (transfer none): A #GVariant or %NULL if the body is + * Returns: (nullable) (transfer none): A #GVariant or %NULL if the body is * empty. Do not free, it is owned by @message. * * Since: 2.26 @@ -1158,7 +1158,13 @@ g_dbus_message_set_body (GDBusMessage *message, * * This method is only available on UNIX. * - * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are + * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE + * values in the body of the message. For example, + * if g_variant_get_handle() returns 5, that is intended to be a reference + * to the file descriptor that can be accessed by + * `g_unix_fd_list_get (list, 5, ...)`. + * + * Returns: (nullable) (transfer none): A #GUnixFDList or %NULL if no file descriptors are * associated. Do not free, this object is owned by @message. * * Since: 2.26 @@ -1182,6 +1188,11 @@ g_dbus_message_get_unix_fd_list (GDBusMessage *message) * * This method is only available on UNIX. * + * When designing D-Bus APIs that are intended to be interoperable, + * please note that non-GDBus implementations of D-Bus can usually only + * access file descriptors if they are referenced by a value of type + * %G_VARIANT_TYPE_HANDLE in the body of the message. + * * Since: 2.26 */ void @@ -2786,7 +2797,7 @@ g_dbus_message_to_blob (GDBusMessage *message, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Message body has signature “%s” but there is no signature header"), - signature_str); + g_variant_get_type_string (message->body)); goto out; } tupled_signature_str = g_strdup_printf ("(%s)", signature_str); @@ -2796,7 +2807,7 @@ g_dbus_message_to_blob (GDBusMessage *message, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Message body has type signature “%s” but signature in the header field is “%s”"), - tupled_signature_str, g_variant_get_type_string (message->body)); + g_variant_get_type_string (message->body), tupled_signature_str); g_free (tupled_signature_str); goto out; } @@ -2983,7 +2994,7 @@ g_dbus_message_set_reply_serial (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field. * - * Returns: The value. + * Returns: (nullable): The value. * * Since: 2.26 */ @@ -2997,7 +3008,7 @@ g_dbus_message_get_interface (GDBusMessage *message) /** * g_dbus_message_set_interface: * @message: A #GDBusMessage. - * @value: The value to set. + * @value: (nullable): The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field. * @@ -3020,7 +3031,7 @@ g_dbus_message_set_interface (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field. * - * Returns: The value. + * Returns: (nullable): The value. * * Since: 2.26 */ @@ -3034,7 +3045,7 @@ g_dbus_message_get_member (GDBusMessage *message) /** * g_dbus_message_set_member: * @message: A #GDBusMessage. - * @value: The value to set. + * @value: (nullable): The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field. * @@ -3057,7 +3068,7 @@ g_dbus_message_set_member (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field. * - * Returns: The value. + * Returns: (nullable): The value. * * Since: 2.26 */ @@ -3071,7 +3082,7 @@ g_dbus_message_get_path (GDBusMessage *message) /** * g_dbus_message_set_path: * @message: A #GDBusMessage. - * @value: The value to set. + * @value: (nullable): The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field. * @@ -3094,7 +3105,7 @@ g_dbus_message_set_path (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field. * - * Returns: The value. + * Returns: (nullable): The value. * * Since: 2.26 */ @@ -3108,7 +3119,7 @@ g_dbus_message_get_sender (GDBusMessage *message) /** * g_dbus_message_set_sender: * @message: A #GDBusMessage. - * @value: The value to set. + * @value: (nullable): The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field. * @@ -3131,7 +3142,7 @@ g_dbus_message_set_sender (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field. * - * Returns: The value. + * Returns: (nullable): The value. * * Since: 2.26 */ @@ -3145,7 +3156,7 @@ g_dbus_message_get_destination (GDBusMessage *message) /** * g_dbus_message_set_destination: * @message: A #GDBusMessage. - * @value: The value to set. + * @value: (nullable): The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field. * @@ -3168,7 +3179,7 @@ g_dbus_message_set_destination (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field. * - * Returns: The value. + * Returns: (nullable): The value. * * Since: 2.26 */ @@ -3181,7 +3192,7 @@ g_dbus_message_get_error_name (GDBusMessage *message) /** * g_dbus_message_set_error_name: - * @message: A #GDBusMessage. + * @message: (nullable): A #GDBusMessage. * @value: The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field. @@ -3223,7 +3234,7 @@ g_dbus_message_get_signature (GDBusMessage *message) /** * g_dbus_message_set_signature: * @message: A #GDBusMessage. - * @value: The value to set. + * @value: (nullable): The value to set. * * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field. * @@ -3246,7 +3257,7 @@ g_dbus_message_set_signature (GDBusMessage *message, * * Convenience to get the first item in the body of @message. * - * Returns: The string item or %NULL if the first item in the body of + * Returns: (nullable): The string item or %NULL if the first item in the body of * @message is not a string. * * Since: 2.26 @@ -3378,7 +3389,7 @@ g_dbus_message_to_gerror (GDBusMessage *message, } else { - /* TOOD: this shouldn't happen - should check this at message serialization + /* TODO: this shouldn't happen - should check this at message serialization * time and disconnect the peer. */ g_set_error (error, diff --git a/gio/gdbusmethodinvocation.c b/gio/gdbusmethodinvocation.c index 18ae9d1be20c4fc70c994999cb8f34b0eb4f3ccc..c22e19ef0d12e05cde0378f040fc260a18652eda 100644 --- a/gio/gdbusmethodinvocation.c +++ b/gio/gdbusmethodinvocation.c @@ -194,7 +194,7 @@ g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation) * returned. See g_dbus_method_invocation_get_property_info() and * #GDBusInterfaceVTable for more information. * - * Returns: A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation. + * Returns: (nullable): A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation. * * Since: 2.26 */ @@ -221,7 +221,7 @@ g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation) * * If the call was GetAll, %NULL will be returned. * - * Returns: (transfer none): a #GDBusPropertyInfo or %NULL + * Returns: (nullable) (transfer none): a #GDBusPropertyInfo or %NULL * * Since: 2.38 */ diff --git a/gio/gdbusmethodinvocation.h b/gio/gdbusmethodinvocation.h index 061256ffe4dfe7b0702d6a030b9feee77ed016ce..775070a2c04aeb0fe692c6bd718ab99c31eee911 100644 --- a/gio/gdbusmethodinvocation.h +++ b/gio/gdbusmethodinvocation.h @@ -33,6 +33,41 @@ G_BEGIN_DECLS #define G_DBUS_METHOD_INVOCATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DBUS_METHOD_INVOCATION, GDBusMethodInvocation)) #define G_IS_DBUS_METHOD_INVOCATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_METHOD_INVOCATION)) +/** + * G_DBUS_METHOD_INVOCATION_HANDLED: + * + * The value returned by handlers of the signals generated by + * the `gdbus-codegen` tool to indicate that a method call has been + * handled by an implementation. It is equal to %TRUE, but using + * this macro is sometimes more readable. + * + * In code that needs to be backwards-compatible with older GLib, + * use %TRUE instead, often written like this: + * + * |[ + * g_dbus_method_invocation_return_error (invocation, ...); + * return TRUE; // handled + * ]| + * + * Since: 2.68 + */ +#define G_DBUS_METHOD_INVOCATION_HANDLED TRUE GLIB_AVAILABLE_MACRO_IN_2_68 + +/** + * G_DBUS_METHOD_INVOCATION_UNHANDLED: + * + * The value returned by handlers of the signals generated by + * the `gdbus-codegen` tool to indicate that a method call has not been + * handled by an implementation. It is equal to %FALSE, but using + * this macro is sometimes more readable. + * + * In code that needs to be backwards-compatible with older GLib, + * use %FALSE instead. + * + * Since: 2.68 + */ +#define G_DBUS_METHOD_INVOCATION_UNHANDLED FALSE GLIB_AVAILABLE_MACRO_IN_2_68 + GLIB_AVAILABLE_IN_ALL GType g_dbus_method_invocation_get_type (void) G_GNUC_CONST; GLIB_AVAILABLE_IN_ALL diff --git a/gio/gdbusnameowning.c b/gio/gdbusnameowning.c index 9764f24762c0ad412c9a72472fd07f175916164d..1130d6789cac233801f17b4b1798be969a901944 100644 --- a/gio/gdbusnameowning.c +++ b/gio/gdbusnameowning.c @@ -55,7 +55,7 @@ typedef enum typedef struct { - volatile gint ref_count; + gint ref_count; /* (atomic) */ guint id; GBusNameOwnerFlags flags; gchar *name; @@ -73,7 +73,7 @@ typedef struct guint name_acquired_subscription_id; guint name_lost_subscription_id; - volatile gboolean cancelled; /* must hold lock when reading or modifying */ + gboolean cancelled; /* must hold lock when reading or modifying */ gboolean needs_release; } Client; @@ -310,7 +310,7 @@ request_name_cb (GObject *source_object, Client *client = user_data; GVariant *result; guint32 request_name_reply; - gboolean subscribe; + gboolean unsubscribe; request_name_reply = 0; result = NULL; @@ -325,22 +325,18 @@ request_name_cb (GObject *source_object, g_variant_unref (result); } - subscribe = FALSE; + unsubscribe = FALSE; switch (request_name_reply) { case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */ /* We got the name - now listen for NameLost and NameAcquired */ call_acquired_handler (client); - subscribe = TRUE; - client->needs_release = TRUE; break; case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */ /* Waiting in line - listen for NameLost and NameAcquired */ call_lost_handler (client); - subscribe = TRUE; - client->needs_release = TRUE; break; default: @@ -349,48 +345,34 @@ request_name_cb (GObject *source_object, case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */ /* Some other part of the process is already owning the name */ call_lost_handler (client); + unsubscribe = TRUE; + client->needs_release = FALSE; break; } - - if (subscribe) + /* If we’re not the owner and not in the queue, there’s no point in continuing + * to listen to NameAcquired or NameLost. */ + if (unsubscribe) { GDBusConnection *connection = NULL; - /* if cancelled, there is no point in subscribing to signals - if not, make sure - * we use a known good Connection object since it may be set to NULL at any point - * after being cancelled + /* make sure we use a known good Connection object since it may be set to + * NULL at any point after being cancelled */ G_LOCK (lock); if (!client->cancelled) connection = g_object_ref (client->connection); G_UNLOCK (lock); - /* start listening to NameLost and NameAcquired messages */ if (connection != NULL) { - client->name_lost_subscription_id = - g_dbus_connection_signal_subscribe (connection, - "org.freedesktop.DBus", - "org.freedesktop.DBus", - "NameLost", - "/org/freedesktop/DBus", - client->name, - G_DBUS_SIGNAL_FLAGS_NONE, - on_name_lost_or_acquired, - client, - NULL); - client->name_acquired_subscription_id = - g_dbus_connection_signal_subscribe (connection, - "org.freedesktop.DBus", - "org.freedesktop.DBus", - "NameAcquired", - "/org/freedesktop/DBus", - client->name, - G_DBUS_SIGNAL_FLAGS_NONE, - on_name_lost_or_acquired, - client, - NULL); + if (client->name_acquired_subscription_id > 0) + g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id); + if (client->name_lost_subscription_id > 0) + g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id); + client->name_acquired_subscription_id = 0; + client->name_lost_subscription_id = 0; + g_object_unref (connection); } } @@ -434,7 +416,42 @@ has_connection (Client *client) G_CALLBACK (on_connection_disconnected), client); + /* Start listening to NameLost and NameAcquired messages. We hold + * references to the Client in the signal closures, since it’s possible + * for a signal to be in-flight after unsubscribing the signal handler. + * This creates a reference count cycle, but that’s explicitly broken by + * disconnecting the signal handlers before calling client_unref() in + * g_bus_unown_name(). + * + * Subscribe to NameLost and NameAcquired before calling RequestName() to + * avoid the potential race of losing the name between receiving a reply to + * RequestName() and subscribing to NameLost. The #PreviousCall state will + * ensure that the user callbacks get called an appropriate number of times. */ + client->name_lost_subscription_id = + g_dbus_connection_signal_subscribe (client->connection, + "org.freedesktop.DBus", + "org.freedesktop.DBus", + "NameLost", + "/org/freedesktop/DBus", + client->name, + G_DBUS_SIGNAL_FLAGS_NONE, + on_name_lost_or_acquired, + client_ref (client), + (GDestroyNotify) client_unref); + client->name_acquired_subscription_id = + g_dbus_connection_signal_subscribe (client->connection, + "org.freedesktop.DBus", + "org.freedesktop.DBus", + "NameAcquired", + "/org/freedesktop/DBus", + client->name, + G_DBUS_SIGNAL_FLAGS_NONE, + on_name_lost_or_acquired, + client_ref (client), + (GDestroyNotify) client_unref); + /* attempt to acquire the name */ + client->needs_release = TRUE; g_dbus_connection_call (client->connection, "org.freedesktop.DBus", /* bus name */ "/org/freedesktop/DBus", /* object path */ @@ -872,6 +889,13 @@ g_bus_own_name_on_connection_with_closures (GDBusConnection *connection, * * Stops owning a name. * + * Note that there may still be D-Bus traffic to process (relating to owning + * and unowning the name) in the current thread-default #GMainContext after + * this function has returned. You should continue to iterate the #GMainContext + * until the #GDestroyNotify function passed to g_bus_own_name() is called, in + * order to avoid memory leaks through callbacks queued on the #GMainContext + * after it’s stopped being iterated. + * * Since: 2.26 */ void @@ -939,6 +963,10 @@ g_bus_unown_name (guint owner_id) { g_warning ("Unexpected reply %d when releasing name %s", release_name_reply, client->name); } + else + { + client->needs_release = FALSE; + } g_variant_unref (result); } } diff --git a/gio/gdbusnamewatching.c b/gio/gdbusnamewatching.c index 3a97c50ee9fd77d111e8d26eff550562a7122a4b..8d24700c5839e149d79b5a898fe4b91105770846 100644 --- a/gio/gdbusnamewatching.c +++ b/gio/gdbusnamewatching.c @@ -56,7 +56,7 @@ typedef enum typedef struct { - volatile gint ref_count; + gint ref_count; /* (atomic) */ guint id; gchar *name; GBusNameWatcherFlags flags; @@ -78,7 +78,7 @@ typedef struct } Client; /* Must be accessed atomically. */ -static volatile guint next_global_id = 1; +static guint next_global_id = 1; /* (atomic) */ /* Must be accessed with @lock held. */ static GHashTable *map_id_to_client = NULL; @@ -148,6 +148,11 @@ call_handler_data_free (CallHandlerData *data) static void actually_do_call (Client *client, GDBusConnection *connection, const gchar *name_owner, CallType call_type) { + /* The client might have been cancelled (g_bus_unwatch_name()) while we were + * sitting in the #GMainContext dispatch queue. */ + if (client->cancelled) + return; + switch (call_type) { case CALL_TYPE_NAME_APPEARED: @@ -234,13 +239,12 @@ call_appeared_handler (Client *client) } static void -call_vanished_handler (Client *client, - gboolean ignore_cancelled) +call_vanished_handler (Client *client) { if (client->previous_call != PREVIOUS_CALL_VANISHED) { client->previous_call = PREVIOUS_CALL_VANISHED; - if (((!client->cancelled) || ignore_cancelled) && client->name_vanished_handler != NULL) + if (!client->cancelled && client->name_vanished_handler != NULL) { do_call (client, CALL_TYPE_NAME_VANISHED); } @@ -296,7 +300,7 @@ on_connection_disconnected (GDBusConnection *connection, client->name_owner_changed_subscription_id = 0; client->connection = NULL; - call_vanished_handler (client, FALSE); + call_vanished_handler (client); client_unref (client); } @@ -345,7 +349,7 @@ on_name_owner_changed (GDBusConnection *connection, { g_free (client->name_owner); client->name_owner = NULL; - call_vanished_handler (client, FALSE); + call_vanished_handler (client); } if (new_owner != NULL && strlen (new_owner) > 0) @@ -390,7 +394,7 @@ get_name_owner_cb (GObject *source_object, } else { - call_vanished_handler (client, FALSE); + call_vanished_handler (client); } client->initialized = TRUE; @@ -450,7 +454,7 @@ start_service_by_name_cb (GObject *source_object, else { g_warning ("Unexpected reply %d from StartServiceByName() method", start_service_result); - call_vanished_handler (client, FALSE); + call_vanished_handler (client); client->initialized = TRUE; } } @@ -529,7 +533,7 @@ connection_get_cb (GObject *source_object, client->connection = g_bus_get_finish (res, NULL); if (client->connection == NULL) { - call_vanished_handler (client, FALSE); + call_vanished_handler (client); goto out; } @@ -603,7 +607,7 @@ g_bus_watch_name (GBusType bus_type, client = g_new0 (Client, 1); client->ref_count = 1; - client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */ + client->id = (guint) g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */ client->name = g_strdup (name); client->flags = flags; client->name_appeared_handler = name_appeared_handler; @@ -665,7 +669,7 @@ guint g_bus_watch_name_on_connection (GDBusConnection *connection, client = g_new0 (Client, 1); client->ref_count = 1; - client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */ + client->id = (guint) g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */ client->name = g_strdup (name); client->flags = flags; client->name_appeared_handler = name_appeared_handler; @@ -854,6 +858,13 @@ guint g_bus_watch_name_on_connection_with_closures ( * * Stops watching a name. * + * Note that there may still be D-Bus traffic to process (relating to watching + * and unwatching the name) in the current thread-default #GMainContext after + * this function has returned. You should continue to iterate the #GMainContext + * until the #GDestroyNotify function passed to g_bus_watch_name() is called, in + * order to avoid memory leaks through callbacks queued on the #GMainContext + * after it’s stopped being iterated. + * * Since: 2.26 */ void diff --git a/gio/gdbusobject.c b/gio/gdbusobject.c index 32393edf6e0df3504b2cb94a76d4d2ad18b42320..c332720c0b966c8e130f5440f0723f249c6e6a65 100644 --- a/gio/gdbusobject.c +++ b/gio/gdbusobject.c @@ -137,7 +137,7 @@ g_dbus_object_get_interfaces (GDBusObject *object) * Gets the D-Bus interface with name @interface_name associated with * @object, if any. * - * Returns: (transfer full): %NULL if not found, otherwise a + * Returns: (nullable) (transfer full): %NULL if not found, otherwise a * #GDBusInterface that must be freed with g_object_unref(). * * Since: 2.30 diff --git a/gio/gdbusobjectmanagerclient.c b/gio/gdbusobjectmanagerclient.c index 38e6f539f526da9e343b8a1355564d41188309d7..88fcff4faaf0e352f842445868eb274176a499e7 100644 --- a/gio/gdbusobjectmanagerclient.c +++ b/gio/gdbusobjectmanagerclient.c @@ -141,6 +141,9 @@ struct _GDBusObjectManagerClientPrivate GDBusProxyTypeFunc get_proxy_type_func; gpointer get_proxy_type_user_data; GDestroyNotify get_proxy_type_destroy_notify; + + gulong name_owner_signal_id; + gulong signal_signal_id; }; enum @@ -197,13 +200,18 @@ g_dbus_object_manager_client_finalize (GObject *object) g_hash_table_unref (manager->priv->map_object_path_to_object_proxy); - if (manager->priv->control_proxy != NULL) - { - g_signal_handlers_disconnect_by_func (manager->priv->control_proxy, - on_control_proxy_g_signal, - manager); - g_object_unref (manager->priv->control_proxy); - } + if (manager->priv->control_proxy != NULL && manager->priv->signal_signal_id != 0) + g_signal_handler_disconnect (manager->priv->control_proxy, + manager->priv->signal_signal_id); + manager->priv->signal_signal_id = 0; + + if (manager->priv->control_proxy != NULL && manager->priv->name_owner_signal_id != 0) + g_signal_handler_disconnect (manager->priv->control_proxy, + manager->priv->name_owner_signal_id); + manager->priv->name_owner_signal_id = 0; + + g_clear_object (&manager->priv->control_proxy); + if (manager->priv->connection != NULL) g_object_unref (manager->priv->connection); g_free (manager->priv->object_path); @@ -1156,7 +1164,7 @@ subscribe_signals (GDBusObjectManagerClient *manager, name_owner, NULL, /* interface */ NULL, /* member */ - NULL, /* path - TODO: really want wilcard support here */ + NULL, /* path - TODO: really want wildcard support here */ NULL, /* arg0 */ G_DBUS_SIGNAL_FLAGS_NONE | G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, @@ -1189,7 +1197,7 @@ subscribe_signals (GDBusObjectManagerClient *manager, name_owner, NULL, /* interface */ NULL, /* member */ - NULL, /* path - TODO: really want wilcard support here */ + NULL, /* path - TODO: really want wildcard support here */ NULL, /* arg0 */ G_DBUS_SIGNAL_FLAGS_NONE, signal_cb, @@ -1241,16 +1249,20 @@ on_notify_g_name_owner (GObject *object, GParamSpec *pspec, gpointer user_data) { - GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data); + GWeakRef *manager_weak = user_data; + GDBusObjectManagerClient *manager = NULL; gchar *old_name_owner; gchar *new_name_owner; + manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak)); + if (manager == NULL) + return; + g_mutex_lock (&manager->priv->lock); old_name_owner = manager->priv->name_owner; new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy); manager->priv->name_owner = NULL; - g_object_ref (manager); if (g_strcmp0 (old_name_owner, new_name_owner) != 0) { GList *l; @@ -1330,6 +1342,21 @@ on_notify_g_name_owner (GObject *object, g_object_unref (manager); } +static GWeakRef * +weak_ref_new (GObject *object) +{ + GWeakRef *weak_ref = g_new0 (GWeakRef, 1); + g_weak_ref_init (weak_ref, object); + return g_steal_pointer (&weak_ref); +} + +static void +weak_ref_free (GWeakRef *weak_ref) +{ + g_weak_ref_clear (weak_ref); + g_free (weak_ref); +} + static gboolean initable_init (GInitable *initable, GCancellable *cancellable, @@ -1365,15 +1392,30 @@ initable_init (GInitable *initable, if (manager->priv->control_proxy == NULL) goto out; - g_signal_connect (G_OBJECT (manager->priv->control_proxy), - "notify::g-name-owner", - G_CALLBACK (on_notify_g_name_owner), - manager); - - g_signal_connect (manager->priv->control_proxy, - "g-signal", - G_CALLBACK (on_control_proxy_g_signal), - manager); + /* Use weak refs here. The @control_proxy will emit its signals in the current + * #GMainContext (since we constructed it just above). However, the user may + * drop the last external reference to this #GDBusObjectManagerClient in + * another thread between a signal being emitted and scheduled in an idle + * callback in this #GMainContext, and that idle callback being invoked. We + * can’t use a strong reference here, as there’s no + * g_dbus_object_manager_client_disconnect() (or similar) method to tell us + * when the last external reference to this object has been dropped, so we + * can’t break a strong reference count cycle. So use weak refs. */ + manager->priv->name_owner_signal_id = + g_signal_connect_data (G_OBJECT (manager->priv->control_proxy), + "notify::g-name-owner", + G_CALLBACK (on_notify_g_name_owner), + weak_ref_new (G_OBJECT (manager)), + (GClosureNotify) weak_ref_free, + 0 /* flags */); + + manager->priv->signal_signal_id = + g_signal_connect_data (manager->priv->control_proxy, + "g-signal", + G_CALLBACK (on_control_proxy_g_signal), + weak_ref_new (G_OBJECT (manager)), + (GClosureNotify) weak_ref_free, + 0 /* flags */); manager->priv->name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy); if (manager->priv->name_owner == NULL && manager->priv->name != NULL) @@ -1397,11 +1439,20 @@ initable_init (GInitable *initable, if (value == NULL) { maybe_unsubscribe_signals (manager); - g_warn_if_fail (g_signal_handlers_disconnect_by_func (manager->priv->control_proxy, - on_control_proxy_g_signal, - manager) == 1); + + g_warn_if_fail (manager->priv->signal_signal_id != 0); + g_signal_handler_disconnect (manager->priv->control_proxy, + manager->priv->signal_signal_id); + manager->priv->signal_signal_id = 0; + + g_warn_if_fail (manager->priv->name_owner_signal_id != 0); + g_signal_handler_disconnect (manager->priv->control_proxy, + manager->priv->name_owner_signal_id); + manager->priv->name_owner_signal_id = 0; + g_object_unref (manager->priv->control_proxy); manager->priv->control_proxy = NULL; + goto out; } @@ -1668,9 +1719,14 @@ on_control_proxy_g_signal (GDBusProxy *proxy, GVariant *parameters, gpointer user_data) { - GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data); + GWeakRef *manager_weak = user_data; + GDBusObjectManagerClient *manager = NULL; const gchar *object_path; + manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak)); + if (manager == NULL) + return; + //g_debug ("yay, g_signal %s: %s\n", signal_name, g_variant_print (parameters, TRUE)); if (g_strcmp0 (signal_name, "InterfacesAdded") == 0) @@ -1693,6 +1749,8 @@ on_control_proxy_g_signal (GDBusProxy *proxy, remove_interfaces (manager, object_path, ifaces); g_free (ifaces); } + + g_object_unref (manager); } /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/gdbusobjectmanagerserver.c b/gio/gdbusobjectmanagerserver.c index 273629dec030ae16894af397f97598e84513c7a4..39f4ed5006424f6790cb38f027feacf9fef596f4 100644 --- a/gio/gdbusobjectmanagerserver.c +++ b/gio/gdbusobjectmanagerserver.c @@ -888,7 +888,8 @@ static const GDBusInterfaceVTable manager_interface_vtable = { manager_method_call, /* handle_method_call */ NULL, /* get_property */ - NULL /* set_property */ + NULL, /* set_property */ + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c index 302c30b42d8693c60a2e4a138ca9dce0b84ffa21..282678f3bc30abc1c17c2d45eee6e8a724a62acb 100644 --- a/gio/gdbusprivate.c +++ b/gio/gdbusprivate.c @@ -183,6 +183,7 @@ _g_socket_read_with_control_messages (GSocket *socket, task = g_task_new (socket, cancellable, callback, user_data); g_task_set_source_tag (task, _g_socket_read_with_control_messages); + g_task_set_name (task, "[gio] D-Bus read"); g_task_set_task_data (task, data, (GDestroyNotify) read_with_control_data_free); if (g_socket_condition_check (socket, G_IO_IN)) @@ -264,7 +265,7 @@ ensure_required_types (void) typedef struct { - volatile gint refcount; + gint refcount; /* (atomic) */ GThread *thread; GMainContext *context; GMainLoop *loop; @@ -340,12 +341,12 @@ typedef enum { struct GDBusWorker { - volatile gint ref_count; + gint ref_count; /* (atomic) */ SharedThreadData *shared_thread_data; /* really a boolean, but GLib 2.28 lacks atomic boolean ops */ - volatile gint stopped; + gint stopped; /* (atomic) */ /* TODO: frozen (e.g. G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) currently * only affects messages received from the other peer (since GDBusServer is the @@ -1084,8 +1085,11 @@ write_message_continue_writing (MessageToWriteData *data) else { #ifdef G_OS_UNIX - if (fd_list != NULL) + if (data->total_written == 0 && fd_list != NULL) { + /* We were trying to write byte 0 of the message, which needs + * the fd list to be attached to it, but this connection doesn't + * support doing that. */ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -1123,6 +1127,7 @@ write_message_async (GDBusWorker *worker, { data->task = g_task_new (NULL, NULL, callback, user_data); g_task_set_source_tag (data->task, write_message_async); + g_task_set_name (data->task, "[gio] D-Bus write message"); data->total_written = 0; write_message_continue_writing (data); } @@ -1504,7 +1509,7 @@ continue_writing (GDBusWorker *worker) } else { - /* filters altered the message -> reencode */ + /* filters altered the message -> re-encode */ error = NULL; new_blob = g_dbus_message_to_blob (data->message, &new_blob_size, @@ -1936,15 +1941,14 @@ _g_dbus_debug_print_unlock (void) void _g_dbus_initialize (void) { - static volatile gsize initialized = 0; + static gsize initialized = 0; if (g_once_init_enter (&initialized)) { - volatile GQuark g_dbus_error_domain; const gchar *debug; - g_dbus_error_domain = G_DBUS_ERROR; - (g_dbus_error_domain); /* To avoid -Wunused-but-set-variable */ + /* Ensure the domain is registered. */ + g_dbus_error_quark (); debug = g_getenv ("G_DBUS_DEBUG"); if (debug != NULL) @@ -2466,31 +2470,63 @@ _g_dbus_get_machine_id (GError **error) return res; #else - gchar *ret; - GError *first_error; - /* TODO: use PACKAGE_LOCALSTATEDIR ? */ - ret = NULL; - first_error = NULL; - if (!g_file_get_contents ("/var/lib/dbus/machine-id", + gchar *ret = NULL; + GError *first_error = NULL; + gsize i; + gboolean non_zero = FALSE; + + /* Copy what dbus.git does: allow the /var/lib path to be configurable at + * build time, but hard-code the system-wide machine ID path in /etc. */ + const gchar *var_lib_path = LOCALSTATEDIR "/lib/dbus/machine-id"; + const gchar *etc_path = "/etc/machine-id"; + + if (!g_file_get_contents (var_lib_path, &ret, NULL, &first_error) && - !g_file_get_contents ("/etc/machine-id", + !g_file_get_contents (etc_path, &ret, NULL, NULL)) { - g_propagate_prefixed_error (error, first_error, - _("Unable to load /var/lib/dbus/machine-id or /etc/machine-id: ")); + g_propagate_prefixed_error (error, g_steal_pointer (&first_error), + /* Translators: Both placeholders are file paths */ + _("Unable to load %s or %s: "), + var_lib_path, etc_path); + return NULL; } - else + + /* ignore the error from the first try, if any */ + g_clear_error (&first_error); + + /* Validate the machine ID. From `man 5 machine-id`: + * > The machine ID is a single newline-terminated, hexadecimal, 32-character, + * > lowercase ID. When decoded from hexadecimal, this corresponds to a + * > 16-byte/128-bit value. This ID may not be all zeros. + */ + for (i = 0; ret[i] != '\0' && ret[i] != '\n'; i++) { - /* ignore the error from the first try, if any */ - g_clear_error (&first_error); - /* TODO: validate value */ - g_strstrip (ret); + /* Break early if it’s invalid. */ + if (!g_ascii_isxdigit (ret[i]) || g_ascii_isupper (ret[i])) + break; + + if (ret[i] != '0') + non_zero = TRUE; } - return ret; + + if (i != 32 || ret[i] != '\n' || ret[i + 1] != '\0' || !non_zero) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Invalid machine ID in %s or %s", + var_lib_path, etc_path); + g_free (ret); + return NULL; + } + + /* Strip trailing newline. */ + ret[32] = '\0'; + + return g_steal_pointer (&ret); #endif } diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c index 39eed1688708719dcd17582987e1ba69b15b052f..45fa99a17dd4ecfaa1502515c554a657f3de36a0 100644 --- a/gio/gdbusproxy.c +++ b/gio/gdbusproxy.c @@ -95,28 +95,19 @@ G_LOCK_DEFINE_STATIC (properties_lock); /* ---------------------------------------------------------------------------------------------------- */ -G_LOCK_DEFINE_STATIC (signal_subscription_lock); - -typedef struct -{ - volatile gint ref_count; - GDBusProxy *proxy; -} SignalSubscriptionData; - -static SignalSubscriptionData * -signal_subscription_ref (SignalSubscriptionData *data) +static GWeakRef * +weak_ref_new (GObject *object) { - g_atomic_int_inc (&data->ref_count); - return data; + GWeakRef *weak_ref = g_new0 (GWeakRef, 1); + g_weak_ref_init (weak_ref, object); + return g_steal_pointer (&weak_ref); } static void -signal_subscription_unref (SignalSubscriptionData *data) +weak_ref_free (GWeakRef *weak_ref) { - if (g_atomic_int_dec_and_test (&data->ref_count)) - { - g_slice_free (SignalSubscriptionData, data); - } + g_weak_ref_clear (weak_ref); + g_free (weak_ref); } /* ---------------------------------------------------------------------------------------------------- */ @@ -152,8 +143,6 @@ struct _GDBusProxyPrivate /* mutable, protected by properties_lock */ GDBusObject *object; - - SignalSubscriptionData *signal_subscription_data; }; enum @@ -189,22 +178,6 @@ G_DEFINE_TYPE_WITH_CODE (GDBusProxy, g_dbus_proxy, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)) -static void -g_dbus_proxy_dispose (GObject *object) -{ - GDBusProxy *proxy = G_DBUS_PROXY (object); - G_LOCK (signal_subscription_lock); - if (proxy->priv->signal_subscription_data != NULL) - { - proxy->priv->signal_subscription_data->proxy = NULL; - signal_subscription_unref (proxy->priv->signal_subscription_data); - proxy->priv->signal_subscription_data = NULL; - } - G_UNLOCK (signal_subscription_lock); - - G_OBJECT_CLASS (g_dbus_proxy_parent_class)->dispose (object); -} - static void g_dbus_proxy_finalize (GObject *object) { @@ -346,7 +319,6 @@ g_dbus_proxy_class_init (GDBusProxyClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->dispose = g_dbus_proxy_dispose; gobject_class->finalize = g_dbus_proxy_finalize; gobject_class->set_property = g_dbus_proxy_set_property; gobject_class->get_property = g_dbus_proxy_get_property; @@ -638,9 +610,6 @@ static void g_dbus_proxy_init (GDBusProxy *proxy) { proxy->priv = g_dbus_proxy_get_instance_private (proxy); - proxy->priv->signal_subscription_data = g_slice_new0 (SignalSubscriptionData); - proxy->priv->signal_subscription_data->ref_count = 1; - proxy->priv->signal_subscription_data->proxy = proxy; proxy->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, @@ -868,21 +837,12 @@ on_signal_received (GDBusConnection *connection, GVariant *parameters, gpointer user_data) { - SignalSubscriptionData *data = user_data; + GWeakRef *proxy_weak = user_data; GDBusProxy *proxy; - G_LOCK (signal_subscription_lock); - proxy = data->proxy; + proxy = G_DBUS_PROXY (g_weak_ref_get (proxy_weak)); if (proxy == NULL) - { - G_UNLOCK (signal_subscription_lock); - return; - } - else - { - g_object_ref (proxy); - G_UNLOCK (signal_subscription_lock); - } + return; if (!proxy->priv->initialized) goto out; @@ -929,8 +889,7 @@ on_signal_received (GDBusConnection *connection, parameters); out: - if (proxy != NULL) - g_object_unref (proxy); + g_clear_object (&proxy); } /* ---------------------------------------------------------------------------------------------------- */ @@ -1038,7 +997,7 @@ on_properties_changed (GDBusConnection *connection, GVariant *parameters, gpointer user_data) { - SignalSubscriptionData *data = user_data; + GWeakRef *proxy_weak = user_data; gboolean emit_g_signal = FALSE; GDBusProxy *proxy; const gchar *interface_name_for_signal; @@ -1052,18 +1011,9 @@ on_properties_changed (GDBusConnection *connection, changed_properties = NULL; invalidated_properties = NULL; - G_LOCK (signal_subscription_lock); - proxy = data->proxy; + proxy = G_DBUS_PROXY (g_weak_ref_get (proxy_weak)); if (proxy == NULL) - { - G_UNLOCK (signal_subscription_lock); - goto out; - } - else - { - g_object_ref (proxy); - G_UNLOCK (signal_subscription_lock); - } + return; if (!proxy->priv->initialized) goto out; @@ -1150,11 +1100,9 @@ on_properties_changed (GDBusConnection *connection, } out: - if (changed_properties != NULL) - g_variant_unref (changed_properties); + g_clear_pointer (&changed_properties, g_variant_unref); g_free (invalidated_properties); - if (proxy != NULL) - g_object_unref (proxy); + g_clear_object (&proxy); } /* ---------------------------------------------------------------------------------------------------- */ @@ -1258,8 +1206,7 @@ on_name_owner_changed_get_all_cb (GDBusConnection *connection, { G_LOCK (properties_lock); g_free (data->proxy->priv->name_owner); - data->proxy->priv->name_owner = data->name_owner; - data->name_owner = NULL; /* to avoid an extra copy, we steal the string */ + data->proxy->priv->name_owner = g_steal_pointer (&data->name_owner); g_hash_table_remove_all (data->proxy->priv->properties); G_UNLOCK (properties_lock); if (result != NULL) @@ -1289,23 +1236,14 @@ on_name_owner_changed (GDBusConnection *connection, GVariant *parameters, gpointer user_data) { - SignalSubscriptionData *data = user_data; + GWeakRef *proxy_weak = user_data; GDBusProxy *proxy; const gchar *old_owner; const gchar *new_owner; - G_LOCK (signal_subscription_lock); - proxy = data->proxy; + proxy = G_DBUS_PROXY (g_weak_ref_get (proxy_weak)); if (proxy == NULL) - { - G_UNLOCK (signal_subscription_lock); - goto out; - } - else - { - g_object_ref (proxy); - G_UNLOCK (signal_subscription_lock); - } + return; /* if we are already trying to load properties, cancel that */ if (proxy->priv->get_all_cancellable != NULL) @@ -1415,8 +1353,7 @@ on_name_owner_changed (GDBusConnection *connection, } out: - if (proxy != NULL) - g_object_unref (proxy); + g_clear_object (&proxy); } /* ---------------------------------------------------------------------------------------------------- */ @@ -1694,6 +1631,7 @@ async_initable_init_second_async (GAsyncInitable *initable, task = g_task_new (proxy, cancellable, callback, user_data); g_task_set_source_tag (task, async_initable_init_second_async); + g_task_set_name (task, "[gio] D-Bus proxy init"); g_task_set_priority (task, io_priority); /* Check name ownership asynchronously - possibly also start the service */ @@ -1762,8 +1700,8 @@ async_initable_init_first (GAsyncInitable *initable) proxy->priv->interface_name, G_DBUS_SIGNAL_FLAGS_NONE, on_properties_changed, - signal_subscription_ref (proxy->priv->signal_subscription_data), - (GDestroyNotify) signal_subscription_unref); + weak_ref_new (G_OBJECT (proxy)), + (GDestroyNotify) weak_ref_free); } if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS)) @@ -1778,8 +1716,8 @@ async_initable_init_first (GAsyncInitable *initable) NULL, /* arg0 */ G_DBUS_SIGNAL_FLAGS_NONE, on_signal_received, - signal_subscription_ref (proxy->priv->signal_subscription_data), - (GDestroyNotify) signal_subscription_unref); + weak_ref_new (G_OBJECT (proxy)), + (GDestroyNotify) weak_ref_free); } if (proxy->priv->name != NULL && @@ -1794,8 +1732,8 @@ async_initable_init_first (GAsyncInitable *initable) proxy->priv->name, /* arg0 */ G_DBUS_SIGNAL_FLAGS_NONE, on_name_owner_changed, - signal_subscription_ref (proxy->priv->signal_subscription_data), - (GDestroyNotify) signal_subscription_unref); + weak_ref_new (G_OBJECT (proxy)), + (GDestroyNotify) weak_ref_free); } } @@ -1865,6 +1803,7 @@ async_initable_init_async (GAsyncInitable *initable, task = g_task_new (proxy, cancellable, callback, user_data); g_task_set_source_tag (task, async_initable_init_async); + g_task_set_name (task, "[gio] D-Bus proxy init"); g_task_set_priority (task, io_priority); if (proxy->priv->bus_type != G_BUS_TYPE_NONE) @@ -2712,6 +2651,7 @@ g_dbus_proxy_call_internal (GDBusProxy *proxy, my_callback = (GAsyncReadyCallback) reply_cb; task = g_task_new (proxy, cancellable, callback, user_data); g_task_set_source_tag (task, g_dbus_proxy_call_internal); + g_task_set_name (task, "[gio] D-Bus proxy call"); } else { diff --git a/gio/gdbusserver.c b/gio/gdbusserver.c index 4a8dab0ea16ec7089a290b9295115a307703d91c..3cf98587bd7fa3843244af2f4948d093ca865770 100644 --- a/gio/gdbusserver.c +++ b/gio/gdbusserver.c @@ -57,6 +57,11 @@ #include "glibintl.h" +#define G_DBUS_SERVER_FLAGS_ALL \ + (G_DBUS_SERVER_FLAGS_RUN_IN_THREAD | \ + G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \ + G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER) + /** * SECTION:gdbusserver * @short_description: Helper for accepting connections @@ -71,13 +76,15 @@ * To just export an object on a well-known name on a message bus, such as the * session or system bus, you should instead use g_bus_own_name(). * - * An example of peer-to-peer communication with G-DBus can be found + * An example of peer-to-peer communication with GDBus can be found * in [gdbus-example-peer.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-peer.c). * * Note that a minimal #GDBusServer will accept connections from any * peer. In many use-cases it will be necessary to add a #GDBusAuthObserver * that only accepts connections that have successfully authenticated - * as the same user that is running the #GDBusServer. + * as the same user that is running the #GDBusServer. Since GLib 2.68 this can + * be achieved more simply by passing the + * %G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flag to the server. */ /** @@ -512,6 +519,7 @@ g_dbus_server_new_sync (const gchar *address, g_return_val_if_fail (address != NULL, NULL); g_return_val_if_fail (g_dbus_is_guid (guid), NULL); + g_return_val_if_fail ((flags & ~G_DBUS_SERVER_FLAGS_ALL) == 0, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); server = g_initable_new (G_TYPE_DBUS_SERVER, @@ -1032,6 +1040,8 @@ on_run (GSocketService *service, G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING; if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; + if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER) + connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER; connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection), server->guid, diff --git a/gio/gdbusutils.c b/gio/gdbusutils.c index ff9b441170d05efd855d79d0e162f9bc0e664b0b..bb34e2d5830108c7c4331d0409d618cf62f532d5 100644 --- a/gio/gdbusutils.c +++ b/gio/gdbusutils.c @@ -533,9 +533,9 @@ g_dbus_gvariant_to_gvalue (GVariant *value, * See the g_dbus_gvariant_to_gvalue() function for how to convert a * #GVariant to a #GValue. * - * Returns: A #GVariant (never floating) of #GVariantType @type holding - * the data from @gvalue or %NULL in case of failure. Free with - * g_variant_unref(). + * Returns: (transfer full): A #GVariant (never floating) of + * #GVariantType @type holding the data from @gvalue or an empty #GVariant + * in case of failure. Free with g_variant_unref(). * * Since: 2.30 */ @@ -693,3 +693,127 @@ g_dbus_gvalue_to_gvariant (const GValue *gvalue, return ret; } + +/** + * g_dbus_escape_object_path_bytestring: + * @bytes: (array zero-terminated=1) (element-type guint8): the string of bytes to escape + * + * Escapes @bytes for use in a D-Bus object path component. + * @bytes is an array of zero or more nonzero bytes in an + * unspecified encoding, followed by a single zero byte. + * + * The escaping method consists of replacing all non-alphanumeric + * characters (see g_ascii_isalnum()) with their hexadecimal value + * preceded by an underscore (`_`). For example: + * `foo.bar.baz` will become `foo_2ebar_2ebaz`. + * + * This method is appropriate to use when the input is nearly + * a valid object path component but is not when your input + * is far from being a valid object path component. + * Other escaping algorithms are also valid to use with + * D-Bus object paths. + * + * This can be reversed with g_dbus_unescape_object_path(). + * + * Returns: an escaped version of @bytes. Free with g_free(). + * + * Since: 2.68 + * + */ +gchar * +g_dbus_escape_object_path_bytestring (const guint8 *bytes) +{ + GString *escaped; + const guint8 *p; + + g_return_val_if_fail (bytes != NULL, NULL); + + if (*bytes == '\0') + return g_strdup ("_"); + + escaped = g_string_new (NULL); + for (p = bytes; *p; p++) + { + if (g_ascii_isalnum (*p)) + g_string_append_c (escaped, *p); + else + g_string_append_printf (escaped, "_%02x", *p); + } + + return g_string_free (escaped, FALSE); +} + +/** + * g_dbus_escape_object_path: + * @s: the string to escape + * + * This is a language binding friendly version of g_dbus_escape_object_path_bytestring(). + * + * Returns: an escaped version of @s. Free with g_free(). + * + * Since: 2.68 + */ +gchar * +g_dbus_escape_object_path (const gchar *s) +{ + return (gchar *) g_dbus_escape_object_path_bytestring ((const guint8 *) s); +} + +/** + * g_dbus_unescape_object_path: + * @s: the string to unescape + * + * Unescapes an string that was previously escaped with + * g_dbus_escape_object_path(). If the string is in a format that could + * not have been returned by g_dbus_escape_object_path(), this function + * returns %NULL. + * + * Encoding alphanumeric characters which do not need to be + * encoded is not allowed (e.g `_63` is not valid, the string + * should contain `c` instead). + * + * Returns: (array zero-terminated=1) (element-type guint8) (nullable): an + * unescaped version of @s, or %NULL if @s is not a string returned + * from g_dbus_escape_object_path(). Free with g_free(). + * + * Since: 2.68 + */ +guint8 * +g_dbus_unescape_object_path (const gchar *s) +{ + GString *unescaped; + const gchar *p; + + g_return_val_if_fail (s != NULL, NULL); + + if (g_str_equal (s, "_")) + return (guint8 *) g_strdup (""); + + unescaped = g_string_new (NULL); + for (p = s; *p; p++) + { + gint hi, lo; + + if (g_ascii_isalnum (*p)) + { + g_string_append_c (unescaped, *p); + } + else if (*p == '_' && + ((hi = g_ascii_xdigit_value (p[1])) >= 0) && + ((lo = g_ascii_xdigit_value (p[2])) >= 0) && + (hi || lo) && /* \0 is not allowed */ + !g_ascii_isalnum ((hi << 4) | lo)) /* alnums must not be encoded */ + { + g_string_append_c (unescaped, (hi << 4) | lo); + p += 2; + } + else + { + /* the string was not encoded correctly */ + g_string_free (unescaped, TRUE); + return NULL; + } + } + + return (guint8 *) g_string_free (unescaped, FALSE); +} diff --git a/gio/gdbusutils.h b/gio/gdbusutils.h index 5aecb5142181778283465d82f4956c65ef204207..fd7358fcf81af48e9287a63df2c568893e938bbd 100644 --- a/gio/gdbusutils.h +++ b/gio/gdbusutils.h @@ -49,6 +49,12 @@ void g_dbus_gvariant_to_gvalue (GVariant *value, GLIB_AVAILABLE_IN_ALL GVariant *g_dbus_gvalue_to_gvariant (const GValue *gvalue, const GVariantType *type); +GLIB_AVAILABLE_IN_2_68 +gchar *g_dbus_escape_object_path_bytestring (const guint8 *bytes); +GLIB_AVAILABLE_IN_2_68 +gchar *g_dbus_escape_object_path (const gchar *s); +GLIB_AVAILABLE_IN_2_68 +guint8 *g_dbus_unescape_object_path (const gchar *s); G_END_DECLS diff --git a/gio/gdelayedsettingsbackend.c b/gio/gdelayedsettingsbackend.c index 9ba3c5b64bd46cc20cfc09630e20a336662bb7c5..93ced25dbdea6051adbbcbc7ea92e395b40337ef 100644 --- a/gio/gdelayedsettingsbackend.c +++ b/gio/gdelayedsettingsbackend.c @@ -403,7 +403,7 @@ delayed_backend_path_writable_changed (GObject *target, if (n_keys > 0) { - CheckPrefixState state = { path, g_new (const gchar *, n_keys) }; + CheckPrefixState state = { path, g_new (const gchar *, n_keys), 0 }; gsize i; /* collect a list of possibly-affected keys (ie: matching the path) */ diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index f1e2fdd653c6b1601fe2d1b5e67dd6bb2b5d3abd..1a4b979181d1be04726a30e4115ab9756c10106d 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -26,7 +26,9 @@ /* For the #GDesktopAppInfoLookup macros; since macro deprecation is implemented * in the preprocessor, we need to define this before including glib.h*/ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include #include @@ -160,7 +162,6 @@ static const gchar *desktop_file_dirs_config_dir = NULL; static DesktopFileDir *desktop_file_dir_user_config = NULL; /* (owned) */ static DesktopFileDir *desktop_file_dir_user_data = NULL; /* (owned) */ static GMutex desktop_file_dir_lock; -static const gchar *gio_launch_desktop_path = NULL; /* Monitor 'changed' signal handler {{{2 */ static void desktop_file_dir_reset (DesktopFileDir *dir); @@ -304,6 +305,55 @@ desktop_file_dir_app_name_is_masked (DesktopFileDir *dir, return FALSE; } +/* Not much to go on from https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html + * so validate it as a non-empty alphanumeric ASCII string with `-` and `_` allowed. + * + * Validation is important as the desktop IDs are used to construct filenames, + * and may be set by an unprivileged caller if running in a setuid program. */ +static gboolean +validate_xdg_desktop (const gchar *desktop) +{ + gsize i; + + for (i = 0; desktop[i] != '\0'; i++) + if (desktop[i] != '-' && desktop[i] != '_' && + !g_ascii_isalnum (desktop[i])) + return FALSE; + + if (i == 0) + return FALSE; + + return TRUE; +} + +static char ** +get_valid_current_desktops (const char *value) +{ + char **tmp; + gsize i; + GPtrArray *valid_desktops; + + if (value == NULL) + value = g_getenv ("XDG_CURRENT_DESKTOP"); + if (value == NULL) + value = ""; + + tmp = g_strsplit (value, G_SEARCHPATH_SEPARATOR_S, 0); + valid_desktops = g_ptr_array_new_full (g_strv_length (tmp) + 1, g_free); + for (i = 0; tmp[i]; i++) + { + if (validate_xdg_desktop (tmp[i])) + g_ptr_array_add (valid_desktops, tmp[i]); + else + g_free (tmp[i]); + } + g_ptr_array_add (valid_desktops, NULL); + g_free (tmp); + tmp = (char **) g_ptr_array_steal (valid_desktops, NULL); + g_ptr_array_unref (valid_desktops); + return tmp; +} + static const gchar * const * get_lowercase_current_desktops (void) { @@ -311,23 +361,15 @@ get_lowercase_current_desktops (void) if (g_once_init_enter (&result)) { - const gchar *envvar; - gchar **tmp; - - envvar = g_getenv ("XDG_CURRENT_DESKTOP"); + char **tmp = get_valid_current_desktops (NULL); + gsize i, j; - if (envvar) + for (i = 0; tmp[i]; i++) { - gint i, j; - - tmp = g_strsplit (envvar, G_SEARCHPATH_SEPARATOR_S, 0); - - for (i = 0; tmp[i]; i++) - for (j = 0; tmp[i][j]; j++) - tmp[i][j] = g_ascii_tolower (tmp[i][j]); + /* Convert to lowercase. */ + for (j = 0; tmp[i][j]; j++) + tmp[i][j] = g_ascii_tolower (tmp[i][j]); } - else - tmp = g_new0 (gchar *, 0 + 1); g_once_init_leave (&result, tmp); } @@ -342,15 +384,7 @@ get_current_desktops (const gchar *value) if (g_once_init_enter (&result)) { - gchar **tmp; - - if (!value) - value = g_getenv ("XDG_CURRENT_DESKTOP"); - - if (!value) - value = ""; - - tmp = g_strsplit (value, ":", 0); + char **tmp = get_valid_current_desktops (value); g_once_init_leave (&result, tmp); } @@ -417,7 +451,7 @@ const gchar desktop_key_match_category[N_DESKTOP_KEYS] = { }; /* Common prefix commands to ignore from Exec= lines */ -const char * const exec_key_match_blacklist[] = { +const char * const exec_key_match_blocklist[] = { "bash", "env", "flatpak", @@ -772,7 +806,7 @@ desktop_file_dir_unindexed_get_tweaks (DesktopFileDir *dir, static void expand_strv (gchar ***strv_ptr, gchar **to_add, - gchar * const *blacklist) + gchar * const *blocklist) { guint strv_len, add_len; gchar **strv; @@ -791,10 +825,10 @@ expand_strv (gchar ***strv_ptr, for (i = 0; to_add[i]; i++) { - /* Don't add blacklisted strings */ - if (blacklist) - for (j = 0; blacklist[j]; j++) - if (g_str_equal (to_add[i], blacklist[j])) + /* Don't add blocklisted strings */ + if (blocklist) + for (j = 0; blocklist[j]; j++) + if (g_str_equal (to_add[i], blocklist[j])) goto no_add; /* Don't add duplicates already in the list */ @@ -916,7 +950,7 @@ desktop_file_dir_unindexed_read_mimeapps_lists (DesktopFileDir *dir) dir->mime_tweaks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_mime_tweaks); - /* We process in order of precedence, using a blacklisting approach to + /* We process in order of precedence, using a blocklisting approach to * avoid recording later instructions that conflict with ones we found * earlier. * @@ -1108,7 +1142,7 @@ desktop_file_dir_unindexed_setup_search (DesktopFileDir *dir) { /* Index the interesting keys... */ gchar **implements; - gint i; + gsize i; for (i = 0; i < G_N_ELEMENTS (desktop_key_match_category); i++) { @@ -1135,8 +1169,8 @@ desktop_file_dir_unindexed_setup_search (DesktopFileDir *dir) if ((slash = strrchr (raw, '/'))) value = slash + 1; - /* Don't match on blacklisted binaries like interpreters */ - if (g_strv_contains (exec_key_match_blacklist, value)) + /* Don't match on blocklisted binaries like interpreters */ + if (g_strv_contains (exec_key_match_blocklist, value)) value = NULL; } @@ -1187,7 +1221,7 @@ static gboolean array_contains (GPtrArray *array, const gchar *str) { - gint i; + guint i; for (i = 0; i < array->len; i++) if (g_str_equal (array->pdata[i], str)) @@ -1200,7 +1234,7 @@ static void desktop_file_dir_unindexed_mime_lookup (DesktopFileDir *dir, const gchar *mime_type, GPtrArray *hits, - GPtrArray *blacklist) + GPtrArray *blocklist) { UnindexedMimeTweaks *tweaks; gint i; @@ -1217,7 +1251,7 @@ desktop_file_dir_unindexed_mime_lookup (DesktopFileDir *dir, gchar *app_name = tweaks->additions[i]; if (!desktop_file_dir_app_name_is_masked (dir, app_name) && - !array_contains (blacklist, app_name) && !array_contains (hits, app_name)) + !array_contains (blocklist, app_name) && !array_contains (hits, app_name)) g_ptr_array_add (hits, app_name); } } @@ -1229,8 +1263,8 @@ desktop_file_dir_unindexed_mime_lookup (DesktopFileDir *dir, gchar *app_name = tweaks->removals[i]; if (!desktop_file_dir_app_name_is_masked (dir, app_name) && - !array_contains (blacklist, app_name) && !array_contains (hits, app_name)) - g_ptr_array_add (blacklist, app_name); + !array_contains (blocklist, app_name) && !array_contains (hits, app_name)) + g_ptr_array_add (blocklist, app_name); } } } @@ -1448,14 +1482,14 @@ desktop_file_dir_get_all (DesktopFileDir *dir, * @dir: a #DesktopFileDir * @mime_type: the mime type to look up * @hits: the array to store the hits - * @blacklist: the array to store the blacklist + * @blocklist: the array to store the blocklist * * Does a lookup of a mimetype against one desktop file directory, - * recording any hits and blacklisting and "Removed" associations (so + * recording any hits and blocklisting and "Removed" associations (so * later directories don't record them as hits). * - * The items added to @hits are duplicated, but the ones in @blacklist - * are weak pointers. This facilitates simply freeing the blacklist + * The items added to @hits are duplicated, but the ones in @blocklist + * are weak pointers. This facilitates simply freeing the blocklist * (which is only used for internal bookkeeping) but using the pdata of * @hits as the result of the operation. */ @@ -1463,9 +1497,9 @@ static void desktop_file_dir_mime_lookup (DesktopFileDir *dir, const gchar *mime_type, GPtrArray *hits, - GPtrArray *blacklist) + GPtrArray *blocklist) { - desktop_file_dir_unindexed_mime_lookup (dir, mime_type, hits, blacklist); + desktop_file_dir_unindexed_mime_lookup (dir, mime_type, hits, blocklist); } /*< internal > @@ -1511,7 +1545,7 @@ desktop_file_dir_get_implementations (DesktopFileDir *dir, static void desktop_file_dirs_lock (void) { - gint i; + guint i; const gchar *user_config_dir = g_get_user_config_dir (); g_mutex_lock (&desktop_file_dir_lock); @@ -2106,7 +2140,7 @@ g_desktop_app_info_get_is_hidden (GDesktopAppInfo *info) * situations such as the #GDesktopAppInfo returned from * g_desktop_app_info_new_from_keyfile(), this function will return %NULL. * - * Returns: (type filename): The full path to the file for @info, + * Returns: (nullable) (type filename): The full path to the file for @info, * or %NULL if not known. * Since: 2.24 */ @@ -2154,7 +2188,7 @@ g_desktop_app_info_get_icon (GAppInfo *appinfo) * * Gets the categories from the desktop file. * - * Returns: The unparsed Categories key from the desktop file; + * Returns: (nullable): The unparsed Categories key from the desktop file; * i.e. no attempt is made to split it by ';' or validate it. */ const char * @@ -2183,9 +2217,9 @@ g_desktop_app_info_get_keywords (GDesktopAppInfo *info) * g_desktop_app_info_get_generic_name: * @info: a #GDesktopAppInfo * - * Gets the generic name from the destkop file. + * Gets the generic name from the desktop file. * - * Returns: The value of the GenericName key + * Returns: (nullable): The value of the GenericName key */ const char * g_desktop_app_info_get_generic_name (GDesktopAppInfo *info) @@ -2566,6 +2600,10 @@ prepend_terminal_to_vector (int *argc, } else { + if (check == NULL) + check = g_find_program_in_path ("tilix"); + if (check == NULL) + check = g_find_program_in_path ("konsole"); if (check == NULL) check = g_find_program_in_path ("nxterm"); if (check == NULL) @@ -2728,7 +2766,7 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, * internally by expand_macro(), so we need to pass a copy of it instead, * and also use that copy to control the exit condition of the loop below. */ - dup_uris = g_list_copy (uris); + dup_uris = uris; do { GPid pid; @@ -2737,6 +2775,15 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, char *sn_id = NULL; char **wrapped_argv; int i; + gsize j; + const gchar * const wrapper_argv[] = + { + "/bin/sh", + "-e", + "-u", + "-c", "export GIO_LAUNCHED_DESKTOP_FILE_PID=$$; exec \"$@\"", + "sh", /* argv[0] for sh */ + }; old_uris = dup_uris; if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error)) @@ -2778,26 +2825,26 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, g_list_free_full (launched_files, g_object_unref); } - if (g_once_init_enter (&gio_launch_desktop_path)) - { - const gchar *tmp; - - /* Allow test suite to specify path to gio-launch-desktop */ - tmp = g_getenv ("GIO_LAUNCH_DESKTOP"); - - /* Fall back on usual searching in $PATH */ - if (tmp == NULL) - tmp = "gio-launch-desktop"; - g_once_init_leave (&gio_launch_desktop_path, tmp); - } - - wrapped_argv = g_new (char *, argc + 2); - wrapped_argv[0] = g_strdup (gio_launch_desktop_path); - + /* Wrap the @argv in a command which will set the + * `GIO_LAUNCHED_DESKTOP_FILE_PID` environment variable. We can’t set this + * in @envp along with `GIO_LAUNCHED_DESKTOP_FILE` because we need to know + * the PID of the new forked process. We can’t use setenv() between fork() + * and exec() because we’d rather use posix_spawn() for speed. + * + * `sh` should be available on all the platforms that `GDesktopAppInfo` + * currently supports (since they are all POSIX). If additional platforms + * need to be supported in future, it will probably have to be replaced + * with a wrapper program (grep the GLib git history for + * `gio-launch-desktop` for an example of this which could be + * resurrected). */ + wrapped_argv = g_new (char *, argc + G_N_ELEMENTS (wrapper_argv) + 1); + + for (j = 0; j < G_N_ELEMENTS (wrapper_argv); j++) + wrapped_argv[j] = g_strdup (wrapper_argv[j]); for (i = 0; i < argc; i++) - wrapped_argv[i + 1] = g_steal_pointer (&argv[i]); + wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = g_steal_pointer (&argv[i]); - wrapped_argv[i + 1] = NULL; + wrapped_argv[i + G_N_ELEMENTS (wrapper_argv)] = NULL; g_free (argv); argv = NULL; @@ -2857,7 +2904,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, completed = TRUE; out: - g_list_free (dup_uris); g_strfreev (argv); g_strfreev (envp); @@ -3624,7 +3670,9 @@ update_mimeapps_list (const char *desktop_id, data = g_key_file_to_data (key_file, &data_size, error); g_key_file_free (key_file); - res = g_file_set_contents (filename, data, data_size, error); + res = g_file_set_contents_full (filename, data, data_size, + G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_ONLY_EXISTING, + 0600, error); desktop_file_dirs_invalidate_user_config (); @@ -3768,7 +3816,9 @@ g_desktop_app_info_set_as_default_for_extension (GAppInfo *appinfo, " \n" "\n", mimetype, extension, extension); - g_file_set_contents (filename, contents, -1, NULL); + g_file_set_contents_full (filename, contents, -1, + G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_ONLY_EXISTING, + 0600, NULL); g_free (contents); run_update_command ("update-mime-database", "mime"); @@ -3917,7 +3967,9 @@ g_desktop_app_info_ensure_saved (GDesktopAppInfo *info, /* FIXME - actually handle error */ (void) g_close (fd, NULL); - res = g_file_set_contents (filename, data, data_size, error); + res = g_file_set_contents_full (filename, data, data_size, + G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_ONLY_EXISTING, + 0600, error); g_free (data); if (!res) { @@ -4095,7 +4147,7 @@ get_list_of_mimetypes (const gchar *content_type, if (include_fallback) { - gint i; + guint i; /* Iterate the array as we grow it, until we have nothing more to add */ for (i = 0; i < array->len; i++) @@ -4124,12 +4176,12 @@ static gchar ** g_desktop_app_info_get_desktop_ids_for_content_type (const gchar *content_type, gboolean include_fallback) { - GPtrArray *hits, *blacklist; + GPtrArray *hits, *blocklist; gchar **types; - gint i, j; + guint i, j; hits = g_ptr_array_new (); - blacklist = g_ptr_array_new (); + blocklist = g_ptr_array_new (); types = get_list_of_mimetypes (content_type, include_fallback); @@ -4137,7 +4189,7 @@ g_desktop_app_info_get_desktop_ids_for_content_type (const gchar *content_type, for (i = 0; types[i]; i++) for (j = 0; j < desktop_file_dirs->len; j++) - desktop_file_dir_mime_lookup (g_ptr_array_index (desktop_file_dirs, j), types[i], hits, blacklist); + desktop_file_dir_mime_lookup (g_ptr_array_index (desktop_file_dirs, j), types[i], hits, blocklist); /* We will keep the hits past unlocking, so we must dup them */ for (i = 0; i < hits->len; i++) @@ -4147,7 +4199,7 @@ g_desktop_app_info_get_desktop_ids_for_content_type (const gchar *content_type, g_ptr_array_add (hits, NULL); - g_ptr_array_free (blacklist, TRUE); + g_ptr_array_free (blocklist, TRUE); g_strfreev (types); return (gchar **) g_ptr_array_free (hits, FALSE); @@ -4313,24 +4365,24 @@ g_app_info_reset_type_associations (const char *content_type) * * Gets the default #GAppInfo for a given content type. * - * Returns: (transfer full): #GAppInfo for given @content_type or + * Returns: (transfer full) (nullable): #GAppInfo for given @content_type or * %NULL on error. */ GAppInfo * g_app_info_get_default_for_type (const char *content_type, gboolean must_support_uris) { - GPtrArray *blacklist; + GPtrArray *blocklist; GPtrArray *results; GAppInfo *info; gchar **types; - gint i, j, k; + guint i, j, k; g_return_val_if_fail (content_type != NULL, NULL); types = get_list_of_mimetypes (content_type, TRUE); - blacklist = g_ptr_array_new (); + blocklist = g_ptr_array_new (); results = g_ptr_array_new (); info = NULL; @@ -4344,7 +4396,7 @@ g_app_info_get_default_for_type (const char *content_type, /* Consider the associations as well... */ for (j = 0; j < desktop_file_dirs->len; j++) - desktop_file_dir_mime_lookup (g_ptr_array_index (desktop_file_dirs, j), types[i], results, blacklist); + desktop_file_dir_mime_lookup (g_ptr_array_index (desktop_file_dirs, j), types[i], results, blocklist); /* (If any), see if one of those apps is installed... */ for (j = 0; j < results->len; j++) @@ -4366,7 +4418,7 @@ g_app_info_get_default_for_type (const char *content_type, } /* Reset the list, ready to try again with the next (parent) - * mimetype, but keep the blacklist in place. + * mimetype, but keep the blocklist in place. */ g_ptr_array_set_size (results, 0); } @@ -4374,7 +4426,7 @@ g_app_info_get_default_for_type (const char *content_type, out: desktop_file_dirs_unlock (); - g_ptr_array_unref (blacklist); + g_ptr_array_unref (blocklist); g_ptr_array_unref (results); g_strfreev (types); @@ -4390,7 +4442,8 @@ out: * of the URI, up to but not including the ':', e.g. "http", * "ftp" or "sip". * - * Returns: (transfer full): #GAppInfo for given @uri_scheme or %NULL on error. + * Returns: (transfer full) (nullable): #GAppInfo for given @uri_scheme or + * %NULL on error. */ GAppInfo * g_app_info_get_default_for_uri_scheme (const char *uri_scheme) @@ -4428,7 +4481,7 @@ g_desktop_app_info_get_implementations (const gchar *interface) { GList *result = NULL; GList **ptr; - gint i; + guint i; desktop_file_dirs_lock (); @@ -4471,6 +4524,13 @@ g_desktop_app_info_get_implementations (const gchar *interface) * The algorithm for determining matches is undefined and may change at * any time. * + * None of the search results are subjected to the normal validation + * checks performed by g_desktop_app_info_new() (for example, checking that + * the executable referenced by a result exists), and so it is possible for + * g_desktop_app_info_new() to return %NULL when passed an app ID returned by + * this function. It is expected that calling code will do this when + * subsequently creating a #GDesktopAppInfo for each result. + * * Returns: (array zero-terminated=1) (element-type GStrv) (transfer full): a * list of strvs. Free each item with g_strfreev() and free the outer * list with g_free(). @@ -4484,6 +4544,7 @@ g_desktop_app_info_search (const gchar *search_string) gint n_categories = 0; gint start_of_category; gint i, j; + guint k; search_tokens = g_str_tokenize_and_fold (search_string, NULL, NULL); @@ -4491,11 +4552,11 @@ g_desktop_app_info_search (const gchar *search_string) reset_total_search_results (); - for (i = 0; i < desktop_file_dirs->len; i++) + for (k = 0; k < desktop_file_dirs->len; k++) { for (j = 0; search_tokens[j]; j++) { - desktop_file_dir_search (g_ptr_array_index (desktop_file_dirs, i), search_tokens[j]); + desktop_file_dir_search (g_ptr_array_index (desktop_file_dirs, k), search_tokens[j]); merge_token_results (j == 0); } merge_directory_results (); @@ -4563,7 +4624,7 @@ g_app_info_get_all (void) GHashTable *apps; GHashTableIter iter; gpointer value; - int i; + guint i; GList *infos; apps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -4626,7 +4687,8 @@ g_desktop_app_info_lookup_default_init (GDesktopAppInfoLookupInterface *iface) * in a GIO module. There is no reason for applications to use it * directly. Applications should use g_app_info_get_default_for_uri_scheme(). * - * Returns: (transfer full): #GAppInfo for given @uri_scheme or %NULL on error. + * Returns: (transfer full) (nullable): #GAppInfo for given @uri_scheme or + * %NULL on error. * * Deprecated: 2.28: The #GDesktopAppInfoLookup interface is deprecated and * unused by GIO. @@ -4656,7 +4718,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS * WM_CLASS property of the main window of the application, if launched * through @info. * - * Returns: (transfer none): the startup WM class, or %NULL if none is set + * Returns: (nullable) (transfer none): the startup WM class, or %NULL if none is set * in the desktop file. * * Since: 2.34 @@ -4678,7 +4740,7 @@ g_desktop_app_info_get_startup_wm_class (GDesktopAppInfo *info) * * The @key is looked up in the "Desktop Entry" group. * - * Returns: a newly allocated string, or %NULL if the key + * Returns: (nullable): a newly allocated string, or %NULL if the key * is not found * * Since: 2.36 diff --git a/gio/gdocumentportal.c b/gio/gdocumentportal.c index 154cc74df3dd90b144e644172da01a93630b4493..644829a716362e9afe73dd0f9275c9bb8cd81d71 100644 --- a/gio/gdocumentportal.c +++ b/gio/gdocumentportal.c @@ -37,56 +37,47 @@ #define HAVE_O_CLOEXEC 1 #endif -static GXdpDocuments *documents; -static char *documents_mountpoint; - static gboolean -init_document_portal (void) +get_document_portal (GXdpDocuments **documents, + char **documents_mountpoint, + GError **error) { - static gsize documents_inited = 0; + GDBusConnection *connection = NULL; - if (g_once_init_enter (&documents_inited)) - { - GError *error = NULL; - GDBusConnection *connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + *documents = NULL; + *documents_mountpoint = NULL; - if (connection != NULL) - { - documents = gxdp_documents_proxy_new_sync (connection, 0, - "org.freedesktop.portal.Documents", - "/org/freedesktop/portal/documents", - NULL, &error); - if (documents != NULL) - { - gxdp_documents_call_get_mount_point_sync (documents, - &documents_mountpoint, - NULL, &error); - - if (error != NULL) - { - g_warning ("Cannot get document portal mount point: %s", error->message); - g_error_free (error); - } - } - else - { - g_warning ("Cannot create document portal proxy: %s", error->message); - g_error_free (error); - } + connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error); + if (connection == NULL) + { + g_prefix_error (error, "Cannot connect to session bus when initializing document portal: "); + goto out; + } - g_object_unref (connection); - } - else - { - g_warning ("Cannot connect to session bus when initializing document portal: %s", - error->message); - g_error_free (error); - } + *documents = gxdp_documents_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + "org.freedesktop.portal.Documents", + "/org/freedesktop/portal/documents", + NULL, error); + if (*documents == NULL) + { + g_prefix_error (error, "Cannot create document portal proxy: "); + goto out; + } - g_once_init_leave (&documents_inited, 1); + if (!gxdp_documents_call_get_mount_point_sync (*documents, + documents_mountpoint, + NULL, error)) + { + g_clear_object (documents); + g_prefix_error (error, "Cannot get document portal mount point: "); + goto out; } - return (documents != NULL && documents_mountpoint != NULL); +out: + g_clear_object (&connection); + return *documents != NULL; } /* Flags accepted by org.freedesktop.portal.Documents.AddFull */ @@ -102,6 +93,8 @@ g_document_portal_add_documents (GList *uris, const char *app_id, GError **error) { + GXdpDocuments *documents = NULL; + char *documents_mountpoint = NULL; int length; GList *ruris = NULL; gboolean *as_is; @@ -113,10 +106,8 @@ g_document_portal_add_documents (GList *uris, char **doc_ids = NULL; GVariant *extra_out = NULL; - if (!init_document_portal ()) + if (!get_document_portal (&documents, &documents_mountpoint, error)) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, - "Document portal is not available"); return NULL; } @@ -213,6 +204,8 @@ g_document_portal_add_documents (GList *uris, } out: + g_clear_object (&documents); + g_clear_pointer (&documents_mountpoint, g_free); g_clear_object (&fd_list); g_clear_pointer (&extra_out, g_variant_unref); g_clear_pointer (&doc_ids, g_strfreev); diff --git a/gio/gdrive.c b/gio/gdrive.c index 08f72b23bccf689430570a89e3d5c2b1bc653ec9..32bdae87969dfd682758bf7d9025cfeccd2ab6ea 100644 --- a/gio/gdrive.c +++ b/gio/gdrive.c @@ -45,7 +45,7 @@ * * If the #GDrive reports that media isn't automatically detected, one * can poll for media; typically one should not do this periodically - * as a poll for media operation is potententially expensive and may + * as a poll for media operation is potentially expensive and may * spin up the drive creating noise. * * #GDrive supports starting and stopping drives with authentication @@ -249,9 +249,9 @@ g_drive_get_volumes (GDrive *drive) * g_drive_is_media_check_automatic: * @drive: a #GDrive. * - * Checks if @drive is capabable of automatically detecting media changes. + * Checks if @drive is capable of automatically detecting media changes. * - * Returns: %TRUE if the @drive is capabable of automatically detecting + * Returns: %TRUE if the @drive is capable of automatically detecting * media changes, %FALSE otherwise. **/ gboolean diff --git a/gio/gdrive.h b/gio/gdrive.h index ec92071c76268932646d5614cd1b3582f23f5767..cd9b7212fdc0631fdd4bb55a814f0cf22e1f8f41 100644 --- a/gio/gdrive.h +++ b/gio/gdrive.h @@ -57,7 +57,7 @@ G_BEGIN_DECLS * @is_removable: Returns %TRUE if the #GDrive and/or its media is considered removable by the user. Since 2.50. * @is_media_removable: Returns %TRUE if the #GDrive supports removal and insertion of media. * @has_media: Returns %TRUE if the #GDrive has media inserted. - * @is_media_check_automatic: Returns %TRUE if the #GDrive is capabable of automatically detecting media changes. + * @is_media_check_automatic: Returns %TRUE if the #GDrive is capable of automatically detecting media changes. * @can_poll_for_media: Returns %TRUE if the #GDrive is capable of manually polling for media change. * @can_eject: Returns %TRUE if the #GDrive can eject media. * @eject: Ejects a #GDrive. diff --git a/gio/gdtlsclientconnection.c b/gio/gdtlsclientconnection.c index 1ce97d3623c8801b6fdec581d5091d331aedb6b1..bdbf890fe96372d3ec76eb2bed0876ec71c078a3 100644 --- a/gio/gdtlsclientconnection.c +++ b/gio/gdtlsclientconnection.c @@ -59,7 +59,7 @@ g_dtls_client_connection_default_init (GDtlsClientConnectionInterface *iface) * GDtlsClientConnection:validation-flags: * * What steps to perform when validating a certificate received from - * a server. Server certificates that fail to validate in all of the + * a server. Server certificates that fail to validate in any of the * ways indicated here will be rejected unless the application * overrides the default via #GDtlsConnection::accept-certificate. * diff --git a/gio/gdtlsconnection.c b/gio/gdtlsconnection.c index 1a74e3cc4eb07cec49de7eecf6fae868a3466892..4bbc88d7a7465882516f4da5de565666a209880f 100644 --- a/gio/gdtlsconnection.c +++ b/gio/gdtlsconnection.c @@ -26,6 +26,7 @@ #include "gsocket.h" #include "gtlsbackend.h" #include "gtlscertificate.h" +#include "gtlsconnection.h" #include "gdtlsclientconnection.h" #include "gtlsdatabase.h" #include "gtlsinteraction.h" @@ -109,7 +110,7 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** - * GDtlsConnection:database: + * GDtlsConnection:database: (nullable) * * The certificate database to use when verifying this TLS connection. * If no certificate database is set, then the default database will be @@ -125,7 +126,7 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** - * GDtlsConnection:interaction: + * GDtlsConnection:interaction: (nullable) * * A #GTlsInteraction object to be used when the connection or certificate * database need to interact with the user. This will be used to prompt the @@ -164,9 +165,7 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) * * Since: 2.48 * - * Deprecated: 2.60. Changing the rehandshake mode is no longer - * required for compatibility. Also, rehandshaking has been removed - * from the TLS protocol in TLS 1.3. + * Deprecated: 2.60: The rehandshake mode is ignored. */ g_object_interface_install_property (iface, g_param_spec_enum ("rehandshake-mode", @@ -194,12 +193,11 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** - * GDtlsConnection:peer-certificate: + * GDtlsConnection:peer-certificate: (nullable) * * The connection's peer's certificate, after the TLS handshake has - * completed and the certificate has been accepted. Note in - * particular that this is not yet set during the emission of - * #GDtlsConnection::accept-certificate. + * completed or failed. Note in particular that this is not yet set + * during the emission of #GDtlsConnection::accept-certificate. * * (You can watch for a #GObject::notify signal on this property to * detect when a handshake has occurred.) @@ -216,7 +214,7 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) /** * GDtlsConnection:peer-certificate-errors: * - * The errors noticed-and-ignored while verifying + * The errors noticed while verifying * #GDtlsConnection:peer-certificate. Normally this should be 0, but * it may not be if #GDtlsClientConnection:validation-flags is not * %G_TLS_CERTIFICATE_VALIDATE_ALL, or if @@ -234,7 +232,7 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /** - * GDtlsConnection:advertised-protocols: + * GDtlsConnection:advertised-protocols: (nullable) * * The list of application-layer protocols that the connection * advertises that it is willing to speak. See @@ -330,7 +328,7 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) /** * g_dtls_connection_set_database: * @conn: a #GDtlsConnection - * @database: a #GTlsDatabase + * @database: (nullable): a #GTlsDatabase * * Sets the certificate database that is used to verify peer certificates. * This is set to the default database by default. See @@ -362,7 +360,7 @@ g_dtls_connection_set_database (GDtlsConnection *conn, * Gets the certificate database that @conn uses to verify * peer certificates. See g_dtls_connection_set_database(). * - * Returns: (transfer none): the certificate database that @conn uses or %NULL + * Returns: (transfer none) (nullable): the certificate database that @conn uses or %NULL * * Since: 2.48 */ @@ -424,7 +422,7 @@ g_dtls_connection_set_certificate (GDtlsConnection *conn, * Gets @conn's certificate, as set by * g_dtls_connection_set_certificate(). * - * Returns: (transfer none): @conn's certificate, or %NULL + * Returns: (transfer none) (nullable): @conn's certificate, or %NULL * * Since: 2.48 */ @@ -474,7 +472,7 @@ g_dtls_connection_set_interaction (GDtlsConnection *conn, * for things like prompting the user for passwords. If %NULL is returned, then * no user interaction will occur for this connection. * - * Returns: (transfer none): The interaction object. + * Returns: (transfer none) (nullable): The interaction object. * * Since: 2.48 */ @@ -496,11 +494,11 @@ g_dtls_connection_get_interaction (GDtlsConnection *conn) * g_dtls_connection_get_peer_certificate: * @conn: a #GDtlsConnection * - * Gets @conn's peer's certificate after the handshake has completed. - * (It is not set during the emission of + * Gets @conn's peer's certificate after the handshake has completed + * or failed. (It is not set during the emission of * #GDtlsConnection::accept-certificate.) * - * Returns: (transfer none): @conn's peer's certificate, or %NULL + * Returns: (transfer none) (nullable): @conn's peer's certificate, or %NULL * * Since: 2.48 */ @@ -523,8 +521,8 @@ g_dtls_connection_get_peer_certificate (GDtlsConnection *conn) * @conn: a #GDtlsConnection * * Gets the errors associated with validating @conn's peer's - * certificate, after the handshake has completed. (It is not set - * during the emission of #GDtlsConnection::accept-certificate.) + * certificate, after the handshake has completed or failed. (It is + * not set during the emission of #GDtlsConnection::accept-certificate.) * * Returns: @conn's peer's certificate errors * @@ -615,26 +613,10 @@ g_dtls_connection_get_require_close_notify (GDtlsConnection *conn) * @conn: a #GDtlsConnection * @mode: the rehandshaking mode * - * Sets how @conn behaves with respect to rehandshaking requests. - * - * %G_TLS_REHANDSHAKE_NEVER means that it will never agree to - * rehandshake after the initial handshake is complete. (For a client, - * this means it will refuse rehandshake requests from the server, and - * for a server, this means it will close the connection with an error - * if the client attempts to rehandshake.) - * - * %G_TLS_REHANDSHAKE_SAFELY means that the connection will allow a - * rehandshake only if the other end of the connection supports the - * TLS `renegotiation_info` extension. This is the default behavior, - * but means that rehandshaking will not work against older - * implementations that do not support that extension. - * - * %G_TLS_REHANDSHAKE_UNSAFELY means that the connection will allow - * rehandshaking even without the `renegotiation_info` extension. On - * the server side in particular, this is not recommended, since it - * leaves the server open to certain attacks. However, this mode is - * necessary if you need to allow renegotiation with older client - * software. + * Since GLib 2.64, changing the rehandshake mode is no longer supported + * and will have no effect. With TLS 1.3, rehandshaking has been removed from + * the TLS protocol, replaced by separate post-handshake authentication and + * rekey operations. * * Since: 2.48 * @@ -650,7 +632,7 @@ g_dtls_connection_set_rehandshake_mode (GDtlsConnection *conn, g_return_if_fail (G_IS_DTLS_CONNECTION (conn)); g_object_set (G_OBJECT (conn), - "rehandshake-mode", mode, + "rehandshake-mode", G_TLS_REHANDSHAKE_SAFELY, NULL); } G_GNUC_END_IGNORE_DEPRECATIONS @@ -662,22 +644,29 @@ G_GNUC_END_IGNORE_DEPRECATIONS * Gets @conn rehandshaking mode. See * g_dtls_connection_set_rehandshake_mode() for details. * - * Returns: @conn's rehandshaking mode + * Returns: %G_TLS_REHANDSHAKE_SAFELY * * Since: 2.48 + * + * Deprecated: 2.64. Changing the rehandshake mode is no longer + * required for compatibility. Also, rehandshaking has been removed + * from the TLS protocol in TLS 1.3. */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS GTlsRehandshakeMode -g_dtls_connection_get_rehandshake_mode (GDtlsConnection *conn) +g_dtls_connection_get_rehandshake_mode (GDtlsConnection *conn) { GTlsRehandshakeMode mode; - g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), G_TLS_REHANDSHAKE_NEVER); + g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), G_TLS_REHANDSHAKE_SAFELY); + /* Continue to call g_object_get(), even though the return value is + * ignored, so that behavior doesn’t change for derived classes. + */ g_object_get (G_OBJECT (conn), "rehandshake-mode", &mode, NULL); - return mode; + return G_TLS_REHANDSHAKE_SAFELY; } G_GNUC_END_IGNORE_DEPRECATIONS @@ -691,28 +680,25 @@ G_GNUC_END_IGNORE_DEPRECATIONS * * On the client side, it is never necessary to call this method; * although the connection needs to perform a handshake after - * connecting (or after sending a "STARTTLS"-type command) and may - * need to rehandshake later if the server requests it, - * #GDtlsConnection will handle this for you automatically when you try - * to send or receive data on the connection. However, you can call - * g_dtls_connection_handshake() manually if you want to know for sure - * whether the initial handshake succeeded or failed (as opposed to - * just immediately trying to write to @conn, in which - * case if it fails, it may not be possible to tell if it failed - * before or after completing the handshake). + * connecting, #GDtlsConnection will handle this for you automatically + * when you try to send or receive data on the connection. You can call + * g_dtls_connection_handshake() manually if you want to know whether + * the initial handshake succeeded or failed (as opposed to just + * immediately trying to use @conn to read or write, in which case, + * if it fails, it may not be possible to tell if it failed before + * or after completing the handshake), but beware that servers may reject + * client authentication after the handshake has completed, so a + * successful handshake does not indicate the connection will be usable. * * Likewise, on the server side, although a handshake is necessary at * the beginning of the communication, you do not need to call this * function explicitly unless you want clearer error reporting. * - * If TLS 1.2 or older is in use, you may call - * g_dtls_connection_handshake() after the initial handshake to - * rehandshake; however, this usage is deprecated because rehandshaking - * is no longer part of the TLS protocol in TLS 1.3. Accordingly, the - * behavior of calling this function after the initial handshake is now - * undefined, except it is guaranteed to be reasonable and - * nondestructive so as to preserve compatibility with code written for - * older versions of GLib. + * Previously, calling g_dtls_connection_handshake() after the initial + * handshake would trigger a rehandshake; however, this usage was + * deprecated in GLib 2.60 because rehandshaking was removed from the + * TLS protocol in TLS 1.3. Since GLib 2.64, calling this function after + * the initial handshake will no longer do anything. * * #GDtlsConnection::accept_certificate may be emitted during the * handshake. @@ -1088,3 +1074,52 @@ g_dtls_connection_get_negotiated_protocol (GDtlsConnection *conn) return iface->get_negotiated_protocol (conn); } + +/** + * g_dtls_connection_get_channel_binding_data: + * @conn: a #GDtlsConnection + * @type: #GTlsChannelBindingType type of data to fetch + * @data: (out callee-allocates)(optional)(transfer none): #GByteArray is + * filled with the binding data, or %NULL + * @error: a #GError pointer, or %NULL + * + * Query the TLS backend for TLS channel binding data of @type for @conn. + * + * This call retrieves TLS channel binding data as specified in RFC + * [5056](https://tools.ietf.org/html/rfc5056), RFC + * [5929](https://tools.ietf.org/html/rfc5929), and related RFCs. The + * binding data is returned in @data. The @data is resized by the callee + * using #GByteArray buffer management and will be freed when the @data + * is destroyed by g_byte_array_unref(). If @data is %NULL, it will only + * check whether TLS backend is able to fetch the data (e.g. whether @type + * is supported by the TLS backend). It does not guarantee that the data + * will be available though. That could happen if TLS connection does not + * support @type or the binding data is not available yet due to additional + * negotiation or input required. + * + * Returns: %TRUE on success, %FALSE otherwise + * + * Since: 2.66 + */ +gboolean +g_dtls_connection_get_channel_binding_data (GDtlsConnection *conn, + GTlsChannelBindingType type, + GByteArray *data, + GError **error) +{ + GDtlsConnectionInterface *iface; + + g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + iface = G_DTLS_CONNECTION_GET_INTERFACE (conn); + if (iface->get_binding_data == NULL) + { + g_set_error_literal (error, G_TLS_CHANNEL_BINDING_ERROR, + G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED, + _("TLS backend does not implement TLS binding retrieval")); + return FALSE; + } + + return iface->get_binding_data (conn, type, data, error); +} diff --git a/gio/gdtlsconnection.h b/gio/gdtlsconnection.h index 3901cdc9ec004e040d536cb9cdaeeee91d3efb57..e73cf14592b118f0323400ea75d36ebfd186a560 100644 --- a/gio/gdtlsconnection.h +++ b/gio/gdtlsconnection.h @@ -95,6 +95,13 @@ struct _GDtlsConnectionInterface void (*set_advertised_protocols) (GDtlsConnection *conn, const gchar * const *protocols); const gchar *(*get_negotiated_protocol) (GDtlsConnection *conn); + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gboolean (*get_binding_data) (GDtlsConnection *conn, + GTlsChannelBindingType type, + GByteArray *data, + GError **error); +G_GNUC_END_IGNORE_DEPRECATIONS }; GLIB_AVAILABLE_IN_2_48 @@ -201,6 +208,14 @@ void g_dtls_connection_set_advertised_protocols (GDtlsConnec GLIB_AVAILABLE_IN_2_60 const gchar * g_dtls_connection_get_negotiated_protocol (GDtlsConnection *conn); +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +GLIB_AVAILABLE_IN_2_66 +gboolean g_dtls_connection_get_channel_binding_data (GDtlsConnection *conn, + GTlsChannelBindingType type, + GByteArray *data, + GError **error); +G_GNUC_END_IGNORE_DEPRECATIONS + G_END_DECLS #endif /* __G_DTLS_CONNECTION_H__ */ diff --git a/gio/gdummyfile.c b/gio/gdummyfile.c index cd4acd0219c388837e955d1775bdd07146fb15a1..3bf5ba9205cc4a073b591eb1daef14ed7b4203c7 100644 --- a/gio/gdummyfile.c +++ b/gio/gdummyfile.c @@ -126,7 +126,7 @@ g_dummy_file_get_basename (GFile *file) if (dummy->decoded_uri) return g_path_get_basename (dummy->decoded_uri->path); - return g_strdup (dummy->text_uri); + return NULL; } static char * @@ -482,7 +482,7 @@ unescape_string (const gchar *escaped_string, } *out = '\0'; - g_warn_if_fail (out - result <= strlen (escaped_string)); + g_warn_if_fail ((gsize) (out - result) <= strlen (escaped_string)); return result; } diff --git a/gio/gdummytlsbackend.c b/gio/gdummytlsbackend.c index 52342d957eada983aa67991a3d594d47c699e101..8744b83639644237494fd83d149c2381e649db17 100644 --- a/gio/gdummytlsbackend.c +++ b/gio/gdummytlsbackend.c @@ -235,7 +235,9 @@ enum PROP_CONN_SERVER_IDENTITY, PROP_CONN_USE_SSL3, PROP_CONN_ACCEPTED_CAS, - PROP_CONN_AUTHENTICATION_MODE + PROP_CONN_AUTHENTICATION_MODE, + PROP_CONN_ADVERTISED_PROTOCOLS, + PROP_CONN_NEGOTIATED_PROTOCOL, }; static void g_dummy_tls_connection_initable_iface_init (GInitableIface *iface); @@ -301,6 +303,8 @@ g_dummy_tls_connection_class_init (GDummyTlsConnectionClass *connection_class) g_object_class_override_property (gobject_class, PROP_CONN_USE_SSL3, "use-ssl3"); g_object_class_override_property (gobject_class, PROP_CONN_ACCEPTED_CAS, "accepted-cas"); g_object_class_override_property (gobject_class, PROP_CONN_AUTHENTICATION_MODE, "authentication-mode"); + g_object_class_override_property (gobject_class, PROP_CONN_ADVERTISED_PROTOCOLS, "advertised-protocols"); + g_object_class_override_property (gobject_class, PROP_CONN_NEGOTIATED_PROTOCOL, "negotiated-protocol"); } static void diff --git a/gio/gfdonotificationbackend.c b/gio/gfdonotificationbackend.c index c4fa0dc1dbff90f55cfe17722b50bf8b8790ef64..b6fbfd2e266f04059212098b659a94082938dfd4 100644 --- a/gio/gfdonotificationbackend.c +++ b/gio/gfdonotificationbackend.c @@ -25,6 +25,7 @@ #include "giomodule-priv.h" #include "gnotification-private.h" #include "gdbusconnection.h" +#include "gdbusnamewatching.h" #include "gactiongroup.h" #include "gaction.h" #include "gthemedicon.h" @@ -42,6 +43,8 @@ struct _GFdoNotificationBackend { GNotificationBackend parent; + guint bus_name_id; + guint notify_subscription; GSList *notifications; }; @@ -205,6 +208,20 @@ notify_signal (GDBusConnection *connection, } } +static void +name_vanished_handler_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + GFdoNotificationBackend *backend = user_data; + + if (backend->notifications) + { + g_slist_free_full (backend->notifications, freedesktop_notification_free); + backend->notifications = NULL; + } +} + /* Converts a GNotificationPriority to an urgency level as defined by * the freedesktop spec (0: low, 1: normal, 2: critical). */ @@ -370,6 +387,12 @@ g_fdo_notification_backend_dispose (GObject *object) { GFdoNotificationBackend *backend = G_FDO_NOTIFICATION_BACKEND (object); + if (backend->bus_name_id) + { + g_bus_unwatch_name (backend->bus_name_id); + backend->bus_name_id = 0; + } + if (backend->notify_subscription) { GDBusConnection *session_bus; @@ -407,6 +430,17 @@ g_fdo_notification_backend_send_notification (GNotificationBackend *backend, GFdoNotificationBackend *self = G_FDO_NOTIFICATION_BACKEND (backend); FreedesktopNotification *n, *tmp; + if (self->bus_name_id == 0) + { + self->bus_name_id = g_bus_watch_name_on_connection (backend->dbus_connection, + "org.freedesktop.Notifications", + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + name_vanished_handler_cb, + backend, + NULL); + } + if (self->notify_subscription == 0) { self->notify_subscription = diff --git a/gio/gfile.c b/gio/gfile.c index 81a92051e21956f70e068fc4fdebf5c3167b9993..d7feca6b9f824b9391f348cb934a7957e194b7e7 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -35,6 +35,20 @@ #include #include #include + +/* + * We duplicate the following Linux kernel header defines here so we can still + * run at full speed on modern kernels in cases where an old toolchain was used + * to build GLib. This is often done deliberately to allow shipping binaries + * that need to run on a wide range of systems. + */ +#ifndef F_SETPIPE_SZ +#define F_SETPIPE_SZ 1031 +#endif +#ifndef F_GETPIPE_SZ +#define F_GETPIPE_SZ 1032 +#endif + #endif #include @@ -456,11 +470,14 @@ g_file_has_uri_scheme (GFile *file, * ]| * Common schemes include "file", "http", "ftp", etc. * + * The scheme can be different from the one used to construct the #GFile, + * in that it might be replaced with one that is logically equivalent to the #GFile. + * * This call does no blocking I/O. * - * Returns: a string containing the URI scheme for the given - * #GFile. The returned string should be freed with g_free() - * when no longer needed. + * Returns: (nullable): a string containing the URI scheme for the given + * #GFile or %NULL if the #GFile was constructed with an invalid URI. The + * returned string should be freed with g_free() when no longer needed. */ char * g_file_get_uri_scheme (GFile *file) @@ -476,7 +493,7 @@ g_file_get_uri_scheme (GFile *file) /** - * g_file_get_basename: + * g_file_get_basename: (virtual get_basename) * @file: input #GFile * * Gets the base name (the last component of the path) for a given #GFile. @@ -510,7 +527,7 @@ g_file_get_basename (GFile *file) } /** - * g_file_get_path: + * g_file_get_path: (virtual get_path) * @file: input #GFile * * Gets the local pathname for #GFile, if one exists. If non-%NULL, this is @@ -534,37 +551,6 @@ g_file_get_path (GFile *file) return (* iface->get_path) (file); } -/* Original commit introducing this in libgsystem: - * - * fileutil: Handle recent: and trash: URIs - * - * The gs_file_get_path_cached() was rather brittle in its handling - * of URIs. It would assert() when a GFile didn't have a backing path - * (such as when handling trash: or recent: URIs), and didn't know - * how to get the target URI for those items either. - * - * Make sure that we do not assert() when a backing path cannot be - * found, and handle recent: and trash: URIs. - * - * https://bugzilla.gnome.org/show_bug.cgi?id=708435 - */ -static char * -file_get_target_path (GFile *file) -{ - GFileInfo *info; - const char *target; - char *path; - - info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, G_FILE_QUERY_INFO_NONE, NULL, NULL); - if (info == NULL) - return NULL; - target = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI); - path = g_filename_from_uri (target, NULL, NULL); - g_object_unref (info); - - return path; -} - static const char * file_peek_path_generic (GFile *file) { @@ -591,11 +577,7 @@ file_peek_path_generic (GFile *file) if (path != NULL) break; - if (g_file_has_uri_scheme (file, "trash") || - g_file_has_uri_scheme (file, "recent")) - new_path = file_get_target_path (file); - else - new_path = g_file_get_path (file); + new_path = g_file_get_path (file); if (new_path == NULL) return NULL; @@ -603,7 +585,10 @@ file_peek_path_generic (GFile *file) if (g_object_replace_qdata ((GObject *) file, _file_path_quark, NULL, (gpointer) new_path, (GDestroyNotify) g_free, NULL)) - break; + { + path = new_path; + break; + } else g_free (new_path); } @@ -643,7 +628,8 @@ g_file_peek_path (GFile *file) * * This call does no blocking I/O. * - * Returns: a string containing the #GFile's URI. + * Returns: a string containing the #GFile's URI. If the #GFile was constructed + * with an invalid URI, an invalid URI is returned. * The returned string should be freed with g_free() * when no longer needed. */ @@ -936,7 +922,7 @@ g_file_get_child_for_display_name (GFile *file, * of @prefix. * * Virtual: prefix_matches - * Returns: %TRUE if the @files's parent, grandparent, etc is @prefix, + * Returns: %TRUE if the @file's parent, grandparent, etc is @prefix, * %FALSE otherwise. */ gboolean @@ -960,7 +946,7 @@ g_file_has_prefix (GFile *file, } /** - * g_file_get_relative_path: + * g_file_get_relative_path: (virtual get_relative_path) * @parent: input #GFile * @descendant: input #GFile * @@ -2727,14 +2713,36 @@ should_copy (GFileAttributeInfo *info, return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE; } -static gboolean -build_attribute_list_for_copy (GFile *file, - GFileCopyFlags flags, - char **out_attributes, - GCancellable *cancellable, - GError **error) +/** + * g_file_build_attribute_list_for_copy: + * @file: a #GFile to copy attributes to + * @flags: a set of #GFileCopyFlags + * @cancellable: (nullable): optional #GCancellable object, + * %NULL to ignore + * @error: a #GError, %NULL to ignore + * + * Prepares the file attribute query string for copying to @file. + * + * This function prepares an attribute query string to be + * passed to g_file_query_info() to get a list of attributes + * normally copied with the file (see g_file_copy_attributes() + * for the detailed description). This function is used by the + * implementation of g_file_copy_attributes() and is useful + * when one needs to query and set the attributes in two + * stages (e.g., for recursive move of a directory). + * + * Returns: an attribute query string for g_file_query_info(), + * or %NULL if an error occurs. + * + * Since: 2.68 + */ +char * +g_file_build_attribute_list_for_copy (GFile *file, + GFileCopyFlags flags, + GCancellable *cancellable, + GError **error) { - gboolean ret = FALSE; + char *ret = NULL; GFileAttributeInfoList *attributes = NULL, *namespaces = NULL; GString *s = NULL; gboolean first; @@ -2742,6 +2750,10 @@ build_attribute_list_for_copy (GFile *file, gboolean copy_all_attributes; gboolean skip_perms; + g_return_val_if_fail (G_IS_FILE (file), NULL); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA; skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0; @@ -2795,8 +2807,7 @@ build_attribute_list_for_copy (GFile *file, } } - ret = TRUE; - *out_attributes = g_string_free (s, FALSE); + ret = g_string_free (s, FALSE); s = NULL; out: if (s) @@ -2842,8 +2853,9 @@ g_file_copy_attributes (GFile *source, GFileInfo *info; gboolean source_nofollow_symlinks; - if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read, - cancellable, error)) + attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags, + cancellable, error); + if (!attrs_to_read) return FALSE; source_nofollow_symlinks = flags & G_FILE_COPY_NOFOLLOW_SYMLINKS; @@ -3017,31 +3029,22 @@ splice_stream_with_progress (GInputStream *in, if (!g_unix_open_pipe (buffer, FD_CLOEXEC, error)) return FALSE; -#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ) /* Try a 1MiB buffer for improved throughput. If that fails, use the default * pipe size. See: https://bugzilla.gnome.org/791457 */ buffer_size = fcntl (buffer[1], F_SETPIPE_SZ, 1024 * 1024); if (buffer_size <= 0) { - int errsv; buffer_size = fcntl (buffer[1], F_GETPIPE_SZ); - errsv = errno; - if (buffer_size <= 0) { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error splicing file: %s"), g_strerror (errsv)); - res = FALSE; - goto out; + /* If #F_GETPIPE_SZ isn’t available, assume we’re on Linux < 2.6.35, + * but ≥ 2.6.11, meaning the pipe capacity is 64KiB. Ignore the + * possibility of running on Linux < 2.6.11 (where the capacity was + * the system page size, typically 4KiB) because it’s ancient. + * See pipe(7). */ + buffer_size = 1024 * 64; } } -#else - /* If #F_GETPIPE_SZ isn’t available, assume we’re on Linux < 2.6.35, - * but ≥ 2.6.11, meaning the pipe capacity is 64KiB. Ignore the possibility of - * running on Linux < 2.6.11 (where the capacity was the system page size, - * typically 4KiB) because it’s ancient. See pipe(7). */ - buffer_size = 1024 * 64; -#endif g_assert (buffer_size > 0); @@ -3189,6 +3192,7 @@ file_copy_fallback (GFile *source, char *attrs_to_read; gboolean do_set_attributes = FALSE; GFileCreateFlags create_flags; + GError *tmp_error = NULL; /* need to know the file type */ info = g_file_query_info (source, @@ -3230,47 +3234,43 @@ file_copy_fallback (GFile *source, goto out; in = G_INPUT_STREAM (file_in); - if (!build_attribute_list_for_copy (destination, flags, &attrs_to_read, - cancellable, error)) + attrs_to_read = g_file_build_attribute_list_for_copy (destination, flags, + cancellable, error); + if (!attrs_to_read) goto out; - if (attrs_to_read != NULL) - { - GError *tmp_error = NULL; + /* Ok, ditch the previous lightweight info (on Unix we just + * called lstat()); at this point we gather all the information + * we need about the source from the opened file descriptor. + */ + g_object_unref (info); - /* Ok, ditch the previous lightweight info (on Unix we just - * called lstat()); at this point we gather all the information - * we need about the source from the opened file descriptor. + info = g_file_input_stream_query_info (file_in, attrs_to_read, + cancellable, &tmp_error); + if (!info) + { + /* Not all gvfs backends implement query_info_on_read(), we + * can just fall back to the pathname again. + * https://bugzilla.gnome.org/706254 */ - g_object_unref (info); - - info = g_file_input_stream_query_info (file_in, attrs_to_read, - cancellable, &tmp_error); - if (!info) + if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) { - /* Not all gvfs backends implement query_info_on_read(), we - * can just fall back to the pathname again. - * https://bugzilla.gnome.org/706254 - */ - if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) - { - g_clear_error (&tmp_error); - info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - } - else - { - g_free (attrs_to_read); - g_propagate_error (error, tmp_error); - goto out; - } + g_clear_error (&tmp_error); + info = g_file_query_info (source, attrs_to_read, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + cancellable, error); + } + else + { + g_free (attrs_to_read); + g_propagate_error (error, tmp_error); + goto out; } - g_free (attrs_to_read); - if (!info) - goto out; - - do_set_attributes = TRUE; } + g_free (attrs_to_read); + if (!info) + goto out; + + do_set_attributes = TRUE; /* In the local file path, we pass down the source info which * includes things like unix::mode, to ensure that the target file @@ -3652,10 +3652,6 @@ g_file_copy_finish (GFile *file, * If the flag #G_FILE_COPY_OVERWRITE is specified an already * existing @destination file is overwritten. * - * If the flag #G_FILE_COPY_NOFOLLOW_SYMLINKS is specified then symlinks - * will be copied as symlinks, otherwise the target of the - * @source symlink will be copied. - * * If @cancellable is not %NULL, then the operation can be cancelled by * triggering the cancellable object from another thread. If the operation * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. @@ -3759,7 +3755,7 @@ g_file_move (GFile *source, return FALSE; } - flags |= G_FILE_COPY_ALL_METADATA; + flags |= G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS; if (!g_file_copy (source, destination, flags, cancellable, progress_callback, progress_callback_data, error)) @@ -4046,7 +4042,7 @@ g_file_make_symbolic_link (GFile *file, { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Operation not supported")); + _("Symbolic links not supported")); return FALSE; } @@ -4063,6 +4059,21 @@ g_file_make_symbolic_link (GFile *file, * Deletes a file. If the @file is a directory, it will only be * deleted if it is empty. This has the same semantics as g_unlink(). * + * If @file doesn’t exist, %G_IO_ERROR_NOT_FOUND will be returned. This allows + * for deletion to be implemented avoiding + * [time-of-check to time-of-use races](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use): + * |[ + * g_autoptr(GError) local_error = NULL; + * if (!g_file_delete (my_file, my_cancellable, &local_error) && + * !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + * { + * // deletion failed for some reason other than the file not existing: + * // so report the error + * g_warning ("Failed to delete %s: %s", + * g_file_peek_path (my_file), local_error->message); + * } + * ]| + * * If @cancellable is not %NULL, then the operation can be cancelled by * triggering the cancellable object from another thread. If the operation * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. @@ -4170,7 +4181,9 @@ g_file_delete_finish (GFile *file, * Sends @file to the "Trashcan", if possible. This is similar to * deleting it, but the user can recover it before emptying the trashcan. * Not all file systems support trashing, so this call can return the - * %G_IO_ERROR_NOT_SUPPORTED error. + * %G_IO_ERROR_NOT_SUPPORTED error. Since GLib 2.66, the `x-gvfs-notrash` unix + * mount option can be used to disable g_file_trash() support for certain + * mounts, the %G_IO_ERROR_NOT_SUPPORTED error will be returned in that case. * * If @cancellable is not %NULL, then the operation can be cancelled by * triggering the cancellable object from another thread. If the operation @@ -4522,7 +4535,7 @@ g_file_query_writable_namespaces (GFile *file, * %NULL to ignore * @error: a #GError, or %NULL * - * Sets an attribute in the file with attribute name @attribute to @value. + * Sets an attribute in the file with attribute name @attribute to @value_p. * * Some attributes can be unset by setting @type to * %G_FILE_ATTRIBUTE_TYPE_INVALID and @value_p to %NULL. @@ -6875,7 +6888,8 @@ g_file_query_default_handler (GFile *file, g_free (uri_scheme); info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, 0, cancellable, error); @@ -6885,6 +6899,8 @@ g_file_query_default_handler (GFile *file, appinfo = NULL; content_type = g_file_info_get_content_type (info); + if (content_type == NULL) + content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE); if (content_type) { /* Don't use is_native(), as we want to support fuse paths if available */ @@ -6926,6 +6942,8 @@ query_default_handler_query_info_cb (GObject *object, } content_type = g_file_info_get_content_type (info); + if (content_type == NULL) + content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE); if (content_type) { char *path; @@ -6996,7 +7014,8 @@ g_file_query_default_handler_async (GFile *file, g_free (uri_scheme); g_file_query_info_async (file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, 0, io_priority, cancellable, @@ -7038,13 +7057,13 @@ g_file_query_default_handler_finish (GFile *file, * @contents: (out) (transfer full) (element-type guint8) (array length=length): a location to place the contents of the file * @length: (out) (optional): a location to place the length of the contents of the file, * or %NULL if the length is not needed - * @etag_out: (out) (optional): a location to place the current entity tag for the file, + * @etag_out: (out) (optional) (nullable): a location to place the current entity tag for the file, * or %NULL if the entity tag is not needed * @error: a #GError, or %NULL * * Loads the content of the file into memory. The data is always * zero-terminated, but this is not included in the resultant @length. - * The returned @content should be freed with g_free() when no longer + * The returned @contents should be freed with g_free() when no longer * needed. * * If @cancellable is not %NULL, then the operation can be cancelled by @@ -7326,14 +7345,14 @@ g_file_load_partial_contents_async (GFile *file, * @contents: (out) (transfer full) (element-type guint8) (array length=length): a location to place the contents of the file * @length: (out) (optional): a location to place the length of the contents of the file, * or %NULL if the length is not needed - * @etag_out: (out) (optional): a location to place the current entity tag for the file, + * @etag_out: (out) (optional) (nullable): a location to place the current entity tag for the file, * or %NULL if the entity tag is not needed * @error: a #GError, or %NULL * * Finishes an asynchronous partial load operation that was started * with g_file_load_partial_contents_async(). The data is always * zero-terminated, but this is not included in the resultant @length. - * The returned @content should be freed with g_free() when no longer + * The returned @contents should be freed with g_free() when no longer * needed. * * Returns: %TRUE if the load was successful. If %FALSE and @error is @@ -7424,13 +7443,13 @@ g_file_load_contents_async (GFile *file, * @contents: (out) (transfer full) (element-type guint8) (array length=length): a location to place the contents of the file * @length: (out) (optional): a location to place the length of the contents of the file, * or %NULL if the length is not needed - * @etag_out: (out) (optional): a location to place the current entity tag for the file, + * @etag_out: (out) (optional) (nullable): a location to place the current entity tag for the file, * or %NULL if the entity tag is not needed * @error: a #GError, or %NULL * * Finishes an asynchronous load of the @file's contents. * The contents are placed in @contents, and @length is set to the - * size of the @contents string. The @content should be freed with + * size of the @contents string. The @contents should be freed with * g_free() when no longer needed. If @etag_out is present, it will be * set to the new entity tag for the @file. * @@ -7462,7 +7481,7 @@ g_file_load_contents_finish (GFile *file, * or %NULL * @make_backup: %TRUE if a backup should be created * @flags: a set of #GFileCreateFlags - * @new_etag: (out) (optional): a location to a new [entity tag][gfile-etag] + * @new_etag: (out) (optional) (nullable): a location to a new [entity tag][gfile-etag] * for the document. This should be freed with g_free() when no longer * needed, or %NULL * @cancellable: optional #GCancellable object, %NULL to ignore @@ -7570,7 +7589,6 @@ replace_contents_close_callback (GObject *obj, /* Ignore errors here, we're only reading anyway */ g_output_stream_close_finish (stream, close_res, NULL); - g_object_unref (stream); if (!data->failed) { @@ -7652,6 +7670,7 @@ replace_contents_open_callback (GObject *obj, g_task_get_cancellable (data->task), replace_contents_write_callback, data); + g_object_unref (stream); /* ownership is transferred to the write_async() call above */ } else { @@ -7687,7 +7706,7 @@ replace_contents_open_callback (GObject *obj, * If @make_backup is %TRUE, this function will attempt to * make a backup of @file. * - * Note that no copy of @content will be made, so it must stay valid + * Note that no copy of @contents will be made, so it must stay valid * until @callback is called. See g_file_replace_contents_bytes_async() * for a #GBytes version that will automatically hold a reference to the * contents (without copying) for the duration of the call. @@ -7770,7 +7789,7 @@ g_file_replace_contents_bytes_async (GFile *file, * g_file_replace_contents_finish: * @file: input #GFile * @res: a #GAsyncResult - * @new_etag: (out) (optional): a location of a new [entity tag][gfile-etag] + * @new_etag: (out) (optional) (nullable): a location of a new [entity tag][gfile-etag] * for the document. This should be freed with g_free() when it is no * longer needed, or %NULL * @error: a #GError, or %NULL diff --git a/gio/gfile.h b/gio/gfile.h index 8441d0bd1e15c2e9beb18f7d3165da5553c42924..4cff1a372923759ffb2f6dc95998a365ccd4ed04 100644 --- a/gio/gfile.h +++ b/gio/gfile.h @@ -111,10 +111,13 @@ typedef struct _GFileIface GFileIface; * @make_directory: Makes a directory. * @make_directory_async: Asynchronously makes a directory. * @make_directory_finish: Finishes making a directory asynchronously. - * @make_symbolic_link: Makes a symbolic link. + * @make_symbolic_link: (nullable): Makes a symbolic link. %NULL if symbolic + * links are unsupported. * @_make_symbolic_link_async: Asynchronously makes a symbolic link * @_make_symbolic_link_finish: Finishes making a symbolic link asynchronously. - * @copy: Copies a file. + * @copy: (nullable): Copies a file. %NULL if copying is unsupported, which will + * cause `GFile` to use a fallback copy method where it reads from the + * source and writes to the destination. * @copy_async: Asynchronously copies a file. * @copy_finish: Finishes an asynchronous copy operation. * @move: Moves a file. @@ -1091,6 +1094,12 @@ gboolean g_file_eject_mountable_with_operation_finish (GFile GAsyncResult *result, GError **error); +GLIB_AVAILABLE_IN_2_68 +char * g_file_build_attribute_list_for_copy (GFile *file, + GFileCopyFlags flags, + GCancellable *cancellable, + GError **error); + GLIB_AVAILABLE_IN_ALL gboolean g_file_copy_attributes (GFile *source, GFile *destination, diff --git a/gio/gfileattribute.c b/gio/gfileattribute.c index 0e4bfc28f308f1ae8978aee34b8bb048a9eba6e4..8075d1d53505eda79208b41e53c9308addc64513 100644 --- a/gio/gfileattribute.c +++ b/gio/gfileattribute.c @@ -38,7 +38,7 @@ * * Keys are strings that contain a key namespace and a key name, separated * by a colon, e.g. "namespace::keyname". Namespaces are included to sort - * key-value pairs by namespaces for relevance. Keys can be retrived + * key-value pairs by namespaces for relevance. Keys can be retrieved * using wildcards, e.g. "standard::*" will return all of the keys in the * "standard" namespace. * @@ -274,8 +274,8 @@ valid_char (char c) static char * escape_byte_string (const char *str) { - size_t len; - int num_invalid, i; + size_t i, len; + int num_invalid; char *escaped_val, *p; unsigned char c; const char hex_digits[] = "0123456789abcdef"; diff --git a/gio/gfiledescriptorbased.h b/gio/gfiledescriptorbased.h index 1709c5f05aee4cf10a5be876451c5ec63b411652..0a2516e169b5f1c4163e6687df545b42c17f2733 100644 --- a/gio/gfiledescriptorbased.h +++ b/gio/gfiledescriptorbased.h @@ -63,4 +63,3 @@ G_END_DECLS #endif /* __G_FILE_DESCRIPTOR_BASED_H__ */ - diff --git a/gio/gfileenumerator.c b/gio/gfileenumerator.c index d96a798af1d3ea88269c83b505da0552abab9f6a..ac2e4eb980e3e5a101335a52e145e3fc4e897666 100644 --- a/gio/gfileenumerator.c +++ b/gio/gfileenumerator.c @@ -866,4 +866,3 @@ g_file_enumerator_real_close_finish (GFileEnumerator *enumerator, return g_task_propagate_boolean (G_TASK (result), error); } - diff --git a/gio/gfileicon.c b/gio/gfileicon.c index 48d4c82890990c3d4029c9136e4d436279c2d348..2f28d48f8af23a052c99fa1c40f0b092bfb3e521 100644 --- a/gio/gfileicon.c +++ b/gio/gfileicon.c @@ -111,6 +111,19 @@ g_file_icon_set_property (GObject *object, } } +static void +g_file_icon_constructed (GObject *object) +{ +#ifndef G_DISABLE_ASSERT + GFileIcon *icon = G_FILE_ICON (object); +#endif + + G_OBJECT_CLASS (g_file_icon_parent_class)->constructed (object); + + /* Must have be set during construction */ + g_assert (icon->file != NULL); +} + static void g_file_icon_finalize (GObject *object) { @@ -132,6 +145,7 @@ g_file_icon_class_init (GFileIconClass *klass) gobject_class->get_property = g_file_icon_get_property; gobject_class->set_property = g_file_icon_set_property; gobject_class->finalize = g_file_icon_finalize; + gobject_class->constructed = g_file_icon_constructed; /** * GFileIcon:file: @@ -174,7 +188,7 @@ g_file_icon_new (GFile *file) * * Gets the #GFile associated with the given @icon. * - * Returns: (transfer none): a #GFile, or %NULL. + * Returns: (transfer none): a #GFile. **/ GFile * g_file_icon_get_file (GFileIcon *icon) diff --git a/gio/gfileinfo.c b/gio/gfileinfo.c index 032d2114471e7244ef536860521a05ed6aded5e4..2a97758b2983fe090d30d0b1c14601564e525ce1 100644 --- a/gio/gfileinfo.c +++ b/gio/gfileinfo.c @@ -318,7 +318,7 @@ static void g_file_info_finalize (GObject *object) { GFileInfo *info; - int i; + guint i; GFileAttribute *attrs; info = G_FILE_INFO (object); @@ -376,7 +376,7 @@ g_file_info_copy_into (GFileInfo *src_info, GFileInfo *dest_info) { GFileAttribute *source, *dest; - int i; + guint i; g_return_if_fail (G_IS_FILE_INFO (src_info)); g_return_if_fail (G_IS_FILE_INFO (dest_info)); @@ -439,7 +439,7 @@ g_file_info_set_attribute_mask (GFileInfo *info, GFileAttributeMatcher *mask) { GFileAttribute *attr; - int i; + guint i; g_return_if_fail (G_IS_FILE_INFO (info)); @@ -491,7 +491,7 @@ void g_file_info_clear_status (GFileInfo *info) { GFileAttribute *attrs; - int i; + guint i; g_return_if_fail (G_IS_FILE_INFO (info)); @@ -536,7 +536,7 @@ g_file_info_find_value (GFileInfo *info, guint32 attr_id) { GFileAttribute *attrs; - int i; + guint i; i = g_file_info_find_place (info, attr_id); attrs = (GFileAttribute *)info->attributes->data; @@ -564,7 +564,7 @@ g_file_info_find_value_by_name (GFileInfo *info, * * Checks if a file info structure has an attribute named @attribute. * - * Returns: %TRUE if @Ginfo has an attribute named @attribute, + * Returns: %TRUE if @info has an attribute named @attribute, * %FALSE otherwise. **/ gboolean @@ -588,7 +588,7 @@ g_file_info_has_attribute (GFileInfo *info, * Checks if a file info structure has an attribute in the * specified @name_space. * - * Returns: %TRUE if @Ginfo has an attribute in @name_space, + * Returns: %TRUE if @info has an attribute in @name_space, * %FALSE otherwise. * * Since: 2.22 @@ -599,7 +599,7 @@ g_file_info_has_namespace (GFileInfo *info, { GFileAttribute *attrs; guint32 ns_id; - int i; + guint i; g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE); g_return_val_if_fail (name_space != NULL, FALSE); @@ -636,7 +636,7 @@ g_file_info_list_attributes (GFileInfo *info, GFileAttribute *attrs; guint32 attribute; guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0; - int i; + guint i; g_return_val_if_fail (G_IS_FILE_INFO (info), NULL); @@ -694,7 +694,7 @@ g_file_info_remove_attribute (GFileInfo *info, { guint32 attr_id; GFileAttribute *attrs; - int i; + guint i; g_return_if_fail (G_IS_FILE_INFO (info)); g_return_if_fail (attribute != NULL && *attribute != '\0'); @@ -734,6 +734,9 @@ g_file_info_get_attribute_data (GFileInfo *info, { GFileAttributeValue *value; + g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE); + g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE); + value = g_file_info_find_value_by_name (info, attribute); if (value == NULL) return FALSE; @@ -830,7 +833,7 @@ _g_file_info_get_attribute_value (GFileInfo *info, * @info: a #GFileInfo. * @attribute: a file attribute key. * - * Gets the value of a attribute, formated as a string. + * Gets the value of a attribute, formatted as a string. * This escapes things as needed to make the string valid * UTF-8. * @@ -858,8 +861,8 @@ g_file_info_get_attribute_as_string (GFileInfo *info, * Gets the value of a #GObject attribute. If the attribute does * not contain a #GObject, %NULL will be returned. * - * Returns: (transfer none): a #GObject associated with the given @attribute, or - * %NULL otherwise. + * Returns: (transfer none) (nullable): a #GObject associated with the given @attribute, + * or %NULL otherwise. **/ GObject * g_file_info_get_attribute_object (GFileInfo *info, @@ -882,8 +885,8 @@ g_file_info_get_attribute_object (GFileInfo *info, * Gets the value of a string attribute. If the attribute does * not contain a string, %NULL will be returned. * - * Returns: the contents of the @attribute value as a UTF-8 string, or - * %NULL otherwise. + * Returns: (nullable): the contents of the @attribute value as a UTF-8 string, + * or %NULL otherwise. **/ const char * g_file_info_get_attribute_string (GFileInfo *info, @@ -906,7 +909,7 @@ g_file_info_get_attribute_string (GFileInfo *info, * Gets the value of a byte string attribute. If the attribute does * not contain a byte string, %NULL will be returned. * - * Returns: the contents of the @attribute value as a byte string, or + * Returns: (nullable): the contents of the @attribute value as a byte string, or * %NULL otherwise. **/ const char * @@ -930,8 +933,8 @@ g_file_info_get_attribute_byte_string (GFileInfo *info, * Gets the value of a stringv attribute. If the attribute does * not contain a stringv, %NULL will be returned. * - * Returns: (transfer none): the contents of the @attribute value as a stringv, or - * %NULL otherwise. Do not free. These returned strings are UTF-8. + * Returns: (transfer none) (nullable): the contents of the @attribute value as a stringv, + * or %NULL otherwise. Do not free. These returned strings are UTF-8. * * Since: 2.22 **/ @@ -1072,7 +1075,7 @@ g_file_info_create_value (GFileInfo *info, guint32 attr_id) { GFileAttribute *attrs; - int i; + guint i; if (info->mask != NO_ATTRIBUTE_MASK && !_g_file_attribute_matcher_matches_id (info->mask, attr_id)) @@ -1454,7 +1457,7 @@ g_file_info_set_attribute_int64 (GFileInfo *info, * available in G_FILE_ATTRIBUTE_TRASH_DELETION_DATE. If the * G_FILE_ATTRIBUTE_TRASH_DELETION_DATE attribute is unset, %NULL is returned. * - * Returns: a #GDateTime, or %NULL. + * Returns: (nullable): a #GDateTime, or %NULL. * * Since: 2.36 **/ @@ -1581,9 +1584,9 @@ g_file_info_get_is_symlink (GFileInfo *info) * g_file_info_get_name: * @info: a #GFileInfo. * - * Gets the name for a file. + * Gets the name for a file. This is guaranteed to always be set. * - * Returns: (type filename): a string containing the file name. + * Returns: (type filename) (not nullable): a string containing the file name. **/ const char * g_file_info_get_name (GFileInfo *info) @@ -1604,9 +1607,9 @@ g_file_info_get_name (GFileInfo *info) * g_file_info_get_display_name: * @info: a #GFileInfo. * - * Gets a display name for a file. + * Gets a display name for a file. This is guaranteed to always be set. * - * Returns: a string containing the display name. + * Returns: (not nullable): a string containing the display name. **/ const char * g_file_info_get_display_name (GFileInfo *info) @@ -1652,7 +1655,7 @@ g_file_info_get_edit_name (GFileInfo *info) * * Gets the icon for a file. * - * Returns: (transfer none): #GIcon for the given @info. + * Returns: (nullable) (transfer none): #GIcon for the given @info. **/ GIcon * g_file_info_get_icon (GFileInfo *info) @@ -1679,7 +1682,7 @@ g_file_info_get_icon (GFileInfo *info) * * Gets the symbolic icon for a file. * - * Returns: (transfer none): #GIcon for the given @info. + * Returns: (nullable) (transfer none): #GIcon for the given @info. * * Since: 2.34 **/ @@ -1708,7 +1711,8 @@ g_file_info_get_symbolic_icon (GFileInfo *info) * * Gets the file's content type. * - * Returns: a string containing the file's content type. + * Returns: (nullable): a string containing the file's content type, + * or %NULL if unknown. **/ const char * g_file_info_get_content_type (GFileInfo *info) @@ -1729,9 +1733,11 @@ g_file_info_get_content_type (GFileInfo *info) * g_file_info_get_size: * @info: a #GFileInfo. * - * Gets the file's size. + * Gets the file's size (in bytes). The size is retrieved through the value of + * the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute and is converted + * from #guint64 to #goffset before returning the result. * - * Returns: a #goffset containing the file's size. + * Returns: a #goffset containing the file's size (in bytes). **/ goffset g_file_info_get_size (GFileInfo *info) @@ -1834,7 +1840,7 @@ g_file_info_get_modification_date_time (GFileInfo *info) * * Gets the symlink target for a given #GFileInfo. * - * Returns: a string containing the symlink target. + * Returns: (nullable): a string containing the symlink target. **/ const char * g_file_info_get_symlink_target (GFileInfo *info) @@ -1858,7 +1864,7 @@ g_file_info_get_symlink_target (GFileInfo *info) * Gets the [entity tag][gfile-etag] for a given * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE. * - * Returns: a string containing the value of the "etag:value" attribute. + * Returns: (nullable): a string containing the value of the "etag:value" attribute. **/ const char * g_file_info_get_etag (GFileInfo *info) @@ -2163,8 +2169,9 @@ g_file_info_set_size (GFileInfo *info, * @info: a #GFileInfo. * @mtime: a #GTimeVal. * - * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED attribute in the file - * info to the given time value. + * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and + * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the + * given time value. * * Deprecated: 2.62: Use g_file_info_set_modification_date_time() instead, as * #GTimeVal is deprecated due to the year 2038 problem. @@ -2200,8 +2207,9 @@ G_GNUC_END_IGNORE_DEPRECATIONS * @info: a #GFileInfo. * @mtime: (not nullable): a #GDateTime. * - * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED attribute in the file - * info to the given date/time value. + * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and + * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the + * given date/time value. * * Since: 2.62 */ @@ -2292,7 +2300,7 @@ struct _GFileAttributeMatcher { GArray *sub_matchers; - /* Interator */ + /* Iterator */ guint32 iterator_ns; gint iterator_pos; }; @@ -2389,7 +2397,7 @@ matcher_optimize (GFileAttributeMatcher *matcher) * the number of references falls to 0, the #GFileAttributeMatcher is * automatically destroyed. * - * The @attribute string should be formatted with specific keys separated + * The @attributes string should be formatted with specific keys separated * from namespaces with a double colon. Several "namespace::key" strings may be * concatenated with a single comma (e.g. "standard::type,standard::is-hidden"). * The wildcard "*" may be used to match all keys and namespaces, or @@ -2461,8 +2469,8 @@ g_file_attribute_matcher_new (const char *attributes) /** * g_file_attribute_matcher_subtract: - * @matcher: Matcher to subtract from - * @subtract: The matcher to subtract + * @matcher: (nullable): Matcher to subtract from + * @subtract: (nullable): The matcher to subtract * * Subtracts all attributes of @subtract from @matcher and returns * a matcher that supports those attributes. @@ -2473,7 +2481,7 @@ g_file_attribute_matcher_new (const char *attributes) * is a limitation of the current implementation, but may be fixed * in the future. * - * Returns: A file attribute matcher matching all attributes of + * Returns: (nullable): A file attribute matcher matching all attributes of * @matcher that are not matched by @subtract **/ GFileAttributeMatcher * @@ -2613,7 +2621,7 @@ matcher_matches_id (GFileAttributeMatcher *matcher, guint32 id) { SubMatcher *sub_matchers; - int i; + guint i; if (matcher->sub_matchers) { @@ -2690,8 +2698,8 @@ g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher, const char *ns) { SubMatcher *sub_matchers; - int ns_id; - int i; + guint ns_id; + guint i; g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE); @@ -2726,13 +2734,13 @@ g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher, * * Gets the next matched attribute from a #GFileAttributeMatcher. * - * Returns: a string containing the next attribute or %NULL if + * Returns: (nullable): a string containing the next attribute or, %NULL if * no more attribute exist. **/ const char * g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher) { - int i; + guint i; SubMatcher *sub_matcher; /* We return a NULL matcher for an empty match string, so handle this */ diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h index 1629a2edb1cfcb508256fe7f9144a4466750d45a..da202e6a7058b7e1af183efb9654708077a05c19 100644 --- a/gio/gfileinfo.h +++ b/gio/gfileinfo.h @@ -108,7 +108,8 @@ typedef struct _GFileInfoClass GFileInfoClass; * * A key in the "standard" namespace for getting the name of the file. * The name is the on-disk filename which may not be in any known encoding, - * and can thus not be generally displayed as is. + * and can thus not be generally displayed as is. It is guaranteed to be set on + * every file. * Use #G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME if you need to display the * name in a user interface. * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING. @@ -119,8 +120,8 @@ typedef struct _GFileInfoClass GFileInfoClass; * G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME: * * A key in the "standard" namespace for getting the display name of the file. - * A display name is guaranteed to be in UTF8 and can thus be displayed in - * the UI. + * A display name is guaranteed to be in UTF-8 and can thus be displayed in + * the UI. It is guaranteed to be set on every file. * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_STRING. **/ #define G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "standard::display-name" /* string */ @@ -157,7 +158,7 @@ typedef struct _GFileInfoClass GFileInfoClass; * * A key in the "standard" namespace for getting the description of the file. * The description is a utf8 string that describes the file, generally containing - * the filename, but can also contain furter information. Example descriptions + * the filename, but can also contain further information. Example descriptions * could be "filename (on hostname)" for a remote file or "filename (in trash)" * for a file in the trash. This is useful for instance as the window title * when displaying a directory or for a bookmarks menu. @@ -539,7 +540,8 @@ typedef struct _GFileInfoClass GFileInfoClass; * and contains the time since the file was created, in seconds since the UNIX * epoch. * - * This corresponds to the NTFS ctime. + * This may correspond to Linux stx_btime, FreeBSD st_birthtim, NetBSD + * st_birthtime or NTFS ctime. **/ #define G_FILE_ATTRIBUTE_TIME_CREATED "time::created" /* uint64 */ @@ -578,8 +580,10 @@ typedef struct _GFileInfoClass GFileInfoClass; * G_FILE_ATTRIBUTE_UNIX_MODE: * * A key in the "unix" namespace for getting the mode of the file - * (e.g. whether the file is a regular file, symlink, etc). See lstat() - * documentation. This attribute is only available for UNIX file systems. + * (e.g. whether the file is a regular file, symlink, etc). See the + * documentation for `lstat()`: this attribute is equivalent to the `st_mode` + * member of `struct stat`, and includes both the file type and permissions. + * This attribute is only available for UNIX file systems. * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_UINT32. **/ #define G_FILE_ATTRIBUTE_UNIX_MODE "unix::mode" /* uint32 */ diff --git a/gio/gfileiostream.c b/gio/gfileiostream.c index 5919c28c020009aff324b12cf9277a2152574d71..f599bcdce09b3c789cc455da632c636a547c4287 100644 --- a/gio/gfileiostream.c +++ b/gio/gfileiostream.c @@ -277,7 +277,7 @@ g_file_io_stream_query_info_finish (GFileIOStream *stream, * This must be called after the stream has been written * and closed, as the etag can change while writing. * - * Returns: the entity tag for the stream. + * Returns: (nullable) (transfer full): the entity tag for the stream. * * Since: 2.22 **/ diff --git a/gio/gfilenamecompleter.c b/gio/gfilenamecompleter.c index 5883b8004717254d8e391ed52973719e6d1828a8..a290c032275bde4c6b7aaad53e4786aab11a4e8a 100644 --- a/gio/gfilenamecompleter.c +++ b/gio/gfilenamecompleter.c @@ -278,7 +278,7 @@ got_enum (GObject *source_object, g_object_unref (data->completer->basenames_dir); g_list_free_full (data->completer->basenames, g_free); - /* Mark uptodate with no basenames */ + /* Mark up-to-date with no basenames */ data->completer->basenames_dir = g_object_ref (data->dir); data->completer->basenames = NULL; data->completer->basenames_are_escaped = data->should_escape; @@ -404,9 +404,9 @@ init_completion (GFilenameCompleter *completer, * * Obtains a completion for @initial_text from @completer. * - * Returns: a completed string, or %NULL if no completion exists. - * This string is not owned by GIO, so remember to g_free() it - * when finished. + * Returns: (nullable) (transfer full): a completed string, or %NULL if no + * completion exists. This string is not owned by GIO, so remember to g_free() + * it when finished. **/ char * g_filename_completer_get_completion_suffix (GFilenameCompleter *completer, diff --git a/gio/gfileoutputstream.c b/gio/gfileoutputstream.c index d0839c2b21e1ae6648d5e0c12298c7b5a9787b40..1dc536febac093c20b2172176ca8d9a04e07d21d 100644 --- a/gio/gfileoutputstream.c +++ b/gio/gfileoutputstream.c @@ -271,7 +271,7 @@ g_file_output_stream_query_info_finish (GFileOutputStream *stream, * This must be called after the stream has been written * and closed, as the etag can change while writing. * - * Returns: the entity tag for the stream. + * Returns: (nullable) (transfer full): the entity tag for the stream. **/ char * g_file_output_stream_get_etag (GFileOutputStream *stream) diff --git a/gio/ghttpproxy.c b/gio/ghttpproxy.c index 554e85ec32ce5038a78c9b107b8273873d10b68c..505a8fecbecbcd95f0de0f78216b01a3ef847ed3 100644 --- a/gio/ghttpproxy.c +++ b/gio/ghttpproxy.c @@ -190,7 +190,7 @@ g_http_proxy_connect (GProxy *proxy, GOutputStream *out; gchar *buffer = NULL; gsize buffer_length; - gssize bytes_read; + gsize bytes_read; gboolean has_cred; GIOStream *tlsconn = NULL; @@ -239,12 +239,15 @@ g_http_proxy_connect (GProxy *proxy, */ do { + gssize signed_nread; gsize nread; - nread = g_input_stream_read (in, buffer + bytes_read, 1, cancellable, error); - if (nread == -1) + signed_nread = + g_input_stream_read (in, buffer + bytes_read, 1, cancellable, error); + if (signed_nread == -1) goto error; + nread = signed_nread; if (nread == 0) break; @@ -252,6 +255,17 @@ g_http_proxy_connect (GProxy *proxy, if (bytes_read == buffer_length) { + /* HTTP specifications does not defines any upper limit for + * headers. But, the most usual size used seems to be 8KB. + * Yet, the biggest we found was Tomcat's HTTP headers whose + * size is 48K. So, for a reasonable error margin, let's accept + * a header with a twice as large size but no more: 96KB */ + if (buffer_length > 98304) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, + _("HTTP proxy response too big")); + goto error; + } buffer_length = 2 * buffer_length; buffer = g_realloc (buffer, buffer_length); } diff --git a/gio/gicon.c b/gio/gicon.c index 4f73d7568ee9fd88e4ae4f33bb8e68970ea1a26e..29fae1068baaf4e98d08b8bd3a3a52b29bdb2142 100644 --- a/gio/gicon.c +++ b/gio/gicon.c @@ -138,7 +138,7 @@ g_icon_to_string_tokenized (GIcon *icon, GString *s) GPtrArray *tokens; gint version; GIconIface *icon_iface; - int i; + guint i; g_return_val_if_fail (icon != NULL, FALSE); g_return_val_if_fail (G_IS_ICON (icon), FALSE); @@ -558,11 +558,11 @@ g_icon_deserialize_emblemed (GVariant *value) /** * g_icon_deserialize: - * @value: a #GVariant created with g_icon_serialize() + * @value: (transfer none): a #GVariant created with g_icon_serialize() * * Deserializes a #GIcon previously serialized using g_icon_serialize(). * - * Returns: (transfer full): a #GIcon, or %NULL when deserialization fails. + * Returns: (nullable) (transfer full): a #GIcon, or %NULL when deserialization fails. * * Since: 2.38 */ @@ -653,7 +653,7 @@ g_icon_deserialize (GVariant *value) * makes sense to transfer the #GVariant between processes on the same machine, * (as opposed to over the network), and within the same file system namespace. * - * Returns: (transfer full): a #GVariant, or %NULL when serialization fails. + * Returns: (nullable) (transfer full): a #GVariant, or %NULL when serialization fails. The #GVariant will not be floating. * * Since: 2.38 */ diff --git a/gio/ginetaddress.c b/gio/ginetaddress.c index 787c757da60d42f153bfc8f663dabd855d65cc91..ada32f8779af51c38f33b2837c5450c9f73fe4a6 100644 --- a/gio/ginetaddress.c +++ b/gio/ginetaddress.c @@ -31,19 +31,14 @@ #include "glibintl.h" #include "gnetworkingprivate.h" -#ifdef G_OS_WIN32 -/* Ensure Windows XP runtime compatibility, while using - * inet_pton() and inet_ntop() if available - */ -#include "gwin32networking.h" -#endif - struct _GInetAddressPrivate { GSocketFamily family; union { struct in_addr ipv4; +#ifdef HAVE_IPV6 struct in6_addr ipv6; +#endif } addr; }; @@ -106,10 +101,16 @@ g_inet_address_set_property (GObject *object, break; case PROP_BYTES: +#ifdef HAVE_IPV6 memcpy (&address->priv->addr, g_value_get_pointer (value), address->priv->family == AF_INET ? sizeof (address->priv->addr.ipv4) : sizeof (address->priv->addr.ipv6)); +#else + g_assert (address->priv->family == AF_INET); + memcpy (&address->priv->addr, g_value_get_pointer (value), + sizeof (address->priv->addr.ipv4)); +#endif break; default: @@ -382,8 +383,8 @@ g_inet_address_init (GInetAddress *address) * * Parses @string as an IP address and creates a new #GInetAddress. * - * Returns: a new #GInetAddress corresponding to @string, or %NULL if - * @string could not be parsed. + * Returns: (nullable) (transfer full): a new #GInetAddress corresponding + * to @string, or %NULL if @string could not be parsed. * Free the returned object with g_object_unref(). * * Since: 2.22 @@ -392,7 +393,9 @@ GInetAddress * g_inet_address_new_from_string (const gchar *string) { struct in_addr in_addr; +#ifdef HAVE_IPV6 struct in6_addr in6_addr; +#endif g_return_val_if_fail (string != NULL, NULL); @@ -404,8 +407,10 @@ g_inet_address_new_from_string (const gchar *string) if (inet_pton (AF_INET, string, &in_addr) > 0) return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET); +#ifdef HAVE_IPV6 else if (inet_pton (AF_INET6, string, &in6_addr) > 0) return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6); +#endif return NULL; } @@ -462,7 +467,11 @@ g_inet_address_new_loopback (GSocketFamily family) return g_inet_address_new_from_bytes (addr, family); } else +#ifdef HAVE_IPV6 return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family); +#else + g_assert_not_reached (); +#endif } /** @@ -490,7 +499,11 @@ g_inet_address_new_any (GSocketFamily family) return g_inet_address_new_from_bytes (addr, family); } else +#ifdef HAVE_IPV6 return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family); +#else + g_assert_not_reached (); +#endif } @@ -513,11 +526,19 @@ g_inet_address_to_string (GInetAddress *address) g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL); if (address->priv->family == AF_INET) - inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer)); + { + inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer)); + return g_strdup (buffer); + } else - inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer)); - - return g_strdup (buffer); + { +#ifdef HAVE_IPV6 + inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer)); + return g_strdup (buffer); +#else + g_assert_not_reached (); +#endif + } } /** @@ -556,7 +577,11 @@ g_inet_address_get_native_size (GInetAddress *address) { if (address->priv->family == AF_INET) return sizeof (address->priv->addr.ipv4); +#ifdef HAVE_IPV6 return sizeof (address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -599,7 +624,11 @@ g_inet_address_get_is_any (GInetAddress *address) return addr4 == INADDR_ANY; } else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -625,7 +654,11 @@ g_inet_address_get_is_loopback (GInetAddress *address) return ((addr4 & 0xff000000) == 0x7f000000); } else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -653,7 +686,11 @@ g_inet_address_get_is_link_local (GInetAddress *address) return ((addr4 & 0xffff0000) == 0xa9fe0000); } else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -684,7 +721,11 @@ g_inet_address_get_is_site_local (GInetAddress *address) (addr4 & 0xffff0000) == 0xc0a80000); } else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -709,7 +750,11 @@ g_inet_address_get_is_multicast (GInetAddress *address) return IN_MULTICAST (addr4); } else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -730,7 +775,11 @@ g_inet_address_get_is_mc_global (GInetAddress *address) if (address->priv->family == AF_INET) return FALSE; else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -751,7 +800,11 @@ g_inet_address_get_is_mc_link_local (GInetAddress *address) if (address->priv->family == AF_INET) return FALSE; else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -772,7 +825,11 @@ g_inet_address_get_is_mc_node_local (GInetAddress *address) if (address->priv->family == AF_INET) return FALSE; else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -793,7 +850,11 @@ g_inet_address_get_is_mc_org_local (GInetAddress *address) if (address->priv->family == AF_INET) return FALSE; else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** @@ -814,7 +875,11 @@ g_inet_address_get_is_mc_site_local (GInetAddress *address) if (address->priv->family == AF_INET) return FALSE; else +#ifdef HAVE_IPV6 return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6); +#else + g_assert_not_reached (); +#endif } /** diff --git a/gio/ginetaddress.h b/gio/ginetaddress.h index 2963affa4b6e75df814636a177d9744cbb66f15a..87bb4e57067c149cb0ca34f7ea0928951f5453c2 100644 --- a/gio/ginetaddress.h +++ b/gio/ginetaddress.h @@ -121,4 +121,3 @@ gboolean g_inet_address_get_is_mc_site_local (GInetAddress G_END_DECLS #endif /* __G_INET_ADDRESS_H__ */ - diff --git a/gio/ginetaddressmask.h b/gio/ginetaddressmask.h index ce5e285c6e855aeec7764e5af5526b0b8b59a86b..1e73281dcef2048c6b90b548be6e0e423cb0b85d 100644 --- a/gio/ginetaddressmask.h +++ b/gio/ginetaddressmask.h @@ -82,4 +82,3 @@ gboolean g_inet_address_mask_equal (GInetAddressMask *mask, G_END_DECLS #endif /* __G_INET_ADDRESS_MASK_H__ */ - diff --git a/gio/ginetsocketaddress.c b/gio/ginetsocketaddress.c index 81a527f6d64a0ba5905dd885420a78de92d72bbe..d7c8134510b84968df63f2c58fddd0ad538f81d5 100644 --- a/gio/ginetsocketaddress.c +++ b/gio/ginetsocketaddress.c @@ -398,8 +398,8 @@ g_inet_socket_address_new (GInetAddress *address, * If @address is an IPv6 address, it can also contain a scope ID * (separated from the address by a `%`). * - * Returns: a new #GInetSocketAddress, or %NULL if @address cannot be - * parsed. + * Returns: (nullable) (transfer full): a new #GInetSocketAddress, + * or %NULL if @address cannot be parsed. * * Since: 2.40 */ diff --git a/gio/ginitable.c b/gio/ginitable.c index f3fd76ffcc123fadc13ffedb65270b1df88add6b..1670a43d985cd72267816655c5f2cf3fca522e92 100644 --- a/gio/ginitable.c +++ b/gio/ginitable.c @@ -50,7 +50,7 @@ * unreferenced). * * For bindings in languages where the native constructor supports - * exceptions the binding could check for objects implemention %GInitable + * exceptions the binding could check for objects implementing %GInitable * during normal construction and automatically initialize them, throwing * an exception on failure. */ diff --git a/gio/ginputstream.c b/gio/ginputstream.c index 20cece53da08ac8a23af96c3b42838ef4a060d16..3834951621ad1b33fd6310f26ad8b0ba9fc37331 100644 --- a/gio/ginputstream.c +++ b/gio/ginputstream.c @@ -411,12 +411,41 @@ g_input_stream_real_skip (GInputStream *stream, if (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream))) { + GSeekable *seekable = G_SEEKABLE (stream); + goffset start, end; + gboolean success; + + /* g_seekable_seek() may try to set pending itself */ + stream->priv->pending = FALSE; + + start = g_seekable_tell (seekable); + if (g_seekable_seek (G_SEEKABLE (stream), - count, - G_SEEK_CUR, - cancellable, - NULL)) - return count; + 0, + G_SEEK_END, + cancellable, + NULL)) + { + end = g_seekable_tell (seekable); + g_assert (end >= start); + if (start > G_MAXSIZE - count || start + count > end) + { + stream->priv->pending = TRUE; + return end - start; + } + + success = g_seekable_seek (G_SEEKABLE (stream), + start + count, + G_SEEK_SET, + cancellable, + error); + stream->priv->pending = TRUE; + + if (success) + return count; + else + return -1; + } } /* If not seekable, or seek failed, fall back to reading data: */ diff --git a/gio/gio-querymodules-wrapper.py b/gio/gio-querymodules-wrapper.py index 8960540b49cce089f912c200f41690ef7052bec2..351700d39d2a7f42d648db32a72eb1c149f8f51c 100644 --- a/gio/gio-querymodules-wrapper.py +++ b/gio/gio-querymodules-wrapper.py @@ -4,6 +4,6 @@ import os import subprocess import sys -if not os.environ.get('DESTDIR'): - print('GIO module cache creation...') - subprocess.call([sys.argv[1], sys.argv[2]]) +if not os.environ.get("DESTDIR"): + print("GIO module cache creation...") + subprocess.call([sys.argv[1], sys.argv[2]]) diff --git a/gio/gio-tool-copy.c b/gio/gio-tool-copy.c index 4cc4a9d968b94cd1bb981c797acff574c717433f..0083eba0895522441fecd417c6092b10b8f9dec1 100644 --- a/gio/gio-tool-copy.c +++ b/gio/gio-tool-copy.c @@ -37,6 +37,7 @@ static gboolean interactive = FALSE; static gboolean preserve = FALSE; static gboolean backup = FALSE; static gboolean no_dereference = FALSE; +static gboolean default_permissions = FALSE; static const GOptionEntry entries[] = { { "no-target-directory", 'T', 0, G_OPTION_ARG_NONE, &no_target_directory, N_("No target directory"), NULL }, @@ -45,6 +46,7 @@ static const GOptionEntry entries[] = { { "preserve", 'p', 0, G_OPTION_ARG_NONE, &preserve, N_("Preserve all attributes"), NULL }, { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, N_("Backup existing destination files"), NULL }, { "no-dereference", 'P', 0, G_OPTION_ARG_NONE, &no_dereference, N_("Never follow symbolic links"), NULL }, + { "default-permissions", 0, 0, G_OPTION_ARG_NONE, &default_permissions, N_("Use default permissions for the destination"), NULL }, { NULL } }; @@ -175,6 +177,8 @@ handle_copy (int argc, char *argv[], gboolean do_help) flags |= G_FILE_COPY_NOFOLLOW_SYMLINKS; if (preserve) flags |= G_FILE_COPY_ALL_METADATA; + if (default_permissions) + flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS; error = NULL; start_time = g_get_monotonic_time (); diff --git a/gio/gio-tool-info.c b/gio/gio-tool-info.c index d6fc6b46c5deb2cac0c1d829ab4e143264bf6a9a..a06263545c34e82be359329474c7f17c9327c837 100644 --- a/gio/gio-tool-info.c +++ b/gio/gio-tool-info.c @@ -22,8 +22,11 @@ #include #include -#include "gio-tool.h" +#ifdef G_OS_UNIX +#include +#endif +#include "gio-tool.h" static gboolean writable = FALSE; static gboolean filesystem = FALSE; @@ -120,6 +123,10 @@ show_info (GFile *file, GFileInfo *info) const char *name, *type; char *escaped, *uri; goffset size; + const char *path; +#ifdef G_OS_UNIX + GUnixMountEntry *entry; +#endif name = g_file_info_get_display_name (info); if (name) @@ -159,6 +166,57 @@ show_info (GFile *file, GFileInfo *info) g_print (_("uri: %s\n"), uri); g_free (uri); + path = g_file_peek_path (file); + if (path) + { + g_print (_("local path: %s\n"), path); + +#ifdef G_OS_UNIX + entry = g_unix_mount_at (path, NULL); + if (entry == NULL) + entry = g_unix_mount_for (path, NULL); + if (entry != NULL) + { + gchar *device; + const gchar *root; + gchar *root_string = NULL; + gchar *mount; + gchar *fs; + const gchar *options; + gchar *options_string = NULL; + + device = g_strescape (g_unix_mount_get_device_path (entry), NULL); + root = g_unix_mount_get_root_path (entry); + if (root != NULL && g_strcmp0 (root, "/") != 0) + { + escaped = g_strescape (root, NULL); + root_string = g_strconcat ("[", escaped, "]", NULL); + g_free (escaped); + } + mount = g_strescape (g_unix_mount_get_mount_path (entry), NULL); + fs = g_strescape (g_unix_mount_get_fs_type (entry), NULL); + + options = g_unix_mount_get_options (entry); + if (options != NULL) + { + options_string = g_strescape (options, NULL); + } + + g_print (_("unix mount: %s%s %s %s %s\n"), device, + root_string ? root_string : "", mount, fs, + options_string ? options_string : ""); + + g_free (device); + g_free (root_string); + g_free (mount); + g_free (fs); + g_free (options_string); + + g_unix_mount_free (entry); + } +#endif + } + show_attributes (info); } diff --git a/gio/gio-tool-launch.c b/gio/gio-tool-launch.c new file mode 100644 index 0000000000000000000000000000000000000000..08c91c68ad9444e25281a72a8f267b0c98606178 --- /dev/null +++ b/gio/gio-tool-launch.c @@ -0,0 +1,131 @@ +/* + * Copyright 2020 Frederic Martinsons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Frederic Martinsons + */ + +#include "config.h" + +#include + +#if defined(G_OS_UNIX) && !defined(HAVE_COCOA) +#include +#endif + +#include + +#include "gio-tool.h" + +static const GOptionEntry entries[] = { + { NULL } +}; + +int +handle_launch (int argc, char *argv[], gboolean do_help) +{ + GOptionContext *context; + GError *error = NULL; +#if defined(G_OS_UNIX) && !defined(HAVE_COCOA) + int i; + GAppInfo *app = NULL; + GAppLaunchContext *app_context = NULL; + GKeyFile *keyfile = NULL; + GList *args = NULL; + char *desktop_file = NULL; +#endif + int retval; + + g_set_prgname ("gio launch"); + + /* Translators: commandline placeholder */ + context = g_option_context_new (_("DESKTOP-FILE [FILE-ARG …]")); + g_option_context_set_help_enabled (context, FALSE); + g_option_context_set_summary (context, + _("Launch an application from a desktop file, passing optional filename arguments to it.")); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + + if (do_help) + { + show_help (context, NULL); + g_option_context_free (context); + return 0; + } + + if (!g_option_context_parse (context, &argc, &argv, &error)) + { + show_help (context, error->message); + g_error_free (error); + g_option_context_free (context); + return 1; + } + + if (argc < 2) + { + show_help (context, _("No desktop file given")); + g_option_context_free (context); + return 1; + } + + g_option_context_free (context); + +#if !defined(G_OS_UNIX) || defined(HAVE_COCOA) + print_error (_("The launch command is not currently supported on this platform")); + retval = 1; +#else + retval = 0; + desktop_file = argv[1]; + + /* Use keyfile api for loading desktop app in order to check for + * - not existing file. + * - invalid keyfile format. + */ + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, desktop_file, G_KEY_FILE_NONE, &error)) + { + print_error (_("Unable to load ‘%s‘: %s"), desktop_file, error->message); + g_clear_error (&error); + retval = 1; + } + else + { + app = (GAppInfo*)g_desktop_app_info_new_from_keyfile (keyfile); + if (!app) + { + print_error (_("Unable to load application information for ‘%s‘"), desktop_file); + retval = 1; + } + else + { + for (i = 2; i < argc; i++) + { + args = g_list_append (args, g_file_new_for_commandline_arg (argv[i])); + } + app_context = g_app_launch_context_new (); + if (!g_app_info_launch (app, args, app_context, &error)) + { + print_error (_("Unable to launch application ‘%s’: %s"), desktop_file, error->message); + g_clear_error (&error); + retval = 1; + } + g_list_free_full (args, g_object_unref); + g_clear_object (&app_context); + } + g_clear_object (&app); + } + g_key_file_free (keyfile); +#endif + return retval; +} diff --git a/gio/gio-tool-list.c b/gio/gio-tool-list.c index d1501b8e04808dc8b5e76b7493fe7dc35508df50..9f52d158d075239b798f4b43bdbec0e3a3bac5b3 100644 --- a/gio/gio-tool-list.c +++ b/gio/gio-tool-list.c @@ -29,6 +29,7 @@ static char *attributes = NULL; static gboolean show_hidden = FALSE; static gboolean show_long = FALSE; static gboolean nofollow_symlinks = FALSE; +static gboolean print_display_names = FALSE; static gboolean print_uris = FALSE; static const GOptionEntry entries[] = { @@ -36,6 +37,7 @@ static const GOptionEntry entries[] = { { "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, N_("Show hidden files"), NULL }, { "long", 'l', 0, G_OPTION_ARG_NONE, &show_long, N_("Use a long listing format"), NULL }, { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL}, + { "print-display-names", 'd', 0, G_OPTION_ARG_NONE, &print_display_names, N_("Print display names"), NULL }, { "print-uris", 'u', 0, G_OPTION_ARG_NONE, &print_uris, N_("Print full URIs"), NULL}, { NULL } }; @@ -54,7 +56,11 @@ show_file_listing (GFileInfo *info, GFile *parent) if ((g_file_info_get_is_hidden (info)) && !show_hidden) return; - name = g_file_info_get_name (info); + if (print_display_names) + name = g_file_info_get_display_name (info); + else + name = g_file_info_get_name (info); + if (name == NULL) name = ""; @@ -81,7 +87,8 @@ show_file_listing (GFileInfo *info, GFile *parent) char *val_as_string; if (!show_long || - strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0 || + (!print_display_names && strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0) || + (print_display_names && strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) == 0) || strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_SIZE) == 0 || strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0 || strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) == 0) @@ -195,7 +202,8 @@ handle_list (int argc, char *argv[], gboolean do_help) if (attributes != NULL) show_long = TRUE; - attributes = g_strconcat (G_FILE_ATTRIBUTE_STANDARD_NAME "," + attributes = g_strconcat (!print_display_names ? G_FILE_ATTRIBUTE_STANDARD_NAME "," : "", + print_display_names ? G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," : "", G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, diff --git a/gio/gio-tool-mkdir.c b/gio/gio-tool-mkdir.c index 7900704c91b098be620dd0d8e24e6e4514c06fc1..66bf8589407a1474ac70407e6466f9dfc99a6451 100644 --- a/gio/gio-tool-mkdir.c +++ b/gio/gio-tool-mkdir.c @@ -108,4 +108,3 @@ handle_mkdir (int argc, char *argv[], gboolean do_help) return retval; } - diff --git a/gio/gio-tool-monitor.c b/gio/gio-tool-monitor.c index f2ffb3387dd5b3af42b9862b58fdff19cc4858b7..73ee1b12e71502b5c880d83fc4bf44ef3f5b00cb 100644 --- a/gio/gio-tool-monitor.c +++ b/gio/gio-tool-monitor.c @@ -45,7 +45,8 @@ static const GOptionEntry entries[] = { N_("Report moves and renames as simple deleted/created events"), NULL }, { "mounts", 'm', 0, G_OPTION_ARG_NONE, &mounts, N_("Watch for mount events"), NULL }, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &watch_default }, + { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &watch_default, + NULL, NULL }, { NULL } }; diff --git a/gio/gio-tool-mount.c b/gio/gio-tool-mount.c index 05647d91ef5843cee698e9559d4c1cd093ba5d8a..67278bb5cc32e625ff89400ccbcc18b41cd4ec84 100644 --- a/gio/gio-tool-mount.c +++ b/gio/gio-tool-mount.c @@ -53,7 +53,7 @@ static gboolean tcrypt_hidden = FALSE; static gboolean tcrypt_system = FALSE; static guint tcrypt_pim = 0; static const char *unmount_scheme = NULL; -static const char *mount_device_file = NULL; +static const char *mount_id = NULL; static const char *stop_device_file = NULL; static gboolean success = TRUE; @@ -61,7 +61,7 @@ static gboolean success = TRUE; static const GOptionEntry entries[] = { { "mountable", 'm', 0, G_OPTION_ARG_NONE, &mount_mountable, N_("Mount as mountable"), NULL }, - { "device", 'd', 0, G_OPTION_ARG_STRING, &mount_device_file, N_("Mount volume with device file"), N_("DEVICE") }, + { "device", 'd', 0, G_OPTION_ARG_STRING, &mount_id, N_("Mount volume with device file, or other identifier"), N_("ID") }, { "unmount", 'u', 0, G_OPTION_ARG_NONE, &mount_unmount, N_("Unmount"), NULL}, { "eject", 'e', 0, G_OPTION_ARG_NONE, &mount_eject, N_("Eject"), NULL}, { "stop", 't', 0, G_OPTION_ARG_STRING, &stop_device_file, N_("Stop drive with device file"), N_("DEVICE") }, @@ -950,7 +950,7 @@ mount_with_device_file_cb (GObject *object, GVolume *volume; gboolean succeeded; GError *error = NULL; - gchar *device_path = (gchar *)user_data; + gchar *id = (gchar *)user_data; volume = G_VOLUME (object); @@ -958,28 +958,12 @@ mount_with_device_file_cb (GObject *object, if (!succeeded) { - print_error ("%s: %s", device_path, error->message); + print_error ("%s: %s", id, error->message); g_error_free (error); success = FALSE; } - else - { - GMount *mount; - GFile *root; - char *mount_path; - - mount = g_volume_get_mount (volume); - root = g_mount_get_root (mount); - mount_path = g_file_get_path (root); - - g_print (_("Mounted %s at %s\n"), device_path, mount_path); - - g_object_unref (mount); - g_object_unref (root); - g_free (mount_path); - } - g_free (device_path); + g_free (id); outstanding_mounts--; @@ -988,7 +972,7 @@ mount_with_device_file_cb (GObject *object, } static void -mount_with_device_file (const char *device_file) +mount_with_id (const char *id) { GList *volumes; GList *l; @@ -997,10 +981,12 @@ mount_with_device_file (const char *device_file) for (l = volumes; l != NULL; l = l->next) { GVolume *volume = G_VOLUME (l->data); - gchar *id; + gchar *device; + gchar *uuid; - id = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); - if (g_strcmp0 (id, device_file) == 0) + device = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + uuid = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UUID); + if (g_strcmp0 (device, id) == 0 || g_strcmp0 (uuid, id) == 0) { GMountOperation *op; @@ -1011,20 +997,21 @@ mount_with_device_file (const char *device_file) op, NULL, mount_with_device_file_cb, - id); + g_strdup (id)); g_object_unref (op); outstanding_mounts++; } - else - g_free (id); + + g_free (device); + g_free (uuid); } g_list_free_full (volumes, g_object_unref); if (outstanding_mounts == 0) { - print_error ("%s: %s", device_file, _("No volume for device file")); + print_error ("%s: %s", id, _("No volume for given ID")); success = FALSE; } } @@ -1236,8 +1223,8 @@ handle_mount (int argc, char *argv[], gboolean do_help) if (mount_list) list_monitor_items (); - else if (mount_device_file != NULL) - mount_with_device_file (mount_device_file); + else if (mount_id != NULL) + mount_with_id (mount_id); else if (stop_device_file) stop_with_device_file (stop_device_file); else if (unmount_scheme != NULL) diff --git a/gio/gio-tool-save.c b/gio/gio-tool-save.c index ddf085f09d7dcbbd4c340da249dc341567a5bfe8..4969b8b9dc118e83682367bf01f1092c12016f6f 100644 --- a/gio/gio-tool-save.c +++ b/gio/gio-tool-save.c @@ -200,4 +200,3 @@ handle_save (int argc, char *argv[], gboolean do_help) return res ? 0 : 2; } - diff --git a/gio/gio-tool-trash.c b/gio/gio-tool-trash.c index 4f9e3668a8c8000a21c85201d57675280f0c9fc0..fc17b4cbaeb528522c3540bbc756fdd582638860 100644 --- a/gio/gio-tool-trash.c +++ b/gio/gio-tool-trash.c @@ -27,9 +27,14 @@ static gboolean force = FALSE; static gboolean empty = FALSE; +static gboolean restore = FALSE; +static gboolean list = FALSE; static const GOptionEntry entries[] = { { "force", 'f', 0, G_OPTION_ARG_NONE, &force, N_("Ignore nonexistent files, never prompt"), NULL }, { "empty", 0, 0, G_OPTION_ARG_NONE, &empty, N_("Empty the trash"), NULL }, + { "list", 0, 0, G_OPTION_ARG_NONE, &list, N_("List files in the trash with their original locations"), NULL }, + { "restore", 0, 0, G_OPTION_ARG_NONE, &restore, N_("Restore a file from trash to its original location (possibly " + "recreating the directory)"), NULL }, { NULL } }; @@ -40,6 +45,8 @@ delete_trash_file (GFile *file, gboolean del_file, gboolean del_children) GFile *child; GFileEnumerator *enumerator; + g_return_if_fail (g_file_has_uri_scheme (file, "trash")); + if (del_children) { enumerator = g_file_enumerate_children (file, @@ -53,7 +60,14 @@ delete_trash_file (GFile *file, gboolean del_file, gboolean del_children) while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL) { child = g_file_get_child (file, g_file_info_get_name (info)); - delete_trash_file (child, TRUE, g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); + + /* The g_file_delete operation works differently for locations + * provided by the trash backend as it prevents modifications of + * trashed items. For that reason, it is enough to call + * g_file_delete on top-level items only. + */ + delete_trash_file (child, TRUE, FALSE); + g_object_unref (child); g_object_unref (info); } @@ -66,6 +80,131 @@ delete_trash_file (GFile *file, gboolean del_file, gboolean del_children) g_file_delete (file, NULL, NULL); } +static gboolean +restore_trash (GFile *file, + gboolean force, + GCancellable *cancellable, + GError **error) +{ + GFileInfo *info = NULL; + GFile *target = NULL; + GFile *dir_target = NULL; + gboolean ret = FALSE; + gchar *orig_path = NULL; + GError *local_error = NULL; + + info = g_file_query_info (file, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH, G_FILE_QUERY_INFO_NONE, cancellable, &local_error); + if (local_error) + { + g_propagate_error (error, local_error); + goto exit_func; + } + + orig_path = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH); + if (!orig_path) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("Unable to find original path")); + goto exit_func; + } + + target = g_file_new_for_commandline_arg (orig_path); + g_free (orig_path); + + dir_target = g_file_get_parent (target); + if (dir_target) + { + g_file_make_directory_with_parents (dir_target, cancellable, &local_error); + if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) + { + g_clear_error (&local_error); + } + else if (local_error != NULL) + { + g_propagate_prefixed_error (error, local_error, _("Unable to recreate original location: ")); + goto exit_func; + } + } + + if (!g_file_move (file, + target, + force ? G_FILE_COPY_OVERWRITE : G_FILE_COPY_NONE, + cancellable, + NULL, + NULL, + &local_error)) + { + g_propagate_prefixed_error (error, local_error, _("Unable to move file to its original location: ")); + goto exit_func; + } + ret = TRUE; + +exit_func: + g_clear_object (&target); + g_clear_object (&dir_target); + g_clear_object (&info); + return ret; +} + +static gboolean +trash_list (GFile *file, + GCancellable *cancellable, + GError **error) +{ + GFileEnumerator *enumerator; + GFileInfo *info; + GError *local_error = NULL; + gboolean res; + + enumerator = g_file_enumerate_children (file, + G_FILE_ATTRIBUTE_STANDARD_NAME "," + G_FILE_ATTRIBUTE_TRASH_ORIG_PATH, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + cancellable, + &local_error); + if (!enumerator) + { + g_propagate_error (error, local_error); + return FALSE; + } + + res = TRUE; + while ((info = g_file_enumerator_next_file (enumerator, cancellable, &local_error)) != NULL) + { + const char *name; + char *orig_path; + char *uri; + GFile* child; + + name = g_file_info_get_name (info); + child = g_file_get_child (file, name); + uri = g_file_get_uri (child); + g_object_unref (child); + orig_path = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH); + + g_print ("%s\t%s\n", uri, orig_path); + + g_object_unref (info); + g_free (orig_path); + g_free (uri); + } + + if (local_error) + { + g_propagate_error (error, local_error); + local_error = NULL; + res = FALSE; + } + + if (!g_file_enumerator_close (enumerator, cancellable, &local_error)) + { + print_file_error (file, local_error->message); + g_clear_error (&local_error); + res = FALSE; + } + + return res; +} + int handle_trash (int argc, char *argv[], gboolean do_help) { @@ -83,7 +222,10 @@ handle_trash (int argc, char *argv[], gboolean do_help) g_free (param); g_option_context_set_help_enabled (context, FALSE); g_option_context_set_summary (context, - _("Move files or directories to the trash.")); + _("Move/Restore files or directories to the trash.")); + g_option_context_set_description (context, + _("Note: for --restore switch, if the original location of the trashed file \n" + "already exists, it will not be overwritten unless --force is set.")); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (do_help) @@ -109,7 +251,20 @@ handle_trash (int argc, char *argv[], gboolean do_help) { file = g_file_new_for_commandline_arg (argv[i]); error = NULL; - if (!g_file_trash (file, NULL, &error)) + if (restore) + { + if (!g_file_has_uri_scheme (file, "trash")) + { + print_file_error (file, _("Location given doesn't start with trash:///")); + retval = 1; + } + else if (!restore_trash (file, force, NULL, &error)) + { + print_file_error (file, error->message); + retval = 1; + } + } + else if (!g_file_trash (file, NULL, &error)) { if (!force || !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) @@ -117,13 +272,25 @@ handle_trash (int argc, char *argv[], gboolean do_help) print_file_error (file, error->message); retval = 1; } - g_error_free (error); } + g_clear_error (&error); g_object_unref (file); } } - - if (empty) + else if (list) + { + GFile *file; + file = g_file_new_for_uri ("trash:"); + trash_list (file, NULL, &error); + if (error) + { + print_file_error (file, error->message); + g_clear_error (&error); + retval = 1; + } + g_object_unref (file); + } + else if (empty) { GFile *file; file = g_file_new_for_uri ("trash:"); @@ -131,7 +298,7 @@ handle_trash (int argc, char *argv[], gboolean do_help) g_object_unref (file); } - if (argc == 1 && !empty) + if (argc == 1 && !empty && !list) { show_help (context, _("No locations given")); g_option_context_free (context); diff --git a/gio/gio-tool-tree.c b/gio/gio-tool-tree.c index e63752edb0a629d77b9fb5ededc31133eab03946..2327c454983e9c4efc3fb7c837a0706596475b1b 100644 --- a/gio/gio-tool-tree.c +++ b/gio/gio-tool-tree.c @@ -52,7 +52,7 @@ sort_info_by_name (GFileInfo *a, GFileInfo *b) } static void -do_tree (GFile *f, int level, guint64 pattern) +do_tree (GFile *f, unsigned int level, guint64 pattern) { GFileEnumerator *enumerator; GError *error = NULL; diff --git a/gio/gio-tool.c b/gio/gio-tool.c index c0aec74925fab2e59041a91a2f00f6ee3d42c47b..e60d56751a51647d49d4aa98fadd752d9d74482e 100644 --- a/gio/gio-tool.c +++ b/gio/gio-tool.c @@ -149,7 +149,7 @@ char * attribute_flags_to_string (GFileAttributeInfoFlags flags) { GString *s; - int i; + gsize i; gboolean first; struct { guint32 mask; @@ -229,6 +229,7 @@ usage (void) g_printerr (" cat %s\n", _("Concatenate files to standard output")); g_printerr (" copy %s\n", _("Copy one or more files")); g_printerr (" info %s\n", _("Show information about locations")); + g_printerr (" launch %s\n", _("Launch an application from a desktop file")); g_printerr (" list %s\n", _("List the contents of locations")); g_printerr (" mime %s\n", _("Get or set the handler for a mimetype")); g_printerr (" mkdir %s\n", _("Create directories")); @@ -312,6 +313,8 @@ main (int argc, char **argv) return handle_copy (argc, argv, do_help); else if (g_str_equal (command, "info")) return handle_info (argc, argv, do_help); + else if (g_str_equal (command, "launch")) + return handle_launch (argc, argv, do_help); else if (g_str_equal (command, "list")) return handle_list (argc, argv, do_help); else if (g_str_equal (command, "mime")) diff --git a/gio/gio-tool.h b/gio/gio-tool.h index 5064165a6433e55bb23ad5218f3d12f93b3663a3..6cd1d946a622fe22d0bb7a32d669b108110e0768 100644 --- a/gio/gio-tool.h +++ b/gio/gio-tool.h @@ -37,6 +37,7 @@ gboolean file_is_dir (GFile *file); int handle_cat (int argc, char *argv[], gboolean do_help); int handle_copy (int argc, char *argv[], gboolean do_help); int handle_info (int argc, char *argv[], gboolean do_help); +int handle_launch (int argc, char *argv[], gboolean do_help); int handle_list (int argc, char *argv[], gboolean do_help); int handle_mime (int argc, char *argv[], gboolean do_help); int handle_mkdir (int argc, char *argv[], gboolean do_help); diff --git a/gio/gio.h b/gio/gio.h index 8053768a00be7906e275ea1d33f505a27080ce1e..f5d2dd5a36a4cbbbd255160bba2b770e17554617 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -47,15 +47,25 @@ #include #include #include +#include #include #include #include #include +#include +#include #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -64,9 +74,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -88,9 +98,15 @@ #include #include #include +#include +#include #include #include +#include #include +#include +#include +#include #include #include #include @@ -98,6 +114,7 @@ #include #include #include +#include #include #include #include @@ -108,30 +125,31 @@ #include #include #include +#include #include #include #include -#include #include +#include #include #include #include #include #include -#include +#include +#include #include +#include #include #include #include #include -#include #include #include #include -#include -#include #include #include +#include #include #include #include @@ -144,34 +162,16 @@ #include #include #include -#include #include +#include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #undef __GIO_GIO_H_INSIDE__ #endif /* __G_IO_H__ */ - diff --git a/gio/gio_trace.h b/gio/gio_trace.h index 47d4eacb217d0dd844eb47d29738e67b788898e4..addb70ae49da2040fa6301ffaaa1081a86955f60 100644 --- a/gio/gio_trace.h +++ b/gio/gio_trace.h @@ -25,7 +25,9 @@ #error "config.h must be included prior to gio_trace.h" #endif -#ifdef HAVE_DTRACE +/* Ignore probes when doing static analysis, as they do weird things which + * confuses the analyser. */ +#if defined(HAVE_DTRACE) && !defined(__clang_analyzer__) /* include the generated probes header and put markers in code */ #include "gio_probes.h" diff --git a/gio/gioenums.h b/gio/gioenums.h index 22fe7005c16392f4eaff4bc6162c3efd5e83fed0..f2f66c875947e34e49534c95c0ac5fcbe4c891d6 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -117,7 +117,7 @@ typedef enum { /** * GFileAttributeType: - * @G_FILE_ATTRIBUTE_TYPE_INVALID: indicates an invalid or uninitalized type. + * @G_FILE_ATTRIBUTE_TYPE_INVALID: indicates an invalid or uninitialized type. * @G_FILE_ATTRIBUTE_TYPE_STRING: a null terminated UTF8 string. * @G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: a zero terminated string of non-zero bytes. * @G_FILE_ATTRIBUTE_TYPE_BOOLEAN: a boolean value. @@ -199,7 +199,9 @@ typedef enum { * rather than a "save new version of" replace operation. * You can think of it as "unlink destination" before * writing to it, although the implementation may not - * be exactly like that. Since 2.20 + * be exactly like that. This flag can only be used with + * g_file_replace() and its variants, including g_file_replace_contents(). + * Since 2.20 * * Flags used when an operation may create a file. */ @@ -1204,6 +1206,8 @@ typedef enum * message bus. This means that the Hello() method will be invoked as part of the connection setup. * @G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING: If set, processing of D-Bus messages is * delayed until g_dbus_connection_start_message_processing() is called. + * @G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER: When authenticating + * as a server, require the UID of the peer to be the same as the UID of the server. (Since: 2.68) * * Flags used when creating a new #GDBusConnection. * @@ -1215,7 +1219,8 @@ typedef enum { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER = (1<<1), G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<2), G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION = (1<<3), - G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING = (1<<4) + G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING = (1<<4), + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_AVAILABLE_ENUMERATOR_IN_2_68 = (1<<5) } GDBusConnectionFlags; /** @@ -1366,6 +1371,8 @@ typedef enum * details). * @G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS: Allow the anonymous * authentication method. + * @G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER: Require the UID of the + * peer to be the same as the UID of the server when authenticating. (Since: 2.68) * * Flags used when creating a #GDBusServer. * @@ -1375,7 +1382,8 @@ typedef enum { G_DBUS_SERVER_FLAGS_NONE = 0, G_DBUS_SERVER_FLAGS_RUN_IN_THREAD = (1<<0), - G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<1) + G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<1), + G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_AVAILABLE_ENUMERATOR_IN_2_68 = (1<<2) } GDBusServerFlags; /** @@ -1423,11 +1431,12 @@ typedef enum /** * GCredentialsType: * @G_CREDENTIALS_TYPE_INVALID: Indicates an invalid native credential type. - * @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a struct ucred. - * @G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED: The native credentials type is a struct cmsgcred. - * @G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED: The native credentials type is a struct sockpeercred. Added in 2.30. - * @G_CREDENTIALS_TYPE_SOLARIS_UCRED: The native credentials type is a ucred_t. Added in 2.40. - * @G_CREDENTIALS_TYPE_NETBSD_UNPCBID: The native credentials type is a struct unpcbid. + * @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a `struct ucred`. + * @G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED: The native credentials type is a `struct cmsgcred`. + * @G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED: The native credentials type is a `struct sockpeercred`. Added in 2.30. + * @G_CREDENTIALS_TYPE_SOLARIS_UCRED: The native credentials type is a `ucred_t`. Added in 2.40. + * @G_CREDENTIALS_TYPE_NETBSD_UNPCBID: The native credentials type is a `struct unpcbid`. Added in 2.42. + * @G_CREDENTIALS_TYPE_APPLE_XUCRED: The native credentials type is a `struct xucred`. Added in 2.66. * * Enumeration describing different kinds of native credential types. * @@ -1440,7 +1449,8 @@ typedef enum G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED, G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED, G_CREDENTIALS_TYPE_SOLARIS_UCRED, - G_CREDENTIALS_TYPE_NETBSD_UNPCBID + G_CREDENTIALS_TYPE_NETBSD_UNPCBID, + G_CREDENTIALS_TYPE_APPLE_XUCRED, } GCredentialsType; /** @@ -1609,6 +1619,61 @@ typedef enum { G_TLS_AUTHENTICATION_REQUIRED } GTlsAuthenticationMode; +/** + * GTlsChannelBindingType: + * @G_TLS_CHANNEL_BINDING_TLS_UNIQUE: + * [`tls-unique`](https://tools.ietf.org/html/rfc5929#section-3) binding + * type + * @G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT: + * [`tls-server-end-point`](https://tools.ietf.org/html/rfc5929#section-4) + * binding type + * + * The type of TLS channel binding data to retrieve from #GTlsConnection + * or #GDtlsConnection, as documented by RFC 5929. The + * [`tls-unique-for-telnet`](https://tools.ietf.org/html/rfc5929#section-5) + * binding type is not currently implemented. + * + * Since: 2.66 + */ +GLIB_AVAILABLE_TYPE_IN_2_66 +typedef enum { + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, + G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT +} GTlsChannelBindingType; + +/** + * GTlsChannelBindingError: + * @G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED: Either entire binding + * retrieval facility or specific binding type is not implemented in the + * TLS backend. + * @G_TLS_CHANNEL_BINDING_ERROR_INVALID_STATE: The handshake is not yet + * complete on the connection which is a strong requirement for any existing + * binding type. + * @G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE: Handshake is complete but + * binding data is not available. That normally indicates the TLS + * implementation failed to provide the binding data. For example, some + * implementations do not provide a peer certificate for resumed connections. + * @G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED: Binding type is not supported + * on the current connection. This error could be triggered when requesting + * `tls-server-end-point` binding data for a certificate which has no hash + * function or uses multiple hash functions. + * @G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR: Any other backend error + * preventing binding data retrieval. + * + * An error code used with %G_TLS_CHANNEL_BINDING_ERROR in a #GError to + * indicate a TLS channel binding retrieval error. + * + * Since: 2.66 + */ +GLIB_AVAILABLE_TYPE_IN_2_66 +typedef enum { + G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED, + G_TLS_CHANNEL_BINDING_ERROR_INVALID_STATE, + G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE, + G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED, + G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR +} GTlsChannelBindingError; + /** * GTlsRehandshakeMode: * @G_TLS_REHANDSHAKE_NEVER: Never allow rehandshaking @@ -1964,6 +2029,35 @@ typedef enum { G_POLLABLE_RETURN_WOULD_BLOCK = -G_IO_ERROR_WOULD_BLOCK } GPollableReturn; +/** + * GMemoryMonitorWarningLevel: + * @G_MEMORY_MONITOR_WARNING_LEVEL_LOW: Memory on the device is low, processes + * should free up unneeded resources (for example, in-memory caches) so they can + * be used elsewhere. + * @G_MEMORY_MONITOR_WARNING_LEVEL_MEDIUM: Same as @G_MEMORY_MONITOR_WARNING_LEVEL_LOW + * but the device has even less free memory, so processes should try harder to free + * up unneeded resources. If your process does not need to stay running, it is a + * good time for it to quit. + * @G_MEMORY_MONITOR_WARNING_LEVEL_CRITICAL: The system will soon start terminating + * processes to reclaim memory, including background processes. + * + * Memory availability warning levels. + * + * Note that because new values might be added, it is recommended that applications check + * #GMemoryMonitorWarningLevel as ranges, for example: + * |[ + * if (warning_level > G_MEMORY_MONITOR_WARNING_LEVEL_LOW) + * drop_caches (); + * ]| + * + * Since: 2.64 + */ +typedef enum { + G_MEMORY_MONITOR_WARNING_LEVEL_LOW = 50, + G_MEMORY_MONITOR_WARNING_LEVEL_MEDIUM = 100, + G_MEMORY_MONITOR_WARNING_LEVEL_CRITICAL = 255 +} GMemoryMonitorWarningLevel; + G_END_DECLS #endif /* __GIO_ENUMS_H__ */ diff --git a/gio/gioenumtypes.c b/gio/gioenumtypes.c index b650f5547b1d105dc40832e08c2418178d152c8d..8c0c3e69ee739f83d2c4e3220574bcfe765063b1 100644 --- a/gio/gioenumtypes.c +++ b/gio/gioenumtypes.c @@ -1,1737 +1,1801 @@ - -/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ - -#include "config.h" -#include "gioenumtypes.h" -#include -/* enumerations from "../gio/gioenums.h" */ -GType -g_app_info_create_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_APP_INFO_CREATE_NONE, "G_APP_INFO_CREATE_NONE", "none" }, - { G_APP_INFO_CREATE_NEEDS_TERMINAL, "G_APP_INFO_CREATE_NEEDS_TERMINAL", "needs-terminal" }, - { G_APP_INFO_CREATE_SUPPORTS_URIS, "G_APP_INFO_CREATE_SUPPORTS_URIS", "supports-uris" }, - { G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION, "G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION", "supports-startup-notification" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GAppInfoCreateFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_converter_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_CONVERTER_NO_FLAGS, "G_CONVERTER_NO_FLAGS", "none" }, - { G_CONVERTER_INPUT_AT_END, "G_CONVERTER_INPUT_AT_END", "input-at-end" }, - { G_CONVERTER_FLUSH, "G_CONVERTER_FLUSH", "flush" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GConverterFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_converter_result_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_CONVERTER_ERROR, "G_CONVERTER_ERROR", "error" }, - { G_CONVERTER_CONVERTED, "G_CONVERTER_CONVERTED", "converted" }, - { G_CONVERTER_FINISHED, "G_CONVERTER_FINISHED", "finished" }, - { G_CONVERTER_FLUSHED, "G_CONVERTER_FLUSHED", "flushed" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GConverterResult"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_data_stream_byte_order_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN, "G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN", "big-endian" }, - { G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN, "G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN", "little-endian" }, - { G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN, "G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN", "host-endian" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDataStreamByteOrder"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_data_stream_newline_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DATA_STREAM_NEWLINE_TYPE_LF, "G_DATA_STREAM_NEWLINE_TYPE_LF", "lf" }, - { G_DATA_STREAM_NEWLINE_TYPE_CR, "G_DATA_STREAM_NEWLINE_TYPE_CR", "cr" }, - { G_DATA_STREAM_NEWLINE_TYPE_CR_LF, "G_DATA_STREAM_NEWLINE_TYPE_CR_LF", "cr-lf" }, - { G_DATA_STREAM_NEWLINE_TYPE_ANY, "G_DATA_STREAM_NEWLINE_TYPE_ANY", "any" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDataStreamNewlineType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_attribute_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_FILE_ATTRIBUTE_TYPE_INVALID, "G_FILE_ATTRIBUTE_TYPE_INVALID", "invalid" }, - { G_FILE_ATTRIBUTE_TYPE_STRING, "G_FILE_ATTRIBUTE_TYPE_STRING", "string" }, - { G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, "G_FILE_ATTRIBUTE_TYPE_BYTE_STRING", "byte-string" }, - { G_FILE_ATTRIBUTE_TYPE_BOOLEAN, "G_FILE_ATTRIBUTE_TYPE_BOOLEAN", "boolean" }, - { G_FILE_ATTRIBUTE_TYPE_UINT32, "G_FILE_ATTRIBUTE_TYPE_UINT32", "uint32" }, - { G_FILE_ATTRIBUTE_TYPE_INT32, "G_FILE_ATTRIBUTE_TYPE_INT32", "int32" }, - { G_FILE_ATTRIBUTE_TYPE_UINT64, "G_FILE_ATTRIBUTE_TYPE_UINT64", "uint64" }, - { G_FILE_ATTRIBUTE_TYPE_INT64, "G_FILE_ATTRIBUTE_TYPE_INT64", "int64" }, - { G_FILE_ATTRIBUTE_TYPE_OBJECT, "G_FILE_ATTRIBUTE_TYPE_OBJECT", "object" }, - { G_FILE_ATTRIBUTE_TYPE_STRINGV, "G_FILE_ATTRIBUTE_TYPE_STRINGV", "stringv" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GFileAttributeType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_attribute_info_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_FILE_ATTRIBUTE_INFO_NONE, "G_FILE_ATTRIBUTE_INFO_NONE", "none" }, - { G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE, "G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE", "copy-with-file" }, - { G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED, "G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED", "copy-when-moved" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GFileAttributeInfoFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_attribute_status_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_FILE_ATTRIBUTE_STATUS_UNSET, "G_FILE_ATTRIBUTE_STATUS_UNSET", "unset" }, - { G_FILE_ATTRIBUTE_STATUS_SET, "G_FILE_ATTRIBUTE_STATUS_SET", "set" }, - { G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING, "G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING", "error-setting" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GFileAttributeStatus"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_query_info_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_FILE_QUERY_INFO_NONE, "G_FILE_QUERY_INFO_NONE", "none" }, - { G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, "G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS", "nofollow-symlinks" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GFileQueryInfoFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_create_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_FILE_CREATE_NONE, "G_FILE_CREATE_NONE", "none" }, - { G_FILE_CREATE_PRIVATE, "G_FILE_CREATE_PRIVATE", "private" }, - { G_FILE_CREATE_REPLACE_DESTINATION, "G_FILE_CREATE_REPLACE_DESTINATION", "replace-destination" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GFileCreateFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_measure_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_FILE_MEASURE_NONE, "G_FILE_MEASURE_NONE", "none" }, - { G_FILE_MEASURE_REPORT_ANY_ERROR, "G_FILE_MEASURE_REPORT_ANY_ERROR", "report-any-error" }, - { G_FILE_MEASURE_APPARENT_SIZE, "G_FILE_MEASURE_APPARENT_SIZE", "apparent-size" }, - { G_FILE_MEASURE_NO_XDEV, "G_FILE_MEASURE_NO_XDEV", "no-xdev" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GFileMeasureFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_mount_mount_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_MOUNT_MOUNT_NONE, "G_MOUNT_MOUNT_NONE", "none" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GMountMountFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_mount_unmount_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_MOUNT_UNMOUNT_NONE, "G_MOUNT_UNMOUNT_NONE", "none" }, - { G_MOUNT_UNMOUNT_FORCE, "G_MOUNT_UNMOUNT_FORCE", "force" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GMountUnmountFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_drive_start_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DRIVE_START_NONE, "G_DRIVE_START_NONE", "none" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDriveStartFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_drive_start_stop_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DRIVE_START_STOP_TYPE_UNKNOWN, "G_DRIVE_START_STOP_TYPE_UNKNOWN", "unknown" }, - { G_DRIVE_START_STOP_TYPE_SHUTDOWN, "G_DRIVE_START_STOP_TYPE_SHUTDOWN", "shutdown" }, - { G_DRIVE_START_STOP_TYPE_NETWORK, "G_DRIVE_START_STOP_TYPE_NETWORK", "network" }, - { G_DRIVE_START_STOP_TYPE_MULTIDISK, "G_DRIVE_START_STOP_TYPE_MULTIDISK", "multidisk" }, - { G_DRIVE_START_STOP_TYPE_PASSWORD, "G_DRIVE_START_STOP_TYPE_PASSWORD", "password" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDriveStartStopType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_copy_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_FILE_COPY_NONE, "G_FILE_COPY_NONE", "none" }, - { G_FILE_COPY_OVERWRITE, "G_FILE_COPY_OVERWRITE", "overwrite" }, - { G_FILE_COPY_BACKUP, "G_FILE_COPY_BACKUP", "backup" }, - { G_FILE_COPY_NOFOLLOW_SYMLINKS, "G_FILE_COPY_NOFOLLOW_SYMLINKS", "nofollow-symlinks" }, - { G_FILE_COPY_ALL_METADATA, "G_FILE_COPY_ALL_METADATA", "all-metadata" }, - { G_FILE_COPY_NO_FALLBACK_FOR_MOVE, "G_FILE_COPY_NO_FALLBACK_FOR_MOVE", "no-fallback-for-move" }, - { G_FILE_COPY_TARGET_DEFAULT_PERMS, "G_FILE_COPY_TARGET_DEFAULT_PERMS", "target-default-perms" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GFileCopyFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_monitor_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_FILE_MONITOR_NONE, "G_FILE_MONITOR_NONE", "none" }, - { G_FILE_MONITOR_WATCH_MOUNTS, "G_FILE_MONITOR_WATCH_MOUNTS", "watch-mounts" }, - { G_FILE_MONITOR_SEND_MOVED, "G_FILE_MONITOR_SEND_MOVED", "send-moved" }, - { G_FILE_MONITOR_WATCH_HARD_LINKS, "G_FILE_MONITOR_WATCH_HARD_LINKS", "watch-hard-links" }, - { G_FILE_MONITOR_WATCH_MOVES, "G_FILE_MONITOR_WATCH_MOVES", "watch-moves" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GFileMonitorFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_FILE_TYPE_UNKNOWN, "G_FILE_TYPE_UNKNOWN", "unknown" }, - { G_FILE_TYPE_REGULAR, "G_FILE_TYPE_REGULAR", "regular" }, - { G_FILE_TYPE_DIRECTORY, "G_FILE_TYPE_DIRECTORY", "directory" }, - { G_FILE_TYPE_SYMBOLIC_LINK, "G_FILE_TYPE_SYMBOLIC_LINK", "symbolic-link" }, - { G_FILE_TYPE_SPECIAL, "G_FILE_TYPE_SPECIAL", "special" }, - { G_FILE_TYPE_SHORTCUT, "G_FILE_TYPE_SHORTCUT", "shortcut" }, - { G_FILE_TYPE_MOUNTABLE, "G_FILE_TYPE_MOUNTABLE", "mountable" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GFileType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_filesystem_preview_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_FILESYSTEM_PREVIEW_TYPE_IF_ALWAYS, "G_FILESYSTEM_PREVIEW_TYPE_IF_ALWAYS", "if-always" }, - { G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL, "G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL", "if-local" }, - { G_FILESYSTEM_PREVIEW_TYPE_NEVER, "G_FILESYSTEM_PREVIEW_TYPE_NEVER", "never" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GFilesystemPreviewType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_file_monitor_event_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_FILE_MONITOR_EVENT_CHANGED, "G_FILE_MONITOR_EVENT_CHANGED", "changed" }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT", "changes-done-hint" }, - { G_FILE_MONITOR_EVENT_DELETED, "G_FILE_MONITOR_EVENT_DELETED", "deleted" }, - { G_FILE_MONITOR_EVENT_CREATED, "G_FILE_MONITOR_EVENT_CREATED", "created" }, - { G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED, "G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED", "attribute-changed" }, - { G_FILE_MONITOR_EVENT_PRE_UNMOUNT, "G_FILE_MONITOR_EVENT_PRE_UNMOUNT", "pre-unmount" }, - { G_FILE_MONITOR_EVENT_UNMOUNTED, "G_FILE_MONITOR_EVENT_UNMOUNTED", "unmounted" }, - { G_FILE_MONITOR_EVENT_MOVED, "G_FILE_MONITOR_EVENT_MOVED", "moved" }, - { G_FILE_MONITOR_EVENT_RENAMED, "G_FILE_MONITOR_EVENT_RENAMED", "renamed" }, - { G_FILE_MONITOR_EVENT_MOVED_IN, "G_FILE_MONITOR_EVENT_MOVED_IN", "moved-in" }, - { G_FILE_MONITOR_EVENT_MOVED_OUT, "G_FILE_MONITOR_EVENT_MOVED_OUT", "moved-out" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GFileMonitorEvent"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_io_error_enum_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_IO_ERROR_FAILED, "G_IO_ERROR_FAILED", "failed" }, - { G_IO_ERROR_NOT_FOUND, "G_IO_ERROR_NOT_FOUND", "not-found" }, - { G_IO_ERROR_EXISTS, "G_IO_ERROR_EXISTS", "exists" }, - { G_IO_ERROR_IS_DIRECTORY, "G_IO_ERROR_IS_DIRECTORY", "is-directory" }, - { G_IO_ERROR_NOT_DIRECTORY, "G_IO_ERROR_NOT_DIRECTORY", "not-directory" }, - { G_IO_ERROR_NOT_EMPTY, "G_IO_ERROR_NOT_EMPTY", "not-empty" }, - { G_IO_ERROR_NOT_REGULAR_FILE, "G_IO_ERROR_NOT_REGULAR_FILE", "not-regular-file" }, - { G_IO_ERROR_NOT_SYMBOLIC_LINK, "G_IO_ERROR_NOT_SYMBOLIC_LINK", "not-symbolic-link" }, - { G_IO_ERROR_NOT_MOUNTABLE_FILE, "G_IO_ERROR_NOT_MOUNTABLE_FILE", "not-mountable-file" }, - { G_IO_ERROR_FILENAME_TOO_LONG, "G_IO_ERROR_FILENAME_TOO_LONG", "filename-too-long" }, - { G_IO_ERROR_INVALID_FILENAME, "G_IO_ERROR_INVALID_FILENAME", "invalid-filename" }, - { G_IO_ERROR_TOO_MANY_LINKS, "G_IO_ERROR_TOO_MANY_LINKS", "too-many-links" }, - { G_IO_ERROR_NO_SPACE, "G_IO_ERROR_NO_SPACE", "no-space" }, - { G_IO_ERROR_INVALID_ARGUMENT, "G_IO_ERROR_INVALID_ARGUMENT", "invalid-argument" }, - { G_IO_ERROR_PERMISSION_DENIED, "G_IO_ERROR_PERMISSION_DENIED", "permission-denied" }, - { G_IO_ERROR_NOT_SUPPORTED, "G_IO_ERROR_NOT_SUPPORTED", "not-supported" }, - { G_IO_ERROR_NOT_MOUNTED, "G_IO_ERROR_NOT_MOUNTED", "not-mounted" }, - { G_IO_ERROR_ALREADY_MOUNTED, "G_IO_ERROR_ALREADY_MOUNTED", "already-mounted" }, - { G_IO_ERROR_CLOSED, "G_IO_ERROR_CLOSED", "closed" }, - { G_IO_ERROR_CANCELLED, "G_IO_ERROR_CANCELLED", "cancelled" }, - { G_IO_ERROR_PENDING, "G_IO_ERROR_PENDING", "pending" }, - { G_IO_ERROR_READ_ONLY, "G_IO_ERROR_READ_ONLY", "read-only" }, - { G_IO_ERROR_CANT_CREATE_BACKUP, "G_IO_ERROR_CANT_CREATE_BACKUP", "cant-create-backup" }, - { G_IO_ERROR_WRONG_ETAG, "G_IO_ERROR_WRONG_ETAG", "wrong-etag" }, - { G_IO_ERROR_TIMED_OUT, "G_IO_ERROR_TIMED_OUT", "timed-out" }, - { G_IO_ERROR_WOULD_RECURSE, "G_IO_ERROR_WOULD_RECURSE", "would-recurse" }, - { G_IO_ERROR_BUSY, "G_IO_ERROR_BUSY", "busy" }, - { G_IO_ERROR_WOULD_BLOCK, "G_IO_ERROR_WOULD_BLOCK", "would-block" }, - { G_IO_ERROR_HOST_NOT_FOUND, "G_IO_ERROR_HOST_NOT_FOUND", "host-not-found" }, - { G_IO_ERROR_WOULD_MERGE, "G_IO_ERROR_WOULD_MERGE", "would-merge" }, - { G_IO_ERROR_FAILED_HANDLED, "G_IO_ERROR_FAILED_HANDLED", "failed-handled" }, - { G_IO_ERROR_TOO_MANY_OPEN_FILES, "G_IO_ERROR_TOO_MANY_OPEN_FILES", "too-many-open-files" }, - { G_IO_ERROR_NOT_INITIALIZED, "G_IO_ERROR_NOT_INITIALIZED", "not-initialized" }, - { G_IO_ERROR_ADDRESS_IN_USE, "G_IO_ERROR_ADDRESS_IN_USE", "address-in-use" }, - { G_IO_ERROR_PARTIAL_INPUT, "G_IO_ERROR_PARTIAL_INPUT", "partial-input" }, - { G_IO_ERROR_INVALID_DATA, "G_IO_ERROR_INVALID_DATA", "invalid-data" }, - { G_IO_ERROR_DBUS_ERROR, "G_IO_ERROR_DBUS_ERROR", "dbus-error" }, - { G_IO_ERROR_HOST_UNREACHABLE, "G_IO_ERROR_HOST_UNREACHABLE", "host-unreachable" }, - { G_IO_ERROR_NETWORK_UNREACHABLE, "G_IO_ERROR_NETWORK_UNREACHABLE", "network-unreachable" }, - { G_IO_ERROR_CONNECTION_REFUSED, "G_IO_ERROR_CONNECTION_REFUSED", "connection-refused" }, - { G_IO_ERROR_PROXY_FAILED, "G_IO_ERROR_PROXY_FAILED", "proxy-failed" }, - { G_IO_ERROR_PROXY_AUTH_FAILED, "G_IO_ERROR_PROXY_AUTH_FAILED", "proxy-auth-failed" }, - { G_IO_ERROR_PROXY_NEED_AUTH, "G_IO_ERROR_PROXY_NEED_AUTH", "proxy-need-auth" }, - { G_IO_ERROR_PROXY_NOT_ALLOWED, "G_IO_ERROR_PROXY_NOT_ALLOWED", "proxy-not-allowed" }, - { G_IO_ERROR_BROKEN_PIPE, "G_IO_ERROR_BROKEN_PIPE", "broken-pipe" }, - { G_IO_ERROR_CONNECTION_CLOSED, "G_IO_ERROR_CONNECTION_CLOSED", "connection-closed" }, - { G_IO_ERROR_NOT_CONNECTED, "G_IO_ERROR_NOT_CONNECTED", "not-connected" }, - { G_IO_ERROR_MESSAGE_TOO_LARGE, "G_IO_ERROR_MESSAGE_TOO_LARGE", "message-too-large" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GIOErrorEnum"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_ask_password_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_ASK_PASSWORD_NEED_PASSWORD, "G_ASK_PASSWORD_NEED_PASSWORD", "need-password" }, - { G_ASK_PASSWORD_NEED_USERNAME, "G_ASK_PASSWORD_NEED_USERNAME", "need-username" }, - { G_ASK_PASSWORD_NEED_DOMAIN, "G_ASK_PASSWORD_NEED_DOMAIN", "need-domain" }, - { G_ASK_PASSWORD_SAVING_SUPPORTED, "G_ASK_PASSWORD_SAVING_SUPPORTED", "saving-supported" }, - { G_ASK_PASSWORD_ANONYMOUS_SUPPORTED, "G_ASK_PASSWORD_ANONYMOUS_SUPPORTED", "anonymous-supported" }, - { G_ASK_PASSWORD_TCRYPT, "G_ASK_PASSWORD_TCRYPT", "tcrypt" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GAskPasswordFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_password_save_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_PASSWORD_SAVE_NEVER, "G_PASSWORD_SAVE_NEVER", "never" }, - { G_PASSWORD_SAVE_FOR_SESSION, "G_PASSWORD_SAVE_FOR_SESSION", "for-session" }, - { G_PASSWORD_SAVE_PERMANENTLY, "G_PASSWORD_SAVE_PERMANENTLY", "permanently" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GPasswordSave"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_mount_operation_result_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_MOUNT_OPERATION_HANDLED, "G_MOUNT_OPERATION_HANDLED", "handled" }, - { G_MOUNT_OPERATION_ABORTED, "G_MOUNT_OPERATION_ABORTED", "aborted" }, - { G_MOUNT_OPERATION_UNHANDLED, "G_MOUNT_OPERATION_UNHANDLED", "unhandled" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GMountOperationResult"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_output_stream_splice_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_OUTPUT_STREAM_SPLICE_NONE, "G_OUTPUT_STREAM_SPLICE_NONE", "none" }, - { G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, "G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE", "close-source" }, - { G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, "G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET", "close-target" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GOutputStreamSpliceFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_io_stream_splice_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_IO_STREAM_SPLICE_NONE, "G_IO_STREAM_SPLICE_NONE", "none" }, - { G_IO_STREAM_SPLICE_CLOSE_STREAM1, "G_IO_STREAM_SPLICE_CLOSE_STREAM1", "close-stream1" }, - { G_IO_STREAM_SPLICE_CLOSE_STREAM2, "G_IO_STREAM_SPLICE_CLOSE_STREAM2", "close-stream2" }, - { G_IO_STREAM_SPLICE_WAIT_FOR_BOTH, "G_IO_STREAM_SPLICE_WAIT_FOR_BOTH", "wait-for-both" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GIOStreamSpliceFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_emblem_origin_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_EMBLEM_ORIGIN_UNKNOWN, "G_EMBLEM_ORIGIN_UNKNOWN", "unknown" }, - { G_EMBLEM_ORIGIN_DEVICE, "G_EMBLEM_ORIGIN_DEVICE", "device" }, - { G_EMBLEM_ORIGIN_LIVEMETADATA, "G_EMBLEM_ORIGIN_LIVEMETADATA", "livemetadata" }, - { G_EMBLEM_ORIGIN_TAG, "G_EMBLEM_ORIGIN_TAG", "tag" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GEmblemOrigin"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_resolver_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_RESOLVER_ERROR_NOT_FOUND, "G_RESOLVER_ERROR_NOT_FOUND", "not-found" }, - { G_RESOLVER_ERROR_TEMPORARY_FAILURE, "G_RESOLVER_ERROR_TEMPORARY_FAILURE", "temporary-failure" }, - { G_RESOLVER_ERROR_INTERNAL, "G_RESOLVER_ERROR_INTERNAL", "internal" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GResolverError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_resolver_record_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_RESOLVER_RECORD_SRV, "G_RESOLVER_RECORD_SRV", "srv" }, - { G_RESOLVER_RECORD_MX, "G_RESOLVER_RECORD_MX", "mx" }, - { G_RESOLVER_RECORD_TXT, "G_RESOLVER_RECORD_TXT", "txt" }, - { G_RESOLVER_RECORD_SOA, "G_RESOLVER_RECORD_SOA", "soa" }, - { G_RESOLVER_RECORD_NS, "G_RESOLVER_RECORD_NS", "ns" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GResolverRecordType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_resource_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_RESOURCE_ERROR_NOT_FOUND, "G_RESOURCE_ERROR_NOT_FOUND", "not-found" }, - { G_RESOURCE_ERROR_INTERNAL, "G_RESOURCE_ERROR_INTERNAL", "internal" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GResourceError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_resource_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_RESOURCE_FLAGS_NONE, "G_RESOURCE_FLAGS_NONE", "none" }, - { G_RESOURCE_FLAGS_COMPRESSED, "G_RESOURCE_FLAGS_COMPRESSED", "compressed" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GResourceFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_resource_lookup_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_RESOURCE_LOOKUP_FLAGS_NONE, "G_RESOURCE_LOOKUP_FLAGS_NONE", "none" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GResourceLookupFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_socket_family_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_SOCKET_FAMILY_INVALID, "G_SOCKET_FAMILY_INVALID", "invalid" }, - { G_SOCKET_FAMILY_UNIX, "G_SOCKET_FAMILY_UNIX", "unix" }, - { G_SOCKET_FAMILY_IPV4, "G_SOCKET_FAMILY_IPV4", "ipv4" }, - { G_SOCKET_FAMILY_IPV6, "G_SOCKET_FAMILY_IPV6", "ipv6" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GSocketFamily"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_socket_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_SOCKET_TYPE_INVALID, "G_SOCKET_TYPE_INVALID", "invalid" }, - { G_SOCKET_TYPE_STREAM, "G_SOCKET_TYPE_STREAM", "stream" }, - { G_SOCKET_TYPE_DATAGRAM, "G_SOCKET_TYPE_DATAGRAM", "datagram" }, - { G_SOCKET_TYPE_SEQPACKET, "G_SOCKET_TYPE_SEQPACKET", "seqpacket" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GSocketType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_socket_msg_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_SOCKET_MSG_NONE, "G_SOCKET_MSG_NONE", "none" }, - { G_SOCKET_MSG_OOB, "G_SOCKET_MSG_OOB", "oob" }, - { G_SOCKET_MSG_PEEK, "G_SOCKET_MSG_PEEK", "peek" }, - { G_SOCKET_MSG_DONTROUTE, "G_SOCKET_MSG_DONTROUTE", "dontroute" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GSocketMsgFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_socket_protocol_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_SOCKET_PROTOCOL_UNKNOWN, "G_SOCKET_PROTOCOL_UNKNOWN", "unknown" }, - { G_SOCKET_PROTOCOL_DEFAULT, "G_SOCKET_PROTOCOL_DEFAULT", "default" }, - { G_SOCKET_PROTOCOL_TCP, "G_SOCKET_PROTOCOL_TCP", "tcp" }, - { G_SOCKET_PROTOCOL_UDP, "G_SOCKET_PROTOCOL_UDP", "udp" }, - { G_SOCKET_PROTOCOL_SCTP, "G_SOCKET_PROTOCOL_SCTP", "sctp" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GSocketProtocol"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_zlib_compressor_format_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_ZLIB_COMPRESSOR_FORMAT_ZLIB, "G_ZLIB_COMPRESSOR_FORMAT_ZLIB", "zlib" }, - { G_ZLIB_COMPRESSOR_FORMAT_GZIP, "G_ZLIB_COMPRESSOR_FORMAT_GZIP", "gzip" }, - { G_ZLIB_COMPRESSOR_FORMAT_RAW, "G_ZLIB_COMPRESSOR_FORMAT_RAW", "raw" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GZlibCompressorFormat"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_unix_socket_address_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_UNIX_SOCKET_ADDRESS_INVALID, "G_UNIX_SOCKET_ADDRESS_INVALID", "invalid" }, - { G_UNIX_SOCKET_ADDRESS_ANONYMOUS, "G_UNIX_SOCKET_ADDRESS_ANONYMOUS", "anonymous" }, - { G_UNIX_SOCKET_ADDRESS_PATH, "G_UNIX_SOCKET_ADDRESS_PATH", "path" }, - { G_UNIX_SOCKET_ADDRESS_ABSTRACT, "G_UNIX_SOCKET_ADDRESS_ABSTRACT", "abstract" }, - { G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED, "G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED", "abstract-padded" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GUnixSocketAddressType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_bus_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_BUS_TYPE_STARTER, "G_BUS_TYPE_STARTER", "starter" }, - { G_BUS_TYPE_NONE, "G_BUS_TYPE_NONE", "none" }, - { G_BUS_TYPE_SYSTEM, "G_BUS_TYPE_SYSTEM", "system" }, - { G_BUS_TYPE_SESSION, "G_BUS_TYPE_SESSION", "session" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GBusType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_bus_name_owner_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_BUS_NAME_OWNER_FLAGS_NONE, "G_BUS_NAME_OWNER_FLAGS_NONE", "none" }, - { G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, "G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT", "allow-replacement" }, - { G_BUS_NAME_OWNER_FLAGS_REPLACE, "G_BUS_NAME_OWNER_FLAGS_REPLACE", "replace" }, - { G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, "G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE", "do-not-queue" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GBusNameOwnerFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_bus_name_watcher_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_BUS_NAME_WATCHER_FLAGS_NONE, "G_BUS_NAME_WATCHER_FLAGS_NONE", "none" }, - { G_BUS_NAME_WATCHER_FLAGS_AUTO_START, "G_BUS_NAME_WATCHER_FLAGS_AUTO_START", "auto-start" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GBusNameWatcherFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_proxy_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_PROXY_FLAGS_NONE, "G_DBUS_PROXY_FLAGS_NONE", "none" }, - { G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, "G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES", "do-not-load-properties" }, - { G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, "G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS", "do-not-connect-signals" }, - { G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, "G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START", "do-not-auto-start" }, - { G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, "G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES", "get-invalidated-properties" }, - { G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION, "G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION", "do-not-auto-start-at-construction" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusProxyFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DBUS_ERROR_FAILED, "G_DBUS_ERROR_FAILED", "failed" }, - { G_DBUS_ERROR_NO_MEMORY, "G_DBUS_ERROR_NO_MEMORY", "no-memory" }, - { G_DBUS_ERROR_SERVICE_UNKNOWN, "G_DBUS_ERROR_SERVICE_UNKNOWN", "service-unknown" }, - { G_DBUS_ERROR_NAME_HAS_NO_OWNER, "G_DBUS_ERROR_NAME_HAS_NO_OWNER", "name-has-no-owner" }, - { G_DBUS_ERROR_NO_REPLY, "G_DBUS_ERROR_NO_REPLY", "no-reply" }, - { G_DBUS_ERROR_IO_ERROR, "G_DBUS_ERROR_IO_ERROR", "io-error" }, - { G_DBUS_ERROR_BAD_ADDRESS, "G_DBUS_ERROR_BAD_ADDRESS", "bad-address" }, - { G_DBUS_ERROR_NOT_SUPPORTED, "G_DBUS_ERROR_NOT_SUPPORTED", "not-supported" }, - { G_DBUS_ERROR_LIMITS_EXCEEDED, "G_DBUS_ERROR_LIMITS_EXCEEDED", "limits-exceeded" }, - { G_DBUS_ERROR_ACCESS_DENIED, "G_DBUS_ERROR_ACCESS_DENIED", "access-denied" }, - { G_DBUS_ERROR_AUTH_FAILED, "G_DBUS_ERROR_AUTH_FAILED", "auth-failed" }, - { G_DBUS_ERROR_NO_SERVER, "G_DBUS_ERROR_NO_SERVER", "no-server" }, - { G_DBUS_ERROR_TIMEOUT, "G_DBUS_ERROR_TIMEOUT", "timeout" }, - { G_DBUS_ERROR_NO_NETWORK, "G_DBUS_ERROR_NO_NETWORK", "no-network" }, - { G_DBUS_ERROR_ADDRESS_IN_USE, "G_DBUS_ERROR_ADDRESS_IN_USE", "address-in-use" }, - { G_DBUS_ERROR_DISCONNECTED, "G_DBUS_ERROR_DISCONNECTED", "disconnected" }, - { G_DBUS_ERROR_INVALID_ARGS, "G_DBUS_ERROR_INVALID_ARGS", "invalid-args" }, - { G_DBUS_ERROR_FILE_NOT_FOUND, "G_DBUS_ERROR_FILE_NOT_FOUND", "file-not-found" }, - { G_DBUS_ERROR_FILE_EXISTS, "G_DBUS_ERROR_FILE_EXISTS", "file-exists" }, - { G_DBUS_ERROR_UNKNOWN_METHOD, "G_DBUS_ERROR_UNKNOWN_METHOD", "unknown-method" }, - { G_DBUS_ERROR_TIMED_OUT, "G_DBUS_ERROR_TIMED_OUT", "timed-out" }, - { G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, "G_DBUS_ERROR_MATCH_RULE_NOT_FOUND", "match-rule-not-found" }, - { G_DBUS_ERROR_MATCH_RULE_INVALID, "G_DBUS_ERROR_MATCH_RULE_INVALID", "match-rule-invalid" }, - { G_DBUS_ERROR_SPAWN_EXEC_FAILED, "G_DBUS_ERROR_SPAWN_EXEC_FAILED", "spawn-exec-failed" }, - { G_DBUS_ERROR_SPAWN_FORK_FAILED, "G_DBUS_ERROR_SPAWN_FORK_FAILED", "spawn-fork-failed" }, - { G_DBUS_ERROR_SPAWN_CHILD_EXITED, "G_DBUS_ERROR_SPAWN_CHILD_EXITED", "spawn-child-exited" }, - { G_DBUS_ERROR_SPAWN_CHILD_SIGNALED, "G_DBUS_ERROR_SPAWN_CHILD_SIGNALED", "spawn-child-signaled" }, - { G_DBUS_ERROR_SPAWN_FAILED, "G_DBUS_ERROR_SPAWN_FAILED", "spawn-failed" }, - { G_DBUS_ERROR_SPAWN_SETUP_FAILED, "G_DBUS_ERROR_SPAWN_SETUP_FAILED", "spawn-setup-failed" }, - { G_DBUS_ERROR_SPAWN_CONFIG_INVALID, "G_DBUS_ERROR_SPAWN_CONFIG_INVALID", "spawn-config-invalid" }, - { G_DBUS_ERROR_SPAWN_SERVICE_INVALID, "G_DBUS_ERROR_SPAWN_SERVICE_INVALID", "spawn-service-invalid" }, - { G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND, "G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND", "spawn-service-not-found" }, - { G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID, "G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID", "spawn-permissions-invalid" }, - { G_DBUS_ERROR_SPAWN_FILE_INVALID, "G_DBUS_ERROR_SPAWN_FILE_INVALID", "spawn-file-invalid" }, - { G_DBUS_ERROR_SPAWN_NO_MEMORY, "G_DBUS_ERROR_SPAWN_NO_MEMORY", "spawn-no-memory" }, - { G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN", "unix-process-id-unknown" }, - { G_DBUS_ERROR_INVALID_SIGNATURE, "G_DBUS_ERROR_INVALID_SIGNATURE", "invalid-signature" }, - { G_DBUS_ERROR_INVALID_FILE_CONTENT, "G_DBUS_ERROR_INVALID_FILE_CONTENT", "invalid-file-content" }, - { G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, "G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN", "selinux-security-context-unknown" }, - { G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN, "G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN", "adt-audit-data-unknown" }, - { G_DBUS_ERROR_OBJECT_PATH_IN_USE, "G_DBUS_ERROR_OBJECT_PATH_IN_USE", "object-path-in-use" }, - { G_DBUS_ERROR_UNKNOWN_OBJECT, "G_DBUS_ERROR_UNKNOWN_OBJECT", "unknown-object" }, - { G_DBUS_ERROR_UNKNOWN_INTERFACE, "G_DBUS_ERROR_UNKNOWN_INTERFACE", "unknown-interface" }, - { G_DBUS_ERROR_UNKNOWN_PROPERTY, "G_DBUS_ERROR_UNKNOWN_PROPERTY", "unknown-property" }, - { G_DBUS_ERROR_PROPERTY_READ_ONLY, "G_DBUS_ERROR_PROPERTY_READ_ONLY", "property-read-only" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDBusError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_connection_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_CONNECTION_FLAGS_NONE, "G_DBUS_CONNECTION_FLAGS_NONE", "none" }, - { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT", "authentication-client" }, - { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER", "authentication-server" }, - { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS", "authentication-allow-anonymous" }, - { G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, "G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION", "message-bus-connection" }, - { G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, "G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING", "delay-message-processing" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusConnectionFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_capability_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_CAPABILITY_FLAGS_NONE, "G_DBUS_CAPABILITY_FLAGS_NONE", "none" }, - { G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING, "G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING", "unix-fd-passing" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusCapabilityFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_call_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_CALL_FLAGS_NONE, "G_DBUS_CALL_FLAGS_NONE", "none" }, - { G_DBUS_CALL_FLAGS_NO_AUTO_START, "G_DBUS_CALL_FLAGS_NO_AUTO_START", "no-auto-start" }, - { G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION, "G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION", "allow-interactive-authorization" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusCallFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_message_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DBUS_MESSAGE_TYPE_INVALID, "G_DBUS_MESSAGE_TYPE_INVALID", "invalid" }, - { G_DBUS_MESSAGE_TYPE_METHOD_CALL, "G_DBUS_MESSAGE_TYPE_METHOD_CALL", "method-call" }, - { G_DBUS_MESSAGE_TYPE_METHOD_RETURN, "G_DBUS_MESSAGE_TYPE_METHOD_RETURN", "method-return" }, - { G_DBUS_MESSAGE_TYPE_ERROR, "G_DBUS_MESSAGE_TYPE_ERROR", "error" }, - { G_DBUS_MESSAGE_TYPE_SIGNAL, "G_DBUS_MESSAGE_TYPE_SIGNAL", "signal" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDBusMessageType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_message_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_MESSAGE_FLAGS_NONE, "G_DBUS_MESSAGE_FLAGS_NONE", "none" }, - { G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED, "G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED", "no-reply-expected" }, - { G_DBUS_MESSAGE_FLAGS_NO_AUTO_START, "G_DBUS_MESSAGE_FLAGS_NO_AUTO_START", "no-auto-start" }, - { G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION, "G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION", "allow-interactive-authorization" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusMessageFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_message_header_field_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DBUS_MESSAGE_HEADER_FIELD_INVALID, "G_DBUS_MESSAGE_HEADER_FIELD_INVALID", "invalid" }, - { G_DBUS_MESSAGE_HEADER_FIELD_PATH, "G_DBUS_MESSAGE_HEADER_FIELD_PATH", "path" }, - { G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, "G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE", "interface" }, - { G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, "G_DBUS_MESSAGE_HEADER_FIELD_MEMBER", "member" }, - { G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, "G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME", "error-name" }, - { G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, "G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL", "reply-serial" }, - { G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, "G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION", "destination" }, - { G_DBUS_MESSAGE_HEADER_FIELD_SENDER, "G_DBUS_MESSAGE_HEADER_FIELD_SENDER", "sender" }, - { G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, "G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE", "signature" }, - { G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, "G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS", "num-unix-fds" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDBusMessageHeaderField"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_property_info_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_PROPERTY_INFO_FLAGS_NONE, "G_DBUS_PROPERTY_INFO_FLAGS_NONE", "none" }, - { G_DBUS_PROPERTY_INFO_FLAGS_READABLE, "G_DBUS_PROPERTY_INFO_FLAGS_READABLE", "readable" }, - { G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE, "G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE", "writable" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusPropertyInfoFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_subtree_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_SUBTREE_FLAGS_NONE, "G_DBUS_SUBTREE_FLAGS_NONE", "none" }, - { G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES, "G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES", "dispatch-to-unenumerated-nodes" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusSubtreeFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_server_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_SERVER_FLAGS_NONE, "G_DBUS_SERVER_FLAGS_NONE", "none" }, - { G_DBUS_SERVER_FLAGS_RUN_IN_THREAD, "G_DBUS_SERVER_FLAGS_RUN_IN_THREAD", "run-in-thread" }, - { G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS, "G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS", "authentication-allow-anonymous" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusServerFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_signal_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_SIGNAL_FLAGS_NONE, "G_DBUS_SIGNAL_FLAGS_NONE", "none" }, - { G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, "G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE", "no-match-rule" }, - { G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE", "match-arg0-namespace" }, - { G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH", "match-arg0-path" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusSignalFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_send_message_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_SEND_MESSAGE_FLAGS_NONE, "G_DBUS_SEND_MESSAGE_FLAGS_NONE", "none" }, - { G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, "G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL", "preserve-serial" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusSendMessageFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_credentials_type_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_CREDENTIALS_TYPE_INVALID, "G_CREDENTIALS_TYPE_INVALID", "invalid" }, - { G_CREDENTIALS_TYPE_LINUX_UCRED, "G_CREDENTIALS_TYPE_LINUX_UCRED", "linux-ucred" }, - { G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED, "G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED", "freebsd-cmsgcred" }, - { G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED, "G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED", "openbsd-sockpeercred" }, - { G_CREDENTIALS_TYPE_SOLARIS_UCRED, "G_CREDENTIALS_TYPE_SOLARIS_UCRED", "solaris-ucred" }, - { G_CREDENTIALS_TYPE_NETBSD_UNPCBID, "G_CREDENTIALS_TYPE_NETBSD_UNPCBID", "netbsd-unpcbid" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GCredentialsType"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_message_byte_order_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN, "G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN", "big-endian" }, - { G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN, "G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN", "little-endian" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GDBusMessageByteOrder"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_application_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_APPLICATION_FLAGS_NONE, "G_APPLICATION_FLAGS_NONE", "flags-none" }, - { G_APPLICATION_IS_SERVICE, "G_APPLICATION_IS_SERVICE", "is-service" }, - { G_APPLICATION_IS_LAUNCHER, "G_APPLICATION_IS_LAUNCHER", "is-launcher" }, - { G_APPLICATION_HANDLES_OPEN, "G_APPLICATION_HANDLES_OPEN", "handles-open" }, - { G_APPLICATION_HANDLES_COMMAND_LINE, "G_APPLICATION_HANDLES_COMMAND_LINE", "handles-command-line" }, - { G_APPLICATION_SEND_ENVIRONMENT, "G_APPLICATION_SEND_ENVIRONMENT", "send-environment" }, - { G_APPLICATION_NON_UNIQUE, "G_APPLICATION_NON_UNIQUE", "non-unique" }, - { G_APPLICATION_CAN_OVERRIDE_APP_ID, "G_APPLICATION_CAN_OVERRIDE_APP_ID", "can-override-app-id" }, - { G_APPLICATION_ALLOW_REPLACEMENT, "G_APPLICATION_ALLOW_REPLACEMENT", "allow-replacement" }, - { G_APPLICATION_REPLACE, "G_APPLICATION_REPLACE", "replace" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GApplicationFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_TLS_ERROR_UNAVAILABLE, "G_TLS_ERROR_UNAVAILABLE", "unavailable" }, - { G_TLS_ERROR_MISC, "G_TLS_ERROR_MISC", "misc" }, - { G_TLS_ERROR_BAD_CERTIFICATE, "G_TLS_ERROR_BAD_CERTIFICATE", "bad-certificate" }, - { G_TLS_ERROR_NOT_TLS, "G_TLS_ERROR_NOT_TLS", "not-tls" }, - { G_TLS_ERROR_HANDSHAKE, "G_TLS_ERROR_HANDSHAKE", "handshake" }, - { G_TLS_ERROR_CERTIFICATE_REQUIRED, "G_TLS_ERROR_CERTIFICATE_REQUIRED", "certificate-required" }, - { G_TLS_ERROR_EOF, "G_TLS_ERROR_EOF", "eof" }, - { G_TLS_ERROR_INAPPROPRIATE_FALLBACK, "G_TLS_ERROR_INAPPROPRIATE_FALLBACK", "inappropriate-fallback" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GTlsError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_certificate_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_TLS_CERTIFICATE_UNKNOWN_CA, "G_TLS_CERTIFICATE_UNKNOWN_CA", "unknown-ca" }, - { G_TLS_CERTIFICATE_BAD_IDENTITY, "G_TLS_CERTIFICATE_BAD_IDENTITY", "bad-identity" }, - { G_TLS_CERTIFICATE_NOT_ACTIVATED, "G_TLS_CERTIFICATE_NOT_ACTIVATED", "not-activated" }, - { G_TLS_CERTIFICATE_EXPIRED, "G_TLS_CERTIFICATE_EXPIRED", "expired" }, - { G_TLS_CERTIFICATE_REVOKED, "G_TLS_CERTIFICATE_REVOKED", "revoked" }, - { G_TLS_CERTIFICATE_INSECURE, "G_TLS_CERTIFICATE_INSECURE", "insecure" }, - { G_TLS_CERTIFICATE_GENERIC_ERROR, "G_TLS_CERTIFICATE_GENERIC_ERROR", "generic-error" }, - { G_TLS_CERTIFICATE_VALIDATE_ALL, "G_TLS_CERTIFICATE_VALIDATE_ALL", "validate-all" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GTlsCertificateFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_authentication_mode_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_TLS_AUTHENTICATION_NONE, "G_TLS_AUTHENTICATION_NONE", "none" }, - { G_TLS_AUTHENTICATION_REQUESTED, "G_TLS_AUTHENTICATION_REQUESTED", "requested" }, - { G_TLS_AUTHENTICATION_REQUIRED, "G_TLS_AUTHENTICATION_REQUIRED", "required" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GTlsAuthenticationMode"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_rehandshake_mode_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_TLS_REHANDSHAKE_NEVER, "G_TLS_REHANDSHAKE_NEVER", "never" }, - { G_TLS_REHANDSHAKE_SAFELY, "G_TLS_REHANDSHAKE_SAFELY", "safely" }, - { G_TLS_REHANDSHAKE_UNSAFELY, "G_TLS_REHANDSHAKE_UNSAFELY", "unsafely" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GTlsRehandshakeMode"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_password_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_TLS_PASSWORD_NONE, "G_TLS_PASSWORD_NONE", "none" }, - { G_TLS_PASSWORD_RETRY, "G_TLS_PASSWORD_RETRY", "retry" }, - { G_TLS_PASSWORD_MANY_TRIES, "G_TLS_PASSWORD_MANY_TRIES", "many-tries" }, - { G_TLS_PASSWORD_FINAL_TRY, "G_TLS_PASSWORD_FINAL_TRY", "final-try" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GTlsPasswordFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_interaction_result_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_TLS_INTERACTION_UNHANDLED, "G_TLS_INTERACTION_UNHANDLED", "unhandled" }, - { G_TLS_INTERACTION_HANDLED, "G_TLS_INTERACTION_HANDLED", "handled" }, - { G_TLS_INTERACTION_FAILED, "G_TLS_INTERACTION_FAILED", "failed" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GTlsInteractionResult"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_interface_skeleton_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_INTERFACE_SKELETON_FLAGS_NONE, "G_DBUS_INTERFACE_SKELETON_FLAGS_NONE", "none" }, - { G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD, "G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD", "handle-method-invocations-in-thread" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusInterfaceSkeletonFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_dbus_object_manager_client_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE", "none" }, - { G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, "G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START", "do-not-auto-start" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GDBusObjectManagerClientFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_database_verify_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_TLS_DATABASE_VERIFY_NONE, "G_TLS_DATABASE_VERIFY_NONE", "none" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GTlsDatabaseVerifyFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_database_lookup_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_TLS_DATABASE_LOOKUP_NONE, "G_TLS_DATABASE_LOOKUP_NONE", "none" }, - { G_TLS_DATABASE_LOOKUP_KEYPAIR, "G_TLS_DATABASE_LOOKUP_KEYPAIR", "keypair" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GTlsDatabaseLookupFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_tls_certificate_request_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_TLS_CERTIFICATE_REQUEST_NONE, "G_TLS_CERTIFICATE_REQUEST_NONE", "none" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GTlsCertificateRequestFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_io_module_scope_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_IO_MODULE_SCOPE_NONE, "G_IO_MODULE_SCOPE_NONE", "none" }, - { G_IO_MODULE_SCOPE_BLOCK_DUPLICATES, "G_IO_MODULE_SCOPE_BLOCK_DUPLICATES", "block-duplicates" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GIOModuleScopeFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_socket_client_event_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_SOCKET_CLIENT_RESOLVING, "G_SOCKET_CLIENT_RESOLVING", "resolving" }, - { G_SOCKET_CLIENT_RESOLVED, "G_SOCKET_CLIENT_RESOLVED", "resolved" }, - { G_SOCKET_CLIENT_CONNECTING, "G_SOCKET_CLIENT_CONNECTING", "connecting" }, - { G_SOCKET_CLIENT_CONNECTED, "G_SOCKET_CLIENT_CONNECTED", "connected" }, - { G_SOCKET_CLIENT_PROXY_NEGOTIATING, "G_SOCKET_CLIENT_PROXY_NEGOTIATING", "proxy-negotiating" }, - { G_SOCKET_CLIENT_PROXY_NEGOTIATED, "G_SOCKET_CLIENT_PROXY_NEGOTIATED", "proxy-negotiated" }, - { G_SOCKET_CLIENT_TLS_HANDSHAKING, "G_SOCKET_CLIENT_TLS_HANDSHAKING", "tls-handshaking" }, - { G_SOCKET_CLIENT_TLS_HANDSHAKED, "G_SOCKET_CLIENT_TLS_HANDSHAKED", "tls-handshaked" }, - { G_SOCKET_CLIENT_COMPLETE, "G_SOCKET_CLIENT_COMPLETE", "complete" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GSocketClientEvent"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_socket_listener_event_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_SOCKET_LISTENER_BINDING, "G_SOCKET_LISTENER_BINDING", "binding" }, - { G_SOCKET_LISTENER_BOUND, "G_SOCKET_LISTENER_BOUND", "bound" }, - { G_SOCKET_LISTENER_LISTENING, "G_SOCKET_LISTENER_LISTENING", "listening" }, - { G_SOCKET_LISTENER_LISTENED, "G_SOCKET_LISTENER_LISTENED", "listened" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GSocketListenerEvent"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_test_dbus_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_TEST_DBUS_NONE, "G_TEST_DBUS_NONE", "none" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GTestDBusFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_subprocess_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_SUBPROCESS_FLAGS_NONE, "G_SUBPROCESS_FLAGS_NONE", "none" }, - { G_SUBPROCESS_FLAGS_STDIN_PIPE, "G_SUBPROCESS_FLAGS_STDIN_PIPE", "stdin-pipe" }, - { G_SUBPROCESS_FLAGS_STDIN_INHERIT, "G_SUBPROCESS_FLAGS_STDIN_INHERIT", "stdin-inherit" }, - { G_SUBPROCESS_FLAGS_STDOUT_PIPE, "G_SUBPROCESS_FLAGS_STDOUT_PIPE", "stdout-pipe" }, - { G_SUBPROCESS_FLAGS_STDOUT_SILENCE, "G_SUBPROCESS_FLAGS_STDOUT_SILENCE", "stdout-silence" }, - { G_SUBPROCESS_FLAGS_STDERR_PIPE, "G_SUBPROCESS_FLAGS_STDERR_PIPE", "stderr-pipe" }, - { G_SUBPROCESS_FLAGS_STDERR_SILENCE, "G_SUBPROCESS_FLAGS_STDERR_SILENCE", "stderr-silence" }, - { G_SUBPROCESS_FLAGS_STDERR_MERGE, "G_SUBPROCESS_FLAGS_STDERR_MERGE", "stderr-merge" }, - { G_SUBPROCESS_FLAGS_INHERIT_FDS, "G_SUBPROCESS_FLAGS_INHERIT_FDS", "inherit-fds" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GSubprocessFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_notification_priority_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_NOTIFICATION_PRIORITY_NORMAL, "G_NOTIFICATION_PRIORITY_NORMAL", "normal" }, - { G_NOTIFICATION_PRIORITY_LOW, "G_NOTIFICATION_PRIORITY_LOW", "low" }, - { G_NOTIFICATION_PRIORITY_HIGH, "G_NOTIFICATION_PRIORITY_HIGH", "high" }, - { G_NOTIFICATION_PRIORITY_URGENT, "G_NOTIFICATION_PRIORITY_URGENT", "urgent" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GNotificationPriority"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_network_connectivity_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_NETWORK_CONNECTIVITY_LOCAL, "G_NETWORK_CONNECTIVITY_LOCAL", "local" }, - { G_NETWORK_CONNECTIVITY_LIMITED, "G_NETWORK_CONNECTIVITY_LIMITED", "limited" }, - { G_NETWORK_CONNECTIVITY_PORTAL, "G_NETWORK_CONNECTIVITY_PORTAL", "portal" }, - { G_NETWORK_CONNECTIVITY_FULL, "G_NETWORK_CONNECTIVITY_FULL", "full" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GNetworkConnectivity"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType -g_pollable_return_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { G_POLLABLE_RETURN_FAILED, "G_POLLABLE_RETURN_FAILED", "failed" }, - { G_POLLABLE_RETURN_OK, "G_POLLABLE_RETURN_OK", "ok" }, - { G_POLLABLE_RETURN_WOULD_BLOCK, "G_POLLABLE_RETURN_WOULD_BLOCK", "would-block" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("GPollableReturn"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -/* enumerations from "../gio/gresolver.h" */ -GType -g_resolver_name_lookup_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, "G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT", "default" }, - { G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY, "G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY", "ipv4-only" }, - { G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY, "G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY", "ipv6-only" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GResolverNameLookupFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -/* enumerations from "../gio/gsettings.h" */ -GType -g_settings_bind_flags_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GFlagsValue values[] = { - { G_SETTINGS_BIND_DEFAULT, "G_SETTINGS_BIND_DEFAULT", "default" }, - { G_SETTINGS_BIND_GET, "G_SETTINGS_BIND_GET", "get" }, - { G_SETTINGS_BIND_SET, "G_SETTINGS_BIND_SET", "set" }, - { G_SETTINGS_BIND_NO_SENSITIVITY, "G_SETTINGS_BIND_NO_SENSITIVITY", "no-sensitivity" }, - { G_SETTINGS_BIND_GET_NO_CHANGES, "G_SETTINGS_BIND_GET_NO_CHANGES", "get-no-changes" }, - { G_SETTINGS_BIND_INVERT_BOOLEAN, "G_SETTINGS_BIND_INVERT_BOOLEAN", "invert-boolean" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_flags_register_static (g_intern_static_string ("GSettingsBindFlags"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/* Generated data ends here */ - + +/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ + +#include "config.h" +#include "gioenumtypes.h" +#include +/* enumerations from "../gio/gioenums.h" */ +GType +g_app_info_create_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_APP_INFO_CREATE_NONE, "G_APP_INFO_CREATE_NONE", "none" }, + { G_APP_INFO_CREATE_NEEDS_TERMINAL, "G_APP_INFO_CREATE_NEEDS_TERMINAL", "needs-terminal" }, + { G_APP_INFO_CREATE_SUPPORTS_URIS, "G_APP_INFO_CREATE_SUPPORTS_URIS", "supports-uris" }, + { G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION, "G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION", "supports-startup-notification" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GAppInfoCreateFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_converter_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_CONVERTER_NO_FLAGS, "G_CONVERTER_NO_FLAGS", "none" }, + { G_CONVERTER_INPUT_AT_END, "G_CONVERTER_INPUT_AT_END", "input-at-end" }, + { G_CONVERTER_FLUSH, "G_CONVERTER_FLUSH", "flush" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GConverterFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_converter_result_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_CONVERTER_ERROR, "G_CONVERTER_ERROR", "error" }, + { G_CONVERTER_CONVERTED, "G_CONVERTER_CONVERTED", "converted" }, + { G_CONVERTER_FINISHED, "G_CONVERTER_FINISHED", "finished" }, + { G_CONVERTER_FLUSHED, "G_CONVERTER_FLUSHED", "flushed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GConverterResult"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_data_stream_byte_order_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN, "G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN", "big-endian" }, + { G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN, "G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN", "little-endian" }, + { G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN, "G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN", "host-endian" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDataStreamByteOrder"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_data_stream_newline_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DATA_STREAM_NEWLINE_TYPE_LF, "G_DATA_STREAM_NEWLINE_TYPE_LF", "lf" }, + { G_DATA_STREAM_NEWLINE_TYPE_CR, "G_DATA_STREAM_NEWLINE_TYPE_CR", "cr" }, + { G_DATA_STREAM_NEWLINE_TYPE_CR_LF, "G_DATA_STREAM_NEWLINE_TYPE_CR_LF", "cr-lf" }, + { G_DATA_STREAM_NEWLINE_TYPE_ANY, "G_DATA_STREAM_NEWLINE_TYPE_ANY", "any" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDataStreamNewlineType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_attribute_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_FILE_ATTRIBUTE_TYPE_INVALID, "G_FILE_ATTRIBUTE_TYPE_INVALID", "invalid" }, + { G_FILE_ATTRIBUTE_TYPE_STRING, "G_FILE_ATTRIBUTE_TYPE_STRING", "string" }, + { G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, "G_FILE_ATTRIBUTE_TYPE_BYTE_STRING", "byte-string" }, + { G_FILE_ATTRIBUTE_TYPE_BOOLEAN, "G_FILE_ATTRIBUTE_TYPE_BOOLEAN", "boolean" }, + { G_FILE_ATTRIBUTE_TYPE_UINT32, "G_FILE_ATTRIBUTE_TYPE_UINT32", "uint32" }, + { G_FILE_ATTRIBUTE_TYPE_INT32, "G_FILE_ATTRIBUTE_TYPE_INT32", "int32" }, + { G_FILE_ATTRIBUTE_TYPE_UINT64, "G_FILE_ATTRIBUTE_TYPE_UINT64", "uint64" }, + { G_FILE_ATTRIBUTE_TYPE_INT64, "G_FILE_ATTRIBUTE_TYPE_INT64", "int64" }, + { G_FILE_ATTRIBUTE_TYPE_OBJECT, "G_FILE_ATTRIBUTE_TYPE_OBJECT", "object" }, + { G_FILE_ATTRIBUTE_TYPE_STRINGV, "G_FILE_ATTRIBUTE_TYPE_STRINGV", "stringv" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GFileAttributeType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_attribute_info_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_FILE_ATTRIBUTE_INFO_NONE, "G_FILE_ATTRIBUTE_INFO_NONE", "none" }, + { G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE, "G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE", "copy-with-file" }, + { G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED, "G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED", "copy-when-moved" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GFileAttributeInfoFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_attribute_status_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_FILE_ATTRIBUTE_STATUS_UNSET, "G_FILE_ATTRIBUTE_STATUS_UNSET", "unset" }, + { G_FILE_ATTRIBUTE_STATUS_SET, "G_FILE_ATTRIBUTE_STATUS_SET", "set" }, + { G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING, "G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING", "error-setting" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GFileAttributeStatus"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_query_info_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_FILE_QUERY_INFO_NONE, "G_FILE_QUERY_INFO_NONE", "none" }, + { G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, "G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS", "nofollow-symlinks" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GFileQueryInfoFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_create_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_FILE_CREATE_NONE, "G_FILE_CREATE_NONE", "none" }, + { G_FILE_CREATE_PRIVATE, "G_FILE_CREATE_PRIVATE", "private" }, + { G_FILE_CREATE_REPLACE_DESTINATION, "G_FILE_CREATE_REPLACE_DESTINATION", "replace-destination" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GFileCreateFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_measure_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_FILE_MEASURE_NONE, "G_FILE_MEASURE_NONE", "none" }, + { G_FILE_MEASURE_REPORT_ANY_ERROR, "G_FILE_MEASURE_REPORT_ANY_ERROR", "report-any-error" }, + { G_FILE_MEASURE_APPARENT_SIZE, "G_FILE_MEASURE_APPARENT_SIZE", "apparent-size" }, + { G_FILE_MEASURE_NO_XDEV, "G_FILE_MEASURE_NO_XDEV", "no-xdev" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GFileMeasureFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_mount_mount_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_MOUNT_MOUNT_NONE, "G_MOUNT_MOUNT_NONE", "none" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GMountMountFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_mount_unmount_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_MOUNT_UNMOUNT_NONE, "G_MOUNT_UNMOUNT_NONE", "none" }, + { G_MOUNT_UNMOUNT_FORCE, "G_MOUNT_UNMOUNT_FORCE", "force" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GMountUnmountFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_drive_start_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DRIVE_START_NONE, "G_DRIVE_START_NONE", "none" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDriveStartFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_drive_start_stop_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DRIVE_START_STOP_TYPE_UNKNOWN, "G_DRIVE_START_STOP_TYPE_UNKNOWN", "unknown" }, + { G_DRIVE_START_STOP_TYPE_SHUTDOWN, "G_DRIVE_START_STOP_TYPE_SHUTDOWN", "shutdown" }, + { G_DRIVE_START_STOP_TYPE_NETWORK, "G_DRIVE_START_STOP_TYPE_NETWORK", "network" }, + { G_DRIVE_START_STOP_TYPE_MULTIDISK, "G_DRIVE_START_STOP_TYPE_MULTIDISK", "multidisk" }, + { G_DRIVE_START_STOP_TYPE_PASSWORD, "G_DRIVE_START_STOP_TYPE_PASSWORD", "password" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDriveStartStopType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_copy_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_FILE_COPY_NONE, "G_FILE_COPY_NONE", "none" }, + { G_FILE_COPY_OVERWRITE, "G_FILE_COPY_OVERWRITE", "overwrite" }, + { G_FILE_COPY_BACKUP, "G_FILE_COPY_BACKUP", "backup" }, + { G_FILE_COPY_NOFOLLOW_SYMLINKS, "G_FILE_COPY_NOFOLLOW_SYMLINKS", "nofollow-symlinks" }, + { G_FILE_COPY_ALL_METADATA, "G_FILE_COPY_ALL_METADATA", "all-metadata" }, + { G_FILE_COPY_NO_FALLBACK_FOR_MOVE, "G_FILE_COPY_NO_FALLBACK_FOR_MOVE", "no-fallback-for-move" }, + { G_FILE_COPY_TARGET_DEFAULT_PERMS, "G_FILE_COPY_TARGET_DEFAULT_PERMS", "target-default-perms" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GFileCopyFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_monitor_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_FILE_MONITOR_NONE, "G_FILE_MONITOR_NONE", "none" }, + { G_FILE_MONITOR_WATCH_MOUNTS, "G_FILE_MONITOR_WATCH_MOUNTS", "watch-mounts" }, + { G_FILE_MONITOR_SEND_MOVED, "G_FILE_MONITOR_SEND_MOVED", "send-moved" }, + { G_FILE_MONITOR_WATCH_HARD_LINKS, "G_FILE_MONITOR_WATCH_HARD_LINKS", "watch-hard-links" }, + { G_FILE_MONITOR_WATCH_MOVES, "G_FILE_MONITOR_WATCH_MOVES", "watch-moves" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GFileMonitorFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_FILE_TYPE_UNKNOWN, "G_FILE_TYPE_UNKNOWN", "unknown" }, + { G_FILE_TYPE_REGULAR, "G_FILE_TYPE_REGULAR", "regular" }, + { G_FILE_TYPE_DIRECTORY, "G_FILE_TYPE_DIRECTORY", "directory" }, + { G_FILE_TYPE_SYMBOLIC_LINK, "G_FILE_TYPE_SYMBOLIC_LINK", "symbolic-link" }, + { G_FILE_TYPE_SPECIAL, "G_FILE_TYPE_SPECIAL", "special" }, + { G_FILE_TYPE_SHORTCUT, "G_FILE_TYPE_SHORTCUT", "shortcut" }, + { G_FILE_TYPE_MOUNTABLE, "G_FILE_TYPE_MOUNTABLE", "mountable" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GFileType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_filesystem_preview_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_FILESYSTEM_PREVIEW_TYPE_IF_ALWAYS, "G_FILESYSTEM_PREVIEW_TYPE_IF_ALWAYS", "if-always" }, + { G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL, "G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL", "if-local" }, + { G_FILESYSTEM_PREVIEW_TYPE_NEVER, "G_FILESYSTEM_PREVIEW_TYPE_NEVER", "never" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GFilesystemPreviewType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_file_monitor_event_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_FILE_MONITOR_EVENT_CHANGED, "G_FILE_MONITOR_EVENT_CHANGED", "changed" }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT", "changes-done-hint" }, + { G_FILE_MONITOR_EVENT_DELETED, "G_FILE_MONITOR_EVENT_DELETED", "deleted" }, + { G_FILE_MONITOR_EVENT_CREATED, "G_FILE_MONITOR_EVENT_CREATED", "created" }, + { G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED, "G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED", "attribute-changed" }, + { G_FILE_MONITOR_EVENT_PRE_UNMOUNT, "G_FILE_MONITOR_EVENT_PRE_UNMOUNT", "pre-unmount" }, + { G_FILE_MONITOR_EVENT_UNMOUNTED, "G_FILE_MONITOR_EVENT_UNMOUNTED", "unmounted" }, + { G_FILE_MONITOR_EVENT_MOVED, "G_FILE_MONITOR_EVENT_MOVED", "moved" }, + { G_FILE_MONITOR_EVENT_RENAMED, "G_FILE_MONITOR_EVENT_RENAMED", "renamed" }, + { G_FILE_MONITOR_EVENT_MOVED_IN, "G_FILE_MONITOR_EVENT_MOVED_IN", "moved-in" }, + { G_FILE_MONITOR_EVENT_MOVED_OUT, "G_FILE_MONITOR_EVENT_MOVED_OUT", "moved-out" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GFileMonitorEvent"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_io_error_enum_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_IO_ERROR_FAILED, "G_IO_ERROR_FAILED", "failed" }, + { G_IO_ERROR_NOT_FOUND, "G_IO_ERROR_NOT_FOUND", "not-found" }, + { G_IO_ERROR_EXISTS, "G_IO_ERROR_EXISTS", "exists" }, + { G_IO_ERROR_IS_DIRECTORY, "G_IO_ERROR_IS_DIRECTORY", "is-directory" }, + { G_IO_ERROR_NOT_DIRECTORY, "G_IO_ERROR_NOT_DIRECTORY", "not-directory" }, + { G_IO_ERROR_NOT_EMPTY, "G_IO_ERROR_NOT_EMPTY", "not-empty" }, + { G_IO_ERROR_NOT_REGULAR_FILE, "G_IO_ERROR_NOT_REGULAR_FILE", "not-regular-file" }, + { G_IO_ERROR_NOT_SYMBOLIC_LINK, "G_IO_ERROR_NOT_SYMBOLIC_LINK", "not-symbolic-link" }, + { G_IO_ERROR_NOT_MOUNTABLE_FILE, "G_IO_ERROR_NOT_MOUNTABLE_FILE", "not-mountable-file" }, + { G_IO_ERROR_FILENAME_TOO_LONG, "G_IO_ERROR_FILENAME_TOO_LONG", "filename-too-long" }, + { G_IO_ERROR_INVALID_FILENAME, "G_IO_ERROR_INVALID_FILENAME", "invalid-filename" }, + { G_IO_ERROR_TOO_MANY_LINKS, "G_IO_ERROR_TOO_MANY_LINKS", "too-many-links" }, + { G_IO_ERROR_NO_SPACE, "G_IO_ERROR_NO_SPACE", "no-space" }, + { G_IO_ERROR_INVALID_ARGUMENT, "G_IO_ERROR_INVALID_ARGUMENT", "invalid-argument" }, + { G_IO_ERROR_PERMISSION_DENIED, "G_IO_ERROR_PERMISSION_DENIED", "permission-denied" }, + { G_IO_ERROR_NOT_SUPPORTED, "G_IO_ERROR_NOT_SUPPORTED", "not-supported" }, + { G_IO_ERROR_NOT_MOUNTED, "G_IO_ERROR_NOT_MOUNTED", "not-mounted" }, + { G_IO_ERROR_ALREADY_MOUNTED, "G_IO_ERROR_ALREADY_MOUNTED", "already-mounted" }, + { G_IO_ERROR_CLOSED, "G_IO_ERROR_CLOSED", "closed" }, + { G_IO_ERROR_CANCELLED, "G_IO_ERROR_CANCELLED", "cancelled" }, + { G_IO_ERROR_PENDING, "G_IO_ERROR_PENDING", "pending" }, + { G_IO_ERROR_READ_ONLY, "G_IO_ERROR_READ_ONLY", "read-only" }, + { G_IO_ERROR_CANT_CREATE_BACKUP, "G_IO_ERROR_CANT_CREATE_BACKUP", "cant-create-backup" }, + { G_IO_ERROR_WRONG_ETAG, "G_IO_ERROR_WRONG_ETAG", "wrong-etag" }, + { G_IO_ERROR_TIMED_OUT, "G_IO_ERROR_TIMED_OUT", "timed-out" }, + { G_IO_ERROR_WOULD_RECURSE, "G_IO_ERROR_WOULD_RECURSE", "would-recurse" }, + { G_IO_ERROR_BUSY, "G_IO_ERROR_BUSY", "busy" }, + { G_IO_ERROR_WOULD_BLOCK, "G_IO_ERROR_WOULD_BLOCK", "would-block" }, + { G_IO_ERROR_HOST_NOT_FOUND, "G_IO_ERROR_HOST_NOT_FOUND", "host-not-found" }, + { G_IO_ERROR_WOULD_MERGE, "G_IO_ERROR_WOULD_MERGE", "would-merge" }, + { G_IO_ERROR_FAILED_HANDLED, "G_IO_ERROR_FAILED_HANDLED", "failed-handled" }, + { G_IO_ERROR_TOO_MANY_OPEN_FILES, "G_IO_ERROR_TOO_MANY_OPEN_FILES", "too-many-open-files" }, + { G_IO_ERROR_NOT_INITIALIZED, "G_IO_ERROR_NOT_INITIALIZED", "not-initialized" }, + { G_IO_ERROR_ADDRESS_IN_USE, "G_IO_ERROR_ADDRESS_IN_USE", "address-in-use" }, + { G_IO_ERROR_PARTIAL_INPUT, "G_IO_ERROR_PARTIAL_INPUT", "partial-input" }, + { G_IO_ERROR_INVALID_DATA, "G_IO_ERROR_INVALID_DATA", "invalid-data" }, + { G_IO_ERROR_DBUS_ERROR, "G_IO_ERROR_DBUS_ERROR", "dbus-error" }, + { G_IO_ERROR_HOST_UNREACHABLE, "G_IO_ERROR_HOST_UNREACHABLE", "host-unreachable" }, + { G_IO_ERROR_NETWORK_UNREACHABLE, "G_IO_ERROR_NETWORK_UNREACHABLE", "network-unreachable" }, + { G_IO_ERROR_CONNECTION_REFUSED, "G_IO_ERROR_CONNECTION_REFUSED", "connection-refused" }, + { G_IO_ERROR_PROXY_FAILED, "G_IO_ERROR_PROXY_FAILED", "proxy-failed" }, + { G_IO_ERROR_PROXY_AUTH_FAILED, "G_IO_ERROR_PROXY_AUTH_FAILED", "proxy-auth-failed" }, + { G_IO_ERROR_PROXY_NEED_AUTH, "G_IO_ERROR_PROXY_NEED_AUTH", "proxy-need-auth" }, + { G_IO_ERROR_PROXY_NOT_ALLOWED, "G_IO_ERROR_PROXY_NOT_ALLOWED", "proxy-not-allowed" }, + { G_IO_ERROR_BROKEN_PIPE, "G_IO_ERROR_BROKEN_PIPE", "broken-pipe" }, + { G_IO_ERROR_CONNECTION_CLOSED, "G_IO_ERROR_CONNECTION_CLOSED", "connection-closed" }, + { G_IO_ERROR_NOT_CONNECTED, "G_IO_ERROR_NOT_CONNECTED", "not-connected" }, + { G_IO_ERROR_MESSAGE_TOO_LARGE, "G_IO_ERROR_MESSAGE_TOO_LARGE", "message-too-large" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GIOErrorEnum"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_ask_password_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_ASK_PASSWORD_NEED_PASSWORD, "G_ASK_PASSWORD_NEED_PASSWORD", "need-password" }, + { G_ASK_PASSWORD_NEED_USERNAME, "G_ASK_PASSWORD_NEED_USERNAME", "need-username" }, + { G_ASK_PASSWORD_NEED_DOMAIN, "G_ASK_PASSWORD_NEED_DOMAIN", "need-domain" }, + { G_ASK_PASSWORD_SAVING_SUPPORTED, "G_ASK_PASSWORD_SAVING_SUPPORTED", "saving-supported" }, + { G_ASK_PASSWORD_ANONYMOUS_SUPPORTED, "G_ASK_PASSWORD_ANONYMOUS_SUPPORTED", "anonymous-supported" }, + { G_ASK_PASSWORD_TCRYPT, "G_ASK_PASSWORD_TCRYPT", "tcrypt" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GAskPasswordFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_password_save_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_PASSWORD_SAVE_NEVER, "G_PASSWORD_SAVE_NEVER", "never" }, + { G_PASSWORD_SAVE_FOR_SESSION, "G_PASSWORD_SAVE_FOR_SESSION", "for-session" }, + { G_PASSWORD_SAVE_PERMANENTLY, "G_PASSWORD_SAVE_PERMANENTLY", "permanently" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GPasswordSave"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_mount_operation_result_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_MOUNT_OPERATION_HANDLED, "G_MOUNT_OPERATION_HANDLED", "handled" }, + { G_MOUNT_OPERATION_ABORTED, "G_MOUNT_OPERATION_ABORTED", "aborted" }, + { G_MOUNT_OPERATION_UNHANDLED, "G_MOUNT_OPERATION_UNHANDLED", "unhandled" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GMountOperationResult"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_output_stream_splice_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_OUTPUT_STREAM_SPLICE_NONE, "G_OUTPUT_STREAM_SPLICE_NONE", "none" }, + { G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, "G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE", "close-source" }, + { G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, "G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET", "close-target" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GOutputStreamSpliceFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_io_stream_splice_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_IO_STREAM_SPLICE_NONE, "G_IO_STREAM_SPLICE_NONE", "none" }, + { G_IO_STREAM_SPLICE_CLOSE_STREAM1, "G_IO_STREAM_SPLICE_CLOSE_STREAM1", "close-stream1" }, + { G_IO_STREAM_SPLICE_CLOSE_STREAM2, "G_IO_STREAM_SPLICE_CLOSE_STREAM2", "close-stream2" }, + { G_IO_STREAM_SPLICE_WAIT_FOR_BOTH, "G_IO_STREAM_SPLICE_WAIT_FOR_BOTH", "wait-for-both" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GIOStreamSpliceFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_emblem_origin_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_EMBLEM_ORIGIN_UNKNOWN, "G_EMBLEM_ORIGIN_UNKNOWN", "unknown" }, + { G_EMBLEM_ORIGIN_DEVICE, "G_EMBLEM_ORIGIN_DEVICE", "device" }, + { G_EMBLEM_ORIGIN_LIVEMETADATA, "G_EMBLEM_ORIGIN_LIVEMETADATA", "livemetadata" }, + { G_EMBLEM_ORIGIN_TAG, "G_EMBLEM_ORIGIN_TAG", "tag" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GEmblemOrigin"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_resolver_error_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_RESOLVER_ERROR_NOT_FOUND, "G_RESOLVER_ERROR_NOT_FOUND", "not-found" }, + { G_RESOLVER_ERROR_TEMPORARY_FAILURE, "G_RESOLVER_ERROR_TEMPORARY_FAILURE", "temporary-failure" }, + { G_RESOLVER_ERROR_INTERNAL, "G_RESOLVER_ERROR_INTERNAL", "internal" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GResolverError"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_resolver_record_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_RESOLVER_RECORD_SRV, "G_RESOLVER_RECORD_SRV", "srv" }, + { G_RESOLVER_RECORD_MX, "G_RESOLVER_RECORD_MX", "mx" }, + { G_RESOLVER_RECORD_TXT, "G_RESOLVER_RECORD_TXT", "txt" }, + { G_RESOLVER_RECORD_SOA, "G_RESOLVER_RECORD_SOA", "soa" }, + { G_RESOLVER_RECORD_NS, "G_RESOLVER_RECORD_NS", "ns" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GResolverRecordType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_resource_error_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_RESOURCE_ERROR_NOT_FOUND, "G_RESOURCE_ERROR_NOT_FOUND", "not-found" }, + { G_RESOURCE_ERROR_INTERNAL, "G_RESOURCE_ERROR_INTERNAL", "internal" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GResourceError"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_resource_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_RESOURCE_FLAGS_NONE, "G_RESOURCE_FLAGS_NONE", "none" }, + { G_RESOURCE_FLAGS_COMPRESSED, "G_RESOURCE_FLAGS_COMPRESSED", "compressed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GResourceFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_resource_lookup_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_RESOURCE_LOOKUP_FLAGS_NONE, "G_RESOURCE_LOOKUP_FLAGS_NONE", "none" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GResourceLookupFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_socket_family_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_SOCKET_FAMILY_INVALID, "G_SOCKET_FAMILY_INVALID", "invalid" }, + { G_SOCKET_FAMILY_UNIX, "G_SOCKET_FAMILY_UNIX", "unix" }, + { G_SOCKET_FAMILY_IPV4, "G_SOCKET_FAMILY_IPV4", "ipv4" }, + { G_SOCKET_FAMILY_IPV6, "G_SOCKET_FAMILY_IPV6", "ipv6" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GSocketFamily"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_socket_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_SOCKET_TYPE_INVALID, "G_SOCKET_TYPE_INVALID", "invalid" }, + { G_SOCKET_TYPE_STREAM, "G_SOCKET_TYPE_STREAM", "stream" }, + { G_SOCKET_TYPE_DATAGRAM, "G_SOCKET_TYPE_DATAGRAM", "datagram" }, + { G_SOCKET_TYPE_SEQPACKET, "G_SOCKET_TYPE_SEQPACKET", "seqpacket" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GSocketType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_socket_msg_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_SOCKET_MSG_NONE, "G_SOCKET_MSG_NONE", "none" }, + { G_SOCKET_MSG_OOB, "G_SOCKET_MSG_OOB", "oob" }, + { G_SOCKET_MSG_PEEK, "G_SOCKET_MSG_PEEK", "peek" }, + { G_SOCKET_MSG_DONTROUTE, "G_SOCKET_MSG_DONTROUTE", "dontroute" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GSocketMsgFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_socket_protocol_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_SOCKET_PROTOCOL_UNKNOWN, "G_SOCKET_PROTOCOL_UNKNOWN", "unknown" }, + { G_SOCKET_PROTOCOL_DEFAULT, "G_SOCKET_PROTOCOL_DEFAULT", "default" }, + { G_SOCKET_PROTOCOL_TCP, "G_SOCKET_PROTOCOL_TCP", "tcp" }, + { G_SOCKET_PROTOCOL_UDP, "G_SOCKET_PROTOCOL_UDP", "udp" }, + { G_SOCKET_PROTOCOL_SCTP, "G_SOCKET_PROTOCOL_SCTP", "sctp" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GSocketProtocol"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_zlib_compressor_format_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_ZLIB_COMPRESSOR_FORMAT_ZLIB, "G_ZLIB_COMPRESSOR_FORMAT_ZLIB", "zlib" }, + { G_ZLIB_COMPRESSOR_FORMAT_GZIP, "G_ZLIB_COMPRESSOR_FORMAT_GZIP", "gzip" }, + { G_ZLIB_COMPRESSOR_FORMAT_RAW, "G_ZLIB_COMPRESSOR_FORMAT_RAW", "raw" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GZlibCompressorFormat"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_unix_socket_address_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_UNIX_SOCKET_ADDRESS_INVALID, "G_UNIX_SOCKET_ADDRESS_INVALID", "invalid" }, + { G_UNIX_SOCKET_ADDRESS_ANONYMOUS, "G_UNIX_SOCKET_ADDRESS_ANONYMOUS", "anonymous" }, + { G_UNIX_SOCKET_ADDRESS_PATH, "G_UNIX_SOCKET_ADDRESS_PATH", "path" }, + { G_UNIX_SOCKET_ADDRESS_ABSTRACT, "G_UNIX_SOCKET_ADDRESS_ABSTRACT", "abstract" }, + { G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED, "G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED", "abstract-padded" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GUnixSocketAddressType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_bus_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_BUS_TYPE_STARTER, "G_BUS_TYPE_STARTER", "starter" }, + { G_BUS_TYPE_NONE, "G_BUS_TYPE_NONE", "none" }, + { G_BUS_TYPE_SYSTEM, "G_BUS_TYPE_SYSTEM", "system" }, + { G_BUS_TYPE_SESSION, "G_BUS_TYPE_SESSION", "session" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GBusType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_bus_name_owner_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_BUS_NAME_OWNER_FLAGS_NONE, "G_BUS_NAME_OWNER_FLAGS_NONE", "none" }, + { G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, "G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT", "allow-replacement" }, + { G_BUS_NAME_OWNER_FLAGS_REPLACE, "G_BUS_NAME_OWNER_FLAGS_REPLACE", "replace" }, + { G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, "G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE", "do-not-queue" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GBusNameOwnerFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_bus_name_watcher_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_BUS_NAME_WATCHER_FLAGS_NONE, "G_BUS_NAME_WATCHER_FLAGS_NONE", "none" }, + { G_BUS_NAME_WATCHER_FLAGS_AUTO_START, "G_BUS_NAME_WATCHER_FLAGS_AUTO_START", "auto-start" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GBusNameWatcherFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_proxy_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_PROXY_FLAGS_NONE, "G_DBUS_PROXY_FLAGS_NONE", "none" }, + { G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, "G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES", "do-not-load-properties" }, + { G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, "G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS", "do-not-connect-signals" }, + { G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, "G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START", "do-not-auto-start" }, + { G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, "G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES", "get-invalidated-properties" }, + { G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION, "G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION", "do-not-auto-start-at-construction" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusProxyFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_error_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DBUS_ERROR_FAILED, "G_DBUS_ERROR_FAILED", "failed" }, + { G_DBUS_ERROR_NO_MEMORY, "G_DBUS_ERROR_NO_MEMORY", "no-memory" }, + { G_DBUS_ERROR_SERVICE_UNKNOWN, "G_DBUS_ERROR_SERVICE_UNKNOWN", "service-unknown" }, + { G_DBUS_ERROR_NAME_HAS_NO_OWNER, "G_DBUS_ERROR_NAME_HAS_NO_OWNER", "name-has-no-owner" }, + { G_DBUS_ERROR_NO_REPLY, "G_DBUS_ERROR_NO_REPLY", "no-reply" }, + { G_DBUS_ERROR_IO_ERROR, "G_DBUS_ERROR_IO_ERROR", "io-error" }, + { G_DBUS_ERROR_BAD_ADDRESS, "G_DBUS_ERROR_BAD_ADDRESS", "bad-address" }, + { G_DBUS_ERROR_NOT_SUPPORTED, "G_DBUS_ERROR_NOT_SUPPORTED", "not-supported" }, + { G_DBUS_ERROR_LIMITS_EXCEEDED, "G_DBUS_ERROR_LIMITS_EXCEEDED", "limits-exceeded" }, + { G_DBUS_ERROR_ACCESS_DENIED, "G_DBUS_ERROR_ACCESS_DENIED", "access-denied" }, + { G_DBUS_ERROR_AUTH_FAILED, "G_DBUS_ERROR_AUTH_FAILED", "auth-failed" }, + { G_DBUS_ERROR_NO_SERVER, "G_DBUS_ERROR_NO_SERVER", "no-server" }, + { G_DBUS_ERROR_TIMEOUT, "G_DBUS_ERROR_TIMEOUT", "timeout" }, + { G_DBUS_ERROR_NO_NETWORK, "G_DBUS_ERROR_NO_NETWORK", "no-network" }, + { G_DBUS_ERROR_ADDRESS_IN_USE, "G_DBUS_ERROR_ADDRESS_IN_USE", "address-in-use" }, + { G_DBUS_ERROR_DISCONNECTED, "G_DBUS_ERROR_DISCONNECTED", "disconnected" }, + { G_DBUS_ERROR_INVALID_ARGS, "G_DBUS_ERROR_INVALID_ARGS", "invalid-args" }, + { G_DBUS_ERROR_FILE_NOT_FOUND, "G_DBUS_ERROR_FILE_NOT_FOUND", "file-not-found" }, + { G_DBUS_ERROR_FILE_EXISTS, "G_DBUS_ERROR_FILE_EXISTS", "file-exists" }, + { G_DBUS_ERROR_UNKNOWN_METHOD, "G_DBUS_ERROR_UNKNOWN_METHOD", "unknown-method" }, + { G_DBUS_ERROR_TIMED_OUT, "G_DBUS_ERROR_TIMED_OUT", "timed-out" }, + { G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, "G_DBUS_ERROR_MATCH_RULE_NOT_FOUND", "match-rule-not-found" }, + { G_DBUS_ERROR_MATCH_RULE_INVALID, "G_DBUS_ERROR_MATCH_RULE_INVALID", "match-rule-invalid" }, + { G_DBUS_ERROR_SPAWN_EXEC_FAILED, "G_DBUS_ERROR_SPAWN_EXEC_FAILED", "spawn-exec-failed" }, + { G_DBUS_ERROR_SPAWN_FORK_FAILED, "G_DBUS_ERROR_SPAWN_FORK_FAILED", "spawn-fork-failed" }, + { G_DBUS_ERROR_SPAWN_CHILD_EXITED, "G_DBUS_ERROR_SPAWN_CHILD_EXITED", "spawn-child-exited" }, + { G_DBUS_ERROR_SPAWN_CHILD_SIGNALED, "G_DBUS_ERROR_SPAWN_CHILD_SIGNALED", "spawn-child-signaled" }, + { G_DBUS_ERROR_SPAWN_FAILED, "G_DBUS_ERROR_SPAWN_FAILED", "spawn-failed" }, + { G_DBUS_ERROR_SPAWN_SETUP_FAILED, "G_DBUS_ERROR_SPAWN_SETUP_FAILED", "spawn-setup-failed" }, + { G_DBUS_ERROR_SPAWN_CONFIG_INVALID, "G_DBUS_ERROR_SPAWN_CONFIG_INVALID", "spawn-config-invalid" }, + { G_DBUS_ERROR_SPAWN_SERVICE_INVALID, "G_DBUS_ERROR_SPAWN_SERVICE_INVALID", "spawn-service-invalid" }, + { G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND, "G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND", "spawn-service-not-found" }, + { G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID, "G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID", "spawn-permissions-invalid" }, + { G_DBUS_ERROR_SPAWN_FILE_INVALID, "G_DBUS_ERROR_SPAWN_FILE_INVALID", "spawn-file-invalid" }, + { G_DBUS_ERROR_SPAWN_NO_MEMORY, "G_DBUS_ERROR_SPAWN_NO_MEMORY", "spawn-no-memory" }, + { G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN", "unix-process-id-unknown" }, + { G_DBUS_ERROR_INVALID_SIGNATURE, "G_DBUS_ERROR_INVALID_SIGNATURE", "invalid-signature" }, + { G_DBUS_ERROR_INVALID_FILE_CONTENT, "G_DBUS_ERROR_INVALID_FILE_CONTENT", "invalid-file-content" }, + { G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, "G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN", "selinux-security-context-unknown" }, + { G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN, "G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN", "adt-audit-data-unknown" }, + { G_DBUS_ERROR_OBJECT_PATH_IN_USE, "G_DBUS_ERROR_OBJECT_PATH_IN_USE", "object-path-in-use" }, + { G_DBUS_ERROR_UNKNOWN_OBJECT, "G_DBUS_ERROR_UNKNOWN_OBJECT", "unknown-object" }, + { G_DBUS_ERROR_UNKNOWN_INTERFACE, "G_DBUS_ERROR_UNKNOWN_INTERFACE", "unknown-interface" }, + { G_DBUS_ERROR_UNKNOWN_PROPERTY, "G_DBUS_ERROR_UNKNOWN_PROPERTY", "unknown-property" }, + { G_DBUS_ERROR_PROPERTY_READ_ONLY, "G_DBUS_ERROR_PROPERTY_READ_ONLY", "property-read-only" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDBusError"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_connection_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_CONNECTION_FLAGS_NONE, "G_DBUS_CONNECTION_FLAGS_NONE", "none" }, + { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT", "authentication-client" }, + { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER", "authentication-server" }, + { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS", "authentication-allow-anonymous" }, + { G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, "G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION", "message-bus-connection" }, + { G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, "G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING", "delay-message-processing" }, + { G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER, "G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER", "authentication-require-same-user" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusConnectionFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_capability_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_CAPABILITY_FLAGS_NONE, "G_DBUS_CAPABILITY_FLAGS_NONE", "none" }, + { G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING, "G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING", "unix-fd-passing" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusCapabilityFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_call_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_CALL_FLAGS_NONE, "G_DBUS_CALL_FLAGS_NONE", "none" }, + { G_DBUS_CALL_FLAGS_NO_AUTO_START, "G_DBUS_CALL_FLAGS_NO_AUTO_START", "no-auto-start" }, + { G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION, "G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION", "allow-interactive-authorization" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusCallFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_message_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DBUS_MESSAGE_TYPE_INVALID, "G_DBUS_MESSAGE_TYPE_INVALID", "invalid" }, + { G_DBUS_MESSAGE_TYPE_METHOD_CALL, "G_DBUS_MESSAGE_TYPE_METHOD_CALL", "method-call" }, + { G_DBUS_MESSAGE_TYPE_METHOD_RETURN, "G_DBUS_MESSAGE_TYPE_METHOD_RETURN", "method-return" }, + { G_DBUS_MESSAGE_TYPE_ERROR, "G_DBUS_MESSAGE_TYPE_ERROR", "error" }, + { G_DBUS_MESSAGE_TYPE_SIGNAL, "G_DBUS_MESSAGE_TYPE_SIGNAL", "signal" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDBusMessageType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_message_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_MESSAGE_FLAGS_NONE, "G_DBUS_MESSAGE_FLAGS_NONE", "none" }, + { G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED, "G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED", "no-reply-expected" }, + { G_DBUS_MESSAGE_FLAGS_NO_AUTO_START, "G_DBUS_MESSAGE_FLAGS_NO_AUTO_START", "no-auto-start" }, + { G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION, "G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION", "allow-interactive-authorization" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusMessageFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_message_header_field_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DBUS_MESSAGE_HEADER_FIELD_INVALID, "G_DBUS_MESSAGE_HEADER_FIELD_INVALID", "invalid" }, + { G_DBUS_MESSAGE_HEADER_FIELD_PATH, "G_DBUS_MESSAGE_HEADER_FIELD_PATH", "path" }, + { G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, "G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE", "interface" }, + { G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, "G_DBUS_MESSAGE_HEADER_FIELD_MEMBER", "member" }, + { G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, "G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME", "error-name" }, + { G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, "G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL", "reply-serial" }, + { G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, "G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION", "destination" }, + { G_DBUS_MESSAGE_HEADER_FIELD_SENDER, "G_DBUS_MESSAGE_HEADER_FIELD_SENDER", "sender" }, + { G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, "G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE", "signature" }, + { G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, "G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS", "num-unix-fds" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDBusMessageHeaderField"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_property_info_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_PROPERTY_INFO_FLAGS_NONE, "G_DBUS_PROPERTY_INFO_FLAGS_NONE", "none" }, + { G_DBUS_PROPERTY_INFO_FLAGS_READABLE, "G_DBUS_PROPERTY_INFO_FLAGS_READABLE", "readable" }, + { G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE, "G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE", "writable" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusPropertyInfoFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_subtree_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_SUBTREE_FLAGS_NONE, "G_DBUS_SUBTREE_FLAGS_NONE", "none" }, + { G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES, "G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES", "dispatch-to-unenumerated-nodes" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusSubtreeFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_server_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_SERVER_FLAGS_NONE, "G_DBUS_SERVER_FLAGS_NONE", "none" }, + { G_DBUS_SERVER_FLAGS_RUN_IN_THREAD, "G_DBUS_SERVER_FLAGS_RUN_IN_THREAD", "run-in-thread" }, + { G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS, "G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS", "authentication-allow-anonymous" }, + { G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER, "G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER", "authentication-require-same-user" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusServerFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_signal_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_SIGNAL_FLAGS_NONE, "G_DBUS_SIGNAL_FLAGS_NONE", "none" }, + { G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, "G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE", "no-match-rule" }, + { G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE", "match-arg0-namespace" }, + { G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH", "match-arg0-path" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusSignalFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_send_message_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_SEND_MESSAGE_FLAGS_NONE, "G_DBUS_SEND_MESSAGE_FLAGS_NONE", "none" }, + { G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, "G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL", "preserve-serial" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusSendMessageFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_credentials_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_CREDENTIALS_TYPE_INVALID, "G_CREDENTIALS_TYPE_INVALID", "invalid" }, + { G_CREDENTIALS_TYPE_LINUX_UCRED, "G_CREDENTIALS_TYPE_LINUX_UCRED", "linux-ucred" }, + { G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED, "G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED", "freebsd-cmsgcred" }, + { G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED, "G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED", "openbsd-sockpeercred" }, + { G_CREDENTIALS_TYPE_SOLARIS_UCRED, "G_CREDENTIALS_TYPE_SOLARIS_UCRED", "solaris-ucred" }, + { G_CREDENTIALS_TYPE_NETBSD_UNPCBID, "G_CREDENTIALS_TYPE_NETBSD_UNPCBID", "netbsd-unpcbid" }, + { G_CREDENTIALS_TYPE_APPLE_XUCRED, "G_CREDENTIALS_TYPE_APPLE_XUCRED", "apple-xucred" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GCredentialsType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_message_byte_order_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN, "G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN", "big-endian" }, + { G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN, "G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN", "little-endian" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GDBusMessageByteOrder"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_application_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_APPLICATION_FLAGS_NONE, "G_APPLICATION_FLAGS_NONE", "flags-none" }, + { G_APPLICATION_IS_SERVICE, "G_APPLICATION_IS_SERVICE", "is-service" }, + { G_APPLICATION_IS_LAUNCHER, "G_APPLICATION_IS_LAUNCHER", "is-launcher" }, + { G_APPLICATION_HANDLES_OPEN, "G_APPLICATION_HANDLES_OPEN", "handles-open" }, + { G_APPLICATION_HANDLES_COMMAND_LINE, "G_APPLICATION_HANDLES_COMMAND_LINE", "handles-command-line" }, + { G_APPLICATION_SEND_ENVIRONMENT, "G_APPLICATION_SEND_ENVIRONMENT", "send-environment" }, + { G_APPLICATION_NON_UNIQUE, "G_APPLICATION_NON_UNIQUE", "non-unique" }, + { G_APPLICATION_CAN_OVERRIDE_APP_ID, "G_APPLICATION_CAN_OVERRIDE_APP_ID", "can-override-app-id" }, + { G_APPLICATION_ALLOW_REPLACEMENT, "G_APPLICATION_ALLOW_REPLACEMENT", "allow-replacement" }, + { G_APPLICATION_REPLACE, "G_APPLICATION_REPLACE", "replace" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GApplicationFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_error_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_ERROR_UNAVAILABLE, "G_TLS_ERROR_UNAVAILABLE", "unavailable" }, + { G_TLS_ERROR_MISC, "G_TLS_ERROR_MISC", "misc" }, + { G_TLS_ERROR_BAD_CERTIFICATE, "G_TLS_ERROR_BAD_CERTIFICATE", "bad-certificate" }, + { G_TLS_ERROR_NOT_TLS, "G_TLS_ERROR_NOT_TLS", "not-tls" }, + { G_TLS_ERROR_HANDSHAKE, "G_TLS_ERROR_HANDSHAKE", "handshake" }, + { G_TLS_ERROR_CERTIFICATE_REQUIRED, "G_TLS_ERROR_CERTIFICATE_REQUIRED", "certificate-required" }, + { G_TLS_ERROR_EOF, "G_TLS_ERROR_EOF", "eof" }, + { G_TLS_ERROR_INAPPROPRIATE_FALLBACK, "G_TLS_ERROR_INAPPROPRIATE_FALLBACK", "inappropriate-fallback" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsError"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_certificate_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_TLS_CERTIFICATE_UNKNOWN_CA, "G_TLS_CERTIFICATE_UNKNOWN_CA", "unknown-ca" }, + { G_TLS_CERTIFICATE_BAD_IDENTITY, "G_TLS_CERTIFICATE_BAD_IDENTITY", "bad-identity" }, + { G_TLS_CERTIFICATE_NOT_ACTIVATED, "G_TLS_CERTIFICATE_NOT_ACTIVATED", "not-activated" }, + { G_TLS_CERTIFICATE_EXPIRED, "G_TLS_CERTIFICATE_EXPIRED", "expired" }, + { G_TLS_CERTIFICATE_REVOKED, "G_TLS_CERTIFICATE_REVOKED", "revoked" }, + { G_TLS_CERTIFICATE_INSECURE, "G_TLS_CERTIFICATE_INSECURE", "insecure" }, + { G_TLS_CERTIFICATE_GENERIC_ERROR, "G_TLS_CERTIFICATE_GENERIC_ERROR", "generic-error" }, + { G_TLS_CERTIFICATE_VALIDATE_ALL, "G_TLS_CERTIFICATE_VALIDATE_ALL", "validate-all" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GTlsCertificateFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_authentication_mode_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_AUTHENTICATION_NONE, "G_TLS_AUTHENTICATION_NONE", "none" }, + { G_TLS_AUTHENTICATION_REQUESTED, "G_TLS_AUTHENTICATION_REQUESTED", "requested" }, + { G_TLS_AUTHENTICATION_REQUIRED, "G_TLS_AUTHENTICATION_REQUIRED", "required" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsAuthenticationMode"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_channel_binding_type_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_CHANNEL_BINDING_TLS_UNIQUE, "G_TLS_CHANNEL_BINDING_TLS_UNIQUE", "unique" }, + { G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT, "G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT", "server-end-point" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsChannelBindingType"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_channel_binding_error_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED, "G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED", "not-implemented" }, + { G_TLS_CHANNEL_BINDING_ERROR_INVALID_STATE, "G_TLS_CHANNEL_BINDING_ERROR_INVALID_STATE", "invalid-state" }, + { G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE, "G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE", "not-available" }, + { G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED, "G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED", "not-supported" }, + { G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR, "G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR", "general-error" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsChannelBindingError"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_rehandshake_mode_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_REHANDSHAKE_NEVER, "G_TLS_REHANDSHAKE_NEVER", "never" }, + { G_TLS_REHANDSHAKE_SAFELY, "G_TLS_REHANDSHAKE_SAFELY", "safely" }, + { G_TLS_REHANDSHAKE_UNSAFELY, "G_TLS_REHANDSHAKE_UNSAFELY", "unsafely" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsRehandshakeMode"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_password_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_TLS_PASSWORD_NONE, "G_TLS_PASSWORD_NONE", "none" }, + { G_TLS_PASSWORD_RETRY, "G_TLS_PASSWORD_RETRY", "retry" }, + { G_TLS_PASSWORD_MANY_TRIES, "G_TLS_PASSWORD_MANY_TRIES", "many-tries" }, + { G_TLS_PASSWORD_FINAL_TRY, "G_TLS_PASSWORD_FINAL_TRY", "final-try" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GTlsPasswordFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_interaction_result_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_INTERACTION_UNHANDLED, "G_TLS_INTERACTION_UNHANDLED", "unhandled" }, + { G_TLS_INTERACTION_HANDLED, "G_TLS_INTERACTION_HANDLED", "handled" }, + { G_TLS_INTERACTION_FAILED, "G_TLS_INTERACTION_FAILED", "failed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsInteractionResult"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_interface_skeleton_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_INTERFACE_SKELETON_FLAGS_NONE, "G_DBUS_INTERFACE_SKELETON_FLAGS_NONE", "none" }, + { G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD, "G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD", "handle-method-invocations-in-thread" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusInterfaceSkeletonFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_dbus_object_manager_client_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE", "none" }, + { G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, "G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START", "do-not-auto-start" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GDBusObjectManagerClientFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_database_verify_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_TLS_DATABASE_VERIFY_NONE, "G_TLS_DATABASE_VERIFY_NONE", "none" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GTlsDatabaseVerifyFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_database_lookup_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_DATABASE_LOOKUP_NONE, "G_TLS_DATABASE_LOOKUP_NONE", "none" }, + { G_TLS_DATABASE_LOOKUP_KEYPAIR, "G_TLS_DATABASE_LOOKUP_KEYPAIR", "keypair" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsDatabaseLookupFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_tls_certificate_request_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_TLS_CERTIFICATE_REQUEST_NONE, "G_TLS_CERTIFICATE_REQUEST_NONE", "none" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GTlsCertificateRequestFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_io_module_scope_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_IO_MODULE_SCOPE_NONE, "G_IO_MODULE_SCOPE_NONE", "none" }, + { G_IO_MODULE_SCOPE_BLOCK_DUPLICATES, "G_IO_MODULE_SCOPE_BLOCK_DUPLICATES", "block-duplicates" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GIOModuleScopeFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_socket_client_event_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_SOCKET_CLIENT_RESOLVING, "G_SOCKET_CLIENT_RESOLVING", "resolving" }, + { G_SOCKET_CLIENT_RESOLVED, "G_SOCKET_CLIENT_RESOLVED", "resolved" }, + { G_SOCKET_CLIENT_CONNECTING, "G_SOCKET_CLIENT_CONNECTING", "connecting" }, + { G_SOCKET_CLIENT_CONNECTED, "G_SOCKET_CLIENT_CONNECTED", "connected" }, + { G_SOCKET_CLIENT_PROXY_NEGOTIATING, "G_SOCKET_CLIENT_PROXY_NEGOTIATING", "proxy-negotiating" }, + { G_SOCKET_CLIENT_PROXY_NEGOTIATED, "G_SOCKET_CLIENT_PROXY_NEGOTIATED", "proxy-negotiated" }, + { G_SOCKET_CLIENT_TLS_HANDSHAKING, "G_SOCKET_CLIENT_TLS_HANDSHAKING", "tls-handshaking" }, + { G_SOCKET_CLIENT_TLS_HANDSHAKED, "G_SOCKET_CLIENT_TLS_HANDSHAKED", "tls-handshaked" }, + { G_SOCKET_CLIENT_COMPLETE, "G_SOCKET_CLIENT_COMPLETE", "complete" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GSocketClientEvent"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_socket_listener_event_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_SOCKET_LISTENER_BINDING, "G_SOCKET_LISTENER_BINDING", "binding" }, + { G_SOCKET_LISTENER_BOUND, "G_SOCKET_LISTENER_BOUND", "bound" }, + { G_SOCKET_LISTENER_LISTENING, "G_SOCKET_LISTENER_LISTENING", "listening" }, + { G_SOCKET_LISTENER_LISTENED, "G_SOCKET_LISTENER_LISTENED", "listened" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GSocketListenerEvent"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_test_dbus_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_TEST_DBUS_NONE, "G_TEST_DBUS_NONE", "none" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GTestDBusFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_subprocess_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_SUBPROCESS_FLAGS_NONE, "G_SUBPROCESS_FLAGS_NONE", "none" }, + { G_SUBPROCESS_FLAGS_STDIN_PIPE, "G_SUBPROCESS_FLAGS_STDIN_PIPE", "stdin-pipe" }, + { G_SUBPROCESS_FLAGS_STDIN_INHERIT, "G_SUBPROCESS_FLAGS_STDIN_INHERIT", "stdin-inherit" }, + { G_SUBPROCESS_FLAGS_STDOUT_PIPE, "G_SUBPROCESS_FLAGS_STDOUT_PIPE", "stdout-pipe" }, + { G_SUBPROCESS_FLAGS_STDOUT_SILENCE, "G_SUBPROCESS_FLAGS_STDOUT_SILENCE", "stdout-silence" }, + { G_SUBPROCESS_FLAGS_STDERR_PIPE, "G_SUBPROCESS_FLAGS_STDERR_PIPE", "stderr-pipe" }, + { G_SUBPROCESS_FLAGS_STDERR_SILENCE, "G_SUBPROCESS_FLAGS_STDERR_SILENCE", "stderr-silence" }, + { G_SUBPROCESS_FLAGS_STDERR_MERGE, "G_SUBPROCESS_FLAGS_STDERR_MERGE", "stderr-merge" }, + { G_SUBPROCESS_FLAGS_INHERIT_FDS, "G_SUBPROCESS_FLAGS_INHERIT_FDS", "inherit-fds" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GSubprocessFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_notification_priority_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_NOTIFICATION_PRIORITY_NORMAL, "G_NOTIFICATION_PRIORITY_NORMAL", "normal" }, + { G_NOTIFICATION_PRIORITY_LOW, "G_NOTIFICATION_PRIORITY_LOW", "low" }, + { G_NOTIFICATION_PRIORITY_HIGH, "G_NOTIFICATION_PRIORITY_HIGH", "high" }, + { G_NOTIFICATION_PRIORITY_URGENT, "G_NOTIFICATION_PRIORITY_URGENT", "urgent" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GNotificationPriority"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_network_connectivity_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_NETWORK_CONNECTIVITY_LOCAL, "G_NETWORK_CONNECTIVITY_LOCAL", "local" }, + { G_NETWORK_CONNECTIVITY_LIMITED, "G_NETWORK_CONNECTIVITY_LIMITED", "limited" }, + { G_NETWORK_CONNECTIVITY_PORTAL, "G_NETWORK_CONNECTIVITY_PORTAL", "portal" }, + { G_NETWORK_CONNECTIVITY_FULL, "G_NETWORK_CONNECTIVITY_FULL", "full" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GNetworkConnectivity"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_pollable_return_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_POLLABLE_RETURN_FAILED, "G_POLLABLE_RETURN_FAILED", "failed" }, + { G_POLLABLE_RETURN_OK, "G_POLLABLE_RETURN_OK", "ok" }, + { G_POLLABLE_RETURN_WOULD_BLOCK, "G_POLLABLE_RETURN_WOULD_BLOCK", "would-block" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GPollableReturn"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +GType +g_memory_monitor_warning_level_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GEnumValue values[] = { + { G_MEMORY_MONITOR_WARNING_LEVEL_LOW, "G_MEMORY_MONITOR_WARNING_LEVEL_LOW", "low" }, + { G_MEMORY_MONITOR_WARNING_LEVEL_MEDIUM, "G_MEMORY_MONITOR_WARNING_LEVEL_MEDIUM", "medium" }, + { G_MEMORY_MONITOR_WARNING_LEVEL_CRITICAL, "G_MEMORY_MONITOR_WARNING_LEVEL_CRITICAL", "critical" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("GMemoryMonitorWarningLevel"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +/* enumerations from "../gio/gresolver.h" */ +GType +g_resolver_name_lookup_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, "G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT", "default" }, + { G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY, "G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY", "ipv4-only" }, + { G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY, "G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY", "ipv6-only" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GResolverNameLookupFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +/* enumerations from "../gio/gsettings.h" */ +GType +g_settings_bind_flags_get_type (void) +{ + static gsize static_g_define_type_id = 0; + + if (g_once_init_enter (&static_g_define_type_id)) + { + static const GFlagsValue values[] = { + { G_SETTINGS_BIND_DEFAULT, "G_SETTINGS_BIND_DEFAULT", "default" }, + { G_SETTINGS_BIND_GET, "G_SETTINGS_BIND_GET", "get" }, + { G_SETTINGS_BIND_SET, "G_SETTINGS_BIND_SET", "set" }, + { G_SETTINGS_BIND_NO_SENSITIVITY, "G_SETTINGS_BIND_NO_SENSITIVITY", "no-sensitivity" }, + { G_SETTINGS_BIND_GET_NO_CHANGES, "G_SETTINGS_BIND_GET_NO_CHANGES", "get-no-changes" }, + { G_SETTINGS_BIND_INVERT_BOOLEAN, "G_SETTINGS_BIND_INVERT_BOOLEAN", "invert-boolean" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("GSettingsBindFlags"), values); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} + +/* Generated data ends here */ + diff --git a/gio/gioenumtypes.c.template b/gio/gioenumtypes.c.template index e9adc4a3829bcc555f36c76674ef9b20e4fb685c..948a01201228a32d76d68a1f20d214241246cd86 100644 --- a/gio/gioenumtypes.c.template +++ b/gio/gioenumtypes.c.template @@ -13,9 +13,9 @@ GType @enum_name@_get_type (void) { - static volatile gsize g_define_type_id__volatile = 0; + static gsize static_g_define_type_id = 0; - if (g_once_init_enter (&g_define_type_id__volatile)) + if (g_once_init_enter (&static_g_define_type_id)) { static const G@Type@Value values[] = { /*** END value-header ***/ @@ -29,10 +29,10 @@ GType }; GType g_define_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + g_once_init_leave (&static_g_define_type_id, g_define_type_id); } - return g_define_type_id__volatile; + return static_g_define_type_id; } /*** END value-tail ***/ diff --git a/gio/gioenumtypes.h b/gio/gioenumtypes.h index cde9829e1f6e1b86c74623eff17c4ec122a8ca70..201be606bee3fa5057dd891c69362ffad52f73f6 100644 --- a/gio/gioenumtypes.h +++ b/gio/gioenumtypes.h @@ -1,177 +1,183 @@ - -/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ - -#ifndef __GIO_ENUM_TYPES_H__ -#define __GIO_ENUM_TYPES_H__ - -#include - -G_BEGIN_DECLS - -/* enumerations from "../gio/gioenums.h" */ -GLIB_AVAILABLE_IN_ALL GType g_app_info_create_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_APP_INFO_CREATE_FLAGS (g_app_info_create_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_converter_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_CONVERTER_FLAGS (g_converter_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_converter_result_get_type (void) G_GNUC_CONST; -#define G_TYPE_CONVERTER_RESULT (g_converter_result_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_data_stream_byte_order_get_type (void) G_GNUC_CONST; -#define G_TYPE_DATA_STREAM_BYTE_ORDER (g_data_stream_byte_order_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_data_stream_newline_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_DATA_STREAM_NEWLINE_TYPE (g_data_stream_newline_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_attribute_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_ATTRIBUTE_TYPE (g_file_attribute_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_attribute_info_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_ATTRIBUTE_INFO_FLAGS (g_file_attribute_info_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_attribute_status_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_ATTRIBUTE_STATUS (g_file_attribute_status_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_query_info_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_QUERY_INFO_FLAGS (g_file_query_info_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_create_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_CREATE_FLAGS (g_file_create_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_measure_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_MEASURE_FLAGS (g_file_measure_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_mount_mount_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_MOUNT_MOUNT_FLAGS (g_mount_mount_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_mount_unmount_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_MOUNT_UNMOUNT_FLAGS (g_mount_unmount_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_drive_start_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DRIVE_START_FLAGS (g_drive_start_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_drive_start_stop_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_DRIVE_START_STOP_TYPE (g_drive_start_stop_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_copy_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_COPY_FLAGS (g_file_copy_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_monitor_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_MONITOR_FLAGS (g_file_monitor_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_TYPE (g_file_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_filesystem_preview_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILESYSTEM_PREVIEW_TYPE (g_filesystem_preview_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_file_monitor_event_get_type (void) G_GNUC_CONST; -#define G_TYPE_FILE_MONITOR_EVENT (g_file_monitor_event_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_io_error_enum_get_type (void) G_GNUC_CONST; -#define G_TYPE_IO_ERROR_ENUM (g_io_error_enum_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_ask_password_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_ASK_PASSWORD_FLAGS (g_ask_password_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_password_save_get_type (void) G_GNUC_CONST; -#define G_TYPE_PASSWORD_SAVE (g_password_save_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_mount_operation_result_get_type (void) G_GNUC_CONST; -#define G_TYPE_MOUNT_OPERATION_RESULT (g_mount_operation_result_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_output_stream_splice_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_OUTPUT_STREAM_SPLICE_FLAGS (g_output_stream_splice_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_io_stream_splice_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_IO_STREAM_SPLICE_FLAGS (g_io_stream_splice_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_emblem_origin_get_type (void) G_GNUC_CONST; -#define G_TYPE_EMBLEM_ORIGIN (g_emblem_origin_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_resolver_error_get_type (void) G_GNUC_CONST; -#define G_TYPE_RESOLVER_ERROR (g_resolver_error_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_resolver_record_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_RESOLVER_RECORD_TYPE (g_resolver_record_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_resource_error_get_type (void) G_GNUC_CONST; -#define G_TYPE_RESOURCE_ERROR (g_resource_error_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_resource_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_RESOURCE_FLAGS (g_resource_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_resource_lookup_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_RESOURCE_LOOKUP_FLAGS (g_resource_lookup_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_socket_family_get_type (void) G_GNUC_CONST; -#define G_TYPE_SOCKET_FAMILY (g_socket_family_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_socket_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_SOCKET_TYPE (g_socket_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_socket_msg_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_SOCKET_MSG_FLAGS (g_socket_msg_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_socket_protocol_get_type (void) G_GNUC_CONST; -#define G_TYPE_SOCKET_PROTOCOL (g_socket_protocol_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_zlib_compressor_format_get_type (void) G_GNUC_CONST; -#define G_TYPE_ZLIB_COMPRESSOR_FORMAT (g_zlib_compressor_format_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_unix_socket_address_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_UNIX_SOCKET_ADDRESS_TYPE (g_unix_socket_address_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_bus_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_BUS_TYPE (g_bus_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_bus_name_owner_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_BUS_NAME_OWNER_FLAGS (g_bus_name_owner_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_bus_name_watcher_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_BUS_NAME_WATCHER_FLAGS (g_bus_name_watcher_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_proxy_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_PROXY_FLAGS (g_dbus_proxy_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_error_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_ERROR (g_dbus_error_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_connection_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_CONNECTION_FLAGS (g_dbus_connection_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_capability_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_CAPABILITY_FLAGS (g_dbus_capability_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_call_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_CALL_FLAGS (g_dbus_call_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_message_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_MESSAGE_TYPE (g_dbus_message_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_message_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_MESSAGE_FLAGS (g_dbus_message_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_message_header_field_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_MESSAGE_HEADER_FIELD (g_dbus_message_header_field_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_property_info_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_PROPERTY_INFO_FLAGS (g_dbus_property_info_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_subtree_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_SUBTREE_FLAGS (g_dbus_subtree_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_server_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_SERVER_FLAGS (g_dbus_server_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_signal_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_SIGNAL_FLAGS (g_dbus_signal_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_send_message_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_SEND_MESSAGE_FLAGS (g_dbus_send_message_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_credentials_type_get_type (void) G_GNUC_CONST; -#define G_TYPE_CREDENTIALS_TYPE (g_credentials_type_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_message_byte_order_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_MESSAGE_BYTE_ORDER (g_dbus_message_byte_order_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_application_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_APPLICATION_FLAGS (g_application_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_error_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_ERROR (g_tls_error_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_certificate_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_CERTIFICATE_FLAGS (g_tls_certificate_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_authentication_mode_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_AUTHENTICATION_MODE (g_tls_authentication_mode_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_rehandshake_mode_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_REHANDSHAKE_MODE (g_tls_rehandshake_mode_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_password_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_PASSWORD_FLAGS (g_tls_password_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_interaction_result_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_INTERACTION_RESULT (g_tls_interaction_result_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_interface_skeleton_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_INTERFACE_SKELETON_FLAGS (g_dbus_interface_skeleton_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_dbus_object_manager_client_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_DBUS_OBJECT_MANAGER_CLIENT_FLAGS (g_dbus_object_manager_client_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_database_verify_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_DATABASE_VERIFY_FLAGS (g_tls_database_verify_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_database_lookup_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_DATABASE_LOOKUP_FLAGS (g_tls_database_lookup_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_tls_certificate_request_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_TLS_CERTIFICATE_REQUEST_FLAGS (g_tls_certificate_request_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_io_module_scope_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_IO_MODULE_SCOPE_FLAGS (g_io_module_scope_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_socket_client_event_get_type (void) G_GNUC_CONST; -#define G_TYPE_SOCKET_CLIENT_EVENT (g_socket_client_event_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_socket_listener_event_get_type (void) G_GNUC_CONST; -#define G_TYPE_SOCKET_LISTENER_EVENT (g_socket_listener_event_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_test_dbus_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_TEST_DBUS_FLAGS (g_test_dbus_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_subprocess_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_SUBPROCESS_FLAGS (g_subprocess_flags_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_notification_priority_get_type (void) G_GNUC_CONST; -#define G_TYPE_NOTIFICATION_PRIORITY (g_notification_priority_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_network_connectivity_get_type (void) G_GNUC_CONST; -#define G_TYPE_NETWORK_CONNECTIVITY (g_network_connectivity_get_type ()) -GLIB_AVAILABLE_IN_ALL GType g_pollable_return_get_type (void) G_GNUC_CONST; -#define G_TYPE_POLLABLE_RETURN (g_pollable_return_get_type ()) - -/* enumerations from "../gio/gresolver.h" */ -GLIB_AVAILABLE_IN_ALL GType g_resolver_name_lookup_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_RESOLVER_NAME_LOOKUP_FLAGS (g_resolver_name_lookup_flags_get_type ()) - -/* enumerations from "../gio/gsettings.h" */ -GLIB_AVAILABLE_IN_ALL GType g_settings_bind_flags_get_type (void) G_GNUC_CONST; -#define G_TYPE_SETTINGS_BIND_FLAGS (g_settings_bind_flags_get_type ()) -G_END_DECLS - -#endif /* __GIO_ENUM_TYPES_H__ */ - -/* Generated data ends here */ - + +/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ + +#ifndef __GIO_ENUM_TYPES_H__ +#define __GIO_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "../gio/gioenums.h" */ +GLIB_AVAILABLE_IN_ALL GType g_app_info_create_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_APP_INFO_CREATE_FLAGS (g_app_info_create_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_converter_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_CONVERTER_FLAGS (g_converter_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_converter_result_get_type (void) G_GNUC_CONST; +#define G_TYPE_CONVERTER_RESULT (g_converter_result_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_data_stream_byte_order_get_type (void) G_GNUC_CONST; +#define G_TYPE_DATA_STREAM_BYTE_ORDER (g_data_stream_byte_order_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_data_stream_newline_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_DATA_STREAM_NEWLINE_TYPE (g_data_stream_newline_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_attribute_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_ATTRIBUTE_TYPE (g_file_attribute_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_attribute_info_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_ATTRIBUTE_INFO_FLAGS (g_file_attribute_info_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_attribute_status_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_ATTRIBUTE_STATUS (g_file_attribute_status_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_query_info_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_QUERY_INFO_FLAGS (g_file_query_info_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_create_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_CREATE_FLAGS (g_file_create_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_measure_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_MEASURE_FLAGS (g_file_measure_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_mount_mount_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_MOUNT_MOUNT_FLAGS (g_mount_mount_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_mount_unmount_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_MOUNT_UNMOUNT_FLAGS (g_mount_unmount_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_drive_start_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DRIVE_START_FLAGS (g_drive_start_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_drive_start_stop_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_DRIVE_START_STOP_TYPE (g_drive_start_stop_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_copy_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_COPY_FLAGS (g_file_copy_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_monitor_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_MONITOR_FLAGS (g_file_monitor_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_TYPE (g_file_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_filesystem_preview_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILESYSTEM_PREVIEW_TYPE (g_filesystem_preview_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_file_monitor_event_get_type (void) G_GNUC_CONST; +#define G_TYPE_FILE_MONITOR_EVENT (g_file_monitor_event_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_io_error_enum_get_type (void) G_GNUC_CONST; +#define G_TYPE_IO_ERROR_ENUM (g_io_error_enum_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_ask_password_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_ASK_PASSWORD_FLAGS (g_ask_password_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_password_save_get_type (void) G_GNUC_CONST; +#define G_TYPE_PASSWORD_SAVE (g_password_save_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_mount_operation_result_get_type (void) G_GNUC_CONST; +#define G_TYPE_MOUNT_OPERATION_RESULT (g_mount_operation_result_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_output_stream_splice_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_OUTPUT_STREAM_SPLICE_FLAGS (g_output_stream_splice_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_io_stream_splice_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_IO_STREAM_SPLICE_FLAGS (g_io_stream_splice_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_emblem_origin_get_type (void) G_GNUC_CONST; +#define G_TYPE_EMBLEM_ORIGIN (g_emblem_origin_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_resolver_error_get_type (void) G_GNUC_CONST; +#define G_TYPE_RESOLVER_ERROR (g_resolver_error_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_resolver_record_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_RESOLVER_RECORD_TYPE (g_resolver_record_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_resource_error_get_type (void) G_GNUC_CONST; +#define G_TYPE_RESOURCE_ERROR (g_resource_error_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_resource_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_RESOURCE_FLAGS (g_resource_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_resource_lookup_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_RESOURCE_LOOKUP_FLAGS (g_resource_lookup_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_socket_family_get_type (void) G_GNUC_CONST; +#define G_TYPE_SOCKET_FAMILY (g_socket_family_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_socket_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_SOCKET_TYPE (g_socket_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_socket_msg_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_SOCKET_MSG_FLAGS (g_socket_msg_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_socket_protocol_get_type (void) G_GNUC_CONST; +#define G_TYPE_SOCKET_PROTOCOL (g_socket_protocol_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_zlib_compressor_format_get_type (void) G_GNUC_CONST; +#define G_TYPE_ZLIB_COMPRESSOR_FORMAT (g_zlib_compressor_format_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_unix_socket_address_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_UNIX_SOCKET_ADDRESS_TYPE (g_unix_socket_address_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_bus_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_BUS_TYPE (g_bus_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_bus_name_owner_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_BUS_NAME_OWNER_FLAGS (g_bus_name_owner_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_bus_name_watcher_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_BUS_NAME_WATCHER_FLAGS (g_bus_name_watcher_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_proxy_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_PROXY_FLAGS (g_dbus_proxy_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_error_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_ERROR (g_dbus_error_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_connection_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_CONNECTION_FLAGS (g_dbus_connection_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_capability_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_CAPABILITY_FLAGS (g_dbus_capability_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_call_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_CALL_FLAGS (g_dbus_call_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_message_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_MESSAGE_TYPE (g_dbus_message_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_message_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_MESSAGE_FLAGS (g_dbus_message_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_message_header_field_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_MESSAGE_HEADER_FIELD (g_dbus_message_header_field_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_property_info_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_PROPERTY_INFO_FLAGS (g_dbus_property_info_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_subtree_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_SUBTREE_FLAGS (g_dbus_subtree_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_server_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_SERVER_FLAGS (g_dbus_server_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_signal_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_SIGNAL_FLAGS (g_dbus_signal_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_send_message_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_SEND_MESSAGE_FLAGS (g_dbus_send_message_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_credentials_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_CREDENTIALS_TYPE (g_credentials_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_message_byte_order_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_MESSAGE_BYTE_ORDER (g_dbus_message_byte_order_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_application_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_APPLICATION_FLAGS (g_application_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_error_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_ERROR (g_tls_error_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_certificate_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_CERTIFICATE_FLAGS (g_tls_certificate_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_authentication_mode_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_AUTHENTICATION_MODE (g_tls_authentication_mode_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_channel_binding_type_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_CHANNEL_BINDING_TYPE (g_tls_channel_binding_type_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_channel_binding_error_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_CHANNEL_BINDING_ERROR (g_tls_channel_binding_error_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_rehandshake_mode_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_REHANDSHAKE_MODE (g_tls_rehandshake_mode_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_password_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_PASSWORD_FLAGS (g_tls_password_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_interaction_result_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_INTERACTION_RESULT (g_tls_interaction_result_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_interface_skeleton_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_INTERFACE_SKELETON_FLAGS (g_dbus_interface_skeleton_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_dbus_object_manager_client_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_DBUS_OBJECT_MANAGER_CLIENT_FLAGS (g_dbus_object_manager_client_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_database_verify_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_DATABASE_VERIFY_FLAGS (g_tls_database_verify_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_database_lookup_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_DATABASE_LOOKUP_FLAGS (g_tls_database_lookup_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_tls_certificate_request_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_TLS_CERTIFICATE_REQUEST_FLAGS (g_tls_certificate_request_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_io_module_scope_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_IO_MODULE_SCOPE_FLAGS (g_io_module_scope_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_socket_client_event_get_type (void) G_GNUC_CONST; +#define G_TYPE_SOCKET_CLIENT_EVENT (g_socket_client_event_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_socket_listener_event_get_type (void) G_GNUC_CONST; +#define G_TYPE_SOCKET_LISTENER_EVENT (g_socket_listener_event_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_test_dbus_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_TEST_DBUS_FLAGS (g_test_dbus_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_subprocess_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_SUBPROCESS_FLAGS (g_subprocess_flags_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_notification_priority_get_type (void) G_GNUC_CONST; +#define G_TYPE_NOTIFICATION_PRIORITY (g_notification_priority_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_network_connectivity_get_type (void) G_GNUC_CONST; +#define G_TYPE_NETWORK_CONNECTIVITY (g_network_connectivity_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_pollable_return_get_type (void) G_GNUC_CONST; +#define G_TYPE_POLLABLE_RETURN (g_pollable_return_get_type ()) +GLIB_AVAILABLE_IN_ALL GType g_memory_monitor_warning_level_get_type (void) G_GNUC_CONST; +#define G_TYPE_MEMORY_MONITOR_WARNING_LEVEL (g_memory_monitor_warning_level_get_type ()) + +/* enumerations from "../gio/gresolver.h" */ +GLIB_AVAILABLE_IN_ALL GType g_resolver_name_lookup_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_RESOLVER_NAME_LOOKUP_FLAGS (g_resolver_name_lookup_flags_get_type ()) + +/* enumerations from "../gio/gsettings.h" */ +GLIB_AVAILABLE_IN_ALL GType g_settings_bind_flags_get_type (void) G_GNUC_CONST; +#define G_TYPE_SETTINGS_BIND_FLAGS (g_settings_bind_flags_get_type ()) +G_END_DECLS + +#endif /* __GIO_ENUM_TYPES_H__ */ + +/* Generated data ends here */ + diff --git a/gio/gioerror.c b/gio/gioerror.c index 1ec120d98b69052542635c42962becbc9328cc6f..38fc3d83f6f66121e5ca6dbe909f89ad04392660 100644 --- a/gio/gioerror.c +++ b/gio/gioerror.c @@ -107,6 +107,12 @@ g_io_error_from_errno (gint err_no) break; #endif +#ifdef ENXIO + case ENXIO: + return G_IO_ERROR_NOT_REGULAR_FILE; + break; +#endif + #ifdef EROFS case EROFS: return G_IO_ERROR_READ_ONLY; @@ -343,6 +349,7 @@ g_io_error_from_win32_error (gint error_code) return G_IO_ERROR_NOT_SUPPORTED; case WSAECONNRESET: + case WSAENETRESET: case WSAESHUTDOWN: return G_IO_ERROR_CONNECTION_CLOSED; diff --git a/gio/giomodule.c b/gio/giomodule.c index 1007abdbf3061dbf99025007b739f0ff741a4c77..a2909a8ef5c0cc9a100ed396eb485b9e54ba8c2e 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -22,12 +22,15 @@ /* For the #GDesktopAppInfoLookup macros; since macro deprecation is implemented * in the preprocessor, we need to define this before including glib.h*/ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include #include "giomodule.h" #include "giomodule-priv.h" +#include "glib-private.h" #include "glocalfilemonitor.h" #include "gnativevolumemonitor.h" #include "gproxyresolver.h" @@ -42,8 +45,12 @@ #include "gnotificationbackend.h" #include "ginitable.h" #include "gnetworkmonitor.h" +#include "gmemorymonitor.h" +#include "gmemorymonitorportal.h" +#include "gmemorymonitordbus.h" #ifdef G_OS_WIN32 #include "gregistrysettingsbackend.h" +#include "giowin32-priv.h" #endif #include @@ -441,7 +448,7 @@ is_valid_module_name (const gchar *basename, * * This may not actually load and initialize all the types in each * module, some modules may be lazily loaded and initialized when - * an extension point it implementes is used with e.g. + * an extension point it implements is used with e.g. * g_io_extension_point_get_extensions() or * g_io_extension_point_get_extension_by_name(). * @@ -459,7 +466,7 @@ g_io_modules_scan_all_in_directory_with_scope (const char *dirname, GDir *dir; GStatBuf statbuf; char *data; - time_t cache_mtime; + time_t cache_time; GHashTable *cache; if (!g_module_supported ()) @@ -471,24 +478,25 @@ g_io_modules_scan_all_in_directory_with_scope (const char *dirname, filename = g_build_filename (dirname, "giomodule.cache", NULL); - cache = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify)g_strfreev); - - cache_mtime = 0; + cache = NULL; + cache_time = 0; if (g_stat (filename, &statbuf) == 0 && g_file_get_contents (filename, &data, NULL, NULL)) { char **lines; int i; - /* Cache mtime is the time the cache file was created, any file - * that has a ctime before this was created then and not modified - * since then (userspace can't change ctime). Its possible to change - * the ctime forward without changing the file content, by e.g. - * chmoding the file, but this is uncommon and will only cause us - * to not use the cache so will not cause bugs. + /* cache_time is the time the cache file was created; we also take + * into account the change time because in ostree based systems, all + * system file have mtime equal to epoch 0. + * + * Any file that has a ctime before this was created then and not modified + * since then (userspace can't change ctime). Its possible to change the + * ctime forward without changing the file content, by e.g. chmoding the + * file, but this is uncommon and will only cause us to not use the cache + * so will not cause bugs. */ - cache_mtime = statbuf.st_mtime; + cache_time = MAX(statbuf.st_mtime, statbuf.st_ctime); lines = g_strsplit (data, "\n", -1); g_free (data); @@ -514,6 +522,10 @@ g_io_modules_scan_all_in_directory_with_scope (const char *dirname, while (g_ascii_isspace (*colon)) colon++; + if (G_UNLIKELY (!cache)) + cache = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify)g_strfreev); + extension_points = g_strsplit (colon, ",", -1); g_hash_table_insert (cache, file, extension_points); } @@ -527,16 +539,18 @@ g_io_modules_scan_all_in_directory_with_scope (const char *dirname, GIOExtensionPoint *extension_point; GIOModule *module; gchar *path; - char **extension_points; + char **extension_points = NULL; int i; path = g_build_filename (dirname, name, NULL); module = g_io_module_new (path); - extension_points = g_hash_table_lookup (cache, name); + if (cache) + extension_points = g_hash_table_lookup (cache, name); + if (extension_points != NULL && g_stat (path, &statbuf) == 0 && - statbuf.st_ctime <= cache_mtime) + statbuf.st_ctime <= cache_time) { /* Lazy load/init the library when first required */ for (i = 0; extension_points[i] != NULL; i++) @@ -568,7 +582,8 @@ g_io_modules_scan_all_in_directory_with_scope (const char *dirname, g_dir_close (dir); - g_hash_table_destroy (cache); + if (cache) + g_hash_table_destroy (cache); g_free (filename); } @@ -583,7 +598,7 @@ g_io_modules_scan_all_in_directory_with_scope (const char *dirname, * * This may not actually load and initialize all the types in each * module, some modules may be lazily loaded and initialized when - * an extension point it implementes is used with e.g. + * an extension point it implements is used with e.g. * g_io_extension_point_get_extensions() or * g_io_extension_point_get_extension_by_name(). * @@ -798,6 +813,9 @@ _g_io_module_get_default_type (const gchar *extension_point, return G_TYPE_INVALID; } + /* It’s OK to query the environment here, even when running as setuid, because + * it only allows a choice between existing already-loaded modules. No new + * code is loaded based on the environment variable value. */ use_this = envvar ? g_getenv (envvar) : NULL; if (g_strcmp0 (use_this, "help") == 0) { @@ -875,6 +893,13 @@ try_implementation (const char *extension_point, } } +static void +weak_ref_free (GWeakRef *weak_ref) +{ + g_weak_ref_clear (weak_ref); + g_free (weak_ref); +} + /** * _g_io_module_get_default: * @extension_point: the name of an extension point @@ -896,10 +921,11 @@ try_implementation (const char *extension_point, * be called on each candidate implementation after construction, to * check if it is actually usable or not. * - * The result is cached after it is generated the first time, and + * The result is cached after it is generated the first time (but the cache does + * not keep a strong reference to the object), and * the function is thread-safe. * - * Returns: (transfer none): an object implementing + * Returns: (transfer full) (nullable): an object implementing * @extension_point, or %NULL if there are no usable * implementations. */ @@ -914,25 +940,33 @@ _g_io_module_get_default (const gchar *extension_point, GList *l; GIOExtensionPoint *ep; GIOExtension *extension = NULL, *preferred; - gpointer impl; + gpointer impl, value; + GWeakRef *impl_weak_ref = NULL; g_rec_mutex_lock (&default_modules_lock); if (default_modules) { - gpointer key; - if (g_hash_table_lookup_extended (default_modules, extension_point, - &key, &impl)) - { + NULL, &value)) + { /* Don’t debug here, since we’re returning a cached object which was * already printed earlier. */ - g_rec_mutex_unlock (&default_modules_lock); - return impl; - } + impl_weak_ref = value; + impl = g_weak_ref_get (impl_weak_ref); + + /* If the object has been finalised (impl == NULL), fall through and + * instantiate a new one. */ + if (impl != NULL) + { + g_rec_mutex_unlock (&default_modules_lock); + return g_steal_pointer (&impl); + } + } } else { - default_modules = g_hash_table_new (g_str_hash, g_str_equal); + default_modules = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) weak_ref_free); } _g_io_modules_ensure_loaded (); @@ -947,6 +981,9 @@ _g_io_module_get_default (const gchar *extension_point, return NULL; } + /* It’s OK to query the environment here, even when running as setuid, because + * it only allows a choice between existing already-loaded modules. No new + * code is loaded based on the environment variable value. */ use_this = envvar ? g_getenv (envvar) : NULL; if (g_strcmp0 (use_this, "help") == 0) { @@ -984,9 +1021,18 @@ _g_io_module_get_default (const gchar *extension_point, impl = NULL; done: - g_hash_table_insert (default_modules, - g_strdup (extension_point), - impl ? g_object_ref (impl) : NULL); + if (impl_weak_ref == NULL) + { + impl_weak_ref = g_new0 (GWeakRef, 1); + g_weak_ref_init (impl_weak_ref, impl); + g_hash_table_insert (default_modules, g_strdup (extension_point), + g_steal_pointer (&impl_weak_ref)); + } + else + { + g_weak_ref_set (impl_weak_ref, impl); + } + g_rec_mutex_unlock (&default_modules_lock); if (impl != NULL) @@ -1000,7 +1046,7 @@ _g_io_module_get_default (const gchar *extension_point, g_debug ("%s: Failed to find default implementation for ‘%s’", G_STRFUNC, extension_point); - return impl; + return g_steal_pointer (&impl); } G_LOCK_DEFINE_STATIC (registered_extensions); @@ -1025,6 +1071,9 @@ extern GType _g_network_monitor_netlink_get_type (void); extern GType _g_network_monitor_nm_get_type (void); #endif +extern GType g_memory_monitor_dbus_get_type (void); +extern GType g_memory_monitor_portal_get_type (void); + #ifdef G_OS_UNIX extern GType g_fdo_notification_backend_get_type (void); extern GType g_gtk_notification_backend_get_type (void); @@ -1057,7 +1106,10 @@ DllMain (HINSTANCE hinstDLL, LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_ATTACH) + { gio_dll = hinstDLL; + gio_win32_appinfo_init (FALSE); + } return TRUE; } @@ -1068,7 +1120,8 @@ void * _g_io_win32_get_module (void) { if (!gio_dll) - GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (const char *) _g_io_win32_get_module, &gio_dll); return gio_dll; @@ -1127,6 +1180,9 @@ _g_io_modules_ensure_extension_points_registered (void) ep = g_io_extension_point_register (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME); g_io_extension_point_set_required_type (ep, G_TYPE_NOTIFICATION_BACKEND); + + ep = g_io_extension_point_register (G_MEMORY_MONITOR_EXTENSION_POINT_NAME); + g_io_extension_point_set_required_type (ep, G_TYPE_MEMORY_MONITOR); } G_UNLOCK (registered_extensions); @@ -1136,26 +1192,25 @@ static gchar * get_gio_module_dir (void) { gchar *module_dir; - - module_dir = g_strdup (g_getenv ("GIO_MODULE_DIR")); + gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) (); + + /* If running as setuid, loading modules from an arbitrary directory + * controlled by the unprivileged user who is running the program could allow + * for execution of arbitrary code (in constructors in modules). + * Don’t allow it. + * + * If a setuid program somehow needs to load additional GIO modules, it should + * explicitly call g_io_modules_scan_all_in_directory(). */ + module_dir = !is_setuid ? g_strdup (g_getenv ("GIO_MODULE_DIR")) : NULL; if (module_dir == NULL) { #ifdef G_OS_WIN32 gchar *install_dir; install_dir = g_win32_get_package_installation_directory_of_module (gio_dll); -#ifdef _MSC_VER - /* On Visual Studio builds we have all the libraries and binaries in bin - * so better load the gio modules from bin instead of lib - */ - module_dir = g_build_filename (install_dir, - "bin", "gio", "modules", - NULL); -#else module_dir = g_build_filename (install_dir, "lib", "gio", "modules", NULL); -#endif g_free (install_dir); #else module_dir = g_strdup (GIO_MODULE_DIR); @@ -1178,13 +1233,14 @@ _g_io_modules_ensure_loaded (void) if (!loaded_dirs) { + gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) (); gchar *module_dir; loaded_dirs = TRUE; scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES); - /* First load any overrides, extras */ - module_path = g_getenv ("GIO_EXTRA_MODULES"); + /* First load any overrides, extras (but not if running as setuid!) */ + module_path = !is_setuid ? g_getenv ("GIO_EXTRA_MODULES") : NULL; if (module_path) { gchar **paths; @@ -1235,6 +1291,8 @@ _g_io_modules_ensure_loaded (void) g_type_ensure (g_fdo_notification_backend_get_type ()); g_type_ensure (g_gtk_notification_backend_get_type ()); g_type_ensure (g_portal_notification_backend_get_type ()); + g_type_ensure (g_memory_monitor_dbus_get_type ()); + g_type_ensure (g_memory_monitor_portal_get_type ()); g_type_ensure (g_network_monitor_portal_get_type ()); g_type_ensure (g_proxy_resolver_portal_get_type ()); #endif diff --git a/gio/gioprivate.h b/gio/gioprivate.h index 2bc54e49be186f4a9e45220262ccda92bffe266b..608d912c0c6a1981d05e97b661d77592c623aa06 100644 --- a/gio/gioprivate.h +++ b/gio/gioprivate.h @@ -43,6 +43,10 @@ void g_socket_connection_set_cached_remote_address (GSocketConnection *connectio #define G_IOV_MAX IOV_MAX #elif defined(UIO_MAXIOV) #define G_IOV_MAX UIO_MAXIOV +#elif defined(__APPLE__) +/* For macOS/iOS, UIO_MAXIOV is documented in writev(2), but + * only declares it if defined(KERNEL) */ +#define G_IOV_MAX 512 #else /* 16 is the minimum value required by POSIX */ #define G_IOV_MAX 16 diff --git a/gio/giostream.c b/gio/giostream.c index 924e39a34ecd82d80efb42bfbcb7b3aec81a399e..f708e77af9d155cfe1a29edb6e3dae9d1512d57f 100644 --- a/gio/giostream.c +++ b/gio/giostream.c @@ -830,7 +830,7 @@ splice_cancelled_cb (GCancellable *cancellable, * @callback: (scope async): a #GAsyncReadyCallback. * @user_data: (closure): user data passed to @callback. * - * Asyncronously splice the output stream of @stream1 to the input stream of + * Asynchronously splice the output stream of @stream1 to the input stream of * @stream2, and splice the output stream of @stream2 to the input stream of * @stream1. * diff --git a/gio/giotypes.h b/gio/giotypes.h index c9ad8dd90ea8d8a931b3b9e3f8fc6d4f7a32179c..995c9cb152aeefb76a07eb520ab869d1c4badf89 100644 --- a/gio/giotypes.h +++ b/gio/giotypes.h @@ -194,7 +194,7 @@ typedef struct _GSocketListener GSocketListener; /** * GSocketService: * - * A helper class for handling accepting incomming connections in the + * A helper class for handling accepting incoming connections in the * glib mainloop. * * Since: 2.22 diff --git a/gio/giounix-private.c b/gio/giounix-private.c new file mode 100644 index 0000000000000000000000000000000000000000..c535a0896dc728cc6603ec0d331aba03b9039fe6 --- /dev/null +++ b/gio/giounix-private.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2021 Ole André Vadla Ravnås + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "config.h" + +#include +#include +#include +#include +#if defined (HAVE_EPOLL_CREATE) +#include +#elif defined (HAVE_KQUEUE) +#include +#include +#endif + +#include "giounix-private.h" + +#define G_TEMP_FAILURE_RETRY(expression) \ + ({ \ + gssize __result; \ + \ + do \ + __result = (gssize) (expression); \ + while (__result == -1 && errno == EINTR); \ + \ + __result; \ + }) + +static gboolean g_fd_is_regular_file (int fd) G_GNUC_UNUSED; + +gboolean +_g_fd_is_pollable (int fd) +{ + /* + * Determining whether a file-descriptor (FD) is pollable turns out to be + * quite hard. + * + * We used to detect this by attempting to lseek() and check if it failed with + * ESPIPE, and if so we'd consider the FD pollable. But this turned out to not + * work on e.g. PTYs and other devices that are pollable. + * + * Another approach that was considered was to call fstat() and if it failed + * we'd assume that the FD is pollable, and if it succeeded we'd consider it + * pollable as long as it's not a regular file. This seemed to work alright + * except for FDs backed by simple devices, such as /dev/null. + * + * There are however OS-specific methods that allow us to figure this out with + * absolute certainty: + */ + +#if defined (HAVE_EPOLL_CREATE) + /* + * Linux + * + * The answer we seek is provided by the kernel's file_can_poll(): + * https://github.com/torvalds/linux/blob/2ab38c17aac10bf55ab3efde4c4db3893d8691d2/include/linux/poll.h#L81-L84 + * But we cannot probe that by using poll() as the returned events for + * non-pollable FDs are always IN | OUT. + * + * The best option then seems to be using epoll, as it will refuse to add FDs + * where file_can_poll() returns FALSE. + */ + + int efd; + struct epoll_event ev = { 0, }; + gboolean add_succeeded; + + efd = epoll_create (1); + if (efd == -1) + g_error ("epoll_create () failed: %s", g_strerror (errno)); + + ev.events = EPOLLIN; + + add_succeeded = epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == 0; + + close (efd); + + return add_succeeded; +#elif defined (HAVE_KQUEUE) + /* + * Apple OSes and BSDs + * + * Like on Linux, we cannot use poll() to do the probing, but kqueue does + * the trick as it will refuse to add non-pollable FDs. (Except for regular + * files, which we need to special-case. Even though kqueue does support them, + * poll() does not.) + */ + + int kfd; + struct kevent ev; + gboolean add_succeeded; + + if (g_fd_is_regular_file (fd)) + return FALSE; + + kfd = kqueue (); + if (kfd == -1) + g_error ("kqueue () failed: %s", g_strerror (errno)); + + EV_SET (&ev, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); + + add_succeeded = + G_TEMP_FAILURE_RETRY (kevent (kfd, &ev, 1, NULL, 0, NULL)) == 0; + + close (kfd); + + return add_succeeded; +#else + /* + * Other UNIXes (AIX, QNX, Solaris, etc.) + * + * We can rule out regular files, but devices such as /dev/null will be + * reported as pollable even though they're not. This is hopefully good + * enough for most use-cases, but easy to expand on later if needed. + */ + + return !g_fd_is_regular_file (fd); +#endif +} + +static gboolean +g_fd_is_regular_file (int fd) +{ + struct stat st; + + if (G_TEMP_FAILURE_RETRY (fstat (fd, &st)) == -1) + return FALSE; + + return S_ISREG (st.st_mode); +} diff --git a/gio/giounix-private.h b/gio/giounix-private.h new file mode 100644 index 0000000000000000000000000000000000000000..aa56b07f87f3076252125283d6e5036705ab6d49 --- /dev/null +++ b/gio/giounix-private.h @@ -0,0 +1,26 @@ +/* + * Copyright © 2021 Ole André Vadla Ravnås + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#pragma once + +#include "gio.h" + +G_BEGIN_DECLS + +gboolean _g_fd_is_pollable (int fd); + +G_END_DECLS diff --git a/gio/giowin32-priv.h b/gio/giowin32-priv.h index 8843845d535ffbb22180ff99cf71dddbebf11593..6f20a95456fff125b827dd6e87005f0a966c8293 100644 --- a/gio/giowin32-priv.h +++ b/gio/giowin32-priv.h @@ -35,6 +35,8 @@ GOutputStream * g_win32_output_stream_new_from_fd (gint fd, gboolean close_fd); +void +gio_win32_appinfo_init (gboolean do_wait); G_END_DECLS #endif /* __G_IO_MODULE_PRIV_H__ */ diff --git a/gio/giowin32-private.c b/gio/giowin32-private.c new file mode 100644 index 0000000000000000000000000000000000000000..6e1926daa948561e0a8495fd25a606d0a2cf2a36 --- /dev/null +++ b/gio/giowin32-private.c @@ -0,0 +1,450 @@ +/* giowin32-private.c - private glib-gio functions for W32 GAppInfo + * + * Copyright 2019 Руслан Ижбулатов + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + + +static gsize +g_utf16_len (const gunichar2 *str) +{ + gsize result; + + for (result = 0; str[0] != 0; str++, result++) + ; + + return result; +} + +static gunichar2 * +g_wcsdup (const gunichar2 *str, gssize str_len) +{ + gsize str_len_unsigned; + gsize str_size; + + g_return_val_if_fail (str != NULL, NULL); + + if (str_len < 0) + str_len_unsigned = g_utf16_len (str); + else + str_len_unsigned = (gsize) str_len; + + g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); + str_size = (str_len_unsigned + 1) * sizeof (gunichar2); + + return g_memdup2 (str, str_size); +} + +static const gunichar2 * +g_utf16_wchr (const gunichar2 *str, const wchar_t wchr) +{ + for (; str != NULL && str[0] != 0; str++) + if ((wchar_t) str[0] == wchr) + return str; + + return NULL; +} + +static gboolean +g_utf16_to_utf8_and_fold (const gunichar2 *str, + gssize length, + gchar **str_u8, + gchar **str_u8_folded) +{ + gchar *u8; + gchar *folded; + u8 = g_utf16_to_utf8 (str, length, NULL, NULL, NULL); + + if (u8 == NULL) + return FALSE; + + folded = g_utf8_casefold (u8, -1); + + if (str_u8) + *str_u8 = g_steal_pointer (&u8); + + g_free (u8); + + if (str_u8_folded) + *str_u8_folded = g_steal_pointer (&folded); + + g_free (folded); + + return TRUE; +} + +/* Finds the last directory separator in @filename, + * returns a pointer to the position after that separator. + * If the string ends with a separator, returned value + * will be pointing at the NUL terminator. + * If the string does not contain separators, returns the + * string itself. + */ +static const gunichar2 * +g_utf16_find_basename (const gunichar2 *filename, + gssize len) +{ + const gunichar2 *result; + + if (len < 0) + len = g_utf16_len (filename); + if (len == 0) + return filename; + + result = &filename[len - 1]; + + while (result > filename) + { + if ((wchar_t) result[0] == L'/' || + (wchar_t) result[0] == L'\\') + { + result += 1; + break; + } + + result -= 1; + } + + return result; +} + +/* Finds the last directory separator in @filename, + * returns a pointer to the position after that separator. + * If the string ends with a separator, returned value + * will be pointing at the NUL terminator. + * If the string does not contain separators, returns the + * string itself. + */ +static const gchar * +g_utf8_find_basename (const gchar *filename, + gssize len) +{ + const gchar *result; + + if (len < 0) + len = strlen (filename); + if (len == 0) + return filename; + + result = &filename[len - 1]; + + while (result > filename) + { + if (result[0] == '/' || + result[0] == '\\') + { + result += 1; + break; + } + + result -= 1; + } + + return result; +} + +/** + * Parses @commandline, figuring out what the filename being invoked + * is. All returned strings are pointers into @commandline. + * @commandline must be a valid UTF-16 string and not be NULL. + * @after_executable is the first character after executable + * (usually a space, but not always). + * If @comma_separator is TRUE, accepts ',' as a separator between + * the filename and the following argument. + */ +static void +_g_win32_parse_filename (const gunichar2 *commandline, + gboolean comma_separator, + const gunichar2 **executable_start, + gssize *executable_len, + const gunichar2 **executable_basename, + const gunichar2 **after_executable) +{ + const gunichar2 *p; + const gunichar2 *first_argument; + gboolean quoted; + gssize len; + gssize execlen; + gboolean found; + + while ((wchar_t) commandline[0] == L' ') + commandline++; + + quoted = FALSE; + execlen = 0; + found = FALSE; + first_argument = NULL; + + if ((wchar_t) commandline[0] == L'"') + { + quoted = TRUE; + commandline += 1; + } + + len = g_utf16_len (commandline); + p = commandline; + + while (p < &commandline[len]) + { + switch ((wchar_t) p[0]) + { + case L'"': + if (quoted) + { + first_argument = p + 1; + /* Note: this is a valid commandline for opening "c:/file.txt": + * > "notepad"c:/file.txt + */ + p = &commandline[len]; + found = TRUE; + } + else + execlen += 1; + break; + case L' ': + if (!quoted) + { + first_argument = p; + p = &commandline[len]; + found = TRUE; + } + else + execlen += 1; + break; + case L',': + if (!quoted && comma_separator) + { + first_argument = p; + p = &commandline[len]; + found = TRUE; + } + else + execlen += 1; + break; + default: + execlen += 1; + break; + } + p += 1; + } + + if (!found) + first_argument = &commandline[len]; + + if (executable_start) + *executable_start = commandline; + + if (executable_len) + *executable_len = execlen; + + if (executable_basename) + *executable_basename = g_utf16_find_basename (commandline, execlen); + + if (after_executable) + *after_executable = first_argument; +} + +/* Make sure @commandline is a valid UTF-16 string before + * calling this function! + * follow_class_chain_to_handler() does perform such validation. + */ +static void +_g_win32_extract_executable (const gunichar2 *commandline, + gchar **ex_out, + gchar **ex_basename_out, + gchar **ex_folded_out, + gchar **ex_folded_basename_out, + gchar **dll_function_out) +{ + gchar *ex; + gchar *ex_folded; + const gunichar2 *first_argument; + const gunichar2 *executable; + const gunichar2 *executable_basename; + gboolean quoted; + gboolean folded; + gssize execlen; + + _g_win32_parse_filename (commandline, FALSE, &executable, &execlen, &executable_basename, &first_argument); + + commandline = executable; + + while ((wchar_t) first_argument[0] == L' ') + first_argument++; + + folded = g_utf16_to_utf8_and_fold (executable, (gssize) execlen, &ex, &ex_folded); + /* This should never fail as @executable has to be valid UTF-16. */ + g_assert (folded); + + if (dll_function_out) + *dll_function_out = NULL; + + /* See if the executable basename is "rundll32.exe". If so, then + * parse the rest of the commandline as r'"?path-to-dll"?[ ]*,*[ ]*dll_function_to_invoke' + */ + /* Using just "rundll32.exe", without an absolute path, seems + * very exploitable, but MS does that sometimes, so we have + * to accept that. + */ + if ((g_strcmp0 (ex_folded, "rundll32.exe") == 0 || + g_str_has_suffix (ex_folded, "\\rundll32.exe") || + g_str_has_suffix (ex_folded, "/rundll32.exe")) && + first_argument[0] != 0 && + dll_function_out != NULL) + { + /* Corner cases: + * > rundll32.exe c:\some,file,with,commas.dll,some_function + * is treated by rundll32 as: + * dll=c:\some + * function=file,with,commas.dll,some_function + * unless the dll name is surrounded by double quotation marks: + * > rundll32.exe "c:\some,file,with,commas.dll",some_function + * in which case everything works normally. + * Also, quoting only works if it surrounds the file name, i.e: + * > rundll32.exe "c:\some,file"",with,commas.dll",some_function + * will not work. + * Also, comma is optional when filename is quoted or when function + * name is separated from the filename by space(s): + * > rundll32.exe "c:\some,file,with,commas.dll"some_function + * will work, + * > rundll32.exe c:\some_dll_without_commas_or_spaces.dll some_function + * will work too. + * Also, any number of commas is accepted: + * > rundll32.exe c:\some_dll_without_commas_or_spaces.dll , , ,,, , some_function + * works just fine. + * And the ultimate example is: + * > "rundll32.exe""c:\some,file,with,commas.dll"some_function + * and it also works. + * Good job, Microsoft! + */ + const gunichar2 *filename_end = NULL; + gssize filename_len = 0; + gssize function_len = 0; + const gunichar2 *dllpart; + + quoted = FALSE; + + if ((wchar_t) first_argument[0] == L'"') + quoted = TRUE; + + _g_win32_parse_filename (first_argument, TRUE, &dllpart, &filename_len, NULL, &filename_end); + + if (filename_end[0] != 0 && filename_len > 0) + { + const gunichar2 *function_begin = filename_end; + + while ((wchar_t) function_begin[0] == L',' || (wchar_t) function_begin[0] == L' ') + function_begin += 1; + + if (function_begin[0] != 0) + { + gchar *dllpart_utf8; + gchar *dllpart_utf8_folded; + gchar *function_utf8; + gboolean folded; + const gunichar2 *space = g_utf16_wchr (function_begin, L' '); + + if (space) + function_len = space - function_begin; + else + function_len = g_utf16_len (function_begin); + + if (quoted) + first_argument += 1; + + folded = g_utf16_to_utf8_and_fold (first_argument, filename_len, &dllpart_utf8, &dllpart_utf8_folded); + g_assert (folded); + + function_utf8 = g_utf16_to_utf8 (function_begin, function_len, NULL, NULL, NULL); + + /* We only take this branch when dll_function_out is not NULL */ + *dll_function_out = g_steal_pointer (&function_utf8); + + g_free (function_utf8); + + /* + * Free our previous output candidate (rundll32) and replace it with the DLL path, + * then proceed forward as if nothing has changed. + */ + g_free (ex); + g_free (ex_folded); + + ex = dllpart_utf8; + ex_folded = dllpart_utf8_folded; + } + } + } + + if (ex_out) + { + if (ex_basename_out) + *ex_basename_out = (gchar *) g_utf8_find_basename (ex, -1); + + *ex_out = g_steal_pointer (&ex); + } + + g_free (ex); + + if (ex_folded_out) + { + if (ex_folded_basename_out) + *ex_folded_basename_out = (gchar *) g_utf8_find_basename (ex_folded, -1); + + *ex_folded_out = g_steal_pointer (&ex_folded); + } + + g_free (ex_folded); +} + +/** + * rundll32 accepts many different commandlines. Among them is this: + * > rundll32.exe "c:/program files/foo/bar.dll",,, , ,,,, , function_name %1 + * rundll32 just reads the first argument as a potentially quoted + * filename until the quotation ends (if quoted) or until a comma, + * or until a space. Then ignores all subsequent spaces (if any) and commas (if any; + * at least one comma is mandatory only if the filename is not quoted), + * and then interprets the rest of the commandline (until a space or a NUL-byte) + * as a name of a function. + * When GLib tries to run a program, it attempts to correctly re-quote the arguments, + * turning the first argument into "c:/program files/foo/bar.dll,,,". + * This breaks rundll32 parsing logic. + * Try to work around this by ensuring that the syntax is like this: + * > rundll32.exe "c:/program files/foo/bar.dll" function_name + * This syntax is valid for rundll32 *and* GLib spawn routines won't break it. + * + * @commandline must have at least 2 arguments, and the second argument + * must contain a (possibly quoted) filename, followed by a space or + * a comma. This can be checked for with an extract_executable() call - + * it should return a non-null dll_function. + */ +static void +_g_win32_fixup_broken_microsoft_rundll_commandline (gunichar2 *commandline) +{ + const gunichar2 *first_argument; + gunichar2 *after_first_argument; + + _g_win32_parse_filename (commandline, FALSE, NULL, NULL, NULL, &first_argument); + + while ((wchar_t) first_argument[0] == L' ') + first_argument++; + + _g_win32_parse_filename (first_argument, TRUE, NULL, NULL, NULL, (const gunichar2 **) &after_first_argument); + + if ((wchar_t) after_first_argument[0] == L',') + after_first_argument[0] = 0x0020; + /* Else everything is ok (first char after filename is ' ' or the first char + * of the function name - either way this will work). + */ +} diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c index 943c70aa5cb3eece99b7a45c5bd4710f84e76919..094be3f913ce7cdd370613b0d596124188797e42 100644 --- a/gio/gkeyfilesettingsbackend.c +++ b/gio/gkeyfilesettingsbackend.c @@ -105,20 +105,24 @@ compute_checksum (guint8 *digest, g_assert (len == 32); } -static void -g_keyfile_settings_backend_keyfile_write (GKeyfileSettingsBackend *kfsb) +static gboolean +g_keyfile_settings_backend_keyfile_write (GKeyfileSettingsBackend *kfsb, + GError **error) { gchar *contents; gsize length; + gboolean success; contents = g_key_file_to_data (kfsb->keyfile, &length, NULL); - g_file_replace_contents (kfsb->file, contents, length, NULL, FALSE, - G_FILE_CREATE_REPLACE_DESTINATION | - G_FILE_CREATE_PRIVATE, - NULL, NULL, NULL); + success = g_file_replace_contents (kfsb->file, contents, length, NULL, FALSE, + G_FILE_CREATE_REPLACE_DESTINATION | + G_FILE_CREATE_PRIVATE, + NULL, NULL, error); compute_checksum (kfsb->digest, contents, length); g_free (contents); + + return success; } static gboolean @@ -157,6 +161,13 @@ convert_path (GKeyfileSettingsBackend *kfsb, last_slash = strrchr (key, '/'); + /* Disallow empty group names or key names */ + if (key_len == 0 || + (last_slash != NULL && + (*(last_slash + 1) == '\0' || + last_slash == key))) + return FALSE; + if (kfsb->root_group) { /* if a root_group was specified, make sure the user hasn't given @@ -184,7 +195,12 @@ convert_path (GKeyfileSettingsBackend *kfsb, } if (basename) - *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); + { + if (last_slash != NULL) + *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); + else + *basename = g_strdup (key); + } return TRUE; } @@ -356,7 +372,9 @@ g_keyfile_settings_backend_write_tree (GSettingsBackend *backend, GTree *tree, gpointer origin_tag) { - WriteManyData data = { G_KEYFILE_SETTINGS_BACKEND (backend) }; + WriteManyData data = { G_KEYFILE_SETTINGS_BACKEND (backend), 0 }; + gboolean success; + GError *error = NULL; if (!data.kfsb->writable) return FALSE; @@ -367,11 +385,16 @@ g_keyfile_settings_backend_write_tree (GSettingsBackend *backend, return FALSE; g_tree_foreach (tree, g_keyfile_settings_backend_write_one, &data); - g_keyfile_settings_backend_keyfile_write (data.kfsb); + success = g_keyfile_settings_backend_keyfile_write (data.kfsb, &error); + if (error) + { + g_warning ("Failed to write keyfile to %s: %s", g_file_peek_path (data.kfsb->file), error->message); + g_error_free (error); + } g_settings_backend_changed_tree (backend, tree, origin_tag); - return TRUE; + return success; } static gboolean @@ -382,6 +405,7 @@ g_keyfile_settings_backend_write (GSettingsBackend *backend, { GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend); gboolean success; + GError *error = NULL; if (!kfsb->writable) return FALSE; @@ -391,7 +415,12 @@ g_keyfile_settings_backend_write (GSettingsBackend *backend, if (success) { g_settings_backend_changed (backend, key, origin_tag); - g_keyfile_settings_backend_keyfile_write (kfsb); + success = g_keyfile_settings_backend_keyfile_write (kfsb, &error); + if (error) + { + g_warning ("Failed to write keyfile to %s: %s", g_file_peek_path (kfsb->file), error->message); + g_error_free (error); + } } return success; @@ -403,9 +432,17 @@ g_keyfile_settings_backend_reset (GSettingsBackend *backend, gpointer origin_tag) { GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend); + GError *error = NULL; if (set_to_keyfile (kfsb, key, NULL)) - g_keyfile_settings_backend_keyfile_write (kfsb); + { + g_keyfile_settings_backend_keyfile_write (kfsb, &error); + if (error) + { + g_warning ("Failed to write keyfile to %s: %s", g_file_peek_path (kfsb->file), error->message); + g_error_free (error); + } + } g_settings_backend_changed (backend, key, origin_tag); } @@ -568,19 +605,24 @@ g_keyfile_settings_backend_finalize (GObject *object) g_hash_table_unref (kfsb->system_locks); g_free (kfsb->defaults_dir); - g_file_monitor_cancel (kfsb->file_monitor); - g_object_unref (kfsb->file_monitor); + if (kfsb->file_monitor) + { + g_file_monitor_cancel (kfsb->file_monitor); + g_object_unref (kfsb->file_monitor); + } g_object_unref (kfsb->file); - g_file_monitor_cancel (kfsb->dir_monitor); - g_object_unref (kfsb->dir_monitor); + if (kfsb->dir_monitor) + { + g_file_monitor_cancel (kfsb->dir_monitor); + g_object_unref (kfsb->dir_monitor); + } g_object_unref (kfsb->dir); g_free (kfsb->root_group); g_free (kfsb->prefix); - G_OBJECT_CLASS (g_keyfile_settings_backend_parent_class) - ->finalize (object); + G_OBJECT_CLASS (g_keyfile_settings_backend_parent_class)->finalize (object); } static void @@ -687,6 +729,8 @@ static void g_keyfile_settings_backend_constructed (GObject *object) { GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object); + GError *error = NULL; + const char *path; if (kfsb->file == NULL) { @@ -707,18 +751,36 @@ g_keyfile_settings_backend_constructed (GObject *object) kfsb->permission = g_simple_permission_new (TRUE); kfsb->dir = g_file_get_parent (kfsb->file); - g_mkdir_with_parents (g_file_peek_path (kfsb->dir), 0700); + path = g_file_peek_path (kfsb->dir); + if (g_mkdir_with_parents (path, 0700) == -1) + g_warning ("Failed to create %s: %s", path, g_strerror (errno)); + + kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, &error); + if (!kfsb->file_monitor) + { + g_warning ("Failed to create file monitor for %s: %s", g_file_peek_path (kfsb->file), error->message); + g_clear_error (&error); + } + else + { + g_signal_connect (kfsb->file_monitor, "changed", + G_CALLBACK (file_changed), kfsb); + } - kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, NULL); - kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, NULL); + kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, &error); + if (!kfsb->dir_monitor) + { + g_warning ("Failed to create file monitor for %s: %s", g_file_peek_path (kfsb->file), error->message); + g_clear_error (&error); + } + else + { + g_signal_connect (kfsb->dir_monitor, "changed", + G_CALLBACK (dir_changed), kfsb); + } compute_checksum (kfsb->digest, NULL, 0); - g_signal_connect (kfsb->file_monitor, "changed", - G_CALLBACK (file_changed), kfsb); - g_signal_connect (kfsb->dir_monitor, "changed", - G_CALLBACK (dir_changed), kfsb); - g_keyfile_settings_backend_keyfile_writable (kfsb); g_keyfile_settings_backend_keyfile_reload (kfsb); diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c index 9b82ebade7eb2aff061e6411f94776dd8f90b0db..74373e5b048e76916a66cf32ee6097b553a1af4b 100644 --- a/gio/glib-compile-resources.c +++ b/gio/glib-compile-resources.c @@ -550,7 +550,7 @@ parse_resource_file (const gchar *filename, gboolean collect_data, GHashTable *files) { - GMarkupParser parser = { start_element, end_element, text }; + GMarkupParser parser = { start_element, end_element, text, NULL, NULL }; ParseState state = { 0, }; GMarkupParseContext *context; GError *error = NULL; @@ -1061,6 +1061,7 @@ main (int argc, char **argv) guint8 *data; gsize data_size; gsize i; + const char *export = "G_MODULE_EXPORT"; if (!g_file_get_contents (binary_target, (char **)&data, &data_size, NULL)) @@ -1081,6 +1082,9 @@ main (int argc, char **argv) return 1; } + if (internal) + export = "G_GNUC_INTERNAL"; + g_fprintf (file, "#include \n" "\n" @@ -1140,30 +1144,36 @@ main (int argc, char **argv) g_fprintf (file, "\n" "static GStaticResource static_resource = { %s_resource_data.data, sizeof (%s_resource_data.data)%s, NULL, NULL, NULL };\n" - "%s GResource *%s_get_resource (void);\n" + "\n" + "%s\n" + "GResource *%s_get_resource (void);\n" "GResource *%s_get_resource (void)\n" "{\n" " return g_static_resource_get_resource (&static_resource);\n" "}\n", - c_name, c_name, (external_data ? "" : " - 1 /* nul terminator */"), linkage, c_name, c_name); + c_name, c_name, (external_data ? "" : " - 1 /* nul terminator */"), + export, c_name, c_name); if (manual_register) { g_fprintf (file, "\n" - "%s void %s_unregister_resource (void);\n" + "%s\n" + "void %s_unregister_resource (void);\n" "void %s_unregister_resource (void)\n" "{\n" " g_static_resource_fini (&static_resource);\n" "}\n" "\n" - "%s void %s_register_resource (void);\n" + "%s\n" + "void %s_register_resource (void);\n" "void %s_register_resource (void)\n" "{\n" " g_static_resource_init (&static_resource);\n" "}\n", - linkage, c_name, c_name, linkage, c_name, c_name); + export, c_name, c_name, + export, c_name, c_name); } else { diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c index 788812048633ae772b6cb366fc5663a6ec6fea25..cfea042f828d1aa9d566c0bb707749230ffcdefe 100644 --- a/gio/glib-compile-schemas.c +++ b/gio/glib-compile-schemas.c @@ -363,7 +363,7 @@ key_state_set_range (KeyState *state, { 'd', "-inf", "inf" }, }; gboolean type_ok = FALSE; - gint i; + gsize i; if (state->minimum) { @@ -705,7 +705,7 @@ key_state_serialise (KeyState *state) guint32 *words; gpointer data; gsize size; - gint i; + gsize i; data = state->strinfo->str; size = state->strinfo->len; @@ -1770,7 +1770,7 @@ static GHashTable * parse_gschema_files (gchar **files, gboolean strict) { - GMarkupParser parser = { start_element, end_element, text }; + GMarkupParser parser = { start_element, end_element, text, NULL, NULL }; ParseState state = { 0, }; const gchar *filename; GError *error = NULL; @@ -2173,7 +2173,7 @@ main (int argc, char **argv) { "targetdir", 0, 0, G_OPTION_ARG_FILENAME, &targetdir, N_("Where to store the gschemas.compiled file"), N_("DIRECTORY") }, { "strict", 0, 0, G_OPTION_ARG_NONE, &strict, N_("Abort on any errors in schemas"), NULL }, { "dry-run", 0, 0, G_OPTION_ARG_NONE, &dry_run, N_("Do not write the gschema.compiled file"), NULL }, - { "allow-any-name", 0, 0, G_OPTION_ARG_NONE, &allow_any_name, N_("Do not enforce key name restrictions") }, + { "allow-any-name", 0, 0, G_OPTION_ARG_NONE, &allow_any_name, N_("Do not enforce key name restrictions"), NULL }, /* These options are only for use in the gschema-compile tests */ { "schema-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &schema_files, NULL, NULL }, diff --git a/gio/glistmodel.c b/gio/glistmodel.c index 0dde9ad1ffc759280e56cb04a6f53c036570907c..eb797caaf845a928c9ea63df559b59c7636b565a 100644 --- a/gio/glistmodel.c +++ b/gio/glistmodel.c @@ -73,7 +73,7 @@ G_DEFINE_INTERFACE (GListModel, g_list_model, G_TYPE_OBJECT) * it are gone. * * On the other side, a consumer is expected only to hold references on - * objects that are currently "user visible", in order to faciliate the + * objects that are currently "user visible", in order to facilitate the * maximum level of laziness in the implementation of the list and to * reduce the required number of signal connections at a given time. * diff --git a/gio/gliststore.c b/gio/gliststore.c index 7b2a453d6c50c5f8393d405fcf8bf991f264d784..da7d12ce57b8a3428d6b43fc745d13f1c1992cb6 100644 --- a/gio/gliststore.c +++ b/gio/gliststore.c @@ -269,7 +269,7 @@ g_list_store_insert (GListStore *store, g_return_if_fail (G_IS_LIST_STORE (store)); g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (item), store->item_type)); - g_return_if_fail (position <= g_sequence_get_length (store->items)); + g_return_if_fail (position <= (guint) g_sequence_get_length (store->items)); it = g_sequence_get_iter_at_pos (store->items, position); g_sequence_insert_before (it, g_object_ref (item)); @@ -477,7 +477,7 @@ g_list_store_splice (GListStore *store, if (n_additions) { - gint i; + guint i; for (i = 0; i < n_additions; i++) { @@ -494,3 +494,86 @@ g_list_store_splice (GListStore *store, g_list_store_items_changed (store, position, n_removals, n_additions); } + +/** + * g_list_store_find_with_equal_func: + * @store: a #GListStore + * @item: (type GObject): an item + * @equal_func: (scope call): A custom equality check function + * @position: (out) (optional): the first position of @item, if it was found. + * + * Looks up the given @item in the list store by looping over the items and + * comparing them with @compare_func until the first occurrence of @item which + * matches. If @item was not found, then @position will not be set, and this + * method will return %FALSE. + * + * Returns: Whether @store contains @item. If it was found, @position will be + * set to the position where @item occurred for the first time. + * + * Since: 2.64 + */ +gboolean +g_list_store_find_with_equal_func (GListStore *store, + gpointer item, + GEqualFunc equal_func, + guint *position) +{ + GSequenceIter *iter, *begin, *end; + + g_return_val_if_fail (G_IS_LIST_STORE (store), FALSE); + g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (item), store->item_type), + FALSE); + g_return_val_if_fail (equal_func != NULL, FALSE); + + /* NOTE: We can't use g_sequence_lookup() or g_sequence_search(), because we + * can't assume the sequence is sorted. */ + begin = g_sequence_get_begin_iter (store->items); + end = g_sequence_get_end_iter (store->items); + + iter = begin; + while (iter != end) + { + gpointer iter_item; + + iter_item = g_sequence_get (iter); + if (equal_func (iter_item, item)) + { + if (position) + *position = g_sequence_iter_get_position (iter); + return TRUE; + } + + iter = g_sequence_iter_next (iter); + } + + return FALSE; +} + +/** + * g_list_store_find: + * @store: a #GListStore + * @item: (type GObject): an item + * @position: (out) (optional): the first position of @item, if it was found. + * + * Looks up the given @item in the list store by looping over the items until + * the first occurrence of @item. If @item was not found, then @position will + * not be set, and this method will return %FALSE. + * + * If you need to compare the two items with a custom comparison function, use + * g_list_store_find_with_equal_func() with a custom #GEqualFunc instead. + * + * Returns: Whether @store contains @item. If it was found, @position will be + * set to the position where @item occurred for the first time. + * + * Since: 2.64 + */ +gboolean +g_list_store_find (GListStore *store, + gpointer item, + guint *position) +{ + return g_list_store_find_with_equal_func (store, + item, + g_direct_equal, + position); +} diff --git a/gio/gliststore.h b/gio/gliststore.h index 407d542fbbdfd79f2c8337847b59bfad6e9c38d9..ef3b839511da12f0b2c70edf05888d75c071a862 100644 --- a/gio/gliststore.h +++ b/gio/gliststore.h @@ -72,6 +72,17 @@ void g_list_store_splice (GListSt gpointer *additions, guint n_additions); +GLIB_AVAILABLE_IN_2_64 +gboolean g_list_store_find (GListStore *store, + gpointer item, + guint *position); + +GLIB_AVAILABLE_IN_2_64 +gboolean g_list_store_find_with_equal_func (GListStore *store, + gpointer item, + GEqualFunc equal_func, + guint *position); + G_END_DECLS #endif /* __G_LIST_STORE_H__ */ diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 62f30b561262808680823f392f6d1429944d4f74..d3d68eca902861501aa99bdb792d1b1f95641fef 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -51,7 +51,6 @@ #include "gfileattribute.h" #include "glocalfile.h" -#include "glocalfileprivate.h" #include "glocalfileinfo.h" #include "glocalfileenumerator.h" #include "glocalfileinputstream.h" @@ -113,6 +112,10 @@ G_DEFINE_TYPE_WITH_CODE (GLocalFile, g_local_file, G_TYPE_OBJECT, static char *find_mountpoint_for (const char *file, dev_t dev, gboolean resolve_basename_symlink); +#ifndef G_OS_WIN32 +static gboolean is_remote_fs_type (const gchar *fsname); +#endif + static void g_local_file_finalize (GObject *object) { @@ -690,6 +693,8 @@ get_fs_type (long f_type) return "smackfs"; case 0x517B: return "smb"; + case 0xfe534d42: + return "smb2"; case 0x534F434B: return "sockfs"; case 0x73717368: @@ -825,36 +830,6 @@ get_mount_info (GFileInfo *fs_info, #ifdef G_OS_WIN32 -static gboolean -is_xp_or_later (void) -{ - static int result = -1; - - if (result == -1) - { -#ifndef _MSC_VER - OSVERSIONINFOEX ver_info = {0}; - DWORDLONG cond_mask = 0; - int op = VER_GREATER_EQUAL; - - ver_info.dwOSVersionInfoSize = sizeof ver_info; - ver_info.dwMajorVersion = 5; - ver_info.dwMinorVersion = 1; - - VER_SET_CONDITION (cond_mask, VER_MAJORVERSION, op); - VER_SET_CONDITION (cond_mask, VER_MINORVERSION, op); - - result = VerifyVersionInfo (&ver_info, - VER_MAJORVERSION | VER_MINORVERSION, - cond_mask) != 0; -#else - result = ((DWORD)(LOBYTE (LOWORD (GetVersion ())))) >= 5; -#endif - } - - return result; -} - static wchar_t * get_volume_for_path (const char *path) { @@ -913,18 +888,10 @@ get_filesystem_readonly (GFileInfo *info, if (rootdir) { - if (is_xp_or_later ()) - { - DWORD flags; - if (GetVolumeInformationW (rootdir, NULL, 0, NULL, NULL, &flags, NULL, 0)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, - (flags & FILE_READ_ONLY_VOLUME) != 0); - } - else - { - if (GetDriveTypeW (rootdir) == DRIVE_CDROM) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE); - } + DWORD flags; + if (GetVolumeInformationW (rootdir, NULL, 0, NULL, NULL, &flags, NULL, 0)) + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, + (flags & FILE_READ_ONLY_VOLUME) != 0); } g_free (rootdir); @@ -1110,11 +1077,13 @@ g_local_file_query_filesystem_info (GFile *file, get_mount_info (info, local->filename, attribute_matcher); #endif /* G_OS_WIN32 */ } - + +#ifndef G_OS_WIN32 if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE, - g_local_file_is_remote (local->filename)); + G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE)) + g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE, + is_remote_fs_type (fstype)); +#endif g_file_attribute_matcher_unref (attribute_matcher); @@ -1383,13 +1352,9 @@ g_local_file_read (GFile *file, return NULL; } -#ifdef G_OS_WIN32 - ret = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &buf); -#else - ret = fstat (fd, &buf); -#endif + ret = g_local_file_fstat (fd, G_LOCAL_FILE_STAT_FIELD_TYPE, G_LOCAL_FILE_STAT_FIELD_ALL, &buf); - if (ret == 0 && S_ISDIR (buf.st_mode)) + if (ret == 0 && S_ISDIR (_g_stat_mode (&buf))) { (void) g_close (fd, NULL); g_set_io_error (error, @@ -1511,7 +1476,7 @@ g_local_file_delete (GFile *file, { int errsv = errno; - /* Posix allows EEXIST too, but the more sane error + /* Posix allows EEXIST too, but the clearer error is G_IO_ERROR_NOT_FOUND, and it's what nautilus expects */ if (errsv == EEXIST) @@ -1808,46 +1773,98 @@ try_make_relative (const char *path, return g_strdup (path); } +static gboolean +ignore_trash_mount (GUnixMountEntry *mount) +{ + GUnixMountPoint *mount_point = NULL; + const gchar *mount_options; + gboolean retval = TRUE; + + if (g_unix_mount_is_system_internal (mount)) + return TRUE; + + mount_options = g_unix_mount_get_options (mount); + if (mount_options == NULL) + { + mount_point = g_unix_mount_point_at (g_unix_mount_get_mount_path (mount), + NULL); + if (mount_point != NULL) + mount_options = g_unix_mount_point_get_options (mount_point); + } + + if (mount_options == NULL || + strstr (mount_options, "x-gvfs-notrash") == NULL) + retval = FALSE; + + g_clear_pointer (&mount_point, g_unix_mount_point_free); + + return retval; +} + +static gboolean +ignore_trash_path (const gchar *topdir) +{ + GUnixMountEntry *mount; + gboolean retval = TRUE; + + mount = g_unix_mount_at (topdir, NULL); + if (mount == NULL) + goto out; + + retval = ignore_trash_mount (mount); + + out: + g_clear_pointer (&mount, g_unix_mount_free); + + return retval; +} + gboolean _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) { static gsize home_dev_set = 0; static dev_t home_dev; + static gboolean home_dev_valid = FALSE; char *topdir, *globaldir, *trashdir, *tmpname; uid_t uid; char uid_str[32]; GStatBuf global_stat, trash_stat; gboolean res; - GUnixMountEntry *mount; if (g_once_init_enter (&home_dev_set)) { GStatBuf home_stat; - g_stat (g_get_home_dir (), &home_stat); - home_dev = home_stat.st_dev; + if (g_stat (g_get_home_dir (), &home_stat) == 0) + { + home_dev = home_stat.st_dev; + home_dev_valid = TRUE; + } + else + { + home_dev_valid = FALSE; + } + g_once_init_leave (&home_dev_set, 1); } /* Assume we can trash to the home */ - if (dir_dev == home_dev) + if (!home_dev_valid) + return FALSE; + else if (dir_dev == home_dev) return TRUE; topdir = find_mountpoint_for (dirname, dir_dev, TRUE); if (topdir == NULL) return FALSE; - mount = g_unix_mount_at (topdir, NULL); - if (mount == NULL || g_unix_mount_is_system_internal (mount)) + if (ignore_trash_path (topdir)) { - g_clear_pointer (&mount, g_unix_mount_free); g_free (topdir); return FALSE; } - g_clear_pointer (&mount, g_unix_mount_free); - globaldir = g_build_filename (topdir, ".Trash", NULL); if (g_lstat (globaldir, &global_stat) == 0 && S_ISDIR (global_stat.st_mode) && @@ -1966,7 +1983,15 @@ g_local_file_trash (GFile *file, } homedir = g_get_home_dir (); - g_stat (homedir, &home_stat); + if (g_stat (homedir, &home_stat) != 0) + { + errsv = errno; + + g_set_io_error (error, + _("Error trashing file %s: %s"), + file, errsv); + return FALSE; + } is_homedir_trash = FALSE; trashdir = NULL; @@ -2001,7 +2026,7 @@ g_local_file_trash (GFile *file, display_name = g_filename_display_name (trashdir); g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Unable to create trash dir %s: %s"), + _("Unable to create trash directory %s: %s"), display_name, g_strerror (errsv)); g_free (display_name); g_free (trashdir); @@ -2013,7 +2038,7 @@ g_local_file_trash (GFile *file, { uid_t uid; char uid_str[32]; - GUnixMountEntry *mount; + gboolean success = FALSE; uid = geteuid (); g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long)uid); @@ -2027,20 +2052,15 @@ g_local_file_trash (GFile *file, return FALSE; } - mount = g_unix_mount_at (topdir, NULL); - if (mount == NULL || g_unix_mount_is_system_internal (mount)) + if (ignore_trash_path (topdir)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Trashing on system internal mounts is not supported")); - - g_clear_pointer (&mount, g_unix_mount_free); g_free (topdir); return FALSE; } - g_clear_pointer (&mount, g_unix_mount_free); - /* Try looking for global trash dir $topdir/.Trash/$uid */ globaldir = g_build_filename (topdir, ".Trash", NULL); if (g_lstat (globaldir, &global_stat) == 0 && @@ -2074,6 +2094,7 @@ g_local_file_trash (GFile *file, /* No global trash dir, or it failed the tests, fall back to $topdir/.Trash-$uid */ dirname = g_strdup_printf (".Trash-%s", uid_str); trashdir = g_build_filename (topdir, dirname, NULL); + success = TRUE; g_free (dirname); tried_create = FALSE; @@ -2089,8 +2110,7 @@ g_local_file_trash (GFile *file, g_remove (trashdir); /* Not a directory or not owned by user, ignore */ - g_free (trashdir); - trashdir = NULL; + success = FALSE; } } else @@ -2105,18 +2125,28 @@ g_local_file_trash (GFile *file, } else { - g_free (trashdir); - trashdir = NULL; + success = FALSE; } } } - if (trashdir == NULL) + if (!success) { - g_free (topdir); - g_set_io_error (error, - _("Unable to find or create trash directory for %s"), - file, G_IO_ERROR_NOT_SUPPORTED); + gchar *trashdir_display_name = NULL, *file_display_name = NULL; + + trashdir_display_name = g_filename_display_name (trashdir); + file_display_name = g_filename_display_name (local->filename); + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Unable to find or create trash directory %s to trash %s"), + trashdir_display_name, file_display_name); + + g_free (trashdir_display_name); + g_free (file_display_name); + + g_free (topdir); + g_free (trashdir); + return FALSE; } } @@ -2125,21 +2155,33 @@ g_local_file_trash (GFile *file, infodir = g_build_filename (trashdir, "info", NULL); filesdir = g_build_filename (trashdir, "files", NULL); - g_free (trashdir); /* Make sure we have the subdirectories */ if ((g_mkdir (infodir, 0700) == -1 && errno != EEXIST) || (g_mkdir (filesdir, 0700) == -1 && errno != EEXIST)) { + gchar *trashdir_display_name = NULL, *file_display_name = NULL; + + trashdir_display_name = g_filename_display_name (trashdir); + file_display_name = g_filename_display_name (local->filename); + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Unable to find or create trash directory %s to trash %s"), + trashdir_display_name, file_display_name); + + g_free (trashdir_display_name); + g_free (file_display_name); + g_free (topdir); + g_free (trashdir); g_free (infodir); g_free (filesdir); - g_set_io_error (error, - _("Unable to find or create trash directory for %s"), - file, G_IO_ERROR_NOT_SUPPORTED); + return FALSE; } + g_free (trashdir); + basename = g_path_get_basename (local->filename); i = 1; trashname = NULL; @@ -2204,7 +2246,9 @@ g_local_file_trash (GFile *file, original_name_escaped, delete_time); g_free (delete_time); - g_file_set_contents (infofile, data, -1, NULL); + g_file_set_contents_full (infofile, data, -1, + G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_ONLY_EXISTING, + 0600, NULL); /* TODO: Maybe we should verify that you can delete the file from the trash * before moving it? OTOH, that is hard, as it needs a recursive scan @@ -2330,13 +2374,13 @@ g_local_file_make_directory (GFile *file, return TRUE; } +#ifdef HAVE_SYMLINK static gboolean g_local_file_make_symbolic_link (GFile *file, const char *symlink_value, GCancellable *cancellable, GError **error) { -#ifdef HAVE_SYMLINK GLocalFile *local = G_LOCAL_FILE (file); if (symlink (symlink_value, local->filename) == -1) @@ -2359,26 +2403,8 @@ g_local_file_make_symbolic_link (GFile *file, return FALSE; } return TRUE; -#else - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Symbolic links not supported")); - return FALSE; -#endif -} - - -static gboolean -g_local_file_copy (GFile *source, - GFile *destination, - GFileCopyFlags flags, - GCancellable *cancellable, - GFileProgressCallback progress_callback, - gpointer progress_callback_data, - GError **error) -{ - /* Fall back to default copy */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Copy not supported"); - return FALSE; } +#endif static gboolean g_local_file_move (GFile *source, @@ -2527,7 +2553,7 @@ g_local_file_move (GFile *source, #ifdef G_OS_WIN32 gboolean -g_local_file_is_remote (const gchar *filename) +g_local_file_is_nfs_home (const gchar *filename) { return FALSE; } @@ -2535,58 +2561,29 @@ g_local_file_is_remote (const gchar *filename) #else static gboolean -is_remote_fs (const gchar *filename) +is_remote_fs_type (const gchar *fsname) { - const char *fsname = NULL; - -#ifdef USE_STATFS - struct statfs statfs_buffer; - int statfs_result = 0; - -#if STATFS_ARGS == 2 - statfs_result = statfs (filename, &statfs_buffer); -#elif STATFS_ARGS == 4 - statfs_result = statfs (filename, &statfs_buffer, sizeof (statfs_buffer), 0); -#endif - -#elif defined(USE_STATVFS) - struct statvfs statfs_buffer; - int statfs_result = 0; - - statfs_result = statvfs (filename, &statfs_buffer); -#else - return FALSE; -#endif - - if (statfs_result == -1) - return FALSE; - -#ifdef USE_STATFS -#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) - fsname = statfs_buffer.f_fstypename; -#else - fsname = get_fs_type (statfs_buffer.f_type); -#endif - -#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE) - fsname = statfs_buffer.f_basetype; -#endif - if (fsname != NULL) { if (strcmp (fsname, "nfs") == 0) return TRUE; if (strcmp (fsname, "nfs4") == 0) return TRUE; + if (strcmp (fsname, "cifs") == 0) + return TRUE; + if (strcmp (fsname, "smb") == 0) + return TRUE; + if (strcmp (fsname, "smb2") == 0) + return TRUE; } return FALSE; } gboolean -g_local_file_is_remote (const gchar *filename) +g_local_file_is_nfs_home (const gchar *filename) { - static gboolean remote_home; + static gboolean remote_home = FALSE; static gsize initialized; const gchar *home; @@ -2595,7 +2592,19 @@ g_local_file_is_remote (const gchar *filename) { if (g_once_init_enter (&initialized)) { - remote_home = is_remote_fs (home); + GFile *file; + GFileInfo *info; + const gchar *fs_type = NULL; + + file = _g_local_file_new (home); + info = g_local_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, NULL, NULL); + if (info != NULL) + fs_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE); + if (g_strcmp0 (fs_type, "nfs") == 0 || g_strcmp0 (fs_type, "nfs4") == 0) + remote_home = TRUE; + g_clear_object (&info); + g_object_unref (file); + g_once_init_leave (&initialized, TRUE); } return remote_home; @@ -2735,7 +2744,10 @@ g_local_file_measure_size_of_file (gint parent_fd, return FALSE; #if defined (AT_FDCWD) - if (fstatat (parent_fd, name->data, &buf, AT_SYMLINK_NOFOLLOW) != 0) + if (g_local_file_fstatat (parent_fd, name->data, AT_SYMLINK_NOFOLLOW, + G_LOCAL_FILE_STAT_FIELD_BASIC_STATS, + G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_ATIME), + &buf) != 0) { int errsv = errno; return g_local_file_measure_size_error (state->flags, errsv, name, error); @@ -2759,7 +2771,7 @@ g_local_file_measure_size_of_file (gint parent_fd, /* If not at the toplevel, check for a device boundary. */ if (state->flags & G_FILE_MEASURE_NO_XDEV) - if (state->contained_on != buf.st_dev) + if (state->contained_on != _g_stat_dev (&buf)) return TRUE; } else @@ -2767,7 +2779,7 @@ g_local_file_measure_size_of_file (gint parent_fd, /* If, however, this is the toplevel, set the device number so * that recursive invocations can compare against it. */ - state->contained_on = buf.st_dev; + state->contained_on = _g_stat_dev (&buf); } #if defined (G_OS_WIN32) @@ -2776,12 +2788,12 @@ g_local_file_measure_size_of_file (gint parent_fd, else #elif defined (HAVE_STRUCT_STAT_ST_BLOCKS) if (~state->flags & G_FILE_MEASURE_APPARENT_SIZE) - state->disk_usage += buf.st_blocks * G_GUINT64_CONSTANT (512); + state->disk_usage += _g_stat_blocks (&buf) * G_GUINT64_CONSTANT (512); else #endif - state->disk_usage += buf.st_size; + state->disk_usage += _g_stat_size (&buf); - if (S_ISDIR (buf.st_mode)) + if (S_ISDIR (_g_stat_mode (&buf))) state->num_dirs++; else state->num_files++; @@ -2816,7 +2828,7 @@ g_local_file_measure_size_of_file (gint parent_fd, } } - if (S_ISDIR (buf.st_mode)) + if (S_ISDIR (_g_stat_mode (&buf))) { int dir_fd = -1; #ifdef AT_FDCWD @@ -2853,22 +2865,24 @@ g_local_file_measure_size_of_contents (gint fd, gboolean success = TRUE; const gchar *name; GDir *dir; + gint saved_errno; #ifdef AT_FDCWD { - /* If this fails, we want to preserve the errno from fopendir() */ + /* If this fails, we want to preserve the errno from fdopendir() */ DIR *dirp; dirp = fdopendir (fd); + saved_errno = errno; dir = dirp ? GLIB_PRIVATE_CALL(g_dir_new_from_dirp) (dirp) : NULL; + g_assert ((dirp == NULL) == (dir == NULL)); } #else dir = GLIB_PRIVATE_CALL(g_dir_open_with_errno) (dir_name->data, 0); + saved_errno = errno; #endif if (dir == NULL) { - gint saved_errno = errno; - #ifdef AT_FDCWD close (fd); #endif @@ -2979,8 +2993,9 @@ g_local_file_file_iface_init (GFileIface *iface) iface->delete_file = g_local_file_delete; iface->trash = g_local_file_trash; iface->make_directory = g_local_file_make_directory; +#ifdef HAVE_SYMLINK iface->make_symbolic_link = g_local_file_make_symbolic_link; - iface->copy = g_local_file_copy; +#endif iface->move = g_local_file_move; iface->monitor_dir = g_local_file_monitor_dir; iface->monitor_file = g_local_file_monitor_file; diff --git a/gio/glocalfile.h b/gio/glocalfile.h index 960cfef1fc458cba94ebe8326b49a62e188f3e77..ac0ad9d733d72185c58b1b41fdf7cffd10050fd1 100644 --- a/gio/glocalfile.h +++ b/gio/glocalfile.h @@ -46,11 +46,13 @@ GFile * _g_local_file_new (const char *filename); const char * _g_local_file_get_filename (GLocalFile *file); -gboolean g_local_file_is_remote (const gchar *filename); +gboolean g_local_file_is_nfs_home (const gchar *filename); GFile * g_local_file_new_from_dirname_and_basename (const char *dirname, const char *basename); +gchar *_g_local_file_find_topdir_for (const char *file_path); + G_END_DECLS #endif /* __G_LOCAL_FILE_H__ */ diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index 487f8cc1a136e84ca618df645fb6214601bbeaac..33c2241860fd4d41bd2c2e5d363457a377711a7d 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -123,13 +123,20 @@ _g_local_file_info_create_etag (GLocalFileStat *statbuf) { glong sec, usec; - sec = statbuf->st_mtime; + g_return_val_if_fail (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_MTIME), NULL); + +#if defined (G_OS_WIN32) + sec = statbuf->st_mtim.tv_sec; + usec = statbuf->st_mtim.tv_nsec / 1000; +#else + sec = _g_stat_mtime (statbuf); #if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) usec = statbuf->st_mtimensec / 1000; #elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - usec = statbuf->st_mtim.tv_nsec / 1000; + usec = _g_stat_mtim_nsec (statbuf) / 1000; #else usec = 0; +#endif #endif return g_strdup_printf ("%lu:%lu", sec, usec); @@ -142,10 +149,10 @@ _g_local_file_info_create_file_id (GLocalFileStat *statbuf) #ifdef G_OS_WIN32 ino = statbuf->file_index; #else - ino = statbuf->st_ino; + ino = _g_stat_ino (statbuf); #endif return g_strdup_printf ("l%" G_GUINT64_FORMAT ":%" G_GUINT64_FORMAT, - (guint64) statbuf->st_dev, + (guint64) _g_stat_dev (statbuf), ino); } @@ -153,7 +160,7 @@ static char * _g_local_file_info_create_fs_id (GLocalFileStat *statbuf) { return g_strdup_printf ("l%" G_GUINT64_FORMAT, - (guint64) statbuf->st_dev); + (guint64) _g_stat_dev (statbuf)); } #if defined (S_ISLNK) || defined (G_OS_WIN32) @@ -163,14 +170,14 @@ read_link (const gchar *full_name) { #if defined (HAVE_READLINK) gchar *buffer; - guint size; + gsize size; size = 256; buffer = g_malloc (size); while (1) { - int read_size; + gssize read_size; read_size = readlink (full_name, buffer, size); if (read_size < 0) @@ -178,7 +185,7 @@ read_link (const gchar *full_name) g_free (buffer); return NULL; } - if (read_size < size) + if ((gsize) read_size < size) { buffer[read_size] = 0; return buffer; @@ -300,17 +307,15 @@ name_is_valid (const char *str) } static char * -hex_escape_string (const char *str, +hex_escape_buffer (const char *str, + size_t len, gboolean *free_return) { - int num_invalid, i; + size_t num_invalid, i; char *escaped_str, *p; unsigned char c; static char *hex_digits = "0123456789abcdef"; - int len; - len = strlen (str); - num_invalid = 0; for (i = 0; i < len; i++) { @@ -346,6 +351,13 @@ hex_escape_string (const char *str, return escaped_str; } +static char * +hex_escape_string (const char *str, + gboolean *free_return) +{ + return hex_escape_buffer (str, strlen (str), free_return); +} + static char * hex_unescape_string (const char *str, int *out_len, @@ -384,10 +396,10 @@ hex_unescape_string (const char *str, else *p++ = str[i]; } - *p++ = 0; - if (out_len) *out_len = p - unescaped_str; + *p++ = 0; + *free_return = TRUE; return unescaped_str; } @@ -401,7 +413,7 @@ escape_xattr (GFileInfo *info, char *escaped_val; gboolean free_escaped_val; - escaped_val = hex_escape_string (value, &free_escaped_val); + escaped_val = hex_escape_buffer (value, len, &free_escaped_val); g_file_info_set_attribute_string (info, gio_attr, escaped_val); @@ -504,7 +516,10 @@ get_xattrs (const char *path, } if (list_res_size == -1) - return; + { + g_free (list); + return; + } attr = list; while (list_res_size > 0) @@ -913,8 +928,8 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher, { uid_t uid = geteuid (); - if (uid == statbuf->st_uid || - uid == parent_info->owner || + if (uid == _g_stat_uid (statbuf) || + uid == (uid_t) parent_info->owner || uid == 0) writable = TRUE; } @@ -946,22 +961,22 @@ set_info_from_stat (GFileInfo *info, file_type = G_FILE_TYPE_UNKNOWN; - if (S_ISREG (statbuf->st_mode)) + if (S_ISREG (_g_stat_mode (statbuf))) file_type = G_FILE_TYPE_REGULAR; - else if (S_ISDIR (statbuf->st_mode)) + else if (S_ISDIR (_g_stat_mode (statbuf))) file_type = G_FILE_TYPE_DIRECTORY; #ifndef G_OS_WIN32 - else if (S_ISCHR (statbuf->st_mode) || - S_ISBLK (statbuf->st_mode) || - S_ISFIFO (statbuf->st_mode) + else if (S_ISCHR (_g_stat_mode (statbuf)) || + S_ISBLK (_g_stat_mode (statbuf)) || + S_ISFIFO (_g_stat_mode (statbuf)) #ifdef S_ISSOCK - || S_ISSOCK (statbuf->st_mode) + || S_ISSOCK (_g_stat_mode (statbuf)) #endif ) file_type = G_FILE_TYPE_SPECIAL; #endif #ifdef S_ISLNK - else if (S_ISLNK (statbuf->st_mode)) + else if (S_ISLNK (_g_stat_mode (statbuf))) file_type = G_FILE_TYPE_SYMBOLIC_LINK; #elif defined (G_OS_WIN32) else if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK || @@ -970,46 +985,56 @@ set_info_from_stat (GFileInfo *info, #endif g_file_info_set_file_type (info, file_type); - g_file_info_set_size (info, statbuf->st_size); + g_file_info_set_size (info, _g_stat_size (statbuf)); - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, statbuf->st_dev); - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, statbuf->st_nlink); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, _g_stat_dev (statbuf)); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, _g_stat_nlink (statbuf)); #ifndef G_OS_WIN32 /* Pointless setting these on Windows even if they exist in the struct */ - _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, statbuf->st_ino); - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, statbuf->st_uid); - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, statbuf->st_gid); - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, statbuf->st_rdev); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, _g_stat_ino (statbuf)); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, _g_stat_uid (statbuf)); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, _g_stat_gid (statbuf)); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, _g_stat_rdev (statbuf)); #endif /* Mostly pointless on Windows. * Still, it allows for S_ISREG/S_ISDIR and IWRITE (read-only) checks. */ - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, statbuf->st_mode); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, _g_stat_mode (statbuf)); #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE) - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, statbuf->st_blksize); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, _g_stat_blksize (statbuf)); #endif #if defined (HAVE_STRUCT_STAT_ST_BLOCKS) - _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, statbuf->st_blocks); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, _g_stat_blocks (statbuf)); _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE, - statbuf->st_blocks * G_GUINT64_CONSTANT (512)); + _g_stat_blocks (statbuf) * G_GUINT64_CONSTANT (512)); #elif defined (G_OS_WIN32) _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE, statbuf->allocated_size); #endif - - _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, statbuf->st_mtime); + +#if defined (G_OS_WIN32) + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, statbuf->st_mtim.tv_sec); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtim.tv_nsec / 1000); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atim.tv_sec); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000); +#else + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, _g_stat_mtime (statbuf)); #if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtim.tv_nsec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, _g_stat_mtim_nsec (statbuf) / 1000); #endif - - _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atime); + + if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_ATIME)) + { + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, _g_stat_atime (statbuf)); #if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC) - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atimensec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC) - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, _g_stat_atim_nsec (statbuf) / 1000); +#endif + } #endif #ifndef G_OS_WIN32 @@ -1018,15 +1043,21 @@ set_info_from_stat (GFileInfo *info, * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions#generic-text-routine-mappings * Thank you, Microsoft! */ - _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, statbuf->st_ctime); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, _g_stat_ctime (statbuf)); #if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC) _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC) - _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctim.tv_nsec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, _g_stat_ctim_nsec (statbuf) / 1000); #endif #endif -#if defined (HAVE_STRUCT_STAT_ST_BIRTHTIME) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) +#if defined (HAVE_STATX) + if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_BTIME)) + { + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->stx_btime.tv_sec); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED_USEC, statbuf->stx_btime.tv_nsec / 1000); + } +#elif defined (HAVE_STRUCT_STAT_ST_BIRTHTIME) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_birthtime); _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED_USEC, statbuf->st_birthtimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_BIRTHTIM) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) @@ -1037,7 +1068,8 @@ set_info_from_stat (GFileInfo *info, #elif defined (HAVE_STRUCT_STAT_ST_BIRTHTIM) _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_birthtim); #elif defined (G_OS_WIN32) - _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_ctime); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_ctim.tv_sec); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED_USEC, statbuf->st_ctim.tv_nsec / 1000); #endif if (_g_file_attribute_matcher_matches_id (attribute_matcher, @@ -1285,16 +1317,16 @@ get_content_type (const char *basename, if (is_symlink && (symlink_broken || (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))) return g_content_type_from_mime_type ("inode/symlink"); - else if (statbuf != NULL && S_ISDIR(statbuf->st_mode)) + else if (statbuf != NULL && S_ISDIR(_g_stat_mode (statbuf))) return g_content_type_from_mime_type ("inode/directory"); #ifndef G_OS_WIN32 - else if (statbuf != NULL && S_ISCHR(statbuf->st_mode)) + else if (statbuf != NULL && S_ISCHR(_g_stat_mode (statbuf))) return g_content_type_from_mime_type ("inode/chardevice"); - else if (statbuf != NULL && S_ISBLK(statbuf->st_mode)) + else if (statbuf != NULL && S_ISBLK(_g_stat_mode (statbuf))) return g_content_type_from_mime_type ("inode/blockdevice"); - else if (statbuf != NULL && S_ISFIFO(statbuf->st_mode)) + else if (statbuf != NULL && S_ISFIFO(_g_stat_mode (statbuf))) return g_content_type_from_mime_type ("inode/fifo"); - else if (statbuf != NULL && S_ISREG(statbuf->st_mode) && statbuf->st_size == 0) + else if (statbuf != NULL && S_ISREG(_g_stat_mode (statbuf)) && _g_stat_size (statbuf) == 0) { /* Don't sniff zero-length files in order to avoid reading files * that appear normal but are not (eg: files in /proc and /sys) @@ -1307,7 +1339,7 @@ get_content_type (const char *basename, } #endif #ifdef S_ISSOCK - else if (statbuf != NULL && S_ISSOCK(statbuf->st_mode)) + else if (statbuf != NULL && S_ISSOCK(_g_stat_mode (statbuf))) return g_content_type_from_mime_type ("inode/socket"); #endif else @@ -1515,15 +1547,45 @@ win32_get_file_user_info (const gchar *filename, /* support for '.hidden' files */ G_LOCK_DEFINE_STATIC (hidden_cache); static GHashTable *hidden_cache; +static GSource *hidden_cache_source = NULL; /* Under the hidden_cache lock */ +static guint hidden_cache_ttl_secs = 5; +static guint hidden_cache_ttl_jitter_secs = 2; + +typedef struct +{ + GHashTable *hidden_files; + gint64 timestamp_secs; +} HiddenCacheData; static gboolean remove_from_hidden_cache (gpointer user_data) { + HiddenCacheData *data; + GHashTableIter iter; + gboolean retval; + gint64 timestamp_secs; + G_LOCK (hidden_cache); - g_hash_table_remove (hidden_cache, user_data); + timestamp_secs = g_source_get_time (hidden_cache_source) / G_USEC_PER_SEC; + + g_hash_table_iter_init (&iter, hidden_cache); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &data)) + { + if (timestamp_secs > data->timestamp_secs + hidden_cache_ttl_secs) + g_hash_table_iter_remove (&iter); + } + + if (g_hash_table_size (hidden_cache) == 0) + { + g_clear_pointer (&hidden_cache_source, g_source_unref); + retval = G_SOURCE_REMOVE; + } + else + retval = G_SOURCE_CONTINUE; + G_UNLOCK (hidden_cache); - return FALSE; + return retval; } static GHashTable * @@ -1561,16 +1623,19 @@ read_hidden_file (const gchar *dirname) } static void -maybe_unref_hash_table (gpointer data) +free_hidden_file_data (gpointer user_data) { - if (data != NULL) - g_hash_table_unref (data); + HiddenCacheData *data = user_data; + + g_clear_pointer (&data->hidden_files, g_hash_table_unref); + g_free (data); } static gboolean file_is_hidden (const gchar *path, const gchar *basename) { + HiddenCacheData *data; gboolean result; gchar *dirname; gpointer table; @@ -1581,28 +1646,38 @@ file_is_hidden (const gchar *path, if G_UNLIKELY (hidden_cache == NULL) hidden_cache = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, maybe_unref_hash_table); + g_free, free_hidden_file_data); if (!g_hash_table_lookup_extended (hidden_cache, dirname, - NULL, &table)) + NULL, (gpointer *) &data)) { gchar *mydirname; - GSource *remove_from_cache_source; + + data = g_new0 (HiddenCacheData, 1); + data->hidden_files = table = read_hidden_file (dirname); + data->timestamp_secs = g_get_monotonic_time () / G_USEC_PER_SEC; g_hash_table_insert (hidden_cache, mydirname = g_strdup (dirname), - table = read_hidden_file (dirname)); + data); - remove_from_cache_source = g_timeout_source_new_seconds (5); - g_source_set_priority (remove_from_cache_source, G_PRIORITY_DEFAULT); - g_source_set_callback (remove_from_cache_source, - remove_from_hidden_cache, - mydirname, - NULL); - g_source_attach (remove_from_cache_source, - GLIB_PRIVATE_CALL (g_get_worker_context) ()); - g_source_unref (remove_from_cache_source); + if (!hidden_cache_source) + { + hidden_cache_source = + g_timeout_source_new_seconds (hidden_cache_ttl_secs + + hidden_cache_ttl_jitter_secs); + g_source_set_priority (hidden_cache_source, G_PRIORITY_DEFAULT); + g_source_set_name (hidden_cache_source, + "[gio] remove_from_hidden_cache"); + g_source_set_callback (hidden_cache_source, + remove_from_hidden_cache, + NULL, NULL); + g_source_attach (hidden_cache_source, + GLIB_PRIVATE_CALL (g_get_worker_context) ()); + } } + else + table = data->hidden_files; result = table != NULL && g_hash_table_contains (table, basename); @@ -1752,11 +1827,7 @@ _g_local_file_info_get (const char *basename, { GFileInfo *info; GLocalFileStat statbuf; -#ifdef S_ISLNK - struct stat statbuf2; -#elif defined (G_OS_WIN32) - GWin32PrivateStat statbuf2; -#endif + GLocalFileStat statbuf2; int res; gboolean stat_ok; gboolean is_symlink, symlink_broken; @@ -1778,11 +1849,10 @@ _g_local_file_info_get (const char *basename, return info; } -#ifndef G_OS_WIN32 - res = g_lstat (path, &statbuf); -#else - res = GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (path, &statbuf); -#endif + res = g_local_file_lstat (path, + G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME, + G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_BTIME) & (~G_LOCAL_FILE_STAT_FIELD_ATIME), + &statbuf); if (res == -1) { @@ -1806,12 +1876,12 @@ _g_local_file_info_get (const char *basename, stat_ok = res != -1; if (stat_ok) - device = statbuf.st_dev; + device = _g_stat_dev (&statbuf); else device = 0; #ifdef S_ISLNK - is_symlink = stat_ok && S_ISLNK (statbuf.st_mode); + is_symlink = stat_ok && S_ISLNK (_g_stat_mode (&statbuf)); #elif defined (G_OS_WIN32) /* glib already checked the FILE_ATTRIBUTE_REPARSE_POINT for us */ is_symlink = stat_ok && @@ -1829,11 +1899,10 @@ _g_local_file_info_get (const char *basename, /* Unless NOFOLLOW was set we default to following symlinks */ if (!(flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)) { -#ifndef G_OS_WIN32 - res = stat (path, &statbuf2); -#else - res = GLIB_PRIVATE_CALL (g_win32_stat_utf8) (path, &statbuf2); -#endif + res = g_local_file_stat (path, + G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME, + G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_BTIME) & (~G_LOCAL_FILE_STAT_FIELD_ATIME), + &statbuf2); /* Report broken links as symlinks */ if (res != -1) @@ -1850,7 +1919,7 @@ _g_local_file_info_get (const char *basename, set_info_from_stat (info, &statbuf, attribute_matcher); #ifdef G_OS_UNIX - if (stat_ok && _g_local_file_is_lost_found_dir (path, statbuf.st_dev)) + if (stat_ok && _g_local_file_is_lost_found_dir (path, _g_stat_dev (&statbuf))) g_file_info_set_is_hidden (info, TRUE); #endif @@ -1865,7 +1934,7 @@ _g_local_file_info_get (const char *basename, } if (basename != NULL && basename[strlen (basename) -1] == '~' && - (stat_ok && S_ISREG (statbuf.st_mode))) + (stat_ok && S_ISREG (_g_stat_mode (&statbuf)))) _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_IS_BACKUP, TRUE); #else if (statbuf.attributes & FILE_ATTRIBUTE_HIDDEN) @@ -1959,7 +2028,7 @@ _g_local_file_info_get (const char *basename, win32_get_file_user_info (path, NULL, &name, NULL); #else if (stat_ok) - name = get_username_from_uid (statbuf.st_uid); + name = get_username_from_uid (_g_stat_uid (&statbuf)); #endif if (name) _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER, name); @@ -1974,7 +2043,7 @@ _g_local_file_info_get (const char *basename, win32_get_file_user_info (path, NULL, NULL, &name); #else if (stat_ok) - name = get_realname_from_uid (statbuf.st_uid); + name = get_realname_from_uid (_g_stat_uid (&statbuf)); #endif if (name) _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER_REAL, name); @@ -1989,7 +2058,7 @@ _g_local_file_info_get (const char *basename, win32_get_file_user_info (path, &name, NULL, NULL); #else if (stat_ok) - name = get_groupname_from_gid (statbuf.st_gid); + name = get_groupname_from_gid (_g_stat_gid (&statbuf)); #endif if (name) _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_GROUP, name); @@ -1998,7 +2067,7 @@ _g_local_file_info_get (const char *basename, if (stat_ok && parent_info && parent_info->device != 0 && _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT) && - (statbuf.st_dev != parent_info->device || statbuf.st_ino == parent_info->inode)) + (_g_stat_dev (&statbuf) != parent_info->device || _g_stat_ino (&statbuf) == parent_info->inode)) _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT, TRUE); if (stat_ok) @@ -2052,14 +2121,11 @@ _g_local_file_info_get_from_fd (int fd, GLocalFileStat stat_buf; GFileAttributeMatcher *matcher; GFileInfo *info; - -#ifdef G_OS_WIN32 -#define FSTAT GLIB_PRIVATE_CALL (g_win32_fstat) -#else -#define FSTAT fstat -#endif - if (FSTAT (fd, &stat_buf) == -1) + if (g_local_file_fstat (fd, + G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME, + G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_BTIME) & (~G_LOCAL_FILE_STAT_FIELD_ATIME), + &stat_buf) == -1) { int errsv = errno; @@ -2119,7 +2185,7 @@ get_uint32 (const GFileAttributeValue *value, return TRUE; } -#ifdef HAVE_UTIMES +#if defined (HAVE_UTIMES) || defined (G_OS_WIN32) static gboolean get_uint64 (const GFileAttributeValue *value, guint64 *val_out, @@ -2352,7 +2418,180 @@ set_symlink (char *filename, } #endif -#ifdef HAVE_UTIMES +#if defined (G_OS_WIN32) +/* From + * https://support.microsoft.com/en-ca/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime + * FT = UT * 10000000 + 116444736000000000. + * Converts unix epoch time (a signed 64-bit integer) to FILETIME. + * Can optionally use a more precise timestamp that has + * a fraction of a second expressed in nanoseconds. + * UT must be between January 1st of year 1601 and December 31st of year 30827. + * nsec must be non-negative and < 1000000000. + * Returns TRUE if conversion succeeded, FALSE otherwise. + * + * The function that does the reverse can be found in + * glib/gstdio.c. + */ +static gboolean +_g_win32_unix_time_to_filetime (gint64 ut, + gint32 nsec, + FILETIME *ft, + GError **error) +{ + gint64 result; + /* 1 unit of FILETIME is 100ns */ + const gint64 hundreds_of_usec_per_sec = 10000000; + /* The difference between January 1, 1601 UTC (FILETIME epoch) and UNIX epoch + * in hundreds of nanoseconds. + */ + const gint64 filetime_unix_epoch_offset = 116444736000000000; + /* This is the maximum timestamp that SYSTEMTIME can + * represent (last millisecond of the year 30827). + * Since FILETIME and SYSTEMTIME are both used on Windows, + * we use this as a limit (FILETIME can support slightly + * larger interval, up to year 30828). + */ + const gint64 max_systemtime = 0x7fff35f4f06c58f0; + + g_return_val_if_fail (ft != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (nsec < 0) + { + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("Extra nanoseconds %d for UNIX timestamp %lld are negative"), + nsec, ut); + return FALSE; + } + + if (nsec >= hundreds_of_usec_per_sec * 100) + { + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("Extra nanoseconds %d for UNIX timestamp %lld reach 1 second"), + nsec, ut); + return FALSE; + } + + if (ut >= (G_MAXINT64 / hundreds_of_usec_per_sec) || + (ut * hundreds_of_usec_per_sec) >= (G_MAXINT64 - filetime_unix_epoch_offset)) + { + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("UNIX timestamp %lld does not fit into 64 bits"), + ut); + return FALSE; + } + + result = ut * hundreds_of_usec_per_sec + filetime_unix_epoch_offset + nsec / 100; + + if (result >= max_systemtime || result < 0) + { + g_set_error (error, G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("UNIX timestamp %lld is outside of the range supported by Windows"), + ut); + return FALSE; + } + + ft->dwLowDateTime = (DWORD) (result); + ft->dwHighDateTime = (DWORD) (result >> 32); + + return TRUE; +} + +static gboolean +set_mtime_atime (const char *filename, + const GFileAttributeValue *mtime_value, + const GFileAttributeValue *mtime_usec_value, + const GFileAttributeValue *atime_value, + const GFileAttributeValue *atime_usec_value, + GError **error) +{ + BOOL res; + guint64 val = 0; + guint32 val_usec = 0; + gunichar2 *filename_utf16; + SECURITY_ATTRIBUTES sec = { sizeof (SECURITY_ATTRIBUTES), NULL, FALSE }; + HANDLE file_handle; + FILETIME mtime; + FILETIME atime; + FILETIME *p_mtime = NULL; + FILETIME *p_atime = NULL; + DWORD gle; + + /* ATIME */ + if (atime_value) + { + if (!get_uint64 (atime_value, &val, error)) + return FALSE; + val_usec = 0; + if (atime_usec_value && + !get_uint32 (atime_usec_value, &val_usec, error)) + return FALSE; + if (!_g_win32_unix_time_to_filetime (val, val_usec, &atime, error)) + return FALSE; + p_atime = &atime; + } + + /* MTIME */ + if (mtime_value) + { + if (!get_uint64 (mtime_value, &val, error)) + return FALSE; + val_usec = 0; + if (mtime_usec_value && + !get_uint32 (mtime_usec_value, &val_usec, error)) + return FALSE; + if (!_g_win32_unix_time_to_filetime (val, val_usec, &mtime, error)) + return FALSE; + p_mtime = &mtime; + } + + filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, error); + + if (filename_utf16 == NULL) + { + g_prefix_error (error, + _("File name “%s” cannot be converted to UTF-16"), + filename); + return FALSE; + } + + file_handle = CreateFileW (filename_utf16, + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + &sec, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + gle = GetLastError (); + g_clear_pointer (&filename_utf16, g_free); + + if (file_handle == INVALID_HANDLE_VALUE) + { + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (gle), + _("File “%s” cannot be opened: Windows Error %lu"), + filename, gle); + + return FALSE; + } + + res = SetFileTime (file_handle, NULL, p_atime, p_mtime); + gle = GetLastError (); + CloseHandle (file_handle); + + if (!res) + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (gle), + _("Error setting modification or access time for file “%s”: %lu"), + filename, gle); + + return res; +} +#elif defined (HAVE_UTIMES) static int lazy_stat (char *filename, struct stat *statbuf, @@ -2460,8 +2699,8 @@ set_mtime_atime (char *filename, #ifdef HAVE_SELINUX static gboolean set_selinux_context (char *filename, - const GFileAttributeValue *value, - GError **error) + const GFileAttributeValue *value, + GError **error) { const char *val; @@ -2469,34 +2708,30 @@ set_selinux_context (char *filename, return FALSE; if (val == NULL) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("SELinux context must be non-NULL")); - return FALSE; - } + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("SELinux context must be non-NULL")); + return FALSE; + } - if (is_selinux_enabled ()) { - security_context_t val_s; - - val_s = g_strdup (val); - - if (setfilecon_raw (filename, val_s) < 0) - { - int errsv = errno; + if (!is_selinux_enabled ()) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("SELinux is not enabled on this system")); + return FALSE; + } + + if (setfilecon_raw (filename, val) < 0) + { + int errsv = errno; - g_set_error (error, G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error setting SELinux context: %s"), - g_strerror (errsv)); - return FALSE; - } - g_free (val_s); - } else { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("SELinux is not enabled on this system")); - return FALSE; - } - + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error setting SELinux context: %s"), + g_strerror (errsv)); + return FALSE; + } + return TRUE; } #endif @@ -2532,7 +2767,7 @@ _g_local_file_info_set_attribute (char *filename, return set_symlink (filename, &value, error); #endif -#ifdef HAVE_UTIMES +#if defined (HAVE_UTIMES) || defined (G_OS_WIN32) else if (strcmp (attribute, G_FILE_ATTRIBUTE_TIME_MODIFIED) == 0) return set_mtime_atime (filename, &value, NULL, NULL, NULL, error); else if (strcmp (attribute, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC) == 0) @@ -2599,9 +2834,11 @@ _g_local_file_info_set_attributes (char *filename, GFileAttributeValue *value; #ifdef G_OS_UNIX GFileAttributeValue *uid, *gid; -#ifdef HAVE_UTIMES +#endif +#if defined (HAVE_UTIMES) || defined (G_OS_WIN32) GFileAttributeValue *mtime, *mtime_usec, *atime, *atime_usec; #endif +#if defined (G_OS_UNIX) || defined (G_OS_WIN32) GFileAttributeStatus status; #endif gboolean res; @@ -2672,7 +2909,7 @@ _g_local_file_info_set_attributes (char *filename, } -#ifdef HAVE_UTIMES +#if defined (HAVE_UTIMES) || defined (G_OS_WIN32) /* Group all time settings into one call * Change times as the last thing to avoid it changing due to metadata changes */ diff --git a/gio/glocalfileinfo.h b/gio/glocalfileinfo.h index 7a6566163b001b18ece0cdc1751abed66e2181e4..e04e921f2c433263a6d94fb9fe53cbc5da99c2f0 100644 --- a/gio/glocalfileinfo.h +++ b/gio/glocalfileinfo.h @@ -21,12 +21,24 @@ #ifndef __G_LOCAL_FILE_INFO_H__ #define __G_LOCAL_FILE_INFO_H__ +/* Needed for statx() */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include #include #include +#include +#include #include #include #include +#ifdef HAVE_STATX +#include +#endif + G_BEGIN_DECLS typedef struct @@ -34,6 +46,7 @@ typedef struct gboolean writable; gboolean is_sticky; gboolean has_trash_dir; + /* owner should be uid_t but it breaks compliance with MS-Windows */ int owner; dev_t device; ino_t inode; @@ -41,6 +54,119 @@ typedef struct GDestroyNotify free_extra_data; } GLocalParentFileInfo; +#ifdef HAVE_STATX +#define GLocalFileStat struct statx + +typedef enum +{ + G_LOCAL_FILE_STAT_FIELD_TYPE = STATX_TYPE, + G_LOCAL_FILE_STAT_FIELD_MODE = STATX_MODE, + G_LOCAL_FILE_STAT_FIELD_NLINK = STATX_NLINK, + G_LOCAL_FILE_STAT_FIELD_UID = STATX_UID, + G_LOCAL_FILE_STAT_FIELD_GID = STATX_GID, + G_LOCAL_FILE_STAT_FIELD_ATIME = STATX_ATIME, + G_LOCAL_FILE_STAT_FIELD_MTIME = STATX_MTIME, + G_LOCAL_FILE_STAT_FIELD_CTIME = STATX_CTIME, + G_LOCAL_FILE_STAT_FIELD_INO = STATX_INO, + G_LOCAL_FILE_STAT_FIELD_SIZE = STATX_SIZE, + G_LOCAL_FILE_STAT_FIELD_BLOCKS = STATX_BLOCKS, + G_LOCAL_FILE_STAT_FIELD_BTIME = STATX_BTIME, +} GLocalFileStatField; + +#define G_LOCAL_FILE_STAT_FIELD_BASIC_STATS STATX_BASIC_STATS +#define G_LOCAL_FILE_STAT_FIELD_ALL STATX_ALL + +static inline int +g_local_file_statx (int dirfd, + const char *pathname, + int flags, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + int retval; + + /* Allow the caller to set mask_required==G_LOCAL_FILE_STAT_FIELD_ALL as a + * shortcut for saying it’s equal to @mask. */ + mask_required &= mask; + + retval = statx (dirfd, pathname, flags, mask, stat_buf); + if (retval == 0 && (stat_buf->stx_mask & mask_required) != mask_required) + { + /* Not all required fields could be returned. */ + errno = ERANGE; + return -1; + } + + return retval; +} + +static inline int +g_local_file_fstat (int fd, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + return g_local_file_statx (fd, "", AT_EMPTY_PATH, mask, mask_required, stat_buf); +} + +static inline int +g_local_file_fstatat (int fd, + const char *path, + int flags, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + return g_local_file_statx (fd, path, flags, mask, mask_required, stat_buf); +} + +static inline int +g_local_file_lstat (const char *path, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + return g_local_file_statx (AT_FDCWD, path, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT, + mask, mask_required, stat_buf); +} + +static inline int +g_local_file_stat (const char *path, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + return g_local_file_statx (AT_FDCWD, path, + AT_NO_AUTOMOUNT | AT_STATX_SYNC_AS_STAT, + mask, mask_required, stat_buf); +} + +inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return buf->stx_mask & field; } + +inline static guint16 _g_stat_mode (const GLocalFileStat *buf) { return buf->stx_mode; } +inline static guint32 _g_stat_nlink (const GLocalFileStat *buf) { return buf->stx_nlink; } +inline static dev_t _g_stat_dev (const GLocalFileStat *buf) { return makedev (buf->stx_dev_major, buf->stx_dev_minor); } +inline static guint64 _g_stat_ino (const GLocalFileStat *buf) { return buf->stx_ino; } +inline static guint64 _g_stat_size (const GLocalFileStat *buf) { return buf->stx_size; } + +inline static guint32 _g_stat_uid (const GLocalFileStat *buf) { return buf->stx_uid; } +inline static guint32 _g_stat_gid (const GLocalFileStat *buf) { return buf->stx_gid; } +inline static dev_t _g_stat_rdev (const GLocalFileStat *buf) { return makedev (buf->stx_rdev_major, buf->stx_rdev_minor); } +inline static guint32 _g_stat_blksize (const GLocalFileStat *buf) { return buf->stx_blksize; } + +inline static guint64 _g_stat_blocks (const GLocalFileStat *buf) { return buf->stx_blocks; } + +inline static gint64 _g_stat_atime (const GLocalFileStat *buf) { return buf->stx_atime.tv_sec; } +inline static gint64 _g_stat_ctime (const GLocalFileStat *buf) { return buf->stx_ctime.tv_sec; } +inline static gint64 _g_stat_mtime (const GLocalFileStat *buf) { return buf->stx_mtime.tv_sec; } +inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->stx_atime.tv_nsec; } +inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->stx_ctime.tv_nsec; } +inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->stx_mtime.tv_nsec; } + +#else /* if !HAVE_STATX */ + #ifdef G_OS_WIN32 /* We want 64-bit file size, file ID and symlink support */ #define GLocalFileStat GWin32PrivateStat @@ -48,6 +174,158 @@ typedef struct #define GLocalFileStat struct stat #endif +/* If the system doesn’t have statx() support, emulate it using traditional + * stat(). It supports fields %G_LOCAL_FILE_STAT_FIELD_BASIC_STATS only, and + * always returns all of them. */ +typedef enum +{ + G_LOCAL_FILE_STAT_FIELD_TYPE = (1 << 0), + G_LOCAL_FILE_STAT_FIELD_MODE = (1 << 1), + G_LOCAL_FILE_STAT_FIELD_NLINK = (1 << 2), + G_LOCAL_FILE_STAT_FIELD_UID = (1 << 3), + G_LOCAL_FILE_STAT_FIELD_GID = (1 << 4), + G_LOCAL_FILE_STAT_FIELD_ATIME = (1 << 5), + G_LOCAL_FILE_STAT_FIELD_MTIME = (1 << 6), + G_LOCAL_FILE_STAT_FIELD_CTIME = (1 << 7), + G_LOCAL_FILE_STAT_FIELD_INO = (1 << 8), + G_LOCAL_FILE_STAT_FIELD_SIZE = (1 << 9), + G_LOCAL_FILE_STAT_FIELD_BLOCKS = (1 << 10), + G_LOCAL_FILE_STAT_FIELD_BTIME = (1 << 11), +} GLocalFileStatField; + +#define G_LOCAL_FILE_STAT_FIELD_BASIC_STATS \ + (G_LOCAL_FILE_STAT_FIELD_TYPE | G_LOCAL_FILE_STAT_FIELD_MODE | \ + G_LOCAL_FILE_STAT_FIELD_NLINK | G_LOCAL_FILE_STAT_FIELD_UID | \ + G_LOCAL_FILE_STAT_FIELD_GID | G_LOCAL_FILE_STAT_FIELD_ATIME | \ + G_LOCAL_FILE_STAT_FIELD_MTIME | G_LOCAL_FILE_STAT_FIELD_CTIME | \ + G_LOCAL_FILE_STAT_FIELD_INO | G_LOCAL_FILE_STAT_FIELD_SIZE | \ + G_LOCAL_FILE_STAT_FIELD_BLOCKS) +#define G_LOCAL_FILE_STAT_FIELD_ALL (G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME) + +static inline int +g_local_file_fstat (int fd, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask)) + { + /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */ + errno = ERANGE; + return -1; + } + +#ifdef G_OS_WIN32 + return GLIB_PRIVATE_CALL (g_win32_fstat) (fd, stat_buf); +#else + return fstat (fd, stat_buf); +#endif +} + +static inline int +g_local_file_fstatat (int fd, + const char *path, + int flags, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask)) + { + /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */ + errno = ERANGE; + return -1; + } + +#if !defined(G_OS_WIN32) && defined(AT_FDCWD) + return fstatat (fd, path, stat_buf, flags); +#else + /* Currently not supported on Windows or macOS < 10.10 */ + errno = ENOSYS; + return -1; +#endif +} + +static inline int +g_local_file_lstat (const char *path, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask)) + { + /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */ + errno = ERANGE; + return -1; + } + +#ifdef G_OS_WIN32 + return GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (path, stat_buf); +#else + return g_lstat (path, stat_buf); +#endif +} + +static inline int +g_local_file_stat (const char *path, + GLocalFileStatField mask, + GLocalFileStatField mask_required, + GLocalFileStat *stat_buf) +{ + if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask)) + { + /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */ + errno = ERANGE; + return -1; + } + +#ifdef G_OS_WIN32 + return GLIB_PRIVATE_CALL (g_win32_stat_utf8) (path, stat_buf); +#else + return stat (path, stat_buf); +#endif +} + +inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return (G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & field) == field; } + +#ifndef G_OS_WIN32 +inline static mode_t _g_stat_mode (const GLocalFileStat *buf) { return buf->st_mode; } +inline static nlink_t _g_stat_nlink (const GLocalFileStat *buf) { return buf->st_nlink; } +#else +inline static guint16 _g_stat_mode (const GLocalFileStat *buf) { return buf->st_mode; } +inline static guint32 _g_stat_nlink (const GLocalFileStat *buf) { return buf->st_nlink; } +#endif +inline static dev_t _g_stat_dev (const GLocalFileStat *buf) { return buf->st_dev; } +inline static ino_t _g_stat_ino (const GLocalFileStat *buf) { return buf->st_ino; } +inline static off_t _g_stat_size (const GLocalFileStat *buf) { return buf->st_size; } + +#ifndef G_OS_WIN32 +inline static uid_t _g_stat_uid (const GLocalFileStat *buf) { return buf->st_uid; } +inline static gid_t _g_stat_gid (const GLocalFileStat *buf) { return buf->st_gid; } +inline static dev_t _g_stat_rdev (const GLocalFileStat *buf) { return buf->st_rdev; } +inline static blksize_t _g_stat_blksize (const GLocalFileStat *buf) { return buf->st_blksize; } +#else +inline static guint16 _g_stat_uid (const GLocalFileStat *buf) { return buf->st_uid; } +inline static guint16 _g_stat_gid (const GLocalFileStat *buf) { return buf->st_gid; } +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS +inline static blkcnt_t _g_stat_blocks (const GLocalFileStat *buf) { return buf->st_blocks; } +#endif + +#ifndef G_OS_WIN32 +inline static time_t _g_stat_atime (const GLocalFileStat *buf) { return buf->st_atime; } +inline static time_t _g_stat_ctime (const GLocalFileStat *buf) { return buf->st_ctime; } +inline static time_t _g_stat_mtime (const GLocalFileStat *buf) { return buf->st_mtime; } +#endif +#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC +inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->st_atim.tv_nsec; } +inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->st_ctim.tv_nsec; } +inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->st_mtim.tv_nsec; } +#endif + +#endif /* !HAVE_STATX */ + #define G_LOCAL_FILE_INFO_NOSTAT_ATTRIBUTES \ G_FILE_ATTRIBUTE_STANDARD_NAME "," \ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," \ @@ -94,5 +372,3 @@ gboolean _g_local_file_info_set_attributes (char *filename, G_END_DECLS #endif /* __G_FILE_LOCAL_FILE_INFO_H__ */ - - diff --git a/gio/glocalfileinputstream.c b/gio/glocalfileinputstream.c index 0d72c52e2170fa45f557cf1ed5440069975f1078..07532a242cb59e338e761675e49f486c5dea4073 100644 --- a/gio/glocalfileinputstream.c +++ b/gio/glocalfileinputstream.c @@ -68,10 +68,6 @@ static gssize g_local_file_input_stream_read (GInputStream *strea gsize count, GCancellable *cancellable, GError **error); -static gssize g_local_file_input_stream_skip (GInputStream *stream, - gsize count, - GCancellable *cancellable, - GError **error); static gboolean g_local_file_input_stream_close (GInputStream *stream, GCancellable *cancellable, GError **error); @@ -104,7 +100,6 @@ g_local_file_input_stream_class_init (GLocalFileInputStreamClass *klass) GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass); stream_class->read_fn = g_local_file_input_stream_read; - stream_class->skip = g_local_file_input_stream_skip; stream_class->close_fn = g_local_file_input_stream_close; file_stream_class->tell = g_local_file_input_stream_tell; file_stream_class->can_seek = g_local_file_input_stream_can_seek; @@ -175,62 +170,6 @@ g_local_file_input_stream_read (GInputStream *stream, return res; } -static gssize -g_local_file_input_stream_skip (GInputStream *stream, - gsize count, - GCancellable *cancellable, - GError **error) -{ - off_t start, end; - GLocalFileInputStream *file; - - file = G_LOCAL_FILE_INPUT_STREAM (stream); - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - return -1; - - start = lseek (file->priv->fd, 0, SEEK_CUR); - if (start == -1) - { - int errsv = errno; - - g_set_error (error, G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error seeking in file: %s"), - g_strerror (errsv)); - return -1; - } - - end = lseek (file->priv->fd, 0, SEEK_END); - if (end == -1) - { - int errsv = errno; - - g_set_error (error, G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error seeking in file: %s"), - g_strerror (errsv)); - return -1; - } - - if (end - start > count) - { - end = lseek (file->priv->fd, count - (end - start), SEEK_CUR); - if (end == -1) - { - int errsv = errno; - - g_set_error (error, G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error seeking in file: %s"), - g_strerror (errsv)); - return -1; - } - } - - return end - start; -} - static gboolean g_local_file_input_stream_close (GInputStream *stream, GCancellable *cancellable, diff --git a/gio/glocalfilemonitor.c b/gio/glocalfilemonitor.c index 3212beff7c274a9bfe456a1ab5cf689d660a4faf..eccab231cabe17b41fd67a8ff074f49310d812e0 100644 --- a/gio/glocalfilemonitor.c +++ b/gio/glocalfilemonitor.c @@ -649,7 +649,8 @@ g_file_monitor_source_new (gpointer instance, static GSourceFuncs source_funcs = { NULL, NULL, g_file_monitor_source_dispatch, - g_file_monitor_source_finalize + g_file_monitor_source_finalize, + NULL, NULL }; GFileMonitorSource *fms; GSource *source; @@ -878,7 +879,7 @@ g_local_file_monitor_new_for_path (const gchar *pathname, GLocalFileMonitor *monitor; gboolean is_remote_fs; - is_remote_fs = g_local_file_is_remote (pathname); + is_remote_fs = g_local_file_is_nfs_home (pathname); monitor = g_local_file_monitor_new (is_remote_fs, is_directory, error); @@ -900,7 +901,7 @@ g_local_file_monitor_new_in_worker (const gchar *pathname, GLocalFileMonitor *monitor; gboolean is_remote_fs; - is_remote_fs = g_local_file_is_remote (pathname); + is_remote_fs = g_local_file_is_nfs_home (pathname); monitor = g_local_file_monitor_new (is_remote_fs, is_directory, error); diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c index 32228866f7477eac894b1e1efc180675370fbedf..78d3e85a66bb81f062a749155c3d1e0cf1c2a1e4 100644 --- a/gio/glocalfileoutputstream.c +++ b/gio/glocalfileoutputstream.c @@ -18,6 +18,11 @@ * Author: Alexander Larsson */ +/* Needed for the statx() calls in inline functions in glocalfileinfo.h */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include "config.h" #include @@ -230,9 +235,9 @@ g_local_file_output_stream_write (GOutputStream *stream, #ifdef G_OS_UNIX /* Macro to check if struct iovec and GOutputVector have the same ABI */ #define G_OUTPUT_VECTOR_IS_IOVEC (sizeof (struct iovec) == sizeof (GOutputVector) && \ - sizeof ((struct iovec *) 0)->iov_base == sizeof ((GOutputVector *) 0)->buffer && \ + G_SIZEOF_MEMBER (struct iovec, iov_base) == G_SIZEOF_MEMBER (GOutputVector, buffer) && \ G_STRUCT_OFFSET (struct iovec, iov_base) == G_STRUCT_OFFSET (GOutputVector, buffer) && \ - sizeof ((struct iovec *) 0)->iov_len == sizeof((GOutputVector *) 0)->size && \ + G_SIZEOF_MEMBER (struct iovec, iov_len) == G_SIZEOF_MEMBER (GOutputVector, size) && \ G_STRUCT_OFFSET (struct iovec, iov_len) == G_STRUCT_OFFSET (GOutputVector, size)) static gboolean @@ -319,9 +324,8 @@ _g_local_file_output_stream_really_close (GLocalFileOutputStream *file, { GLocalFileStat final_stat; -#ifdef HAVE_FSYNC if (file->priv->sync_on_close && - fsync (file->priv->fd) != 0) + g_fsync (file->priv->fd) != 0) { int errsv = errno; @@ -331,8 +335,7 @@ _g_local_file_output_stream_really_close (GLocalFileOutputStream *file, g_strerror (errsv)); goto err_out; } -#endif - + #ifdef G_OS_WIN32 /* Must close before renaming on Windows, so just do the close first @@ -432,7 +435,7 @@ _g_local_file_output_stream_really_close (GLocalFileOutputStream *file, #ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */ - if (fstat (file->priv->fd, &final_stat) == 0) + if (g_local_file_fstat (file->priv->fd, G_LOCAL_FILE_STAT_FIELD_MTIME, G_LOCAL_FILE_STAT_FIELD_ALL, &final_stat) == 0) file->priv->etag = _g_local_file_info_create_etag (&final_stat); if (!g_close (file->priv->fd, NULL)) @@ -906,16 +909,31 @@ handle_overwrite_open (const char *filename, g_free (display_name); return -1; } - -#ifdef G_OS_WIN32 - res = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &original_stat); -#else + if (!is_symlink) - res = fstat (fd, &original_stat); + { + res = g_local_file_fstat (fd, + G_LOCAL_FILE_STAT_FIELD_TYPE | + G_LOCAL_FILE_STAT_FIELD_MODE | + G_LOCAL_FILE_STAT_FIELD_UID | + G_LOCAL_FILE_STAT_FIELD_GID | + G_LOCAL_FILE_STAT_FIELD_MTIME | + G_LOCAL_FILE_STAT_FIELD_NLINK, + G_LOCAL_FILE_STAT_FIELD_ALL, &original_stat); + errsv = errno; + } else - res = lstat (filename, &original_stat); -#endif - errsv = errno; + { + res = g_local_file_lstat (filename, + G_LOCAL_FILE_STAT_FIELD_TYPE | + G_LOCAL_FILE_STAT_FIELD_MODE | + G_LOCAL_FILE_STAT_FIELD_UID | + G_LOCAL_FILE_STAT_FIELD_GID | + G_LOCAL_FILE_STAT_FIELD_MTIME | + G_LOCAL_FILE_STAT_FIELD_NLINK, + G_LOCAL_FILE_STAT_FIELD_ALL, &original_stat); + errsv = errno; + } if (res != 0) { @@ -929,9 +947,9 @@ handle_overwrite_open (const char *filename, } /* not a regular file */ - if (!S_ISREG (original_stat.st_mode)) + if (!S_ISREG (_g_stat_mode (&original_stat))) { - if (S_ISDIR (original_stat.st_mode)) + if (S_ISDIR (_g_stat_mode (&original_stat))) { g_set_error_literal (error, G_IO_ERROR, @@ -941,7 +959,7 @@ handle_overwrite_open (const char *filename, } else if (!is_symlink || #ifdef S_ISLNK - !S_ISLNK (original_stat.st_mode) + !S_ISLNK (_g_stat_mode (&original_stat)) #else FALSE #endif @@ -965,7 +983,7 @@ handle_overwrite_open (const char *filename, G_IO_ERROR_WRONG_ETAG, _("The file was externally modified")); g_free (current_etag); - goto error; + goto error; } g_free (current_etag); } @@ -982,7 +1000,7 @@ handle_overwrite_open (const char *filename, */ if (replace_destination_set || - (!(original_stat.st_nlink > 1) && !is_symlink)) + (!(_g_stat_nlink (&original_stat) > 1) && !is_symlink)) { char *dirname, *tmp_filename; int tmpfd; @@ -1003,10 +1021,10 @@ handle_overwrite_open (const char *filename, if (!replace_destination_set && ( #ifdef HAVE_FCHOWN - fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 || + fchown (tmpfd, _g_stat_uid (&original_stat), _g_stat_gid (&original_stat)) == -1 || #endif #ifdef HAVE_FCHMOD - fchmod (tmpfd, original_stat.st_mode) == -1 || + fchmod (tmpfd, _g_stat_mode (&original_stat) & ~S_IFMT) == -1 || #endif 0 ) @@ -1015,16 +1033,18 @@ handle_overwrite_open (const char *filename, GLocalFileStat tmp_statbuf; int tres; -#ifdef G_OS_WIN32 - tres = GLIB_PRIVATE_CALL (g_win32_fstat) (tmpfd, &tmp_statbuf); -#else - tres = fstat (tmpfd, &tmp_statbuf); -#endif + tres = g_local_file_fstat (tmpfd, + G_LOCAL_FILE_STAT_FIELD_TYPE | + G_LOCAL_FILE_STAT_FIELD_MODE | + G_LOCAL_FILE_STAT_FIELD_UID | + G_LOCAL_FILE_STAT_FIELD_GID, + G_LOCAL_FILE_STAT_FIELD_ALL, &tmp_statbuf); + /* Check that we really needed to change something */ if (tres != 0 || - original_stat.st_uid != tmp_statbuf.st_uid || - original_stat.st_gid != tmp_statbuf.st_gid || - original_stat.st_mode != tmp_statbuf.st_mode) + _g_stat_uid (&original_stat) != _g_stat_uid (&tmp_statbuf) || + _g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf) || + _g_stat_mode (&original_stat) != _g_stat_mode (&tmp_statbuf)) { g_close (tmpfd, NULL); g_unlink (tmp_filename); @@ -1044,7 +1064,7 @@ handle_overwrite_open (const char *filename, if (create_backup) { #if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD) - struct stat tmp_statbuf; + GLocalFileStat tmp_statbuf; #endif char *backup_filename; int bfd; @@ -1058,12 +1078,12 @@ handle_overwrite_open (const char *filename, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_free (backup_filename); - goto error; + goto error; } bfd = g_open (backup_filename, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, - original_stat.st_mode & 0777); + _g_stat_mode (&original_stat) & 0777); if (bfd == -1) { @@ -1072,7 +1092,7 @@ handle_overwrite_open (const char *filename, G_IO_ERROR_CANT_CREATE_BACKUP, _("Backup file creation failed")); g_free (backup_filename); - goto error; + goto error; } /* If needed, Try to set the group of the backup same as the @@ -1080,7 +1100,7 @@ handle_overwrite_open (const char *filename, * bits for the group same as the protection bits for * others. */ #if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD) - if (fstat (bfd, &tmp_statbuf) != 0) + if (g_local_file_fstat (bfd, G_LOCAL_FILE_STAT_FIELD_GID, G_LOCAL_FILE_STAT_FIELD_ALL, &tmp_statbuf) != 0) { g_set_error_literal (error, G_IO_ERROR, @@ -1089,15 +1109,15 @@ handle_overwrite_open (const char *filename, g_unlink (backup_filename); g_close (bfd, NULL); g_free (backup_filename); - goto error; + goto error; } - if ((original_stat.st_gid != tmp_statbuf.st_gid) && - fchown (bfd, (uid_t) -1, original_stat.st_gid) != 0) + if ((_g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf)) && + fchown (bfd, (uid_t) -1, _g_stat_gid (&original_stat)) != 0) { if (fchmod (bfd, - (original_stat.st_mode & 0707) | - ((original_stat.st_mode & 07) << 3)) != 0) + (_g_stat_mode (&original_stat) & 0707) | + ((_g_stat_mode (&original_stat) & 07) << 3)) != 0) { g_set_error_literal (error, G_IO_ERROR, @@ -1106,7 +1126,7 @@ handle_overwrite_open (const char *filename, g_unlink (backup_filename); g_close (bfd, NULL); g_free (backup_filename); - goto error; + goto error; } } #endif @@ -1121,7 +1141,7 @@ handle_overwrite_open (const char *filename, g_close (bfd, NULL); g_free (backup_filename); - goto error; + goto error; } g_close (bfd, NULL); @@ -1136,7 +1156,7 @@ handle_overwrite_open (const char *filename, g_io_error_from_errno (errsv), _("Error seeking in file: %s"), g_strerror (errsv)); - goto error; + goto error; } } @@ -1152,7 +1172,7 @@ handle_overwrite_open (const char *filename, g_io_error_from_errno (errsv), _("Error removing old file: %s"), g_strerror (errsv)); - goto error; + goto error; } if (readable) @@ -1169,7 +1189,7 @@ handle_overwrite_open (const char *filename, _("Error opening file “%s”: %s"), display_name, g_strerror (errsv)); g_free (display_name); - goto error; + goto error; } } else @@ -1187,7 +1207,7 @@ handle_overwrite_open (const char *filename, g_io_error_from_errno (errsv), _("Error truncating file: %s"), g_strerror (errsv)); - goto error; + goto error; } } @@ -1256,7 +1276,6 @@ _g_local_file_output_stream_replace (const char *filename, set_error_from_open_errno (filename, error); return NULL; } - #if !defined(HAVE_O_CLOEXEC) && defined(F_SETFD) else fcntl (fd, F_SETFD, FD_CLOEXEC); diff --git a/gio/glocalvfs.c b/gio/glocalvfs.c index c29d071b7fb59ddb0deef68cce8897056340b9e4..2dc0f2de7e68d64c16f0a09602ba80b83101b12c 100644 --- a/gio/glocalvfs.c +++ b/gio/glocalvfs.c @@ -27,6 +27,7 @@ #include #include #ifdef G_OS_UNIX +#include "glib-unix.h" #include #endif #include @@ -79,7 +80,10 @@ static GFile * g_local_vfs_get_file_for_path (GVfs *vfs, const char *path) { - return _g_local_file_new (path); + if (*path == '\0') + return _g_dummy_file_new (path); + else + return _g_local_file_new (path); } static GFile * @@ -160,15 +164,17 @@ g_local_vfs_parse_name (GVfs *vfs, struct passwd *passwd_file_entry; char *user_name; - user_name = g_strndup (user_start, user_end - user_start); - passwd_file_entry = getpwnam (user_name); - g_free (user_name); - - if (passwd_file_entry != NULL && - passwd_file_entry->pw_dir != NULL) - user_prefix = g_strdup (passwd_file_entry->pw_dir); - else - user_prefix = g_strdup (g_get_home_dir ()); + user_name = g_strndup (user_start, user_end - user_start); + passwd_file_entry = g_unix_get_passwd_entry (user_name, NULL); + g_free (user_name); + + if (passwd_file_entry != NULL && + passwd_file_entry->pw_dir != NULL) + user_prefix = g_strdup (passwd_file_entry->pw_dir); + else + user_prefix = g_strdup (g_get_home_dir ()); + + g_free (passwd_file_entry); } #else user_prefix = g_strdup (g_get_home_dir ()); diff --git a/gio/gmarshal-internal.c b/gio/gmarshal-internal.c index f9571c42e996fd99191a3ec916c09cb44401e5ea..6858907ee7ae3488585b3f5d023b9dbe0d68d527 100644 --- a/gio/gmarshal-internal.c +++ b/gio/gmarshal-internal.c @@ -2629,4 +2629,3 @@ _g_cclosure_marshal_VOID__VARIANT_BOXEDv (GClosure *closure, if ((param_types[1] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg1 != NULL) g_boxed_free (param_types[1] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg1); } - diff --git a/gio/gmemoryinputstream.c b/gio/gmemoryinputstream.c index 37846b6ac6d91635dc66dfa488a8de86357dacf4..a9e855cef9da0344bcd324d14075e1eff7102bed 100644 --- a/gio/gmemoryinputstream.c +++ b/gio/gmemoryinputstream.c @@ -476,7 +476,7 @@ g_memory_input_stream_seek (GSeekable *seekable, return FALSE; } - if (absolute < 0 || absolute > priv->len) + if (absolute < 0 || (gsize) absolute > priv->len) { g_set_error_literal (error, G_IO_ERROR, diff --git a/gio/gmemorymonitor.c b/gio/gmemorymonitor.c new file mode 100644 index 0000000000000000000000000000000000000000..37ddf48cab269cad5d921868ffb95adb77da381f --- /dev/null +++ b/gio/gmemorymonitor.c @@ -0,0 +1,157 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2019 Red Hat, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include "config.h" +#include "glib.h" +#include "glibintl.h" + +#include "gmemorymonitor.h" +#include "ginetaddress.h" +#include "ginetsocketaddress.h" +#include "ginitable.h" +#include "gioenumtypes.h" +#include "giomodule-priv.h" +#include "gtask.h" + +/** + * SECTION:gmemorymonitor + * @title: GMemoryMonitor + * @short_description: Memory usage monitor + * @include: gio/gio.h + * + * #GMemoryMonitor will monitor system memory and suggest to the application + * when to free memory so as to leave more room for other applications. + * It is implemented on Linux using the [Low Memory Monitor](https://gitlab.freedesktop.org/hadess/low-memory-monitor/) + * ([API documentation](https://hadess.pages.freedesktop.org/low-memory-monitor/)). + * + * There is also an implementation for use inside Flatpak sandboxes. + * + * Possible actions to take when the signal is received are: + * - Free caches + * - Save files that haven't been looked at in a while to disk, ready to be reopened when needed + * - Run a garbage collection cycle + * - Try and compress fragmented allocations + * - Exit on idle if the process has no reason to stay around + * - Call [`malloc_trim(3)`](man:malloc_trim) to return cached heap pages to + * the kernel (if supported by your libc) + * + * Note that some actions may not always improve system performance, and so + * should be profiled for your application. `malloc_trim()`, for example, may + * make future heap allocations slower (due to releasing cached heap pages back + * to the kernel). + * + * See #GMemoryMonitorWarningLevel for details on the various warning levels. + * + * |[ + * static void + * warning_cb (GMemoryMonitor *m, GMemoryMonitorWarningLevel level) + * { + * g_debug ("Warning level: %d", level); + * if (warning_level > G_MEMORY_MONITOR_WARNING_LEVEL_LOW) + * drop_caches (); + * } + * + * static GMemoryMonitor * + * monitor_low_memory (void) + * { + * GMemoryMonitor *m; + * m = g_memory_monitor_dup_default (); + * g_signal_connect (G_OBJECT (m), "low-memory-warning", + * G_CALLBACK (warning_cb), NULL); + * return m; + * } + * ]| + * + * Don't forget to disconnect the #GMemoryMonitor::low-memory-warning + * signal, and unref the #GMemoryMonitor itself when exiting. + * + * Since: 2.64 + */ + +/** + * GMemoryMonitor: + * + * #GMemoryMonitor monitors system memory and indicates when + * the system is low on memory. + * + * Since: 2.64 + */ + +/** + * GMemoryMonitorInterface: + * @g_iface: The parent interface. + * @low_memory_warning: the virtual function pointer for the + * #GMemoryMonitor::low-memory-warning signal. + * + * The virtual function table for #GMemoryMonitor. + * + * Since: 2.64 + */ + +G_DEFINE_INTERFACE_WITH_CODE (GMemoryMonitor, g_memory_monitor, G_TYPE_OBJECT, + g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_INITABLE)) + +enum { + LOW_MEMORY_WARNING, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/** + * g_memory_monitor_dup_default: + * + * Gets a reference to the default #GMemoryMonitor for the system. + * + * Returns: (not nullable) (transfer full): a new reference to the default #GMemoryMonitor + * + * Since: 2.64 + */ +GMemoryMonitor * +g_memory_monitor_dup_default (void) +{ + return g_object_ref (_g_io_module_get_default (G_MEMORY_MONITOR_EXTENSION_POINT_NAME, + "GIO_USE_MEMORY_MONITOR", + NULL)); +} + +static void +g_memory_monitor_default_init (GMemoryMonitorInterface *iface) +{ + /** + * GMemoryMonitor::low-memory-warning: + * @monitor: a #GMemoryMonitor + * @level: the #GMemoryMonitorWarningLevel warning level + * + * Emitted when the system is running low on free memory. The signal + * handler should then take the appropriate action depending on the + * warning level. See the #GMemoryMonitorWarningLevel documentation for + * details. + * + * Since: 2.64 + */ + signals[LOW_MEMORY_WARNING] = + g_signal_new (I_("low-memory-warning"), + G_TYPE_MEMORY_MONITOR, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GMemoryMonitorInterface, low_memory_warning), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_MEMORY_MONITOR_WARNING_LEVEL); +} diff --git a/gio/gmemorymonitor.h b/gio/gmemorymonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..a3ad216c3fd167a8f8558dfba1cf6ea98ededee5 --- /dev/null +++ b/gio/gmemorymonitor.h @@ -0,0 +1,62 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#ifndef __G_MEMORY_MONITOR_H__ +#define __G_MEMORY_MONITOR_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +/** + * G_MEMORY_MONITOR_EXTENSION_POINT_NAME: + * + * Extension point for memory usage monitoring functionality. + * See [Extending GIO][extending-gio]. + * + * Since: 2.64 + */ +#define G_MEMORY_MONITOR_EXTENSION_POINT_NAME "gio-memory-monitor" + +#define G_TYPE_MEMORY_MONITOR (g_memory_monitor_get_type ()) +GLIB_AVAILABLE_IN_2_64 +G_DECLARE_INTERFACE(GMemoryMonitor, g_memory_monitor, g, memory_monitor, GObject) + +#define G_MEMORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MEMORY_MONITOR, GMemoryMonitor)) +#define G_IS_MEMORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MEMORY_MONITOR)) +#define G_MEMORY_MONITOR_GET_INTERFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_MEMORY_MONITOR, GMemoryMonitorInterface)) + +struct _GMemoryMonitorInterface { + /*< private >*/ + GTypeInterface g_iface; + + /*< public >*/ + void (*low_memory_warning) (GMemoryMonitor *monitor, + GMemoryMonitorWarningLevel level); +}; + +GLIB_AVAILABLE_IN_2_64 +GMemoryMonitor *g_memory_monitor_dup_default (void); + +G_END_DECLS + +#endif /* __G_MEMORY_MONITOR_H__ */ diff --git a/gio/gmemorymonitordbus.c b/gio/gmemorymonitordbus.c new file mode 100644 index 0000000000000000000000000000000000000000..a34a58d3ba7feb8bb2443add6ecfff9089e5b298 --- /dev/null +++ b/gio/gmemorymonitordbus.c @@ -0,0 +1,171 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include "config.h" + +#include "gmemorymonitor.h" +#include "gmemorymonitordbus.h" +#include "gioerror.h" +#include "ginitable.h" +#include "giomodule-priv.h" +#include "glibintl.h" +#include "glib/gstdio.h" +#include "gdbusproxy.h" +#include "gdbusnamewatching.h" + +#define G_MEMORY_MONITOR_DBUS_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) + +static void g_memory_monitor_dbus_iface_init (GMemoryMonitorInterface *iface); +static void g_memory_monitor_dbus_initable_iface_init (GInitableIface *iface); + +struct _GMemoryMonitorDBus +{ + GObject parent_instance; + + guint watch_id; + GDBusProxy *proxy; + gulong signal_id; +}; + +G_DEFINE_TYPE_WITH_CODE (GMemoryMonitorDBus, g_memory_monitor_dbus, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_memory_monitor_dbus_initable_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_MEMORY_MONITOR, + g_memory_monitor_dbus_iface_init) + _g_io_modules_ensure_extension_points_registered (); + g_io_extension_point_implement (G_MEMORY_MONITOR_EXTENSION_POINT_NAME, + g_define_type_id, + "dbus", + 30)) + +static void +g_memory_monitor_dbus_init (GMemoryMonitorDBus *dbus) +{ +} + +static void +proxy_signal_cb (GDBusProxy *proxy, + const gchar *sender_name, + const gchar *signal_name, + GVariant *parameters, + GMemoryMonitorDBus *dbus) +{ + guint8 level; + + if (g_strcmp0 (signal_name, "LowMemoryWarning") != 0) + return; + if (parameters == NULL) + return; + + g_variant_get (parameters, "(y)", &level); + g_signal_emit_by_name (dbus, "low-memory-warning", level); +} + +static void +lmm_appeared_cb (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + GMemoryMonitorDBus *dbus = user_data; + GDBusProxy *proxy; + GError *error = NULL; + + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "org.freedesktop.LowMemoryMonitor", + "/org/freedesktop/LowMemoryMonitor", + "org.freedesktop.LowMemoryMonitor", + NULL, + &error); + + if (!proxy) + { + g_debug ("Failed to create LowMemoryMonitor D-Bus proxy: %s", + error->message); + g_error_free (error); + return; + } + + dbus->signal_id = g_signal_connect (G_OBJECT (proxy), "g-signal", + G_CALLBACK (proxy_signal_cb), dbus); + dbus->proxy = proxy; +} + +static void +lmm_vanished_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + GMemoryMonitorDBus *dbus = user_data; + + if (dbus->proxy != NULL) + g_clear_signal_handler (&dbus->signal_id, dbus->proxy); + g_clear_object (&dbus->proxy); +} + +static gboolean +g_memory_monitor_dbus_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (initable); + + dbus->watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + "org.freedesktop.LowMemoryMonitor", + G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + lmm_appeared_cb, + lmm_vanished_cb, + dbus, + NULL); + + return TRUE; +} + +static void +g_memory_monitor_dbus_finalize (GObject *object) +{ + GMemoryMonitorDBus *dbus = G_MEMORY_MONITOR_DBUS (object); + + if (dbus->proxy != NULL) + g_clear_signal_handler (&dbus->signal_id, dbus->proxy); + g_clear_object (&dbus->proxy); + g_clear_handle_id (&dbus->watch_id, g_bus_unwatch_name); + + G_OBJECT_CLASS (g_memory_monitor_dbus_parent_class)->finalize (object); +} + +static void +g_memory_monitor_dbus_class_init (GMemoryMonitorDBusClass *nl_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class); + + gobject_class->finalize = g_memory_monitor_dbus_finalize; +} + +static void +g_memory_monitor_dbus_iface_init (GMemoryMonitorInterface *monitor_iface) +{ +} + +static void +g_memory_monitor_dbus_initable_iface_init (GInitableIface *iface) +{ + iface->init = g_memory_monitor_dbus_initable_init; +} diff --git a/gio/glocalfileprivate.h b/gio/gmemorymonitordbus.h similarity index 68% rename from gio/glocalfileprivate.h rename to gio/gmemorymonitordbus.h index 6b77305e70542d76890aded6c8631deccd36de65..e48e7557f8277b74111d32225fbde8745d29b4f2 100644 --- a/gio/glocalfileprivate.h +++ b/gio/gmemorymonitordbus.h @@ -1,6 +1,6 @@ /* GIO - GLib Input, Output and Streaming Library * - * Copyright (C) 2016 Red Hat, Inc. + * Copyright 2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -14,17 +14,18 @@ * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, see . - * - * Author: Ondrej Holy */ -#ifndef __G_LOCAL_FILE_PRIVATE_H__ -#define __G_LOCAL_FILE_PRIVATE_H__ +#ifndef __G_MEMORY_MONITOR_DBUS_H__ +#define __G_MEMORY_MONITOR_DBUS_H__ + +#include G_BEGIN_DECLS -gchar *_g_local_file_find_topdir_for (const char *file_path); +#define G_TYPE_MEMORY_MONITOR_DBUS (g_memory_monitor_dbus_get_type ()) +G_DECLARE_FINAL_TYPE (GMemoryMonitorDBus, g_memory_monitor_dbus, G, MEMORY_MONITOR_DBUS, GObject) G_END_DECLS -#endif /* __G_LOCAL_FILE_PRIVATE_H__ */ +#endif /* __G_MEMORY_MONITOR_DBUS_H__ */ diff --git a/gio/gmemorymonitorportal.c b/gio/gmemorymonitorportal.c new file mode 100644 index 0000000000000000000000000000000000000000..440629f4146aa8b8e6c35b264b122964b06d449d --- /dev/null +++ b/gio/gmemorymonitorportal.c @@ -0,0 +1,152 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include "config.h" + +#include "gmemorymonitor.h" +#include "gmemorymonitorportal.h" +#include "ginitable.h" +#include "giomodule-priv.h" +#include "xdp-dbus.h" +#include "gportalsupport.h" + +#define G_MEMORY_MONITOR_PORTAL_GET_INITABLE_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), G_TYPE_INITABLE, GInitable)) + +static void g_memory_monitor_portal_iface_init (GMemoryMonitorInterface *iface); +static void g_memory_monitor_portal_initable_iface_init (GInitableIface *iface); + +struct _GMemoryMonitorPortal +{ + GObject parent_instance; + + GDBusProxy *proxy; + gulong signal_id; +}; + +G_DEFINE_TYPE_WITH_CODE (GMemoryMonitorPortal, g_memory_monitor_portal, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_memory_monitor_portal_initable_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_MEMORY_MONITOR, + g_memory_monitor_portal_iface_init) + _g_io_modules_ensure_extension_points_registered (); + g_io_extension_point_implement (G_MEMORY_MONITOR_EXTENSION_POINT_NAME, + g_define_type_id, + "portal", + 40)) + +static void +g_memory_monitor_portal_init (GMemoryMonitorPortal *portal) +{ +} + +static void +proxy_signal (GDBusProxy *proxy, + const char *sender, + const char *signal, + GVariant *parameters, + GMemoryMonitorPortal *portal) +{ + guint8 level; + + if (strcmp (signal, "LowMemoryWarning") != 0) + return; + if (!parameters) + return; + + g_variant_get (parameters, "(y)", &level); + g_signal_emit_by_name (portal, "low-memory-warning", level); +} + +static gboolean +g_memory_monitor_portal_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GMemoryMonitorPortal *portal = G_MEMORY_MONITOR_PORTAL (initable); + GDBusProxy *proxy; + gchar *name_owner = NULL; + + if (!glib_should_use_portal ()) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not using portals"); + return FALSE; + } + + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.MemoryMonitor", + cancellable, + error); + if (!proxy) + return FALSE; + + name_owner = g_dbus_proxy_get_name_owner (proxy); + + if (name_owner == NULL) + { + g_object_unref (proxy); + g_set_error (error, + G_DBUS_ERROR, + G_DBUS_ERROR_NAME_HAS_NO_OWNER, + "Desktop portal not found"); + return FALSE; + } + + g_free (name_owner); + + portal->signal_id = g_signal_connect (proxy, "g-signal", + G_CALLBACK (proxy_signal), portal); + + portal->proxy = proxy; + + return TRUE; +} + +static void +g_memory_monitor_portal_finalize (GObject *object) +{ + GMemoryMonitorPortal *portal = G_MEMORY_MONITOR_PORTAL (object); + + if (portal->proxy != NULL) + g_clear_signal_handler (&portal->signal_id, portal->proxy); + g_clear_object (&portal->proxy); + + G_OBJECT_CLASS (g_memory_monitor_portal_parent_class)->finalize (object); +} + +static void +g_memory_monitor_portal_class_init (GMemoryMonitorPortalClass *nl_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (nl_class); + + gobject_class->finalize = g_memory_monitor_portal_finalize; +} + +static void +g_memory_monitor_portal_iface_init (GMemoryMonitorInterface *monitor_iface) +{ +} + +static void +g_memory_monitor_portal_initable_iface_init (GInitableIface *iface) +{ + iface->init = g_memory_monitor_portal_initable_init; +} diff --git a/gio/gwin32networking.h b/gio/gmemorymonitorportal.h similarity index 52% rename from gio/gwin32networking.h rename to gio/gmemorymonitorportal.h index 9e1396cc6add7d7c46a1e7522361a1e771ac4140..57074b48a7925849dd3b1868b2e7599e4bdc4075 100644 --- a/gio/gwin32networking.h +++ b/gio/gmemorymonitorportal.h @@ -1,6 +1,6 @@ /* GIO - GLib Input, Output and Streaming Library * - * Copyright (C) 2015 Chun-wei Fan + * Copyright 2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,27 +16,16 @@ * Public License along with this library; if not, see . */ -#ifndef __G_WIN32_NETWORKING_H__ -#define __G_WIN32_NETWORKING_H__ +#ifndef __G_MEMORY_MONITOR_PORTAL_H__ +#define __G_MEMORY_MONITOR_PORTAL_H__ -G_BEGIN_DECLS - -/* Check if more ANSI-compliant Winsock2 functions are provided */ -/* For run-time compatibility with Windows XP, remove when XP support dropped */ +#include -typedef INT (WSAAPI *PFN_InetPton) (INT, PCTSTR, PVOID); -typedef PCTSTR (WSAAPI *PFN_InetNtop) (INT, PVOID, PTSTR, size_t); -typedef NET_IFINDEX (WINAPI *PFN_IfNameToIndex) (PCSTR); - -typedef struct _GWin32WinsockFuncs -{ - PFN_InetPton pInetPton; - PFN_InetNtop pInetNtop; - PFN_IfNameToIndex pIfNameToIndex; -} GWin32WinsockFuncs; +G_BEGIN_DECLS -extern GWin32WinsockFuncs ws2funcs; +#define G_TYPE_MEMORY_MONITOR_PORTAL (g_memory_monitor_portal_get_type ()) +G_DECLARE_FINAL_TYPE (GMemoryMonitorPortal, g_memory_monitor_portal, G, MEMORY_MONITOR_PORTAL, GObject) -G_END_DECLS /* __G_WIN32_NETWORKING_H__ */ +G_END_DECLS -#endif +#endif /* __G_MEMORY_MONITOR_PORTAL_H__ */ diff --git a/gio/gmemoryoutputstream.c b/gio/gmemoryoutputstream.c index de8babfa5bc5b4830509bc16c97037f9612c9da1..b120ccedc0eeb4d95770507d128af40875a9f062 100644 --- a/gio/gmemoryoutputstream.c +++ b/gio/gmemoryoutputstream.c @@ -789,7 +789,7 @@ g_memory_output_stream_seek (GSeekable *seekable, * stream is valid (eg: a 1-byte fixed sized stream can have position * 0 or 1). Therefore '>' is what we want. * */ - if (priv->realloc_fn == NULL && absolute > priv->len) + if (priv->realloc_fn == NULL && (gsize) absolute > priv->len) { g_set_error_literal (error, G_IO_ERROR, diff --git a/gio/gmenu.c b/gio/gmenu.c index 95602520cb40870e7f76550f3abdb30da9aaf457..2c8c6c93f5af04ef824ce772a8ecf1986df8a137 100644 --- a/gio/gmenu.c +++ b/gio/gmenu.c @@ -162,7 +162,7 @@ g_menu_insert_item (GMenu *menu, g_return_if_fail (G_IS_MENU (menu)); g_return_if_fail (G_IS_MENU_ITEM (item)); - if (position < 0 || position > menu->items->len) + if (position < 0 || (guint) position > menu->items->len) position = menu->items->len; new_item.attributes = g_hash_table_ref (item->attributes); @@ -480,7 +480,7 @@ g_menu_remove (GMenu *menu, gint position) { g_return_if_fail (G_IS_MENU (menu)); - g_return_if_fail (0 <= position && position < menu->items->len); + g_return_if_fail (0 <= position && (guint) position < menu->items->len); g_menu_clear_item (&g_array_index (menu->items, struct item, position)); g_array_remove_index (menu->items, position); @@ -781,7 +781,7 @@ g_menu_item_set_link (GMenuItem *menu_item, * type, %NULL is returned. %NULL is also returned if the attribute * simply does not exist. * - * Returns: (transfer full): the attribute value, or %NULL + * Returns: (nullable) (transfer full): the attribute value, or %NULL * * Since: 2.34 */ @@ -865,7 +865,7 @@ g_menu_item_get_attribute (GMenuItem *menu_item, * * Queries the named @link on @menu_item. * - * Returns: (transfer full): the link, or %NULL + * Returns: (nullable) (transfer full): the link, or %NULL * * Since: 2.34 */ diff --git a/gio/gmenuexporter.c b/gio/gmenuexporter.c index f319b886b1ff49e83b31d6d7e88d30dbf8cae85f..a212b29f3e39773b4bcd0e7009d6a0f61ecc6954 100644 --- a/gio/gmenuexporter.c +++ b/gio/gmenuexporter.c @@ -783,7 +783,7 @@ g_dbus_connection_export_menu_model (GDBusConnection *connection, GError **error) { const GDBusInterfaceVTable vtable = { - g_menu_exporter_method_call, + g_menu_exporter_method_call, NULL, NULL, { 0 } }; GMenuExporter *exporter; guint id; diff --git a/gio/gmenumodel.c b/gio/gmenumodel.c index 8ca45e0981c10d54fa8f3b4c70d5c45c1d593f3a..bd60dc5f68842aacb6dd52fbf9a228898ebd6e13 100644 --- a/gio/gmenumodel.c +++ b/gio/gmenumodel.c @@ -309,7 +309,7 @@ g_menu_model_real_iterate_item_attributes (GMenuModel *model, else { g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_attributes() " - "and fails to return sane values from get_item_attributes()", + "and fails to return valid values from get_item_attributes()", G_OBJECT_TYPE_NAME (model)); result = NULL; } @@ -373,7 +373,7 @@ g_menu_model_real_iterate_item_links (GMenuModel *model, else { g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_links() " - "and fails to return sane values from get_item_links()", + "and fails to return valid values from get_item_links()", G_OBJECT_TYPE_NAME (model)); result = NULL; } @@ -429,7 +429,7 @@ g_menu_model_class_init (GMenuModelClass *class) * @removed: the number of items removed * @added: the number of items added * - * Emitted when a change has occured to the menu. + * Emitted when a change has occurred to the menu. * * The only changes that can occur to a menu is that items are removed * or added. Items may not change (except by being removed and added @@ -541,7 +541,7 @@ g_menu_model_iterate_item_attributes (GMenuModel *model, * If the attribute does not exist, or does not match the expected type * then %NULL is returned. * - * Returns: (transfer full): the value of the attribute + * Returns: (nullable) (transfer full): the value of the attribute * * Since: 2.32 */ @@ -648,7 +648,7 @@ g_menu_model_iterate_item_links (GMenuModel *model, * If the link exists, the linked #GMenuModel is returned. If the link * does not exist, %NULL is returned. * - * Returns: (transfer full): the linked #GMenuModel, or %NULL + * Returns: (nullable) (transfer full): the linked #GMenuModel, or %NULL * * Since: 2.32 */ diff --git a/gio/gmountoperation.c b/gio/gmountoperation.c index 39762e51d70175ca38905163da9bfd3376455fcb..4bc19a88be984de74e9292d4a1754734bf1cc335 100644 --- a/gio/gmountoperation.c +++ b/gio/gmountoperation.c @@ -431,7 +431,7 @@ g_mount_operation_class_init (GMountOperationClass *klass) /** * GMountOperation::show-unmount-progress: * @op: a #GMountOperation: - * @message: string containing a mesage to display to the user + * @message: string containing a message to display to the user * @time_left: the estimated time left before the operation completes, * in microseconds, or -1 * @bytes_left: the amount of bytes to be written before the operation @@ -638,7 +638,7 @@ g_mount_operation_new (void) * * Get the user name from the mount operation. * - * Returns: a string containing the user name. + * Returns: (nullable): a string containing the user name. **/ const char * g_mount_operation_get_username (GMountOperation *op) @@ -650,7 +650,7 @@ g_mount_operation_get_username (GMountOperation *op) /** * g_mount_operation_set_username: * @op: a #GMountOperation. - * @username: input username. + * @username: (nullable): input username. * * Sets the user name within @op to @username. **/ @@ -670,7 +670,7 @@ g_mount_operation_set_username (GMountOperation *op, * * Gets a password from the mount operation. * - * Returns: a string containing the password within @op. + * Returns: (nullable): a string containing the password within @op. **/ const char * g_mount_operation_get_password (GMountOperation *op) @@ -682,7 +682,7 @@ g_mount_operation_get_password (GMountOperation *op) /** * g_mount_operation_set_password: * @op: a #GMountOperation. - * @password: password to set. + * @password: (nullable): password to set. * * Sets the mount operation's password to @password. * @@ -741,7 +741,7 @@ g_mount_operation_set_anonymous (GMountOperation *op, * * Gets the domain of the mount operation. * - * Returns: a string set to the domain. + * Returns: (nullable): a string set to the domain. **/ const char * g_mount_operation_get_domain (GMountOperation *op) @@ -753,7 +753,7 @@ g_mount_operation_get_domain (GMountOperation *op) /** * g_mount_operation_set_domain: * @op: a #GMountOperation. - * @domain: the domain to set. + * @domain: (nullable): the domain to set. * * Sets the mount operation's domain. **/ diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c index f12f935852746238f43e722c1817f161a6014202..ef1940a920083b9e7a0a6ca8617e4cc956e078be 100644 --- a/gio/gnetworkaddress.c +++ b/gio/gnetworkaddress.c @@ -518,292 +518,6 @@ g_network_address_parse (const gchar *host_and_port, return connectable; } -/* Allowed characters outside alphanumeric for unreserved. */ -#define G_URI_OTHER_UNRESERVED "-._~" - -/* This or something equivalent will eventually go into glib/guri.h */ -gboolean -_g_uri_parse_authority (const char *uri, - char **host, - guint16 *port, - char **userinfo, - GError **error) -{ - char *ascii_uri, *tmp_str; - const char *start, *p, *at, *delim; - char c; - - g_return_val_if_fail (uri != NULL, FALSE); - - if (host) - *host = NULL; - - if (port) - *port = 0; - - if (userinfo) - *userinfo = NULL; - - /* Catch broken URIs early by trying to convert to ASCII. */ - ascii_uri = g_hostname_to_ascii (uri); - if (!ascii_uri) - goto error; - - /* From RFC 3986 Decodes: - * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] - * hier-part = "//" authority path-abempty - * path-abempty = *( "/" segment ) - * authority = [ userinfo "@" ] host [ ":" port ] - */ - - /* Check we have a valid scheme */ - tmp_str = g_uri_parse_scheme (ascii_uri); - - if (tmp_str == NULL) - goto error; - - g_free (tmp_str); - - /* Decode hier-part: - * hier-part = "//" authority path-abempty - */ - p = ascii_uri; - start = strstr (p, "//"); - - if (start == NULL) - goto error; - - start += 2; - - /* check if the @ sign is part of the authority before attempting to - * decode the userinfo */ - delim = strpbrk (start, "/?#[]"); - at = strchr (start, '@'); - if (at && delim && at > delim) - at = NULL; - - if (at != NULL) - { - /* Decode userinfo: - * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - */ - p = start; - while (1) - { - c = *p++; - - if (c == '@') - break; - - /* pct-encoded */ - if (c == '%') - { - if (!(g_ascii_isxdigit (p[0]) || - g_ascii_isxdigit (p[1]))) - goto error; - - p++; - - continue; - } - - /* unreserved / sub-delims / : */ - if (!(g_ascii_isalnum (c) || - strchr (G_URI_OTHER_UNRESERVED, c) || - strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c) || - c == ':')) - goto error; - } - - if (userinfo) - *userinfo = g_strndup (start, p - start - 1); - - start = p; - } - else - { - p = start; - } - - - /* decode host: - * host = IP-literal / IPv4address / reg-name - * reg-name = *( unreserved / pct-encoded / sub-delims ) - */ - - /* If IPv6 or IPvFuture */ - if (*p == '[') - { - gboolean has_scope_id = FALSE, has_bad_scope_id = FALSE; - - start++; - p++; - while (1) - { - c = *p++; - - if (c == ']') - break; - - if (c == '%' && !has_scope_id) - { - has_scope_id = TRUE; - if (p[0] != '2' || p[1] != '5') - has_bad_scope_id = TRUE; - continue; - } - - /* unreserved / sub-delims */ - if (!(g_ascii_isalnum (c) || - strchr (G_URI_OTHER_UNRESERVED, c) || - strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c) || - c == ':' || - c == '.')) - goto error; - } - - if (host) - { - if (has_bad_scope_id) - *host = g_strndup (start, p - start - 1); - else - *host = g_uri_unescape_segment (start, p - 1, NULL); - } - - c = *p++; - } - else - { - while (1) - { - c = *p++; - - if (c == ':' || - c == '/' || - c == '?' || - c == '#' || - c == '\0') - break; - - /* pct-encoded */ - if (c == '%') - { - if (!(g_ascii_isxdigit (p[0]) || - g_ascii_isxdigit (p[1]))) - goto error; - - p++; - - continue; - } - - /* unreserved / sub-delims */ - if (!(g_ascii_isalnum (c) || - strchr (G_URI_OTHER_UNRESERVED, c) || - strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c))) - goto error; - } - - if (host) - *host = g_uri_unescape_segment (start, p - 1, NULL); - } - - if (c == ':') - { - /* Decode port: - * port = *DIGIT - */ - guint tmp = 0; - - while (1) - { - c = *p++; - - if (c == '/' || - c == '?' || - c == '#' || - c == '\0') - break; - - if (!g_ascii_isdigit (c)) - goto error; - - tmp = (tmp * 10) + (c - '0'); - - if (tmp > 65535) - goto error; - } - if (port) - *port = (guint16) tmp; - } - - g_free (ascii_uri); - - return TRUE; - -error: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Invalid URI ‘%s’", uri); - - if (host && *host) - { - g_free (*host); - *host = NULL; - } - - if (userinfo && *userinfo) - { - g_free (*userinfo); - *userinfo = NULL; - } - - g_free (ascii_uri); - - return FALSE; -} - -gchar * -_g_uri_from_authority (const gchar *protocol, - const gchar *host, - guint port, - const gchar *userinfo) -{ - GString *uri; - - uri = g_string_new (protocol); - g_string_append (uri, "://"); - - if (userinfo) - { - g_string_append_uri_escaped (uri, userinfo, G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, FALSE); - g_string_append_c (uri, '@'); - } - - if (g_hostname_is_non_ascii (host)) - { - gchar *ace_encoded = g_hostname_to_ascii (host); - - if (!ace_encoded) - { - g_string_free (uri, TRUE); - return NULL; - } - g_string_append (uri, ace_encoded); - g_free (ace_encoded); - } - else if (strchr (host, ':')) - g_string_append_printf (uri, "[%s]", host); - else - g_string_append (uri, host); - - if (port != 0) - g_string_append_printf (uri, ":%u", port); - - return g_string_free (uri, FALSE); -} - /** * g_network_address_parse_uri: * @uri: the hostname and optionally a port @@ -827,25 +541,27 @@ g_network_address_parse_uri (const gchar *uri, guint16 default_port, GError **error) { - GSocketConnectable *conn; - gchar *scheme; - gchar *hostname; - guint16 port; + GSocketConnectable *conn = NULL; + gchar *scheme = NULL; + gchar *hostname = NULL; + gint port; - if (!_g_uri_parse_authority (uri, &hostname, &port, NULL, error)) - return NULL; + if (!g_uri_split_network (uri, G_URI_FLAGS_NONE, + &scheme, &hostname, &port, NULL)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "Invalid URI ‘%s’", uri); + return NULL; + } - if (port == 0) + if (port <= 0) port = default_port; - scheme = g_uri_parse_scheme (uri); - conn = g_object_new (G_TYPE_NETWORK_ADDRESS, "hostname", hostname, - "port", port, + "port", (guint) port, "scheme", scheme, NULL); - g_free (scheme); g_free (hostname); @@ -895,7 +611,7 @@ g_network_address_get_port (GNetworkAddress *addr) * * Gets @addr's scheme * - * Returns: @addr's scheme (%NULL if not built from URI) + * Returns: (nullable): @addr's scheme (%NULL if not built from URI) * * Since: 2.26 */ @@ -1459,10 +1175,14 @@ g_network_address_connectable_proxy_enumerate (GSocketConnectable *connectable) GSocketAddressEnumerator *proxy_enum; gchar *uri; - uri = _g_uri_from_authority (self->priv->scheme ? self->priv->scheme : "none", - self->priv->hostname, - self->priv->port, - NULL); + uri = g_uri_join (G_URI_FLAGS_NONE, + self->priv->scheme ? self->priv->scheme : "none", + NULL, + self->priv->hostname, + self->priv->port, + "", + NULL, + NULL); proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, diff --git a/gio/gnetworking.c b/gio/gnetworking.c index fea4309dd601ba5b9b2a6864cb6db7fb91552303..7bc6d73c44d9aca21b4db4cfb224793232c0e087 100644 --- a/gio/gnetworking.c +++ b/gio/gnetworking.c @@ -22,13 +22,6 @@ #include "gnetworking.h" -#ifdef G_OS_WIN32 -/* For Windows XP run-time compatibility */ -#include "gwin32networking.h" - -GWin32WinsockFuncs ws2funcs = {0}; -#endif - /** * SECTION:gnetworking * @title: gnetworking.h @@ -68,45 +61,15 @@ void g_networking_init (void) { #ifdef G_OS_WIN32 - static volatile gsize inited = 0; + static gsize inited = 0; if (g_once_init_enter (&inited)) { WSADATA wsadata; - HMODULE ws2dll, iphlpapidll; if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0) g_error ("Windows Sockets could not be initialized"); - /* We want to use these functions if they are available, but - * still need to make sure the code still runs on Windows XP - */ - ws2dll = LoadLibraryW (L"ws2_32.dll"); - iphlpapidll = LoadLibraryW (L"iphlpapi.dll"); - - if (ws2dll != NULL) - { - ws2funcs.pInetNtop = - (PFN_InetNtop) GetProcAddress (ws2dll, "inet_ntop"); - ws2funcs.pInetPton = - (PFN_InetPton) GetProcAddress (ws2dll, "inet_pton"); - FreeLibrary (ws2dll); - } - else - { - ws2funcs.pInetNtop = NULL; - ws2funcs.pInetPton = NULL; - } - - if (iphlpapidll != NULL) - { - ws2funcs.pIfNameToIndex = - (PFN_IfNameToIndex) GetProcAddress (iphlpapidll, "if_nametoindex"); - FreeLibrary (iphlpapidll); - } - else - ws2funcs.pIfNameToIndex = NULL; - g_once_init_leave (&inited, 1); } #endif diff --git a/gio/gnetworking.h b/gio/gnetworking.h index aea296e718fb2d4a54dd802491ac57b6596984be..1f1124a4809b3a8be20df0efde4e27a9a29e764b 100644 --- a/gio/gnetworking.h +++ b/gio/gnetworking.h @@ -1,82 +1,78 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2008-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#ifndef __G_NETWORKING_H__ -#define __G_NETWORKING_H__ - -#include - -#ifdef G_OS_WIN32 - -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#include -#include -#include -#include - -#include -#undef interface - -#else /* !G_OS_WIN32 */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -#ifndef T_SRV -#define T_SRV 33 -#endif - -#ifndef _PATH_RESCONF -#define _PATH_RESCONF "/etc/resolv.conf" -#endif - -#ifndef CMSG_LEN -/* CMSG_LEN and CMSG_SPACE are defined by RFC 2292, but missing on - * some older platforms. - */ -#define CMSG_LEN(len) ((size_t)CMSG_DATA((struct cmsghdr *)NULL) + (len)) - -/* CMSG_SPACE must add at least as much padding as CMSG_NXTHDR() - * adds. We overestimate here. - */ -#define GLIB_ALIGN_TO_SIZEOF(len, obj) (((len) + sizeof (obj) - 1) & ~(sizeof (obj) - 1)) -#define CMSG_SPACE(len) GLIB_ALIGN_TO_SIZEOF (CMSG_LEN (len), struct cmsghdr) -#endif -#endif - -G_BEGIN_DECLS - -GLIB_AVAILABLE_IN_2_36 -void g_networking_init (void); - -G_END_DECLS - -#endif /* __G_NETWORKING_H__ */ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2008-2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef __G_NETWORKING_H__ +#define __G_NETWORKING_H__ + +#include + +#ifdef G_OS_WIN32 +#include +#include +#include +#include +#include +#include +#undef interface + +#else /* !G_OS_WIN32 */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#ifndef T_SRV +#define T_SRV 33 +#endif + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +#ifndef CMSG_LEN +/* CMSG_LEN and CMSG_SPACE are defined by RFC 2292, but missing on + * some older platforms. + */ +#define CMSG_LEN(len) ((size_t)CMSG_DATA((struct cmsghdr *)NULL) + (len)) + +/* CMSG_SPACE must add at least as much padding as CMSG_NXTHDR() + * adds. We overestimate here. + */ +#define GLIB_ALIGN_TO_SIZEOF(len, obj) (((len) + sizeof (obj) - 1) & ~(sizeof (obj) - 1)) +#define CMSG_SPACE(len) GLIB_ALIGN_TO_SIZEOF (CMSG_LEN (len), struct cmsghdr) +#endif +#endif + +G_BEGIN_DECLS + +GLIB_AVAILABLE_IN_2_36 +void g_networking_init (void); + +G_END_DECLS + +#endif /* __G_NETWORKING_H__ */ diff --git a/gio/gnetworking.h.in b/gio/gnetworking.h.in index f9582b99e67487a8268f4e535b565109bbd197bd..2fa95ff65d36e0b89f18fa9649b22a8176ef3ce2 100644 --- a/gio/gnetworking.h.in +++ b/gio/gnetworking.h.in @@ -22,15 +22,11 @@ #include #ifdef G_OS_WIN32 - -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif #include #include #include #include -@WSPIAPI_INCLUDE@ +#include #include #undef interface diff --git a/gio/gnetworkingprivate.h b/gio/gnetworkingprivate.h index ed0feb823a57f9f04ec3d1dfeab375a849653402..dd8a277a5bb07026bab5291e55042df83a7fbed8 100644 --- a/gio/gnetworkingprivate.h +++ b/gio/gnetworkingprivate.h @@ -23,16 +23,6 @@ G_BEGIN_DECLS -gboolean _g_uri_parse_authority (const char *uri, - char **host, - guint16 *port, - char **userinfo, - GError **error); -gchar * _g_uri_from_authority (const gchar *protocol, - const gchar *host, - guint port, - const gchar *userinfo); - guint64 g_resolver_get_serial (GResolver *resolver); gint g_socket (gint domain, diff --git a/gio/gnetworkmonitor.c b/gio/gnetworkmonitor.c index f9853fca59f4c3441dbbc39ccbbda5ad4afc3074..d32c60154b2a541b13358ea85cb4678ba8a49212 100644 --- a/gio/gnetworkmonitor.c +++ b/gio/gnetworkmonitor.c @@ -77,22 +77,33 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; +static GNetworkMonitor *network_monitor_default_singleton = NULL; /* (owned) (atomic) */ /** * g_network_monitor_get_default: * * Gets the default #GNetworkMonitor for the system. * - * Returns: (transfer none): a #GNetworkMonitor + * Returns: (not nullable) (transfer none): a #GNetworkMonitor, which will be + * a dummy object if no network monitor is available * * Since: 2.32 */ GNetworkMonitor * g_network_monitor_get_default (void) { - return _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME, - "GIO_USE_NETWORK_MONITOR", - NULL); + if (g_once_init_enter (&network_monitor_default_singleton)) + { + GNetworkMonitor *singleton; + + singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME, + "GIO_USE_NETWORK_MONITOR", + NULL); + + g_once_init_leave (&network_monitor_default_singleton, singleton); + } + + return network_monitor_default_singleton; } /** diff --git a/gio/gnetworkmonitorbase.c b/gio/gnetworkmonitorbase.c index 6ac37c490c548d8353c8f8ec31f6ed571b537f3b..d503759c14d7cb1287179cd646c8783f03731773 100644 --- a/gio/gnetworkmonitorbase.c +++ b/gio/gnetworkmonitorbase.c @@ -45,7 +45,7 @@ enum struct _GNetworkMonitorBasePrivate { - GPtrArray *networks; + GHashTable *networks /* (element-type GInetAddressMask) (owned) */; gboolean have_ipv4_default_route; gboolean have_ipv6_default_route; gboolean is_available; @@ -58,6 +58,9 @@ struct _GNetworkMonitorBasePrivate static guint network_changed_signal = 0; static void queue_network_changed (GNetworkMonitorBase *monitor); +static guint inet_address_mask_hash (gconstpointer key); +static gboolean inet_address_mask_equal (gconstpointer a, + gconstpointer b); G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorBase, g_network_monitor_base, G_TYPE_OBJECT, G_ADD_PRIVATE (GNetworkMonitorBase) @@ -75,7 +78,9 @@ static void g_network_monitor_base_init (GNetworkMonitorBase *monitor) { monitor->priv = g_network_monitor_base_get_instance_private (monitor); - monitor->priv->networks = g_ptr_array_new_with_free_func (g_object_unref); + monitor->priv->networks = g_hash_table_new_full (inet_address_mask_hash, + inet_address_mask_equal, + g_object_unref, NULL); monitor->priv->context = g_main_context_get_thread_default (); if (monitor->priv->context) g_main_context_ref (monitor->priv->context); @@ -149,7 +154,7 @@ g_network_monitor_base_finalize (GObject *object) { GNetworkMonitorBase *monitor = G_NETWORK_MONITOR_BASE (object); - g_ptr_array_free (monitor->priv->networks, TRUE); + g_hash_table_unref (monitor->priv->networks); if (monitor->priv->network_changed_source) { g_source_destroy (monitor->priv->network_changed_source); @@ -180,15 +185,18 @@ g_network_monitor_base_can_reach_sockaddr (GNetworkMonitorBase *base, GSocketAddress *sockaddr) { GInetAddress *iaddr; - int i; + GHashTableIter iter; + gpointer key; if (!G_IS_INET_SOCKET_ADDRESS (sockaddr)) return FALSE; iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (sockaddr)); - for (i = 0; i < base->priv->networks->len; i++) + g_hash_table_iter_init (&iter, base->priv->networks); + while (g_hash_table_iter_next (&iter, &key, NULL)) { - if (g_inet_address_mask_matches (base->priv->networks->pdata[i], iaddr)) + GInetAddressMask *mask = key; + if (g_inet_address_mask_matches (mask, iaddr)) return TRUE; } @@ -205,7 +213,7 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor, GSocketAddressEnumerator *enumerator; GSocketAddress *addr; - if (base->priv->networks->len == 0) + if (g_hash_table_size (base->priv->networks) == 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, _("Network unreachable")); @@ -309,7 +317,7 @@ g_network_monitor_base_can_reach_async (GNetworkMonitor *monitor, task = g_task_new (monitor, cancellable, callback, user_data); g_task_set_source_tag (task, g_network_monitor_base_can_reach_async); - if (G_NETWORK_MONITOR_BASE (monitor)->priv->networks->len == 0) + if (g_hash_table_size (G_NETWORK_MONITOR_BASE (monitor)->priv->networks) == 0) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, _("Network unreachable")); @@ -361,6 +369,60 @@ g_network_monitor_base_initable_iface_init (GInitableIface *iface) iface->init = g_network_monitor_base_initable_init; } +static guint +inet_address_mask_hash (gconstpointer key) +{ + GInetAddressMask *mask = G_INET_ADDRESS_MASK (key); + guint addr_hash; + guint mask_length = g_inet_address_mask_get_length (mask); + GInetAddress *addr = g_inet_address_mask_get_address (mask); + const guint8 *bytes = g_inet_address_to_bytes (addr); + gsize bytes_length = g_inet_address_get_native_size (addr); + + union + { + const guint8 *bytes; + guint32 *hash32; + guint64 *hash64; + } integerifier; + + /* If we can fit the entire address into the hash key, do it. Don’t worry + * about endianness; the address should always be in network endianness. */ + if (bytes_length == sizeof (guint32)) + { + integerifier.bytes = bytes; + addr_hash = *integerifier.hash32; + } + else if (bytes_length == sizeof (guint64)) + { + integerifier.bytes = bytes; + addr_hash = *integerifier.hash64; + } + else + { + gsize i; + + /* Otherwise, fall back to adding the bytes together. We do this, rather + * than XORing them, as routes often have repeated tuples which would + * cancel out under XOR. */ + addr_hash = 0; + for (i = 0; i < bytes_length; i++) + addr_hash += bytes[i]; + } + + return addr_hash + mask_length;; +} + +static gboolean +inet_address_mask_equal (gconstpointer a, + gconstpointer b) +{ + GInetAddressMask *mask_a = G_INET_ADDRESS_MASK (a); + GInetAddressMask *mask_b = G_INET_ADDRESS_MASK (b); + + return g_inet_address_mask_equal (mask_a, mask_b); +} + static gboolean emit_network_changed (gpointer user_data) { @@ -424,7 +486,7 @@ queue_network_changed (GNetworkMonitorBase *monitor) /** * g_network_monitor_base_add_network: * @monitor: the #GNetworkMonitorBase - * @network: a #GInetAddressMask + * @network: (transfer none): a #GInetAddressMask * * Adds @network to @monitor's list of available networks. * @@ -434,15 +496,9 @@ void g_network_monitor_base_add_network (GNetworkMonitorBase *monitor, GInetAddressMask *network) { - int i; - - for (i = 0; i < monitor->priv->networks->len; i++) - { - if (g_inet_address_mask_equal (monitor->priv->networks->pdata[i], network)) - return; - } + if (!g_hash_table_add (monitor->priv->networks, g_object_ref (network))) + return; - g_ptr_array_add (monitor->priv->networks, g_object_ref (network)); if (g_inet_address_mask_get_length (network) == 0) { switch (g_inet_address_mask_get_family (network)) @@ -481,33 +537,25 @@ void g_network_monitor_base_remove_network (GNetworkMonitorBase *monitor, GInetAddressMask *network) { - int i; + if (!g_hash_table_remove (monitor->priv->networks, network)) + return; - for (i = 0; i < monitor->priv->networks->len; i++) + if (g_inet_address_mask_get_length (network) == 0) { - if (g_inet_address_mask_equal (monitor->priv->networks->pdata[i], network)) + switch (g_inet_address_mask_get_family (network)) { - g_ptr_array_remove_index_fast (monitor->priv->networks, i); - - if (g_inet_address_mask_get_length (network) == 0) - { - switch (g_inet_address_mask_get_family (network)) - { - case G_SOCKET_FAMILY_IPV4: - monitor->priv->have_ipv4_default_route = FALSE; - break; - case G_SOCKET_FAMILY_IPV6: - monitor->priv->have_ipv6_default_route = FALSE; - break; - default: - break; - } - } - - queue_network_changed (monitor); - return; + case G_SOCKET_FAMILY_IPV4: + monitor->priv->have_ipv4_default_route = FALSE; + break; + case G_SOCKET_FAMILY_IPV6: + monitor->priv->have_ipv6_default_route = FALSE; + break; + default: + break; } } + + queue_network_changed (monitor); } /** @@ -526,7 +574,7 @@ g_network_monitor_base_set_networks (GNetworkMonitorBase *monitor, { int i; - g_ptr_array_set_size (monitor->priv->networks, 0); + g_hash_table_remove_all (monitor->priv->networks); monitor->priv->have_ipv4_default_route = FALSE; monitor->priv->have_ipv6_default_route = FALSE; diff --git a/gio/gnetworkmonitornetlink.c b/gio/gnetworkmonitornetlink.c index 20db551888ed64459991ff7089f27b887791b93e..53eab336499bbea1dd54ea31b856e40039d9b888 100644 --- a/gio/gnetworkmonitornetlink.c +++ b/gio/gnetworkmonitornetlink.c @@ -267,7 +267,7 @@ remove_network (GNetworkMonitorNetlink *nl, if (nl->priv->dump_networks) { GInetAddressMask **dump_networks = (GInetAddressMask **)nl->priv->dump_networks->pdata; - int i; + guint i; for (i = 0; i < nl->priv->dump_networks->len; i++) { diff --git a/gio/gnetworkservice.c b/gio/gnetworkservice.c index 40fe3ab0c397cca93945d2c470dca3e523251f80..2b8571e9bc4f8308ee8e060ca54cd30c6eae7754 100644 --- a/gio/gnetworkservice.c +++ b/gio/gnetworkservice.c @@ -318,7 +318,7 @@ g_network_service_get_domain (GNetworkService *srv) * g_network_service_get_scheme: * @srv: a #GNetworkService * - * Get's the URI scheme used to resolve proxies. By default, the service name + * Gets the URI scheme used to resolve proxies. By default, the service name * is used as scheme. * * Returns: @srv's scheme name @@ -465,10 +465,14 @@ g_network_service_address_enumerator_next (GSocketAddressEnumerator *enumerator continue; } - uri = _g_uri_from_authority (g_network_service_get_scheme (srv_enum->srv), - hostname, - g_srv_target_get_port (target), - NULL); + uri = g_uri_join (G_URI_FLAGS_NONE, + g_network_service_get_scheme (srv_enum->srv), + NULL, + hostname, + g_srv_target_get_port (target), + "", + NULL, + NULL); g_free (hostname); addr = g_network_address_parse_uri (uri, diff --git a/gio/gnetworkservice.h b/gio/gnetworkservice.h index 9cdb4ab47bc0f692cf8590815bb7b4f56a1cf75f..e4d76cb2a456b3de026268b7d2f9df49f1fb814b 100644 --- a/gio/gnetworkservice.h +++ b/gio/gnetworkservice.h @@ -73,4 +73,3 @@ void g_network_service_set_scheme (GNetworkService *srv, cons G_END_DECLS #endif /* __G_NETWORK_SERVICE_H__ */ - diff --git a/gio/gosxappinfo.h b/gio/gosxappinfo.h index 7beeaad161ceb5180e68461a6c404fa926cdb657..793ce1fcd1ec82e3416266a27e742e0b52dcdbfb 100644 --- a/gio/gosxappinfo.h +++ b/gio/gosxappinfo.h @@ -43,7 +43,7 @@ GLIB_AVAILABLE_IN_2_52 GType g_osx_app_info_get_type (void) G_GNUC_CONST; GLIB_AVAILABLE_IN_2_52 -char * g_osx_app_info_get_filename (GOsxAppInfo *info); +const char *g_osx_app_info_get_filename (GOsxAppInfo *info); GLIB_AVAILABLE_IN_2_52 GList * g_osx_app_info_get_all_for_scheme (const gchar *scheme); diff --git a/gio/gosxappinfo.m b/gio/gosxappinfo.m index 463b2da3c5978c9a3ac89b4b6a28344aba7e4ea5..03c37377881ef98ddc6597ba916d8ba8f18d8e4c 100644 --- a/gio/gosxappinfo.m +++ b/gio/gosxappinfo.m @@ -168,6 +168,7 @@ get_bundle_string_value (NSBundle *bundle, static CFStringRef create_cfstring_from_cstr (const gchar *cstr) { + g_return_val_if_fail (cstr != NULL, NULL); return CFStringCreateWithCString (NULL, cstr, kCFStringEncodingUTF8); } @@ -226,8 +227,8 @@ url_escape_hostname (const char *url) } static CFURLRef -create_url_from_cstr (gchar *cstr, - gboolean is_file) +create_url_from_cstr (const gchar *cstr, + gboolean is_file) { gchar *puny_cstr; CFStringRef str; @@ -279,11 +280,17 @@ create_urlspec_for_appinfo (GOsxAppInfo *info, GList *uris, gboolean are_files) { - LSLaunchURLSpec *urlspec = g_new0 (LSLaunchURLSpec, 1); - gchar *app_cstr = g_osx_app_info_get_filename (info); + LSLaunchURLSpec *urlspec = NULL; + const gchar *app_cstr; + + g_return_val_if_fail (G_IS_OSX_APP_INFO (info), NULL); + + urlspec = g_new0 (LSLaunchURLSpec, 1); + app_cstr = g_osx_app_info_get_filename (info); + g_assert (app_cstr != NULL); /* Strip file:// from app url but ensure filesystem url */ - urlspec->appURL = create_url_from_cstr (app_cstr + 7, TRUE); + urlspec->appURL = create_url_from_cstr (app_cstr + strlen ("file://"), TRUE); urlspec->launchFlags = kLSLaunchDefaults; urlspec->itemURLs = create_url_list_from_glist (uris, are_files); @@ -326,7 +333,7 @@ get_bundle_for_id (CFStringRef bundle_id) CFArrayRef urls = LSCopyApplicationURLsForBundleIdentifier (bundle_id, NULL); if (urls) { - /* TODO: if there's multiple, we should perhaps prefer one thats in $HOME, + /* TODO: if there's multiple, we should perhaps prefer one that's in $HOME, * instead of just always picking the first. */ app_url = CFArrayGetValueAtIndex (urls, 0); @@ -402,7 +409,7 @@ g_osx_app_info_get_executable (GAppInfo *appinfo) return info->executable; } -char * +const char * g_osx_app_info_get_filename (GOsxAppInfo *info) { g_return_val_if_fail (info != NULL, NULL); @@ -431,7 +438,8 @@ g_osx_app_info_get_icon (GAppInfo *appinfo) if (!info->icon) { - gchar *icon_name, *app_uri, *icon_uri; + const gchar *app_uri; + gchar *icon_name, *icon_uri; GFile *file; icon_name = get_bundle_string_value (info->bundle, @"CFBundleIconFile"); @@ -439,7 +447,7 @@ g_osx_app_info_get_icon (GAppInfo *appinfo) return NULL; app_uri = g_osx_app_info_get_filename (info); - icon_uri = g_strconcat (app_uri + 7, "/Contents/Resources/", icon_name, + icon_uri = g_strconcat (app_uri + strlen ("file://"), "/Contents/Resources/", icon_name, g_str_has_suffix (icon_name, ".icns") ? NULL : ".icns", NULL); g_free (icon_name); @@ -459,9 +467,14 @@ g_osx_app_info_launch_internal (GAppInfo *appinfo, GError **error) { GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); - LSLaunchURLSpec *urlspec = create_urlspec_for_appinfo (info, uris, are_files); + LSLaunchURLSpec *urlspec; gint ret, success = TRUE; + g_return_val_if_fail (G_IS_OSX_APP_INFO (appinfo), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + urlspec = create_urlspec_for_appinfo (info, uris, are_files); + if ((ret = LSOpenFromURLSpec (urlspec, NULL))) { /* TODO: Better error codes */ diff --git a/gio/goutputstream.c b/gio/goutputstream.c index 10f9aa732c2b3e39d020f4752a9aebe5f4f0db8a..8e48803be58b46e5a73c9f8e9d739463a8243d7b 100644 --- a/gio/goutputstream.c +++ b/gio/goutputstream.c @@ -2344,7 +2344,7 @@ g_output_stream_real_writev (GOutputStream *stream, _bytes_written += res; /* if we had a short write break the loop here */ - if (res < vectors[i].size) + if ((gsize) res < vectors[i].size) break; } @@ -2643,6 +2643,8 @@ g_output_stream_real_writev_finish (GOutputStream *stream, typedef struct { GInputStream *source; GOutputStreamSpliceFlags flags; + guint istream_closed : 1; + guint ostream_closed : 1; gssize n_read; gssize n_written; gsize bytes_copied; @@ -2665,11 +2667,11 @@ real_splice_async_complete_cb (GTask *task) SpliceData *op = g_task_get_task_data (task); if (op->flags & G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE && - !g_input_stream_is_closed (op->source)) + !op->istream_closed) return; if (op->flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET && - !g_output_stream_is_closed (g_task_get_source_object (task))) + !op->ostream_closed) return; if (op->error != NULL) @@ -2691,8 +2693,10 @@ real_splice_async_close_input_cb (GObject *source, gpointer user_data) { GTask *task = user_data; + SpliceData *op = g_task_get_task_data (task); g_input_stream_close_finish (G_INPUT_STREAM (source), res, NULL); + op->istream_closed = TRUE; real_splice_async_complete_cb (task); } @@ -2707,6 +2711,7 @@ real_splice_async_close_output_cb (GObject *source, GError **error = (op->error == NULL) ? &op->error : NULL; g_output_stream_internal_close_finish (G_OUTPUT_STREAM (source), res, error); + op->ostream_closed = TRUE; real_splice_async_complete_cb (task); } @@ -2953,7 +2958,7 @@ close_async_thread (GTask *task, result = class->flush (stream, cancellable, &error); } - /* Auto handling of cancelation disabled, and ignore + /* Auto handling of cancellation disabled, and ignore cancellation, since we want to close things anyway, although possibly in a quick-n-dirty way. At least we never want to leak open handles */ diff --git a/gio/gpollableinputstream.h b/gio/gpollableinputstream.h index ce50312e7b9cd7ae7b40a9c2b6a13f3cd3e9655d..823c83c24d30391cfbdb3c15fb9ac0996967e730 100644 --- a/gio/gpollableinputstream.h +++ b/gio/gpollableinputstream.h @@ -102,4 +102,3 @@ G_END_DECLS #endif /* __G_POLLABLE_INPUT_STREAM_H__ */ - diff --git a/gio/gpollableoutputstream.c b/gio/gpollableoutputstream.c index c17cf9268ed36a4122a9d71140a1bf3ac6c4fab5..2d36144238487557635b5f80b8066680ac20ebe3 100644 --- a/gio/gpollableoutputstream.c +++ b/gio/gpollableoutputstream.c @@ -214,7 +214,7 @@ g_pollable_output_stream_default_writev_nonblocking (GPollableOutputStream *str _bytes_written += res; /* if we had a short write break the loop here */ - if (res < vectors[i].size) + if ((gsize) res < vectors[i].size) break; } diff --git a/gio/gpollableoutputstream.h b/gio/gpollableoutputstream.h index c282afdec4355f1f6cdb3daaae18336756584403..e27841ed42fbbd05b15c4dea68019eec703279df 100644 --- a/gio/gpollableoutputstream.h +++ b/gio/gpollableoutputstream.h @@ -123,4 +123,3 @@ G_END_DECLS #endif /* __G_POLLABLE_OUTPUT_STREAM_H__ */ - diff --git a/gio/gpollableutils.c b/gio/gpollableutils.c index b77e65404ce389863c6cea6b499883b4591141f8..77bf82174e09fc12ed8c028cfe34a013b845514a 100644 --- a/gio/gpollableutils.c +++ b/gio/gpollableutils.c @@ -89,6 +89,7 @@ static GSourceFuncs pollable_source_funcs = pollable_source_dispatch, pollable_source_finalize, (GSourceFunc)pollable_source_closure_callback, + NULL, }; /** diff --git a/gio/gportalsupport.c b/gio/gportalsupport.c index b0a94b360ad4aa3a87336973adcb131e16578249..233f6af459173b53ea91a176df48e507b209899e 100644 --- a/gio/gportalsupport.c +++ b/gio/gportalsupport.c @@ -20,7 +20,6 @@ #include "gportalsupport.h" -static gboolean flatpak_info_read; static gboolean use_portal; static gboolean network_available; static gboolean dconf_access; @@ -28,13 +27,12 @@ static gboolean dconf_access; static void read_flatpak_info (void) { + static gsize flatpak_info_read = 0; const gchar *path = "/.flatpak-info"; - if (flatpak_info_read) + if (!g_once_init_enter (&flatpak_info_read)) return; - flatpak_info_read = TRUE; - if (g_file_test (path, G_FILE_TEST_EXISTS)) { GKeyFile *keyfile; @@ -77,6 +75,8 @@ read_flatpak_info (void) network_available = TRUE; dconf_access = TRUE; } + + g_once_init_leave (&flatpak_info_read, 1); } gboolean diff --git a/gio/gproxy.c b/gio/gproxy.c index 60bb5b8e5c0761b801c03c78ca5f3b5ccf1eccbb..4c80a4746cd39d066cd5b61d54fb46f772972b16 100644 --- a/gio/gproxy.c +++ b/gio/gproxy.c @@ -55,7 +55,7 @@ g_proxy_default_init (GProxyInterface *iface) * Find the `gio-proxy` extension point for a proxy implementation that supports * the specified protocol. * - * Returns: (transfer full): return a #GProxy or NULL if protocol + * Returns: (nullable) (transfer full): return a #GProxy or NULL if protocol * is not supported. * * Since: 2.26 diff --git a/gio/gproxyaddress.c b/gio/gproxyaddress.c index 0b78caa912daa4703905c88e799f963be54499ff..a9405eb48f1550f3bfa33530b4b23d5be4a82b4d 100644 --- a/gio/gproxyaddress.c +++ b/gio/gproxyaddress.c @@ -233,7 +233,7 @@ g_proxy_address_class_init (GProxyAddressClass *klass) g_object_class_install_property (gobject_class, PROP_DESTINATION_PROTOCOL, g_param_spec_string ("destination-protocol", - P_("Destionation Protocol"), + P_("Destination Protocol"), P_("The proxy destination protocol"), NULL, G_PARAM_READWRITE | @@ -409,7 +409,7 @@ g_proxy_address_get_destination_port (GProxyAddress *proxy) * * Gets @proxy's username. * - * Returns: the @proxy's username + * Returns: (nullable): the @proxy's username * * Since: 2.26 */ @@ -425,7 +425,7 @@ g_proxy_address_get_username (GProxyAddress *proxy) * * Gets @proxy's password. * - * Returns: the @proxy's password + * Returns: (nullable): the @proxy's password * * Since: 2.26 */ @@ -442,7 +442,7 @@ g_proxy_address_get_password (GProxyAddress *proxy) * * Gets the proxy URI that @proxy was constructed from. * - * Returns: the @proxy's URI, or %NULL if unknown + * Returns: (nullable): the @proxy's URI, or %NULL if unknown * * Since: 2.34 */ diff --git a/gio/gproxyaddressenumerator.c b/gio/gproxyaddressenumerator.c index ecf04d11070ce4b6189e112ebb43500e718e59f9..d3de4940c9f182e7144f9d1881e410899a3afafa 100644 --- a/gio/gproxyaddressenumerator.c +++ b/gio/gproxyaddressenumerator.c @@ -93,39 +93,14 @@ G_DEFINE_TYPE_WITH_PRIVATE (GProxyAddressEnumerator, g_proxy_address_enumerator, static void save_userinfo (GProxyAddressEnumeratorPrivate *priv, - const gchar *proxy) + const gchar *proxy) { - gchar *userinfo; + g_clear_pointer (&priv->proxy_username, g_free); + g_clear_pointer (&priv->proxy_password, g_free); - if (priv->proxy_username) - { - g_free (priv->proxy_username); - priv->proxy_username = NULL; - } - - if (priv->proxy_password) - { - g_free (priv->proxy_password); - priv->proxy_password = NULL; - } - - if (_g_uri_parse_authority (proxy, NULL, NULL, &userinfo, NULL)) - { - if (userinfo) - { - gchar **split = g_strsplit (userinfo, ":", 2); - - if (split[0] != NULL) - { - priv->proxy_username = g_uri_unescape_string (split[0], NULL); - if (split[1] != NULL) - priv->proxy_password = g_uri_unescape_string (split[1], NULL); - } - - g_strfreev (split); - g_free (userinfo); - } - } + g_uri_split_with_user (proxy, G_URI_FLAGS_HAS_PASSWORD, NULL, + &priv->proxy_username, &priv->proxy_password, + NULL, NULL, NULL, NULL, NULL, NULL, NULL); } static void diff --git a/gio/gproxyresolver.c b/gio/gproxyresolver.c index bd9528dd0e1462e2daa7331129e94bec72837147..0df51eb6025a4e9b2616b845d079d76de1df274b 100644 --- a/gio/gproxyresolver.c +++ b/gio/gproxyresolver.c @@ -29,6 +29,7 @@ #include "gcancellable.h" #include "gtask.h" #include "giomodule.h" +#include "gioerror.h" #include "giomodule-priv.h" #include "gnetworkingprivate.h" @@ -66,21 +67,33 @@ g_proxy_resolver_default_init (GProxyResolverInterface *iface) { } +static GProxyResolver *proxy_resolver_default_singleton = NULL; /* (owned) (atomic) */ + /** * g_proxy_resolver_get_default: * * Gets the default #GProxyResolver for the system. * - * Returns: (transfer none): the default #GProxyResolver. + * Returns: (not nullable) (transfer none): the default #GProxyResolver, which + * will be a dummy object if no proxy resolver is available * * Since: 2.26 */ GProxyResolver * g_proxy_resolver_get_default (void) { - return _g_io_module_get_default (G_PROXY_RESOLVER_EXTENSION_POINT_NAME, - "GIO_USE_PROXY_RESOLVER", - (GIOModuleVerifyFunc)g_proxy_resolver_is_supported); + if (g_once_init_enter (&proxy_resolver_default_singleton)) + { + GProxyResolver *singleton; + + singleton = _g_io_module_get_default (G_PROXY_RESOLVER_EXTENSION_POINT_NAME, + "GIO_USE_PROXY_RESOLVER", + (GIOModuleVerifyFunc) g_proxy_resolver_is_supported); + + g_once_init_leave (&proxy_resolver_default_singleton, singleton); + } + + return proxy_resolver_default_singleton; } /** @@ -147,8 +160,12 @@ g_proxy_resolver_lookup (GProxyResolver *resolver, g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL); g_return_val_if_fail (uri != NULL, NULL); - if (!_g_uri_parse_authority (uri, NULL, NULL, NULL, error)) - return NULL; + if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "Invalid URI ‘%s’", uri); + return NULL; + } iface = G_PROXY_RESOLVER_GET_IFACE (resolver); @@ -181,8 +198,10 @@ g_proxy_resolver_lookup_async (GProxyResolver *resolver, g_return_if_fail (G_IS_PROXY_RESOLVER (resolver)); g_return_if_fail (uri != NULL); - if (!_g_uri_parse_authority (uri, NULL, NULL, NULL, &error)) + if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL)) { + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "Invalid URI ‘%s’", uri); g_task_report_error (resolver, callback, user_data, g_proxy_resolver_lookup_async, g_steal_pointer (&error)); diff --git a/gio/gproxyresolverportal.h b/gio/gproxyresolverportal.h index e1eabdb941a0a01a068442f61d60c271eccb7668..ae00599663018443c668e1fcd20041553ea6f125 100644 --- a/gio/gproxyresolverportal.h +++ b/gio/gproxyresolverportal.h @@ -44,4 +44,3 @@ GType g_proxy_resolver_portal_get_type (void); G_END_DECLS #endif /* __G_PROXY_RESOLVER_PORTAL_H__ */ - diff --git a/gio/gregistrysettingsbackend.c b/gio/gregistrysettingsbackend.c index 26de2518cdb884324b5515354bdcd009afb7123f..bae066a0aa42bb909cc8993a2d44657d8b73d0e5 100644 --- a/gio/gregistrysettingsbackend.c +++ b/gio/gregistrysettingsbackend.c @@ -98,7 +98,7 @@ //#define TRACE /* GSettings' limit */ -#define MAX_KEY_NAME_LENGTH 32 +#define MAX_KEY_NAME_LENGTH 128 /* Testing (on Windows XP SP3) shows that WaitForMultipleObjects fails with * "The parameter is incorrect" after 64 watches. We need one for the @@ -201,7 +201,7 @@ trace (const char *format, * equivalent function for g_warning because none of the registry errors can * result from programmer error (Microsoft programmers don't count), instead * they will mostly occur from people messing with the registry by hand. */ -static void +static void G_GNUC_PRINTF (2, 3) g_message_win32_error (DWORD result_code, const gchar *format, ...) @@ -312,7 +312,7 @@ handle_read_error (LONG result, { /* file not found means key value not set, this isn't an error for us. */ if (result != ERROR_FILE_NOT_FOUND) - g_message_win32_error (result, "Unable to query value %s/%s: %s.\n", + g_message_win32_error (result, "Unable to query value %s/%s", path_name, value_name); } @@ -745,7 +745,7 @@ registry_cache_update_node (GNode *cache_node, } /* Blocking notifications is a useful optimisation. When a change is made - * through GSettings we update the cache manually, but a notifcation is + * through GSettings we update the cache manually, but a notification is * triggered as well. This function is also used for nested notifications, * eg. if /test and /test/foo are watched, and /test/foo/value is changed then * we will get notified both for /test/foo and /test and it is helpful to block diff --git a/gio/gresolver.c b/gio/gresolver.c index 732d2170935df99772ed1e3f472f35f82b61cefd..cd5445a65f1970a1ef1c0ed2bbf51994911801b6 100644 --- a/gio/gresolver.c +++ b/gio/gresolver.c @@ -296,15 +296,50 @@ remove_duplicates (GList *addrs) } } +static gboolean +hostname_is_localhost (const char *hostname) +{ + size_t len = strlen (hostname); + const char *p; + + /* Match "localhost", "localhost.", "*.localhost" and "*.localhost." */ + if (len < strlen ("localhost")) + return FALSE; + + if (hostname[len - 1] == '.') + len--; + + /* Scan backwards in @hostname to find the right-most dot (excluding the final dot, if it exists, as it was chopped off above). + * We can’t use strrchr() because because we need to operate with string lengths. + * End with @p pointing to the character after the right-most dot. */ + p = hostname + len - 1; + while (p >= hostname) + { + if (*p == '.') + { + p++; + break; + } + else if (p == hostname) + break; + p--; + } + + len -= p - hostname; + + return g_ascii_strncasecmp (p, "localhost", MAX (len, strlen ("localhost"))) == 0; +} + /* Note that this does not follow the "FALSE means @error is set" * convention. The return value tells the caller whether it should * return @addrs and @error to the caller right away, or if it should * continue and trying to resolve the name as a hostname. */ static gboolean -handle_ip_address (const char *hostname, - GList **addrs, - GError **error) +handle_ip_address_or_localhost (const char *hostname, + GList **addrs, + GResolverNameLookupFlags flags, + GError **error) { GInetAddress *addr; @@ -355,6 +390,28 @@ handle_ip_address (const char *hostname, return TRUE; } + /* Always resolve localhost to a loopback address so it can be reliably considered secure. + This behavior is being adopted by browsers: + - https://w3c.github.io/webappsec-secure-contexts/ + - https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/RC9dSw-O3fE/E3_0XaT0BAAJ + - https://chromium.googlesource.com/chromium/src.git/+/8da2a80724a9b896890602ff77ef2216cb951399 + - https://bugs.webkit.org/show_bug.cgi?id=171934 + - https://tools.ietf.org/html/draft-west-let-localhost-be-localhost-06 + */ + if (hostname_is_localhost (hostname)) + { + if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY) + *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6)); + if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY) + *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4)); + if (*addrs == NULL) + { + *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6)); + *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4)); + } + return TRUE; + } + return FALSE; } @@ -374,7 +431,7 @@ lookup_by_name_real (GResolver *resolver, g_return_val_if_fail (error == NULL || *error == NULL, NULL); /* Check if @hostname is just an IP address */ - if (handle_ip_address (hostname, &addrs, error)) + if (handle_ip_address_or_localhost (hostname, &addrs, flags, error)) return addrs; if (g_hostname_is_non_ascii (hostname)) @@ -513,12 +570,13 @@ lookup_by_name_async_real (GResolver *resolver, g_return_if_fail (!(flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY && flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY)); /* Check if @hostname is just an IP address */ - if (handle_ip_address (hostname, &addrs, &error)) + if (handle_ip_address_or_localhost (hostname, &addrs, flags, &error)) { GTask *task; task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_async_real); + g_task_set_name (task, "[gio] resolver lookup"); if (addrs) g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses); else @@ -538,6 +596,7 @@ lookup_by_name_async_real (GResolver *resolver, _("Invalid hostname")); task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_async_real); + g_task_set_name (task, "[gio] resolver lookup"); g_task_return_error (task, error); g_object_unref (task); return; @@ -556,6 +615,7 @@ lookup_by_name_async_real (GResolver *resolver, _("%s not implemented"), "lookup_by_name_with_flags_async"); task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_async_real); + g_task_set_name (task, "[gio] resolver lookup"); g_task_return_error (task, error); g_object_unref (task); } diff --git a/gio/gresource.c b/gio/gresource.c index cdcb1ac3f30e64c0ea0a0f96c80492ad272e0179..53933f9d23fc7b0900a7dc63be7894e9e1d11ad1 100644 --- a/gio/gresource.c +++ b/gio/gresource.c @@ -32,6 +32,8 @@ #include #include +#include "glib-private.h" + struct _GResource { int ref_count; @@ -76,12 +78,23 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref) * the xmllint executable, or xmllint must be in the `PATH`; otherwise * the preprocessing step is skipped. * - * `to-pixdata` which will use the gdk-pixbuf-pixdata command to convert - * images to the GdkPixdata format, which allows you to create pixbufs directly using the data inside - * the resource file, rather than an (uncompressed) copy of it. For this, the gdk-pixbuf-pixdata - * program must be in the PATH, or the `GDK_PIXBUF_PIXDATA` environment variable must be - * set to the full path to the gdk-pixbuf-pixdata executable; otherwise the resource compiler will - * abort. + * `to-pixdata` (deprecated since gdk-pixbuf 2.32) which will use the + * `gdk-pixbuf-pixdata` command to convert images to the #GdkPixdata format, + * which allows you to create pixbufs directly using the data inside the + * resource file, rather than an (uncompressed) copy of it. For this, the + * `gdk-pixbuf-pixdata` program must be in the `PATH`, or the + * `GDK_PIXBUF_PIXDATA` environment variable must be set to the full path to the + * `gdk-pixbuf-pixdata` executable; otherwise the resource compiler will abort. + * `to-pixdata` has been deprecated since gdk-pixbuf 2.32, as #GResource + * supports embedding modern image formats just as well. Instead of using it, + * embed a PNG or SVG file in your #GResource. + * + * `json-stripblanks` which will use the `json-glib-format` command to strip + * ignorable whitespace from the JSON file. For this to work, the + * `JSON_GLIB_FORMAT` environment variable must be set to the full path to the + * `json-glib-format` executable, or it must be in the `PATH`; + * otherwise the preprocessing step is skipped. In addition, at least version + * 1.6 of `json-glib-format` is required. * * Resource files will be exported in the GResource namespace using the * combination of the given `prefix` and the filename from the `file` element. @@ -152,7 +165,7 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref) * replace resources in the program or library, without recompiling, for debugging or quick hacking and testing * purposes. Since GLib 2.50, it is possible to use the `G_RESOURCE_OVERLAYS` environment variable to selectively overlay * resources with replacements from the filesystem. It is a %G_SEARCHPATH_SEPARATOR-separated list of substitutions to perform - * during resource lookups. + * during resource lookups. It is ignored when running in a setuid process. * * A substitution has the form * @@ -323,10 +336,13 @@ g_resource_find_overlay (const gchar *path, if (g_once_init_enter (&overlay_dirs)) { + gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) (); const gchar * const *result; const gchar *envvar; - envvar = g_getenv ("G_RESOURCE_OVERLAYS"); + /* Don’t load overlays if setuid, as they could allow reading privileged + * files. */ + envvar = !is_setuid ? g_getenv ("G_RESOURCE_OVERLAYS") : NULL; if (envvar != NULL) { gchar **parts; @@ -793,7 +809,9 @@ g_resource_lookup_data (GResource *resource, if (!do_lookup (resource, path, lookup_flags, &size, &flags, &data, &data_size, error)) return NULL; - if (flags & G_RESOURCE_FLAGS_COMPRESSED) + if (size == 0) + return g_bytes_new_with_free_func ("", 0, (GDestroyNotify) g_resource_unref, g_resource_ref (resource)); + else if (flags & G_RESOURCE_FLAGS_COMPRESSED) { char *uncompressed, *d; const char *s; @@ -920,9 +938,10 @@ g_resource_enumerate_children (GResource *resource, if (*path == 0) { - g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND, - _("The resource at “%s” does not exist"), - path); + if (error) + g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND, + _("The resource at “%s” does not exist"), + path); return NULL; } @@ -959,9 +978,10 @@ g_resource_enumerate_children (GResource *resource, if (children == NULL) { - g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND, - _("The resource at “%s” does not exist"), - path); + if (error) + g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND, + _("The resource at “%s” does not exist"), + path); return NULL; } @@ -1228,9 +1248,10 @@ g_resources_enumerate_children (const gchar *path, if (hash == NULL) { - g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND, - _("The resource at “%s” does not exist"), - path); + if (error) + g_set_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND, + _("The resource at “%s” does not exist"), + path); return NULL; } else @@ -1389,7 +1410,7 @@ register_lazy_static_resources (void) void g_static_resource_init (GStaticResource *static_resource) { - gpointer next; + GStaticResource *next; do { diff --git a/gio/gseekable.c b/gio/gseekable.c index 6886683ebf821d54679c5d19a4486aa7dc0be9b8..28e815703bb5f9004857d8d1a2b7a94cab7b9604 100644 --- a/gio/gseekable.c +++ b/gio/gseekable.c @@ -168,7 +168,7 @@ g_seekable_can_truncate (GSeekable *seekable) * * Sets the length of the stream to @offset. If the stream was previously * larger than @offset, the extra data is discarded. If the stream was - * previouly shorter than @offset, it is extended with NUL ('\0') bytes. + * previously shorter than @offset, it is extended with NUL ('\0') bytes. * * If @cancellable is not %NULL, then the operation can be cancelled by * triggering the cancellable object from another thread. If the operation diff --git a/gio/gsettings-mapping.c b/gio/gsettings-mapping.c index 8c64b02a50a750040763989aba9c954fe819f553..4db9724fe3e3fca784349f4b48e006167d3653aa 100644 --- a/gio/gsettings-mapping.c +++ b/gio/gsettings-mapping.c @@ -62,7 +62,7 @@ g_settings_set_mapping_int (const GValue *value, } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64)) { - if (0 <= l && l <= G_MAXUINT64) + if (0 <= l && (guint64) l <= G_MAXUINT64) variant = g_variant_new_uint64 ((guint64) l); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE)) @@ -117,7 +117,7 @@ g_settings_set_mapping_float (const GValue *value, } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64)) { - if (0 <= l && l <= G_MAXUINT64) + if (0 <= l && (guint64) l <= G_MAXUINT64) variant = g_variant_new_uint64 ((guint64) l); } else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE)) @@ -221,7 +221,7 @@ g_settings_get_mapping_int (GValue *value, else if (G_VALUE_HOLDS_UINT64 (value)) { g_value_set_uint64 (value, l); - return (0 <= l && l <= G_MAXUINT64); + return (0 <= l && (guint64) l <= G_MAXUINT64); } else if (G_VALUE_HOLDS_DOUBLE (value)) { @@ -266,7 +266,7 @@ g_settings_get_mapping_float (GValue *value, else if (G_VALUE_HOLDS_UINT64 (value)) { g_value_set_uint64 (value, l); - return (0 <= l && l <= G_MAXUINT64); + return (0 <= l && (guint64) l <= G_MAXUINT64); } else if (G_VALUE_HOLDS_DOUBLE (value)) { diff --git a/gio/gsettings.c b/gio/gsettings.c index 1e46d5ae53bb5503d3ae27812e75bca3f2356cf0..9a04a863099c5520ab5849a9f87541493f1c69de 100644 --- a/gio/gsettings.c +++ b/gio/gsettings.c @@ -961,6 +961,12 @@ g_settings_class_init (GSettingsClass *class) * Creates a new #GSettings object with the schema specified by * @schema_id. * + * It is an error for the schema to not exist: schemas are an + * essential part of a program, as they provide type information. + * If schemas need to be dynamically loaded (for example, from an + * optional runtime dependency), g_settings_schema_source_lookup() + * can be used to test for their existence before loading them. + * * Signals on the newly created #GSettings object will be dispatched * via the thread-default #GMainContext in effect at the time of the * call to g_settings_new(). The new #GSettings will hold a reference @@ -2469,7 +2475,7 @@ g_settings_get_child (GSettings *settings, * * Returns: (transfer full) (element-type utf8): a list of the keys on * @settings, in no defined order - * Deprecated: 2.46: Use g_settings_schema_list_keys instead(). + * Deprecated: 2.46: Use g_settings_schema_list_keys() instead. */ gchar ** g_settings_list_keys (GSettings *settings) @@ -3290,7 +3296,7 @@ g_settings_action_get_property (GObject *object, guint prop_id, break; case ACTION_PROP_STATE: - g_value_set_variant (value, g_settings_action_get_state (action)); + g_value_take_variant (value, g_settings_action_get_state (action)); break; default: diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c index f53a0239288392c622556b9c8724d66d712c26a7..b124bc7ec244ec3c8b58bb81b06596566586172b 100644 --- a/gio/gsettingsbackend.c +++ b/gio/gsettingsbackend.c @@ -992,6 +992,12 @@ g_settings_backend_verify (gpointer impl) return TRUE; } +/* We need to cache the default #GSettingsBackend for the entire process + * lifetime, especially if the backend is #GMemorySettingsBackend: it needs to + * keep the in-memory settings around even while there are no #GSettings + * instances alive. */ +static GSettingsBackend *settings_backend_default_singleton = NULL; /* (owned) (atomic) */ + /** * g_settings_backend_get_default: * @@ -1001,19 +1007,27 @@ g_settings_backend_verify (gpointer impl) * * The user gets a reference to the backend. * - * Returns: (transfer full): the default #GSettingsBackend + * Returns: (not nullable) (transfer full): the default #GSettingsBackend, + * which will be a dummy (memory) settings backend if no other settings + * backend is available. * * Since: 2.28 */ GSettingsBackend * g_settings_backend_get_default (void) { - GSettingsBackend *backend; + if (g_once_init_enter (&settings_backend_default_singleton)) + { + GSettingsBackend *singleton; + + singleton = _g_io_module_get_default (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, + "GSETTINGS_BACKEND", + g_settings_backend_verify); + + g_once_init_leave (&settings_backend_default_singleton, singleton); + } - backend = _g_io_module_get_default (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, - "GSETTINGS_BACKEND", - g_settings_backend_verify); - return g_object_ref (backend); + return g_object_ref (settings_backend_default_singleton); } /*< private > diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c index 4b71a6602f20aae142cbe88999fa76b1a15aa10b..a46d5056f0c07e2b44abd2b39cc6d12cf02de9da 100644 --- a/gio/gsettingsschema.c +++ b/gio/gsettingsschema.c @@ -18,6 +18,7 @@ #include "config.h" +#include "glib-private.h" #include "gsettingsschema-internal.h" #include "gsettings.h" @@ -343,8 +344,10 @@ initialise_schema_sources (void) */ if G_UNLIKELY (g_once_init_enter (&initialised)) { + gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) (); const gchar * const *dirs; const gchar *path; + gchar **extra_schema_dirs; gint i; /* iterate in reverse: count up, then count down */ @@ -356,8 +359,18 @@ initialise_schema_sources (void) try_prepend_data_dir (g_get_user_data_dir ()); - if ((path = g_getenv ("GSETTINGS_SCHEMA_DIR")) != NULL) - try_prepend_dir (path); + /* Disallow loading extra schemas if running as setuid, as that could + * allow reading privileged files. */ + if (!is_setuid && (path = g_getenv ("GSETTINGS_SCHEMA_DIR")) != NULL) + { + extra_schema_dirs = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; extra_schema_dirs[i]; i++); + + while (i--) + try_prepend_dir (extra_schema_dirs[i]); + + g_strfreev (extra_schema_dirs); + } g_once_init_leave (&initialised, TRUE); } @@ -670,8 +683,8 @@ parse_into_text_tables (const gchar *directory, GHashTable *summaries, GHashTable *descriptions) { - GMarkupParser parser = { start_element, end_element, text }; - TextTableParseInfo info = { summaries, descriptions }; + GMarkupParser parser = { start_element, end_element, text, NULL, NULL }; + TextTableParseInfo info = { summaries, descriptions, NULL, NULL, NULL, NULL }; const gchar *basename; GDir *dir; @@ -989,10 +1002,10 @@ g_settings_schema_get_value (GSettingsSchema *schema, * database: those located at the path returned by this function. * * Relocatable schemas can be referenced by other schemas and can - * threfore describe multiple sets of keys at different locations. For + * therefore describe multiple sets of keys at different locations. For * relocatable schemas, this function will return %NULL. * - * Returns: (transfer none): the path of the schema, or %NULL + * Returns: (nullable) (transfer none): the path of the schema, or %NULL * * Since: 2.32 **/ @@ -1651,7 +1664,7 @@ g_settings_schema_key_get_name (GSettingsSchemaKey *key) * function has to parse all of the source XML files in the schema * directory. * - * Returns: the summary for @key, or %NULL + * Returns: (nullable): the summary for @key, or %NULL * * Since: 2.34 **/ @@ -1686,7 +1699,7 @@ g_settings_schema_key_get_summary (GSettingsSchemaKey *key) * function has to parse all of the source XML files in the schema * directory. * - * Returns: the description for @key, or %NULL + * Returns: (nullable): the description for @key, or %NULL * * Since: 2.34 **/ diff --git a/gio/gsimpleproxyresolver.c b/gio/gsimpleproxyresolver.c index f33d49f8c64d18d4fcc4b5171906850f95996d26..2d600997527dbe799652c9d2fcb12f43254ebee6 100644 --- a/gio/gsimpleproxyresolver.c +++ b/gio/gsimpleproxyresolver.c @@ -50,7 +50,7 @@ typedef struct { gchar *name; - gint length; + gsize length; gushort port; } GSimpleProxyResolverDomain; @@ -259,7 +259,8 @@ ignore_host (GSimpleProxyResolver *resolver, GSimpleProxyResolverPrivate *priv = resolver->priv; gchar *ascii_host = NULL; gboolean ignore = FALSE; - gint i, length, offset; + gsize offset, length; + guint i; if (priv->ignore_ips) { @@ -297,6 +298,9 @@ ignore_host (GSimpleProxyResolver *resolver, { GSimpleProxyResolverDomain *domain = &priv->ignore_domains[i]; + if (domain->length > length) + continue; + offset = length - domain->length; if ((domain->port == 0 || domain->port == port) && (offset == 0 || (offset > 0 && host[offset - 1] == '.')) && @@ -327,10 +331,11 @@ g_simple_proxy_resolver_lookup (GProxyResolver *proxy_resolver, if (priv->ignore_ips || priv->ignore_domains) { gchar *host = NULL; - gushort port; + gint port; - if (_g_uri_parse_authority (uri, &host, &port, NULL, NULL) && - ignore_host (resolver, host, port)) + if (g_uri_split_network (uri, G_URI_FLAGS_NONE, NULL, + &host, &port, NULL) && + ignore_host (resolver, host, port > 0 ? port : 0)) proxy = "direct://"; g_free (host); diff --git a/gio/gsocket.c b/gio/gsocket.c index f323ef9750f0a49b0087f7cdcd988b629e72c733..f39a568b303f45b78d008c0727632571da98b8c4 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -76,11 +76,6 @@ #include "glibintl.h" #include "gioprivate.h" -#ifdef G_OS_WIN32 -/* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */ -#include "gwin32networking.h" -#endif - /** * SECTION:gsocket * @short_description: Low-level socket object @@ -364,6 +359,50 @@ _win32_unset_event_mask (GSocket *socket, int mask) recv (sockfd, (gpointer)buf, len, flags) #endif +static gchar * +address_to_string (GSocketAddress *address) +{ + GString *ret = g_string_new (""); + + if (G_IS_INET_SOCKET_ADDRESS (address)) + { + GInetSocketAddress *isa = G_INET_SOCKET_ADDRESS (address); + GInetAddress *ia = g_inet_socket_address_get_address (isa); + GSocketFamily family = g_inet_address_get_family (ia); + gchar *tmp; + + /* Represent IPv6 addresses in URL style: + * ::1 port 12345 -> [::1]:12345 */ + if (family == G_SOCKET_FAMILY_IPV6) + g_string_append_c (ret, '['); + + tmp = g_inet_address_to_string (ia); + g_string_append (ret, tmp); + g_free (tmp); + + if (family == G_SOCKET_FAMILY_IPV6) + { + guint32 scope = g_inet_socket_address_get_scope_id (isa); + + if (scope != 0) + g_string_append_printf (ret, "%%%u", scope); + + g_string_append_c (ret, ']'); + } + + g_string_append_c (ret, ':'); + + g_string_append_printf (ret, "%u", g_inet_socket_address_get_port (isa)); + } + else + { + /* For unknown address types, just show the type */ + g_string_append_printf (ret, "(%s)", G_OBJECT_TYPE_NAME (address)); + } + + return g_string_free (ret, FALSE); +} + static gboolean check_socket (GSocket *socket, GError **error) @@ -585,6 +624,16 @@ g_socket (gint domain, fcntl (fd, F_SETFD, flags); } } +#else + if ((domain == AF_INET || domain == AF_INET6) && type == SOCK_DGRAM) + { + BOOL new_behavior = FALSE; + DWORD bytes_returned = 0; + + /* Disable connection reset error on ICMP port unreachable. */ + WSAIoctl (fd, SIO_UDP_CONNRESET, &new_behavior, sizeof (new_behavior), + NULL, 0, &bytes_returned, NULL, NULL); + } #endif return fd; @@ -2153,9 +2202,13 @@ g_socket_bind (GSocket *socket, g_socket_address_get_native_size (address)) < 0) { int errsv = get_socket_errno (); + gchar *address_string = address_to_string (address); + g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv), - _("Error binding to address: %s"), socket_strerror (errsv)); + _("Error binding to address %s: %s"), + address_string, socket_strerror (errsv)); + g_free (address_string); return FALSE; } @@ -2201,7 +2254,7 @@ g_socket_w32_get_adapter_ipv4_addr (const gchar *name_or_ip) */ if_index = if_nametoindex (name_or_ip); - /* Step 3: Prepare wchar string for friendly name comparision */ + /* Step 3: Prepare wchar string for friendly name comparison */ if (if_index == 0) { size_t if_name_len = strlen (name_or_ip); @@ -2211,7 +2264,7 @@ g_socket_w32_get_adapter_ipv4_addr (const gchar *name_or_ip) wchar_name_or_ip = (wchar_t *) g_try_malloc ((if_name_len + 1) * sizeof(wchar_t)); if (wchar_name_or_ip) mbstowcs (wchar_name_or_ip, name_or_ip, if_name_len + 1); - /* NOTE: Even if malloc fails here, some comparisions can still be done later... so no exit here! */ + /* NOTE: Even if malloc fails here, some comparisons can still be done later... so no exit here! */ } /* @@ -3069,6 +3122,9 @@ g_socket_get_available_bytes (GSocket *socket) g_return_val_if_fail (G_IS_SOCKET (socket), -1); + if (!check_socket (socket, NULL)) + return -1; + #ifdef SO_NREAD if (!g_socket_get_option (socket, SOL_SOCKET, SO_NREAD, &avail, NULL)) return -1; @@ -3211,8 +3267,8 @@ g_socket_receive_with_timeout (GSocket *socket, /** * g_socket_receive: * @socket: a #GSocket - * @buffer: (array length=size) (element-type guint8): a buffer to - * read data into (which should be at least @size bytes long). + * @buffer: (array length=size) (element-type guint8) (out caller-allocates): + * a buffer to read data into (which should be at least @size bytes long). * @size: the number of bytes you want to read from the socket * @cancellable: (nullable): a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. @@ -3261,8 +3317,8 @@ g_socket_receive (GSocket *socket, /** * g_socket_receive_with_blocking: * @socket: a #GSocket - * @buffer: (array length=size) (element-type guint8): a buffer to - * read data into (which should be at least @size bytes long). + * @buffer: (array length=size) (element-type guint8) (out caller-allocates): + * a buffer to read data into (which should be at least @size bytes long). * @size: the number of bytes you want to read from the socket * @blocking: whether to do blocking or non-blocking I/O * @cancellable: (nullable): a %GCancellable or %NULL @@ -3294,8 +3350,8 @@ g_socket_receive_with_blocking (GSocket *socket, * @socket: a #GSocket * @address: (out) (optional): a pointer to a #GSocketAddress * pointer, or %NULL - * @buffer: (array length=size) (element-type guint8): a buffer to - * read data into (which should be at least @size bytes long). + * @buffer: (array length=size) (element-type guint8) (out caller-allocates): + * a buffer to read data into (which should be at least @size bytes long). * @size: the number of bytes you want to read from the socket * @cancellable: (nullable): a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. @@ -3697,7 +3753,6 @@ g_socket_is_closed (GSocket *socket) return socket->priv->closed; } -#ifdef G_OS_WIN32 /* Broken source, used on errors */ static gboolean broken_dispatch (GSource *source, @@ -3712,9 +3767,12 @@ static GSourceFuncs broken_funcs = NULL, NULL, broken_dispatch, - NULL + NULL, + NULL, + NULL, }; +#ifdef G_OS_WIN32 static gint network_events_for_condition (GIOCondition condition) { @@ -3744,6 +3802,9 @@ update_select_events (GSocket *socket) GList *l; WSAEVENT event; + if (socket->priv->closed) + return; + ensure_event (socket); event_mask = 0; @@ -3802,7 +3863,8 @@ update_condition_unlocked (GSocket *socket) WSANETWORKEVENTS events; GIOCondition condition; - if (WSAEnumNetworkEvents (socket->priv->fd, + if (!socket->priv->closed && + WSAEnumNetworkEvents (socket->priv->fd, socket->priv->event, &events) == 0) { @@ -4022,6 +4084,7 @@ static GSourceFuncs socket_source_funcs = socket_source_dispatch, socket_source_finalize, (GSourceFunc)socket_source_closure_callback, + NULL, }; static GSource * @@ -4042,6 +4105,12 @@ socket_source_new (GSocket *socket, } #endif + if (!check_socket (socket, NULL)) + { + g_warning ("Socket check failed"); + return g_source_new (&broken_funcs, sizeof (GSource)); + } + condition |= G_IO_HUP | G_IO_ERR | G_IO_NVAL; source = g_source_new (&socket_source_funcs, sizeof (GSocketSource)); @@ -4417,6 +4486,15 @@ g_socket_condition_timed_wait (GSocket *socket, #ifndef G_OS_WIN32 +#ifdef HAVE_QNX +/* QNX has this weird upper limit, or at least used to back in the 6.x days. + * This was discovered empirically and doesn't appear to be mentioned in any + * of the official documentation. */ +# define G_SOCKET_CONTROL_BUFFER_SIZE_BYTES 2016 +#else +# define G_SOCKET_CONTROL_BUFFER_SIZE_BYTES 2048 +#endif + /* Unfortunately these have to be macros rather than inline functions due to * using alloca(). */ #define output_message_to_msghdr(message, prev_message, msg, prev_msg, error) \ @@ -4467,7 +4545,7 @@ G_STMT_START { \ else \ /* ABI is incompatible */ \ { \ - gint i; \ + guint i; \ \ _msg->msg_iov = g_newa (struct iovec, _message->num_vectors); \ for (i = 0; i < _message->num_vectors; i++) \ @@ -4482,7 +4560,7 @@ G_STMT_START { \ /* control */ \ { \ struct cmsghdr *cmsg; \ - gint i; \ + guint i; \ \ _msg->msg_controllen = 0; \ for (i = 0; i < _message->num_control_messages; i++) \ @@ -4563,7 +4641,7 @@ G_STMT_START { \ } \ else \ { \ - _msg->msg_controllen = 2048; \ + _msg->msg_controllen = G_SOCKET_CONTROL_BUFFER_SIZE_BYTES; \ _msg->msg_control = g_alloca (_msg->msg_controllen); \ } \ \ @@ -4688,6 +4766,11 @@ input_message_from_msghdr (const struct msghdr *msg, * notified of a %G_IO_OUT condition. (On Windows in particular, this is * very common due to the way the underlying APIs work.) * + * The sum of the sizes of each #GOutputVector in vectors must not be + * greater than %G_MAXSSIZE. If the message can be larger than this, + * then it is mandatory to use the g_socket_send_message_with_timeout() + * function. + * * On error -1 is returned and @error is set accordingly. * * Returns: Number of bytes written (which may be less than @size), or -1 @@ -4708,6 +4791,53 @@ g_socket_send_message (GSocket *socket, { GPollableReturn res; gsize bytes_written = 0; + gsize vectors_size = 0; + + if (num_vectors != -1) + { + gint i; + + for (i = 0; i < num_vectors; i++) + { + /* No wrap-around for vectors_size */ + if (vectors_size > vectors_size + vectors[i].size) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Unable to send message: %s"), + _("Message vectors too large")); + return -1; + } + + vectors_size += vectors[i].size; + } + } + else + { + gsize i; + + for (i = 0; vectors[i].buffer != NULL; i++) + { + /* No wrap-around for vectors_size */ + if (vectors_size > vectors_size + vectors[i].size) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Unable to send message: %s"), + _("Message vectors too large")); + return -1; + } + + vectors_size += vectors[i].size; + } + } + + /* Check if vector's buffers are too big for gssize */ + if (vectors_size > G_MAXSSIZE) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Unable to send message: %s"), + _("Message vectors too large")); + return -1; + } res = g_socket_send_message_with_timeout (socket, address, vectors, num_vectors, @@ -4716,6 +4846,8 @@ g_socket_send_message (GSocket *socket, &bytes_written, cancellable, error); + g_assert (res != G_POLLABLE_RETURN_OK || bytes_written <= G_MAXSSIZE); + if (res == G_POLLABLE_RETURN_WOULD_BLOCK) { #ifndef G_OS_WIN32 @@ -4725,7 +4857,7 @@ g_socket_send_message (GSocket *socket, #endif } - return res == G_POLLABLE_RETURN_OK ? bytes_written : -1; + return res == G_POLLABLE_RETURN_OK ? (gssize) bytes_written : -1; } /** @@ -5065,7 +5197,7 @@ g_socket_send_messages_with_timeout (GSocket *socket, #if !defined (G_OS_WIN32) && defined (HAVE_SENDMMSG) { struct mmsghdr *msgvec; - gint i, num_sent; + guint i, num_sent; /* Clamp the number of vectors if more given than we can write in one go. * The caller has to handle short writes anyway. @@ -5426,10 +5558,10 @@ g_socket_receive_message_with_timeout (GSocket *socket, if (errsv == WSAEINTR) continue; + win32_unset_event_mask (socket, FD_READ); + if (errsv == WSAEWOULDBLOCK) { - win32_unset_event_mask (socket, FD_READ); - if (timeout_us != 0) { if (!block_on_timeout (socket, G_IO_IN, timeout_us, @@ -5865,6 +5997,7 @@ g_socket_receive_message (GSocket *socket, * - OpenBSD since GLib 2.30 * - Solaris, Illumos and OpenSolaris since GLib 2.40 * - NetBSD since GLib 2.42 + * - macOS, tvOS, iOS since GLib 2.66 * * Other ways to obtain credentials from a foreign peer includes the * #GUnixCredentialsMessage type and @@ -5885,6 +6018,9 @@ g_socket_get_credentials (GSocket *socket, g_return_val_if_fail (G_IS_SOCKET (socket), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); + if (!check_socket (socket, error)) + return NULL; + ret = NULL; #if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED @@ -5906,6 +6042,51 @@ g_socket_get_credentials (GSocket *socket, native_creds_buf); } } +#elif G_CREDENTIALS_USE_APPLE_XUCRED + { + struct xucred cred; + socklen_t optlen = sizeof (cred); + + if (getsockopt (socket->priv->fd, + SOL_LOCAL, + LOCAL_PEERCRED, + &cred, + &optlen) == 0 + && optlen != 0) + { + if (cred.cr_version == XUCRED_VERSION) + { + ret = g_credentials_new (); + g_credentials_set_native (ret, + G_CREDENTIALS_NATIVE_TYPE, + &cred); + } + else + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + /* No point in translating this! */ + "struct xucred cr_version %u != %u", + cred.cr_version, XUCRED_VERSION); + /* Reuse a translatable string we already have */ + g_prefix_error (error, + _("Unable to read socket credentials: %s"), + ""); + + return NULL; + } + } + else if (optlen == 0 || errno == EINVAL) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Unable to read socket credentials: %s"), + "unsupported socket type"); + return NULL; + } + } #elif G_CREDENTIALS_USE_NETBSD_UNPCBID { struct unpcbid cred; @@ -6001,6 +6182,11 @@ g_socket_get_option (GSocket *socket, g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + /* g_socket_get_option() is called during socket init, so skip the init checks + * in check_socket() */ + if (socket->priv->inited && !check_socket (socket, error)) + return FALSE; + *value = 0; size = sizeof (gint); if (getsockopt (socket->priv->fd, level, optname, value, &size) != 0) @@ -6064,6 +6250,11 @@ g_socket_set_option (GSocket *socket, g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + /* g_socket_set_option() is called during socket init, so skip the init checks + * in check_socket() */ + if (socket->priv->inited && !check_socket (socket, error)) + return FALSE; + if (setsockopt (socket->priv->fd, level, optname, &value, sizeof (gint)) == 0) return TRUE; @@ -6092,4 +6283,3 @@ g_socket_set_option (GSocket *socket, #endif return FALSE; } - diff --git a/gio/gsocketaddress.c b/gio/gsocketaddress.c index 848e37b0b8e038c8f2ffdcbc097a5a58591963c6..2b7e83ccf98a2aae5e3087fd8d545542280335a3 100644 --- a/gio/gsocketaddress.c +++ b/gio/gsocketaddress.c @@ -398,7 +398,7 @@ g_socket_address_connectable_proxy_enumerate (GSocketConnectable *connectable) g_object_get (connectable, "address", &addr, "port", &port, NULL); ip = g_inet_address_to_string (addr); - uri = _g_uri_from_authority ("none", ip, port, NULL); + uri = g_uri_join (G_URI_FLAGS_NONE, "none", NULL, ip, port, "", NULL, NULL); addr_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, diff --git a/gio/gsocketaddressenumerator.c b/gio/gsocketaddressenumerator.c index ebbb5decfd54e3af7c5d7e6235840a2bb093a3ae..fabd242e7245452ea075324db4f29e9a90574350 100644 --- a/gio/gsocketaddressenumerator.c +++ b/gio/gsocketaddressenumerator.c @@ -38,7 +38,7 @@ * g_socket_address_enumerator_next_finish() should be used where possible. * * Each #GSocketAddressEnumerator can only be enumerated once. Once - * g_socket_address_enumerator_next() has returned %NULL (and no error), further + * g_socket_address_enumerator_next() has returned %NULL, further * enumeration with that #GSocketAddressEnumerator is not possible, and it can * be unreffed. */ diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c index ad6214f26f8a9e95ca2e75dcb3da121ac200b065..62b1afbcdbee9c8aedf02f007b0aaf58470ed5c9 100644 --- a/gio/gsocketclient.c +++ b/gio/gsocketclient.c @@ -24,6 +24,10 @@ #include "config.h" #include "gsocketclient.h" +#ifndef G_OS_WIN32 +#include +#endif + #include #include @@ -39,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +147,10 @@ create_socket (GSocketClient *client, if (client->priv->local_address) { +#ifdef IP_BIND_ADDRESS_NO_PORT + g_socket_set_option (socket, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, 1, NULL); +#endif + if (!g_socket_bind (socket, client->priv->local_address, FALSE, @@ -482,7 +491,7 @@ g_socket_client_set_protocol (GSocketClient *client, * * See g_socket_client_set_local_address() for details. * - * Returns: (transfer none): a #GSocketAddress or %NULL. Do not free. + * Returns: (nullable) (transfer none): a #GSocketAddress or %NULL. Do not free. * * Since: 2.22 */ @@ -819,7 +828,7 @@ g_socket_client_class_init (GSocketClientClass *class) * multiple times (or not at all) for a given connectable (in * particular, if @client ends up attempting to connect to more than * one address). However, if @client emits the #GSocketClient::event - * signal at all for a given connectable, that it will always emit + * signal at all for a given connectable, then it will always emit * it with %G_SOCKET_CLIENT_COMPLETE when it is done. * * Note that there may be additional #GSocketClientEvent values in @@ -936,7 +945,7 @@ g_socket_client_class_init (GSocketClientClass *class) static void g_socket_client_emit_event (GSocketClient *client, - GSocketClientEvent event, + GSocketClientEvent event, GSocketConnectable *connectable, GIOStream *connection) { @@ -944,6 +953,72 @@ g_socket_client_emit_event (GSocketClient *client, event, connectable, connection); } +/* Originally, GSocketClient returned whatever error occured last. Turns + * out this doesn't work well in practice. Consider the following case: + * DNS returns an IPv4 and IPv6 address. First we'll connect() to the + * IPv4 address, and say that succeeds, but TLS is enabled and the TLS + * handshake fails. Then we try the IPv6 address and receive ENETUNREACH + * because IPv6 isn't supported. We wind up returning NETWORK_UNREACHABLE + * even though the address can be pinged and a TLS error would be more + * appropriate. So instead, we now try to return the error corresponding + * to the latest attempted GSocketClientEvent in the connection process. + * TLS errors take precedence over proxy errors, which take precedence + * over connect() errors, which take precedence over DNS errors. + * + * Note that the example above considers a sync codepath, but this is an + * issue for the async codepath too, where events and errors may occur + * in confusing orders. + */ +typedef struct +{ + GError *tmp_error; + GError *best_error; + GSocketClientEvent best_error_event; +} SocketClientErrorInfo; + +static SocketClientErrorInfo * +socket_client_error_info_new (void) +{ + return g_new0 (SocketClientErrorInfo, 1); +} + +static void +socket_client_error_info_free (SocketClientErrorInfo *info) +{ + g_assert (info->tmp_error == NULL); + g_clear_error (&info->best_error); + g_free (info); +} + +static void +consider_tmp_error (SocketClientErrorInfo *info, + GSocketClientEvent event) +{ + if (info->tmp_error == NULL) + return; + + /* If we ever add more GSocketClientEvents in the future, then we'll + * no longer be able to use >= for this comparison, because future + * events will compare greater than G_SOCKET_CLIENT_COMPLETE. Until + * then, this is convenient. Note G_SOCKET_CLIENT_RESOLVING is 0 so we + * need to use >= here or those errors would never be set. That means + * if we get two errors on the same GSocketClientEvent, we wind up + * preferring the last one, which is fine. + */ + g_assert (event <= G_SOCKET_CLIENT_COMPLETE); + if (event >= info->best_error_event) + { + g_clear_error (&info->best_error); + info->best_error = info->tmp_error; + info->tmp_error = NULL; + info->best_error_event = event; + } + else + { + g_clear_error (&info->tmp_error); + } +} + /** * g_socket_client_connect: * @client: a #GSocketClient. @@ -982,9 +1057,10 @@ g_socket_client_connect (GSocketClient *client, { GIOStream *connection = NULL; GSocketAddressEnumerator *enumerator = NULL; - GError *last_error, *tmp_error; + SocketClientErrorInfo *error_info; + gboolean ever_resolved = FALSE; - last_error = NULL; + error_info = socket_client_error_info_new (); if (can_use_proxy (client)) { @@ -1009,44 +1085,38 @@ g_socket_client_connect (GSocketClient *client, if (g_cancellable_is_cancelled (cancellable)) { - g_clear_error (error); - g_clear_error (&last_error); - g_cancellable_set_error_if_cancelled (cancellable, error); + g_clear_error (&error_info->best_error); + g_cancellable_set_error_if_cancelled (cancellable, &error_info->best_error); break; } - tmp_error = NULL; - g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING, - connectable, NULL); + if (!ever_resolved) + { + g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING, + connectable, NULL); + } address = g_socket_address_enumerator_next (enumerator, cancellable, - &tmp_error); + &error_info->tmp_error); + consider_tmp_error (error_info, G_SOCKET_CLIENT_RESOLVING); + if (!ever_resolved) + { + g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED, + connectable, NULL); + ever_resolved = TRUE; + } if (address == NULL) { - if (tmp_error) - { - g_clear_error (&last_error); - g_propagate_error (error, tmp_error); - } - else if (last_error) - { - g_propagate_error (error, last_error); - } - else - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Unknown error on connect")); + /* Enumeration is finished. */ + g_assert (&error_info->best_error != NULL); break; } - g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED, - connectable, NULL); using_proxy = (G_IS_PROXY_ADDRESS (address) && client->priv->enable_proxy); - /* clear error from previous attempt */ - g_clear_error (&last_error); - - socket = create_socket (client, address, &last_error); + socket = create_socket (client, address, &error_info->tmp_error); + consider_tmp_error (error_info, G_SOCKET_CLIENT_CONNECTING); if (socket == NULL) { g_object_unref (address); @@ -1058,14 +1128,15 @@ g_socket_client_connect (GSocketClient *client, g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTING, connectable, connection); if (g_socket_connection_connect (G_SOCKET_CONNECTION (connection), - address, cancellable, &last_error)) + address, cancellable, &error_info->tmp_error)) { g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, NULL); g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTED, connectable, connection); } else { - clarify_connect_error (last_error, connectable, address); + clarify_connect_error (error_info->tmp_error, connectable, address); + consider_tmp_error (error_info, G_SOCKET_CLIENT_CONNECTING); g_object_unref (connection); connection = NULL; } @@ -1086,9 +1157,10 @@ g_socket_client_connect (GSocketClient *client, g_critical ("Trying to proxy over non-TCP connection, this is " "most likely a bug in GLib IO library."); - g_set_error_literal (&last_error, + g_set_error_literal (&error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Proxying over a non-TCP connection is not supported.")); + consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING); g_object_unref (connection); connection = NULL; @@ -1106,7 +1178,9 @@ g_socket_client_connect (GSocketClient *client, connection, proxy_addr, cancellable, - &last_error); + &error_info->tmp_error); + consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING); + g_object_unref (connection); connection = proxy_connection; g_object_unref (proxy); @@ -1116,9 +1190,10 @@ g_socket_client_connect (GSocketClient *client, } else { - g_set_error (&last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + g_set_error (&error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Proxy protocol “%s” is not supported."), protocol); + consider_tmp_error (error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING); g_object_unref (connection); connection = NULL; } @@ -1128,7 +1203,7 @@ g_socket_client_connect (GSocketClient *client, { GIOStream *tlsconn; - tlsconn = g_tls_client_connection_new (connection, connectable, &last_error); + tlsconn = g_tls_client_connection_new (connection, connectable, &error_info->tmp_error); g_object_unref (connection); connection = tlsconn; @@ -1138,16 +1213,21 @@ g_socket_client_connect (GSocketClient *client, client->priv->tls_validation_flags); g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKING, connectable, connection); if (g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn), - cancellable, &last_error)) + cancellable, &error_info->tmp_error)) { g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKED, connectable, connection); } else { + consider_tmp_error (error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING); g_object_unref (tlsconn); connection = NULL; } } + else + { + consider_tmp_error (error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING); + } } if (connection && !G_IS_SOCKET_CONNECTION (connection)) @@ -1164,6 +1244,10 @@ g_socket_client_connect (GSocketClient *client, } g_object_unref (enumerator); + if (!connection) + g_propagate_error (error, g_steal_pointer (&error_info->best_error)); + socket_client_error_info_free (error_info); + g_socket_client_emit_event (client, G_SOCKET_CLIENT_COMPLETE, connectable, connection); return G_SOCKET_CONNECTION (connection); } @@ -1341,7 +1425,7 @@ typedef struct GSList *connection_attempts; GSList *successful_connections; - GError *last_error; + SocketClientErrorInfo *error_info; gboolean enumerated_at_least_once; gboolean enumeration_completed; @@ -1361,7 +1445,7 @@ g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data) g_slist_free_full (data->connection_attempts, connection_attempt_unref); g_slist_free_full (data->successful_connections, connection_attempt_unref); - g_clear_error (&data->last_error); + g_clear_pointer (&data->error_info, socket_client_error_info_free); g_slice_free (GSocketClientAsyncConnectData, data); } @@ -1483,14 +1567,6 @@ g_socket_client_enumerator_callback (GObject *object, GAsyncResult *result, gpointer user_data); -static void -set_last_error (GSocketClientAsyncConnectData *data, - GError *error) -{ - g_clear_error (&data->last_error); - data->last_error = error; -} - static void enumerator_next_async (GSocketClientAsyncConnectData *data, gboolean add_task_ref) @@ -1500,7 +1576,8 @@ enumerator_next_async (GSocketClientAsyncConnectData *data, if (add_task_ref) g_object_ref (data->task); - g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL); + if (!data->enumerated_at_least_once) + g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL); g_debug ("GSocketClient: Starting new address enumeration"); g_socket_address_enumerator_next_async (data->enumerator, data->enumeration_cancellable, @@ -1520,7 +1597,7 @@ g_socket_client_tls_handshake_callback (GObject *object, if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object), result, - &data->last_error)) + &data->error_info->tmp_error)) { g_object_unref (attempt->connection); attempt->connection = G_IO_STREAM (object); @@ -1533,7 +1610,9 @@ g_socket_client_tls_handshake_callback (GObject *object, { g_object_unref (object); connection_attempt_unref (attempt); - g_debug ("GSocketClient: TLS handshake failed: %s", data->last_error->message); + + g_debug ("GSocketClient: TLS handshake failed: %s", data->error_info->tmp_error->message); + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING); try_next_connection_or_finish (data, TRUE); } } @@ -1553,7 +1632,7 @@ g_socket_client_tls_handshake (ConnectionAttempt *attempt) g_debug ("GSocketClient: Starting TLS handshake"); tlsconn = g_tls_client_connection_new (attempt->connection, data->connectable, - &data->last_error); + &data->error_info->tmp_error); if (tlsconn) { g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn), @@ -1568,6 +1647,8 @@ g_socket_client_tls_handshake (ConnectionAttempt *attempt) else { connection_attempt_unref (attempt); + + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_TLS_HANDSHAKING); try_next_connection_or_finish (data, TRUE); } } @@ -1583,19 +1664,19 @@ g_socket_client_proxy_connect_callback (GObject *object, g_object_unref (attempt->connection); attempt->connection = g_proxy_connect_finish (G_PROXY (object), result, - &data->last_error); + &data->error_info->tmp_error); if (attempt->connection) { g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, attempt->connection); + g_socket_client_tls_handshake (attempt); } else { connection_attempt_unref (attempt); + + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING); try_next_connection_or_finish (data, TRUE); - return; } - - g_socket_client_tls_handshake (attempt); } static void @@ -1663,9 +1744,10 @@ try_next_successful_connection (GSocketClientAsyncConnectData *data) g_critical ("Trying to proxy over non-TCP connection, this is " "most likely a bug in GLib IO library."); - g_set_error_literal (&data->last_error, + g_set_error_literal (&data->error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Proxying over a non-TCP connection is not supported.")); + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING); } else if (g_hash_table_contains (data->client->priv->app_proxies, protocol)) { @@ -1692,11 +1774,10 @@ try_next_successful_connection (GSocketClientAsyncConnectData *data) } else { - g_clear_error (&data->last_error); - - g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + g_set_error (&data->error_info->tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Proxy protocol “%s” is not supported."), protocol); + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_PROXY_NEGOTIATING); } data->connection_in_progress = FALSE; @@ -1727,7 +1808,7 @@ try_next_connection_or_finish (GSocketClientAsyncConnectData *data, return; } - complete_connection_with_error (data, data->last_error); + complete_connection_with_error (data, g_steal_pointer (&data->error_info->best_error)); } static void @@ -1737,7 +1818,6 @@ g_socket_client_connected_callback (GObject *source, { ConnectionAttempt *attempt = user_data; GSocketClientAsyncConnectData *data = attempt->data; - GError *error = NULL; if (task_completed_or_cancelled (data) || g_cancellable_is_cancelled (attempt->cancellable)) { @@ -1753,20 +1833,20 @@ g_socket_client_connected_callback (GObject *source, } if (!g_socket_connection_connect_finish (G_SOCKET_CONNECTION (source), - result, &error)) + result, &data->error_info->tmp_error)) { if (!g_cancellable_is_cancelled (attempt->cancellable)) { - clarify_connect_error (error, data->connectable, attempt->address); - set_last_error (data, error); - g_debug ("GSocketClient: Connection attempt failed: %s", error->message); + g_debug ("GSocketClient: Connection attempt failed: %s", data->error_info->tmp_error->message); + clarify_connect_error (data->error_info->tmp_error, data->connectable, attempt->address); + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_CONNECTING); connection_attempt_remove (attempt); connection_attempt_unref (attempt); try_next_connection_or_finish (data, FALSE); } else /* Silently ignore cancelled attempts */ { - g_clear_error (&error); + g_clear_error (&data->error_info->tmp_error); g_object_unref (data->task); connection_attempt_unref (attempt); } @@ -1824,7 +1904,6 @@ g_socket_client_enumerator_callback (GObject *object, GSocketAddress *address = NULL; GSocket *socket; ConnectionAttempt *attempt; - GError *error = NULL; if (task_completed_or_cancelled (data)) { @@ -1833,7 +1912,7 @@ g_socket_client_enumerator_callback (GObject *object, } address = g_socket_address_enumerator_next_finish (data->enumerator, - result, &error); + result, &data->error_info->tmp_error); if (address == NULL) { if (G_UNLIKELY (data->enumeration_completed)) @@ -1842,7 +1921,7 @@ g_socket_client_enumerator_callback (GObject *object, data->enumeration_completed = TRUE; g_debug ("GSocketClient: Address enumeration completed (out of addresses)"); - /* As per API docs: We only care about error if its the first call, + /* As per API docs: We only care about error if it's the first call, after that the enumerator is done. Note that we don't care about cancellation errors because @@ -1853,20 +1932,11 @@ g_socket_client_enumerator_callback (GObject *object, if ((data->enumerated_at_least_once && !data->connection_attempts && !data->connection_in_progress) || !data->enumerated_at_least_once) { - g_debug ("GSocketClient: Address enumeration failed: %s", error ? error->message : NULL); - if (data->last_error) - { - g_clear_error (&error); - error = data->last_error; - data->last_error = NULL; - } - else if (!error) - { - g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Unknown error on connect")); - } - - complete_connection_with_error (data, error); + g_debug ("GSocketClient: Address enumeration failed: %s", + data->error_info->tmp_error ? data->error_info->tmp_error->message : NULL); + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_RESOLVING); + g_assert (data->error_info->best_error); + complete_connection_with_error (data, g_steal_pointer (&data->error_info->best_error)); } /* Enumeration should never trigger again, drop our ref */ @@ -1874,17 +1944,19 @@ g_socket_client_enumerator_callback (GObject *object, return; } - data->enumerated_at_least_once = TRUE; g_debug ("GSocketClient: Address enumeration succeeded"); - g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED, - data->connectable, NULL); - - g_clear_error (&data->last_error); + if (!data->enumerated_at_least_once) + { + g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED, + data->connectable, NULL); + data->enumerated_at_least_once = TRUE; + } - socket = create_socket (data->client, address, &data->last_error); + socket = create_socket (data->client, address, &data->error_info->tmp_error); if (socket == NULL) { g_object_unref (address); + consider_tmp_error (data->error_info, G_SOCKET_CLIENT_CONNECTING); enumerator_next_async (data, FALSE); return; } @@ -1901,7 +1973,7 @@ g_socket_client_enumerator_callback (GObject *object, attempt->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address)); g_source_set_callback (attempt->timeout_source, on_connection_attempt_timeout, attempt, NULL); - g_source_attach (attempt->timeout_source, g_main_context_get_thread_default ()); + g_source_attach (attempt->timeout_source, g_task_get_context (data->task)); data->connection_attempts = g_slist_append (data->connection_attempts, attempt); if (g_task_get_cancellable (data->task)) @@ -1927,6 +1999,15 @@ g_socket_client_enumerator_callback (GObject *object, * * This is the asynchronous version of g_socket_client_connect(). * + * You may wish to prefer the asynchronous version even in synchronous + * command line programs because, since 2.60, it implements + * [RFC 8305](https://tools.ietf.org/html/rfc8305) "Happy Eyeballs" + * recommendations to work around long connection timeouts in networks + * where IPv6 is broken by performing an IPv4 connection simultaneously + * without waiting for IPv6 to time out, which is not supported by the + * synchronous call. (This is not an API guarantee, and may change in + * the future.) + * * When the operation is finished @callback will be * called. You can then call g_socket_client_connect_finish() to get * the result of the operation. @@ -1947,6 +2028,7 @@ g_socket_client_connect_async (GSocketClient *client, data = g_slice_new0 (GSocketClientAsyncConnectData); data->client = client; data->connectable = g_object_ref (connectable); + data->error_info = socket_client_error_info_new (); if (can_use_proxy (client)) { diff --git a/gio/gsocketcontrolmessage.c b/gio/gsocketcontrolmessage.c index 7acf6b3585603e0483d5a43900573302cc7e60f9..255610c46553ac243e74f70e24059aaecc46fe7d 100644 --- a/gio/gsocketcontrolmessage.c +++ b/gio/gsocketcontrolmessage.c @@ -175,7 +175,7 @@ g_socket_control_message_deserialize (int level, GSocketControlMessage *message; GType *message_types; guint n_message_types; - int i; + guint i; /* Ensure we know about the built in types */ #ifndef G_OS_WIN32 diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c index d11f10ae479848efa56eee0295cd42837e23cf74..bdf1608dc51a6aac9105976aa03947a595477c52 100644 --- a/gio/gsocketlistener.c +++ b/gio/gsocketlistener.c @@ -606,7 +606,7 @@ add_sources (GSocketListener *listener, GSocket *socket; GSource *source; GList *sources; - int i; + guint i; sources = NULL; for (i = 0; i < listener->priv->sockets->len; i++) @@ -983,7 +983,7 @@ g_socket_listener_set_backlog (GSocketListener *listener, int listen_backlog) { GSocket *socket; - int i; + guint i; if (listener->priv->closed) return; @@ -1009,7 +1009,7 @@ void g_socket_listener_close (GSocketListener *listener) { GSocket *socket; - int i; + guint i; g_return_if_fail (G_IS_SOCKET_LISTENER (listener)); diff --git a/gio/gsocketservice.h b/gio/gsocketservice.h index f25a1b6b755b5bf2d1e2adb26988a117e11f3a98..4dc1e8f3b420e8b7d953052756da578bb70305ff 100644 --- a/gio/gsocketservice.h +++ b/gio/gsocketservice.h @@ -48,7 +48,7 @@ typedef struct _GSocketServiceClass GSocketServiceClass; /** * GSocketServiceClass: - * @incomming: signal emitted when new connections are accepted + * @incoming: signal emitted when new connections are accepted * * Class structure for #GSocketService. */ diff --git a/gio/gsocks5proxy.c b/gio/gsocks5proxy.c index c58be83695e4cb6a1f1fb72efaf8902b8c027882..873db7ea6d887c331f48089237925c96616adf77 100644 --- a/gio/gsocks5proxy.c +++ b/gio/gsocks5proxy.c @@ -170,8 +170,22 @@ parse_nego_reply (const guint8 *data, *must_auth = TRUE; break; - case SOCKS5_AUTH_GSSAPI: case SOCKS5_AUTH_NO_ACCEPT: + if (!has_auth) + { + /* The server has said it accepts none of our authentication methods, + * but given the slightly odd implementation of set_nego_msg(), we + * actually only gave it the choice of %SOCKS5_AUTH_NONE, since the + * caller specified no username or password. + * Return %G_IO_ERROR_PROXY_NEED_AUTH so the caller knows that if + * they specify a username and password and try again, authentication + * might succeed (since we’ll send %SOCKS5_AUTH_USR_PASS next time). */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_NEED_AUTH, + _("The SOCKSv5 proxy requires authentication.")); + return FALSE; + } + G_GNUC_FALLTHROUGH; + case SOCKS5_AUTH_GSSAPI: default: g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED, _("The SOCKSv5 proxy requires an authentication " @@ -229,7 +243,7 @@ set_auth_msg (guint8 *msg, static gboolean check_auth_status (const guint8 *data, GError **error) { - if (data[0] != SOCKS5_VERSION + if (data[0] != SOCKS5_AUTH_VERSION || data[1] != SOCKS5_REP_SUCCEEDED) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED, @@ -309,7 +323,7 @@ set_connect_msg (guint8 *msg, * +----+-----+-------+------+----------+----------+ * | 1 | 1 | X'00' | 1 | Variable | 2 | * +----+-----+-------+------+----------+----------+ - * This reply need to be read by small part to determin size. Buffer + * This reply need to be read by small part to determine size. Buffer * size is determined in function of the biggest part to read. * * The parser only requires 4 bytes. @@ -703,6 +717,16 @@ nego_reply_read_cb (GObject *source, return; } + if (read == 0) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + "Connection to SOCKSv5 proxy server lost"); + g_object_unref (task); + return; + } + data->offset += read; if (data->offset == data->length) @@ -807,6 +831,16 @@ auth_reply_read_cb (GObject *source, return; } + if (read == 0) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + "Connection to SOCKSv5 proxy server lost"); + g_object_unref (task); + return; + } + data->offset += read; if (data->offset == data->length) @@ -909,6 +943,16 @@ connect_reply_read_cb (GObject *source, return; } + if (read == 0) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + "Connection to SOCKSv5 proxy server lost"); + g_object_unref (task); + return; + } + data->offset += read; if (data->offset == data->length) @@ -969,6 +1013,16 @@ connect_addr_len_read_cb (GObject *source, return; } + if (read == 0) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + "Connection to SOCKSv5 proxy server lost"); + g_object_unref (task); + return; + } + data->length = data->buffer[0] + 2; data->offset = 0; @@ -995,6 +1049,16 @@ connect_addr_read_cb (GObject *source, return; } + if (read == 0) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + "Connection to SOCKSv5 proxy server lost"); + g_object_unref (task); + return; + } + data->offset += read; if (data->offset == data->length) diff --git a/gio/gsrvtarget.h b/gio/gsrvtarget.h index 3ef16f1398feb03f319a275bb94deb7bf8870ab7..49569159e87eff7ecf2ec8ee558b1c96aa796396 100644 --- a/gio/gsrvtarget.h +++ b/gio/gsrvtarget.h @@ -56,4 +56,3 @@ GList *g_srv_target_list_sort (GList *targets); G_END_DECLS #endif /* __G_SRV_TARGET_H__ */ - diff --git a/gio/gsubprocess.c b/gio/gsubprocess.c index b5515c705ac3c037af6f4601016f09974adb6d3c..77a23efc3d8fe6f816f2c2ee3773d43e407b5ba9 100644 --- a/gio/gsubprocess.c +++ b/gio/gsubprocess.c @@ -179,160 +179,6 @@ enum N_PROPS }; -#ifdef G_OS_UNIX -typedef struct -{ - gint fds[3]; - GSpawnChildSetupFunc child_setup_func; - gpointer child_setup_data; - GArray *basic_fd_assignments; - GArray *needdup_fd_assignments; -} ChildData; - -static void -unset_cloexec (int fd) -{ - int flags; - int result; - - flags = fcntl (fd, F_GETFD, 0); - - if (flags != -1) - { - int errsv; - flags &= (~FD_CLOEXEC); - do - { - result = fcntl (fd, F_SETFD, flags); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - } -} - -static int -dupfd_cloexec (int parent_fd) -{ - int fd, errsv; -#ifdef F_DUPFD_CLOEXEC - do - { - fd = fcntl (parent_fd, F_DUPFD_CLOEXEC, 3); - errsv = errno; - } - while (fd == -1 && errsv == EINTR); -#else - /* OS X Snow Lion and earlier don't have F_DUPFD_CLOEXEC: - * https://bugzilla.gnome.org/show_bug.cgi?id=710962 - */ - int result, flags; - do - { - fd = fcntl (parent_fd, F_DUPFD, 3); - errsv = errno; - } - while (fd == -1 && errsv == EINTR); - flags = fcntl (fd, F_GETFD, 0); - if (flags != -1) - { - flags |= FD_CLOEXEC; - do - { - result = fcntl (fd, F_SETFD, flags); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - } -#endif - return fd; -} - -/* - * Based on code derived from - * gnome-terminal:src/terminal-screen.c:terminal_screen_child_setup(), - * used under the LGPLv2+ with permission from author. - */ -static void -child_setup (gpointer user_data) -{ - ChildData *child_data = user_data; - gint i; - gint result; - int errsv; - - /* We're on the child side now. "Rename" the file descriptors in - * child_data.fds[] to stdin/stdout/stderr. - * - * We don't close the originals. It's possible that the originals - * should not be closed and if they should be closed then they should - * have been created O_CLOEXEC. - */ - for (i = 0; i < 3; i++) - if (child_data->fds[i] != -1 && child_data->fds[i] != i) - { - do - { - result = dup2 (child_data->fds[i], i); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - } - - /* Basic fd assignments we can just unset FD_CLOEXEC */ - if (child_data->basic_fd_assignments) - { - for (i = 0; i < child_data->basic_fd_assignments->len; i++) - { - gint fd = g_array_index (child_data->basic_fd_assignments, int, i); - - unset_cloexec (fd); - } - } - - /* If we're doing remapping fd assignments, we need to handle - * the case where the user has specified e.g.: - * 5 -> 4, 4 -> 6 - * - * We do this by duping the source fds temporarily. - */ - if (child_data->needdup_fd_assignments) - { - for (i = 0; i < child_data->needdup_fd_assignments->len; i += 2) - { - gint parent_fd = g_array_index (child_data->needdup_fd_assignments, int, i); - gint new_parent_fd; - - new_parent_fd = dupfd_cloexec (parent_fd); - - g_array_index (child_data->needdup_fd_assignments, int, i) = new_parent_fd; - } - for (i = 0; i < child_data->needdup_fd_assignments->len; i += 2) - { - gint parent_fd = g_array_index (child_data->needdup_fd_assignments, int, i); - gint child_fd = g_array_index (child_data->needdup_fd_assignments, int, i+1); - - if (parent_fd == child_fd) - { - unset_cloexec (parent_fd); - } - else - { - do - { - result = dup2 (parent_fd, child_fd); - errsv = errno; - } - while (result == -1 && errsv == EINTR); - (void) close (parent_fd); - } - } - } - - if (child_data->child_setup_func) - child_data->child_setup_func (child_data->child_setup_data); -} -#endif - static GInputStream * platform_input_stream_from_spawn_fd (gint fd) { @@ -450,12 +296,12 @@ initable_init (GInitable *initable, GError **error) { GSubprocess *self = G_SUBPROCESS (initable); -#ifdef G_OS_UNIX - ChildData child_data = { { -1, -1, -1 }, 0 }; -#endif gint *pipe_ptrs[3] = { NULL, NULL, NULL }; gint pipe_fds[3] = { -1, -1, -1 }; gint close_fds[3] = { -1, -1, -1 }; +#ifdef G_OS_UNIX + gint stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; +#endif GSpawnFlags spawn_flags = 0; gboolean success = FALSE; gint i; @@ -480,11 +326,11 @@ initable_init (GInitable *initable, else if (self->launcher) { if (self->launcher->stdin_fd != -1) - child_data.fds[0] = self->launcher->stdin_fd; + stdin_fd = self->launcher->stdin_fd; else if (self->launcher->stdin_path != NULL) { - child_data.fds[0] = close_fds[0] = unix_open_file (self->launcher->stdin_path, O_RDONLY, error); - if (child_data.fds[0] == -1) + stdin_fd = close_fds[0] = unix_open_file (self->launcher->stdin_path, O_RDONLY, error); + if (stdin_fd == -1) goto out; } } @@ -499,11 +345,11 @@ initable_init (GInitable *initable, else if (self->launcher) { if (self->launcher->stdout_fd != -1) - child_data.fds[1] = self->launcher->stdout_fd; + stdout_fd = self->launcher->stdout_fd; else if (self->launcher->stdout_path != NULL) { - child_data.fds[1] = close_fds[1] = unix_open_file (self->launcher->stdout_path, O_CREAT | O_WRONLY, error); - if (child_data.fds[1] == -1) + stdout_fd = close_fds[1] = unix_open_file (self->launcher->stdout_path, O_CREAT | O_WRONLY, error); + if (stdout_fd == -1) goto out; } } @@ -516,29 +362,21 @@ initable_init (GInitable *initable, pipe_ptrs[2] = &pipe_fds[2]; #ifdef G_OS_UNIX else if (self->flags & G_SUBPROCESS_FLAGS_STDERR_MERGE) - /* This will work because stderr gets setup after stdout. */ - child_data.fds[2] = 1; + /* This will work because stderr gets set up after stdout. */ + stderr_fd = 1; else if (self->launcher) { if (self->launcher->stderr_fd != -1) - child_data.fds[2] = self->launcher->stderr_fd; + stderr_fd = self->launcher->stderr_fd; else if (self->launcher->stderr_path != NULL) { - child_data.fds[2] = close_fds[2] = unix_open_file (self->launcher->stderr_path, O_CREAT | O_WRONLY, error); - if (child_data.fds[2] == -1) + stderr_fd = close_fds[2] = unix_open_file (self->launcher->stderr_path, O_CREAT | O_WRONLY, error); + if (stderr_fd == -1) goto out; } } #endif -#ifdef G_OS_UNIX - if (self->launcher) - { - child_data.basic_fd_assignments = self->launcher->basic_fd_assignments; - child_data.needdup_fd_assignments = self->launcher->needdup_fd_assignments; - } -#endif - /* argv0 has no '/' in it? We better do a PATH lookup. */ if (strchr (self->argv[0], G_DIR_SEPARATOR) == NULL) { @@ -554,23 +392,25 @@ initable_init (GInitable *initable, spawn_flags |= G_SPAWN_DO_NOT_REAP_CHILD; spawn_flags |= G_SPAWN_CLOEXEC_PIPES; + success = g_spawn_async_with_pipes_and_fds (self->launcher ? self->launcher->cwd : NULL, + (const gchar * const *) self->argv, + (const gchar * const *) (self->launcher ? self->launcher->envp : NULL), + spawn_flags, #ifdef G_OS_UNIX - child_data.child_setup_func = self->launcher ? self->launcher->child_setup_func : NULL; - child_data.child_setup_data = self->launcher ? self->launcher->child_setup_user_data : NULL; -#endif - - success = g_spawn_async_with_pipes (self->launcher ? self->launcher->cwd : NULL, - self->argv, - self->launcher ? self->launcher->envp : NULL, - spawn_flags, -#ifdef G_OS_UNIX - child_setup, &child_data, + self->launcher ? self->launcher->child_setup_func : NULL, + self->launcher ? self->launcher->child_setup_user_data : NULL, + stdin_fd, stdout_fd, stderr_fd, + self->launcher ? (const gint *) self->launcher->source_fds->data : NULL, + self->launcher ? (const gint *) self->launcher->target_fds->data : NULL, + self->launcher ? self->launcher->source_fds->len : 0, #else - NULL, NULL, + NULL, NULL, + -1, -1, -1, + NULL, NULL, 0, #endif - &self->pid, - pipe_ptrs[0], pipe_ptrs[1], pipe_ptrs[2], - error); + &self->pid, + pipe_ptrs[0], pipe_ptrs[1], pipe_ptrs[2], + error); g_assert (success == (self->pid != 0)); { @@ -584,7 +424,7 @@ initable_init (GInitable *initable, #endif s = g_snprintf (self->identifier, sizeof self->identifier, "%"G_GUINT64_FORMAT, identifier); - g_assert (0 < s && s < sizeof self->identifier); + g_assert (0 < s && (gsize) s < sizeof self->identifier); } /* Start attempting to reap the child immediately */ @@ -773,10 +613,10 @@ g_subprocess_get_identifier (GSubprocess *subprocess) * Gets the #GOutputStream that you can write to in order to give data * to the stdin of @subprocess. * - * The process must have been created with - * %G_SUBPROCESS_FLAGS_STDIN_PIPE. + * The process must have been created with %G_SUBPROCESS_FLAGS_STDIN_PIPE and + * not %G_SUBPROCESS_FLAGS_STDIN_INHERIT, otherwise %NULL will be returned. * - * Returns: (transfer none): the stdout pipe + * Returns: (nullable) (transfer none): the stdout pipe * * Since: 2.40 **/ @@ -784,7 +624,6 @@ GOutputStream * g_subprocess_get_stdin_pipe (GSubprocess *subprocess) { g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL); - g_return_val_if_fail (subprocess->stdin_pipe, NULL); return subprocess->stdin_pipe; } @@ -796,10 +635,10 @@ g_subprocess_get_stdin_pipe (GSubprocess *subprocess) * Gets the #GInputStream from which to read the stdout output of * @subprocess. * - * The process must have been created with - * %G_SUBPROCESS_FLAGS_STDOUT_PIPE. + * The process must have been created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, + * otherwise %NULL will be returned. * - * Returns: (transfer none): the stdout pipe + * Returns: (nullable) (transfer none): the stdout pipe * * Since: 2.40 **/ @@ -807,7 +646,6 @@ GInputStream * g_subprocess_get_stdout_pipe (GSubprocess *subprocess) { g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL); - g_return_val_if_fail (subprocess->stdout_pipe, NULL); return subprocess->stdout_pipe; } @@ -819,10 +657,10 @@ g_subprocess_get_stdout_pipe (GSubprocess *subprocess) * Gets the #GInputStream from which to read the stderr output of * @subprocess. * - * The process must have been created with - * %G_SUBPROCESS_FLAGS_STDERR_PIPE. + * The process must have been created with %G_SUBPROCESS_FLAGS_STDERR_PIPE, + * otherwise %NULL will be returned. * - * Returns: (transfer none): the stderr pipe + * Returns: (nullable) (transfer none): the stderr pipe * * Since: 2.40 **/ @@ -830,7 +668,6 @@ GInputStream * g_subprocess_get_stderr_pipe (GSubprocess *subprocess) { g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), NULL); - g_return_val_if_fail (subprocess->stderr_pipe, NULL); return subprocess->stderr_pipe; } @@ -1595,6 +1432,23 @@ g_subprocess_communicate_internal (GSubprocess *subprocess, if (subprocess->stdin_pipe) { g_assert (stdin_buf != NULL); + +#ifdef G_OS_UNIX + /* We're doing async writes to the pipe, and the async write mechanism assumes + * that streams polling as writable do SOME progress (possibly partial) and then + * stop, but never block. + * + * However, for blocking pipes, unix will return writable if there is *any* space left + * but still block until the full buffer size is available before returning from write. + * So, to avoid async blocking on the main loop we make this non-blocking here. + * + * It should be safe to change the fd because we're the only user at this point as + * per the g_subprocess_communicate() docs, and all the code called by this function + * properly handles non-blocking fds. + */ + g_unix_set_fd_nonblocking (g_unix_output_stream_get_fd (G_UNIX_OUTPUT_STREAM (subprocess->stdin_pipe)), TRUE, NULL); +#endif + state->stdin_buf = g_memory_input_stream_new_from_bytes (stdin_buf); g_output_stream_splice_async (subprocess->stdin_pipe, (GInputStream*)state->stdin_buf, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, diff --git a/gio/gsubprocesslauncher-private.h b/gio/gsubprocesslauncher-private.h index 64374a02d86c0f95b17154d2eba3c4c3e3fa37d3..d6fe0d784a2267fab1c6c1f0284289335c04629e 100644 --- a/gio/gsubprocesslauncher-private.h +++ b/gio/gsubprocesslauncher-private.h @@ -42,8 +42,9 @@ struct _GSubprocessLauncher gint stderr_fd; gchar *stderr_path; - GArray *basic_fd_assignments; - GArray *needdup_fd_assignments; + GArray *source_fds; /* GSubprocessLauncher has ownership of the FD elements */ + GArray *target_fds; /* always the same length as source_fds; elements are just integers and not FDs in this process */ + gboolean closed_fd; GSpawnChildSetupFunc child_setup_func; gpointer child_setup_user_data; diff --git a/gio/gsubprocesslauncher.c b/gio/gsubprocesslauncher.c index 8c2f1c179869089330c9bb7f31625a40537a3ac8..a1c65e94714d4eee2b31327ee162eda63c4e6d87 100644 --- a/gio/gsubprocesslauncher.c +++ b/gio/gsubprocesslauncher.c @@ -46,6 +46,7 @@ #include "gioenumtypes.h" #include "gsubprocess.h" #include "ginitable.h" +#include "gioerror.h" #ifdef G_OS_UNIX #include @@ -131,47 +132,27 @@ g_subprocess_launcher_set_property (GObject *object, guint prop_id, } static void -g_subprocess_launcher_finalize (GObject *object) +g_subprocess_launcher_dispose (GObject *object) { GSubprocessLauncher *self = G_SUBPROCESS_LAUNCHER (object); #ifdef G_OS_UNIX - guint i; - - g_free (self->stdin_path); - g_free (self->stdout_path); - g_free (self->stderr_path); - - if (self->stdin_fd != -1) - close (self->stdin_fd); - - if (self->stdout_fd != -1) - close (self->stdout_fd); + g_clear_pointer (&self->stdin_path, g_free); + g_clear_pointer (&self->stdout_path, g_free); + g_clear_pointer (&self->stderr_path, g_free); - if (self->stderr_fd != -1) - close (self->stderr_fd); - - if (self->basic_fd_assignments) - { - for (i = 0; i < self->basic_fd_assignments->len; i++) - (void) close (g_array_index (self->basic_fd_assignments, int, i)); - g_array_unref (self->basic_fd_assignments); - } - if (self->needdup_fd_assignments) - { - for (i = 0; i < self->needdup_fd_assignments->len; i += 2) - (void) close (g_array_index (self->needdup_fd_assignments, int, i)); - g_array_unref (self->needdup_fd_assignments); - } + g_subprocess_launcher_close (self); if (self->child_setup_destroy_notify) (* self->child_setup_destroy_notify) (self->child_setup_user_data); + self->child_setup_destroy_notify = NULL; + self->child_setup_user_data = NULL; #endif - g_strfreev (self->envp); - g_free (self->cwd); + g_clear_pointer (&self->envp, g_strfreev); + g_clear_pointer (&self->cwd, g_free); - G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->finalize (object); + G_OBJECT_CLASS (g_subprocess_launcher_parent_class)->dispose (object); } static void @@ -183,8 +164,8 @@ g_subprocess_launcher_init (GSubprocessLauncher *self) self->stdin_fd = -1; self->stdout_fd = -1; self->stderr_fd = -1; - self->basic_fd_assignments = g_array_new (FALSE, 0, sizeof (int)); - self->needdup_fd_assignments = g_array_new (FALSE, 0, sizeof (int)); + self->source_fds = g_array_new (FALSE, 0, sizeof (int)); + self->target_fds = g_array_new (FALSE, 0, sizeof (int)); #endif } @@ -194,7 +175,7 @@ g_subprocess_launcher_class_init (GSubprocessLauncherClass *class) GObjectClass *gobject_class = G_OBJECT_CLASS (class); gobject_class->set_property = g_subprocess_launcher_set_property; - gobject_class->finalize = g_subprocess_launcher_finalize; + gobject_class->dispose = g_subprocess_launcher_dispose; g_object_class_install_property (gobject_class, 1, g_param_spec_flags ("flags", "Flags", "GSubprocessFlags for launched processes", @@ -322,7 +303,7 @@ g_subprocess_launcher_unsetenv (GSubprocessLauncher *self, * On UNIX, the returned string can be an arbitrary byte string. * On Windows, it will be UTF-8. * - * Returns: (type filename): the value of the environment variable, + * Returns: (nullable) (type filename): the value of the environment variable, * %NULL if unset * * Since: 2.40 @@ -615,16 +596,16 @@ g_subprocess_launcher_take_stderr_fd (GSubprocessLauncher *self, * @target_fd: Target descriptor for child process * * Transfer an arbitrary file descriptor from parent process to the - * child. This function takes "ownership" of the fd; it will be closed + * child. This function takes ownership of the @source_fd; it will be closed * in the parent when @self is freed. * * By default, all file descriptors from the parent will be closed. - * This function allows you to create (for example) a custom pipe() or - * socketpair() before launching the process, and choose the target + * This function allows you to create (for example) a custom `pipe()` or + * `socketpair()` before launching the process, and choose the target * descriptor in the child. * * An example use case is GNUPG, which has a command line argument - * --passphrase-fd providing a file descriptor number where it expects + * `--passphrase-fd` providing a file descriptor number where it expects * the passphrase to be written. */ void @@ -632,15 +613,64 @@ g_subprocess_launcher_take_fd (GSubprocessLauncher *self, gint source_fd, gint target_fd) { - if (source_fd == target_fd) + if (self->source_fds != NULL && self->target_fds != NULL) { - g_array_append_val (self->basic_fd_assignments, source_fd); + g_array_append_val (self->source_fds, source_fd); + g_array_append_val (self->target_fds, target_fd); } - else +} + +/** + * g_subprocess_launcher_close: + * @self: a #GSubprocessLauncher + * + * Closes all the file descriptors previously passed to the object with + * g_subprocess_launcher_take_fd(), g_subprocess_launcher_take_stderr_fd(), etc. + * + * After calling this method, any subsequent calls to g_subprocess_launcher_spawn() or g_subprocess_launcher_spawnv() will + * return %G_IO_ERROR_CLOSED. This method is idempotent if + * called more than once. + * + * This function is called automatically when the #GSubprocessLauncher + * is disposed, but is provided separately so that garbage collected + * language bindings can call it earlier to guarantee when FDs are closed. + * + * Since: 2.68 + */ +void +g_subprocess_launcher_close (GSubprocessLauncher *self) +{ + guint i; + + g_return_if_fail (G_IS_SUBPROCESS_LAUNCHER (self)); + + if (self->stdin_fd != -1) + close (self->stdin_fd); + self->stdin_fd = -1; + + if (self->stdout_fd != -1) + close (self->stdout_fd); + self->stdout_fd = -1; + + if (self->stderr_fd != -1) + close (self->stderr_fd); + self->stderr_fd = -1; + + if (self->source_fds) { - g_array_append_val (self->needdup_fd_assignments, source_fd); - g_array_append_val (self->needdup_fd_assignments, target_fd); + g_assert (self->target_fds != NULL); + g_assert (self->source_fds->len == self->target_fds->len); + + /* Note: Don’t close the target_fds, as they’re only valid FDs in the + * child process. This code never executes in the child process. */ + for (i = 0; i < self->source_fds->len; i++) + (void) close (g_array_index (self->source_fds, int, i)); + + g_clear_pointer (&self->source_fds, g_array_unref); + g_clear_pointer (&self->target_fds, g_array_unref); } + + self->closed_fd = TRUE; } /** @@ -745,6 +775,17 @@ g_subprocess_launcher_spawnv (GSubprocessLauncher *launcher, g_return_val_if_fail (argv != NULL && argv[0] != NULL && argv[0][0] != '\0', NULL); +#ifdef G_OS_UNIX + if (launcher->closed_fd) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_CLOSED, + "Can't spawn a new child because a passed file descriptor has been closed."); + return NULL; + } +#endif + subprocess = g_object_new (G_TYPE_SUBPROCESS, "argv", argv, "flags", launcher->flags, diff --git a/gio/gsubprocesslauncher.h b/gio/gsubprocesslauncher.h index 05d83f131d346d8f583669df833ee25a1c69e911..0654c2b7018842cef3a79f4bf2867ec20ccff221 100644 --- a/gio/gsubprocesslauncher.h +++ b/gio/gsubprocesslauncher.h @@ -103,6 +103,9 @@ void g_subprocess_launcher_take_fd (GSubpro gint source_fd, gint target_fd); +GLIB_AVAILABLE_IN_2_68 +void g_subprocess_launcher_close (GSubprocessLauncher *self); + /* Child setup, only available on UNIX */ GLIB_AVAILABLE_IN_2_40 void g_subprocess_launcher_set_child_setup (GSubprocessLauncher *self, diff --git a/gio/gtask.c b/gio/gtask.c index 9950bb36ba47a621c493a643b371ab9a4d4f15e0..2b4720de89d52fe4f826ee7746af77a3e749d24b 100644 --- a/gio/gtask.c +++ b/gio/gtask.c @@ -24,9 +24,12 @@ #include "gasyncresult.h" #include "gcancellable.h" #include "glib-private.h" +#include "gtrace-private.h" #include "glibintl.h" +#include + /** * SECTION:gtask * @short_description: Cancellable synchronous or asynchronous task @@ -616,6 +619,9 @@ static GSource *task_pool_manager; static guint64 task_wait_time; static gint tasks_running; +static guint task_pool_max_counter; +static guint tasks_running_counter; + /* When the task pool fills up and blocks, and the program keeps * queueing more tasks, we will slowly add more threads to the pool * (in case the existing tasks are trying to queue subtasks of their @@ -757,6 +763,7 @@ g_task_report_error (gpointer source_object, task = g_task_new (source_object, NULL, callback, callback_data); g_task_set_source_tag (task, source_tag); + g_task_set_name (task, G_STRFUNC); g_task_return_error (task, error); g_object_unref (task); } @@ -909,7 +916,7 @@ static void g_task_thread_complete (GTask *task); * g_task_return_error_if_cancelled() and then returned. * * This allows you to create a cancellable wrapper around an - * uninterruptable function. The #GTaskThreadFunc just needs to be + * uninterruptible function. The #GTaskThreadFunc just needs to be * careful that it does not modify any externally-visible state after * it has been cancelled. To do that, the thread should call * g_task_set_return_on_cancel() again to (atomically) set @@ -980,8 +987,8 @@ g_task_set_return_on_cancel (GTask *task, * Since: 2.36 */ void -g_task_set_source_tag (GTask *task, - gpointer source_tag) +(g_task_set_source_tag) (GTask *task, + gpointer source_tag) { g_return_if_fail (G_IS_TASK (task)); @@ -1239,6 +1246,7 @@ g_task_return (GTask *task, GTaskReturnType type) { GSource *source; + gchar *source_name = NULL; if (type != G_TASK_RETURN_FROM_THREAD) task->ever_returned = TRUE; @@ -1287,7 +1295,10 @@ g_task_return (GTask *task, /* Otherwise, complete in the next iteration */ source = g_idle_source_new (); - g_source_set_name (source, "[gio] complete_in_idle_cb"); + source_name = g_strdup_printf ("[gio] %s complete_in_idle_cb", + (task->name != NULL) ? task->name : "(unnamed)"); + g_source_set_name (source, source_name); + g_free (source_name); g_task_attach_source (task, source, complete_in_idle_cb); g_source_unref (source); } @@ -1354,6 +1365,7 @@ task_pool_manager_timeout (gpointer user_data) { g_mutex_lock (&task_pool_mutex); g_thread_pool_set_max_threads (task_pool, tasks_running + 1, NULL); + g_trace_set_int64_counter (task_pool_max_counter, tasks_running + 1); g_source_set_ready_time (task_pool_manager, -1); g_mutex_unlock (&task_pool_mutex); @@ -1367,6 +1379,8 @@ g_task_thread_setup (void) g_mutex_lock (&task_pool_mutex); tasks_running++; + g_trace_set_int64_counter (tasks_running_counter, tasks_running); + if (tasks_running == G_TASK_POOL_SIZE) task_wait_time = G_TASK_WAIT_TIME_BASE; else if (tasks_running > G_TASK_POOL_SIZE && tasks_running < G_TASK_WAIT_TIME_MAX_POOL_SIZE) @@ -1387,7 +1401,10 @@ g_task_thread_cleanup (void) tasks_pending = g_thread_pool_unprocessed (task_pool); if (tasks_running > G_TASK_POOL_SIZE) - g_thread_pool_set_max_threads (task_pool, tasks_running - 1, NULL); + { + g_thread_pool_set_max_threads (task_pool, tasks_running - 1, NULL); + g_trace_set_int64_counter (task_pool_max_counter, tasks_running - 1); + } else if (tasks_running + tasks_pending < G_TASK_POOL_SIZE) g_source_set_ready_time (task_pool_manager, -1); @@ -1395,6 +1412,9 @@ g_task_thread_cleanup (void) task_wait_time /= G_TASK_WAIT_TIME_MULTIPLIER; tasks_running--; + + g_trace_set_int64_counter (tasks_running_counter, tasks_running); + g_mutex_unlock (&task_pool_mutex); g_private_set (&task_private, GUINT_TO_POINTER (FALSE)); } @@ -1497,7 +1517,7 @@ g_task_start_task_thread (GTask *task, /** * g_task_run_in_thread: * @task: a #GTask - * @task_func: a #GTaskThreadFunc + * @task_func: (scope async): a #GTaskThreadFunc * * Runs @task_func in another thread. When @task_func returns, @task's * #GAsyncReadyCallback will be invoked in @task's #GMainContext. @@ -1540,7 +1560,7 @@ g_task_run_in_thread (GTask *task, /** * g_task_run_in_thread_sync: * @task: a #GTask - * @task_func: a #GTaskThreadFunc + * @task_func: (scope async): a #GTaskThreadFunc * * Runs @task_func in another thread, and waits for it to return or be * cancelled. You can use g_task_propagate_pointer(), etc, afterward @@ -1959,6 +1979,100 @@ g_task_had_error (GTask *task) return FALSE; } +static void +value_free (gpointer value) +{ + g_value_unset (value); + g_free (value); +} + +/** + * g_task_return_value: + * @task: a #GTask + * @result: (nullable) (transfer none): the #GValue result of + * a task function + * + * Sets @task's result to @result (by copying it) and completes the task. + * + * If @result is %NULL then a #GValue of type #G_TYPE_POINTER + * with a value of %NULL will be used for the result. + * + * This is a very generic low-level method intended primarily for use + * by language bindings; for C code, g_task_return_pointer() and the + * like will normally be much easier to use. + * + * Since: 2.64 + */ +void +g_task_return_value (GTask *task, + GValue *result) +{ + GValue *value; + + g_return_if_fail (G_IS_TASK (task)); + g_return_if_fail (!task->ever_returned); + + value = g_new0 (GValue, 1); + + if (result == NULL) + { + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, NULL); + } + else + { + g_value_init (value, G_VALUE_TYPE (result)); + g_value_copy (result, value); + } + + g_task_return_pointer (task, value, value_free); +} + +/** + * g_task_propagate_value: + * @task: a #GTask + * @value: (out caller-allocates): return location for the #GValue + * @error: return location for a #GError + * + * Gets the result of @task as a #GValue, and transfers ownership of + * that value to the caller. As with g_task_return_value(), this is + * a generic low-level method; g_task_propagate_pointer() and the like + * will usually be more useful for C code. + * + * If the task resulted in an error, or was cancelled, then this will + * instead set @error and return %FALSE. + * + * Since this method transfers ownership of the return value (or + * error) to the caller, you may only call it once. + * + * Returns: %TRUE if @task succeeded, %FALSE on error. + * + * Since: 2.64 + */ +gboolean +g_task_propagate_value (GTask *task, + GValue *value, + GError **error) +{ + g_return_val_if_fail (G_IS_TASK (task), FALSE); + g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (g_task_propagate_error (task, error)) + return FALSE; + + g_return_val_if_fail (task->result_set, FALSE); + g_return_val_if_fail (task->result_destroy == value_free, FALSE); + + memcpy (value, task->result.pointer, sizeof (GValue)); + g_free (task->result.pointer); + + task->result_destroy = NULL; + task->result_set = FALSE; + + return TRUE; +} + /** * g_task_get_completed: * @task: a #GTask. @@ -2048,7 +2162,9 @@ GSourceFuncs trivial_source_funcs = { NULL, /* prepare */ NULL, /* check */ trivial_source_dispatch, - NULL + NULL, /* finalize */ + NULL, /* closure */ + NULL /* marshal */ }; static void @@ -2113,6 +2229,16 @@ g_task_class_init (GTaskClass *klass) P_("Task completed"), P_("Whether the task has completed yet"), FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + if (G_UNLIKELY (task_pool_max_counter == 0)) + { + /* We use two counters to track characteristics of the GTask thread pool. + * task pool max size - the value of g_thread_pool_set_max_threads() + * tasks running - the number of running threads + */ + task_pool_max_counter = g_trace_define_int64_counter ("GIO", "task pool max size", "Maximum number of threads allowed in the GTask thread pool; see g_thread_pool_set_max_threads()"); + tasks_running_counter = g_trace_define_int64_counter ("GIO", "tasks running", "Number of currently running tasks in the GTask thread pool"); + } } static gpointer diff --git a/gio/gtask.h b/gio/gtask.h index 4fc1c859e3c87e14bacd0f4ad4edc3cb969aed70..bc6454a255dabc7001ad21af8334e9ecec458e6f 100644 --- a/gio/gtask.h +++ b/gio/gtask.h @@ -78,6 +78,16 @@ GLIB_AVAILABLE_IN_2_60 void g_task_set_name (GTask *task, const gchar *name); +/* Macro wrapper to set the task name when setting the source tag. */ +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_60 +#define g_task_set_source_tag(task, tag) G_STMT_START { \ + GTask *_task = (task); \ + (g_task_set_source_tag) (_task, tag); \ + if (g_task_get_name (_task) == NULL) \ + g_task_set_name (_task, G_STRINGIFY (tag)); \ +} G_STMT_END +#endif + GLIB_AVAILABLE_IN_2_36 gpointer g_task_get_source_object (GTask *task); GLIB_AVAILABLE_IN_2_36 @@ -142,6 +152,9 @@ void g_task_return_new_error (GTask *task, gint code, const char *format, ...) G_GNUC_PRINTF (4, 5); +GLIB_AVAILABLE_IN_2_64 +void g_task_return_value (GTask *task, + GValue *result); GLIB_AVAILABLE_IN_2_36 gboolean g_task_return_error_if_cancelled (GTask *task); @@ -155,6 +168,10 @@ gboolean g_task_propagate_boolean (GTask *task, GLIB_AVAILABLE_IN_2_36 gssize g_task_propagate_int (GTask *task, GError **error); +GLIB_AVAILABLE_IN_2_64 +gboolean g_task_propagate_value (GTask *task, + GValue *value, + GError **error); GLIB_AVAILABLE_IN_2_36 gboolean g_task_had_error (GTask *task); GLIB_AVAILABLE_IN_2_44 diff --git a/gio/gtcpwrapperconnection.c b/gio/gtcpwrapperconnection.c index 9c00869daa675d7072c179f4161fe8a5bb1e4dde..7c3bf694c7440407f5455e74d6fe937181c0dc49 100644 --- a/gio/gtcpwrapperconnection.c +++ b/gio/gtcpwrapperconnection.c @@ -188,7 +188,7 @@ g_tcp_wrapper_connection_new (GIOStream *base_io_stream, * g_tcp_wrapper_connection_get_base_io_stream: * @conn: a #GTcpWrapperConnection * - * Get's @conn's base #GIOStream + * Gets @conn's base #GIOStream * * Returns: (transfer none): @conn's base #GIOStream */ diff --git a/gio/gtestdbus.c b/gio/gtestdbus.c index 11cf029d9058c33f66ed32a5e8d4398636bdb2d3..d362f94789230d39536550c40bce7b0ea0c2a7f0 100644 --- a/gio/gtestdbus.c +++ b/gio/gtestdbus.c @@ -251,6 +251,16 @@ watcher_init (void) g_assert_not_reached (); } + /* flush streams to avoid buffers being duplicated in the child and + * flushed by both the child and parent later + * + * FIXME: This is a workaround for the fact that watch_parent() uses + * non-async-signal-safe API. See + * https://gitlab.gnome.org/GNOME/glib/-/issues/2322#note_1034330 + */ + fflush (stdout); + fflush (stderr); + switch (fork ()) { case -1: @@ -282,10 +292,13 @@ watcher_send_command (const gchar *command) { GIOChannel *channel; GError *error = NULL; + GIOStatus status; channel = watcher_init (); - g_io_channel_write_chars (channel, command, -1, NULL, &error); + do + status = g_io_channel_write_chars (channel, command, -1, NULL, &error); + while (status == G_IO_STATUS_AGAIN); g_assert_no_error (error); g_io_channel_flush (channel, &error); @@ -573,7 +586,9 @@ write_config_file (GTestDBus *self) "\n"); close (fd); - g_file_set_contents (path, contents->str, contents->len, &error); + g_file_set_contents_full (path, contents->str, contents->len, + G_FILE_SET_CONTENTS_NONE, + 0600, &error); g_assert_no_error (error); g_string_free (contents, TRUE); @@ -604,11 +619,12 @@ start_daemon (GTestDBus *self) g_spawn_async_with_pipes (NULL, (gchar **) argv, NULL, -#ifdef G_OS_WIN32 /* We Need this to get the pid returned on win32 */ G_SPAWN_DO_NOT_REAP_CHILD | -#endif - G_SPAWN_SEARCH_PATH, + G_SPAWN_SEARCH_PATH | + /* dbus-daemon will not abuse our descriptors, and + * passing this means we can use posix_spawn() for speed */ + G_SPAWN_LEAVE_DESCRIPTORS_OPEN, NULL, NULL, &self->priv->bus_pid, diff --git a/gio/gthreadedresolver.c b/gio/gthreadedresolver.c index 7691b91240c236105bc710206ee9910c1311d988..d170c73a9c58e04ba50b9e713792645a1d131fdf 100644 --- a/gio/gthreadedresolver.c +++ b/gio/gthreadedresolver.c @@ -187,6 +187,7 @@ lookup_by_name (GResolver *resolver, data = lookup_data_new (hostname, AF_UNSPEC); task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_by_name); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, do_lookup_by_name); @@ -228,6 +229,7 @@ lookup_by_name_with_flags (GResolver *resolver, data = lookup_data_new (hostname, AF_UNSPEC); task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_by_name_with_flags); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, do_lookup_by_name); @@ -251,6 +253,7 @@ lookup_by_name_with_flags_async (GResolver *resolver, data = lookup_data_new (hostname, flags_to_family (flags)); task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_with_flags_async); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread (task, do_lookup_by_name); @@ -350,6 +353,7 @@ lookup_by_address (GResolver *resolver, task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_by_address); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, g_object_ref (address), g_object_unref); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, do_lookup_by_address); @@ -370,6 +374,7 @@ lookup_by_address_async (GResolver *resolver, task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_address_async); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, g_object_ref (address), g_object_unref); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread (task, do_lookup_by_address); @@ -398,7 +403,7 @@ typedef struct { /* fields in third byte */ unsigned qr: 1; /* response flag */ unsigned opcode: 4; /* purpose of message */ - unsigned aa: 1; /* authoritive answer */ + unsigned aa: 1; /* authoritative answer */ unsigned tc: 1; /* truncated message */ unsigned rd: 1; /* recursion desired */ /* fields in fourth byte */ @@ -412,7 +417,7 @@ typedef struct { /* fields in third byte */ unsigned rd :1; /* recursion desired */ unsigned tc :1; /* truncated message */ - unsigned aa :1; /* authoritive answer */ + unsigned aa :1; /* authoritative answer */ unsigned opcode :4; /* purpose of message */ unsigned qr :1; /* response flag */ /* fields in fourth byte */ @@ -508,7 +513,7 @@ typedef enum __ns_type { ns_t_cert = 37, /* Certification record */ ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ - ns_t_sink = 40, /* Kitchen sink (experimentatl) */ + ns_t_sink = 40, /* Kitchen sink (experimental) */ ns_t_opt = 41, /* EDNS0 option (meta-RR) */ ns_t_apl = 42, /* Address prefix list (RFC 3123) */ ns_t_tkey = 249, /* Transaction key */ @@ -615,7 +620,7 @@ parse_res_txt (guchar *answer, while (at < end) { len = *(at++); - if (len > at - end) + if (len > (gsize) (end - at)) break; g_ptr_array_add (array, g_strndup ((gchar *)at, len)); at += len; @@ -1040,6 +1045,7 @@ lookup_records (GResolver *resolver, task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_records); + g_task_set_name (task, "[gio] resolver lookup records"); lrd = g_slice_new (LookupRecordsData); lrd->rrname = g_strdup (rrname); @@ -1067,6 +1073,7 @@ lookup_records_async (GResolver *resolver, task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_records_async); + g_task_set_name (task, "[gio] resolver lookup records"); lrd = g_slice_new (LookupRecordsData); lrd->rrname = g_strdup (rrname); diff --git a/gio/gthreadedsocketservice.c b/gio/gthreadedsocketservice.c index c48a934242f0e350f64100d4db2b93fbcf32bf6a..6416e3a16758860ba44c6cc519fdf7414686f3a1 100644 --- a/gio/gthreadedsocketservice.c +++ b/gio/gthreadedsocketservice.c @@ -226,7 +226,7 @@ g_threaded_socket_service_class_init (GThreadedSocketServiceClass *class) * GThreadedSocketService::run: * @service: the #GThreadedSocketService. * @connection: a new #GSocketConnection object. - * @source_object: the source_object passed to g_socket_listener_add_address(). + * @source_object: (nullable): the source_object passed to g_socket_listener_add_address(). * * The ::run signal is emitted in a worker thread in response to an * incoming connection. This thread is dedicated to handling diff --git a/gio/gtlsbackend.c b/gio/gtlsbackend.c index d67e49012b04f7f27106146eae5dd1fd1468cb1b..25569aad73b2554c4faf80930dc634c2b9118382 100644 --- a/gio/gtlsbackend.c +++ b/gio/gtlsbackend.c @@ -93,20 +93,33 @@ g_tls_backend_default_init (GTlsBackendInterface *iface) { } +static GTlsBackend *tls_backend_default_singleton = NULL; /* (owned) (atomic) */ + /** * g_tls_backend_get_default: * * Gets the default #GTlsBackend for the system. * - * Returns: (transfer none): a #GTlsBackend + * Returns: (not nullable) (transfer none): a #GTlsBackend, which will be a + * dummy object if no TLS backend is available * * Since: 2.28 */ GTlsBackend * g_tls_backend_get_default (void) { - return _g_io_module_get_default (G_TLS_BACKEND_EXTENSION_POINT_NAME, - "GIO_USE_TLS", NULL); + if (g_once_init_enter (&tls_backend_default_singleton)) + { + GTlsBackend *singleton; + + singleton = _g_io_module_get_default (G_TLS_BACKEND_EXTENSION_POINT_NAME, + "GIO_USE_TLS", + NULL); + + g_once_init_leave (&tls_backend_default_singleton, singleton); + } + + return tls_backend_default_singleton; } /** diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c index 72de5eb1fc3977effb80ba271a9038a8c4dde182..9d00272f8461e32aba2079160b98f67625307814 100644 --- a/gio/gtlscertificate.c +++ b/gio/gtlscertificate.c @@ -60,7 +60,9 @@ enum PROP_CERTIFICATE_PEM, PROP_PRIVATE_KEY, PROP_PRIVATE_KEY_PEM, - PROP_ISSUER + PROP_ISSUER, + PROP_PKCS11_URI, + PROP_PRIVATE_KEY_PKCS11_URI, }; static void @@ -74,7 +76,16 @@ g_tls_certificate_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) + { + case PROP_PKCS11_URI: + case PROP_PRIVATE_KEY_PKCS11_URI: + /* Subclasses must override this property but this allows older backends to not fatally error */ + g_value_set_static_string (value, NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void @@ -83,7 +94,15 @@ g_tls_certificate_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) + { + case PROP_PKCS11_URI: + case PROP_PRIVATE_KEY_PKCS11_URI: + /* Subclasses must override this property but this allows older backends to not fatally error */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void @@ -193,6 +212,42 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:pkcs11-uri: (nullable) + * + * A URI referencing the PKCS \#11 objects containing an X.509 certificate + * and optionally a private key. + * + * If %NULL the certificate is either not backed by PKCS \#11 or the + * #GTlsBackend does not support PKCS \#11. + * + * Since: 2.68 + */ + g_object_class_install_property (gobject_class, PROP_PKCS11_URI, + g_param_spec_string ("pkcs11-uri", + P_("PKCS #11 URI"), + P_("The PKCS #11 URI"), + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:private-key-pkcs11-uri: (nullable) + * + * A URI referencing a PKCS \#11 object containing a private key. + * + * Since: 2.68 + */ + g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_PKCS11_URI, + g_param_spec_string ("private-key-pkcs11-uri", + P_("PKCS #11 URI"), + P_("The PKCS #11 URI for a private key"), + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); } static GTlsCertificate * @@ -591,6 +646,77 @@ g_tls_certificate_new_from_files (const gchar *cert_file, return cert; } +/** + * g_tls_certificate_new_from_pkcs11_uris: + * @pkcs11_uri: A PKCS \#11 URI + * @private_key_pkcs11_uri: (nullable): A PKCS \#11 URI + * @error: #GError for error reporting, or %NULL to ignore. + * + * Creates a #GTlsCertificate from a PKCS \#11 URI. + * + * An example @pkcs11_uri would be `pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01` + * + * Where the token’s layout is: + * + * ``` + * Object 0: + * URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=private%20key;type=private + * Type: Private key (RSA-2048) + * ID: 01 + * + * Object 1: + * URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=Certificate%20for%20Authentication;type=cert + * Type: X.509 Certificate (RSA-2048) + * ID: 01 + * ``` + * + * In this case the certificate and private key would both be detected and used as expected. + * @pkcs_uri may also just reference an X.509 certificate object and then optionally + * @private_key_pkcs11_uri allows using a private key exposed under a different URI. + * + * Note that the private key is not accessed until usage and may fail or require a PIN later. + * + * Returns: (transfer full): the new certificate, or %NULL on error + * + * Since: 2.68 + */ +GTlsCertificate * +g_tls_certificate_new_from_pkcs11_uris (const gchar *pkcs11_uri, + const gchar *private_key_pkcs11_uri, + GError **error) +{ + GObject *cert; + GTlsBackend *backend; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + g_return_val_if_fail (pkcs11_uri, NULL); + + backend = g_tls_backend_get_default (); + + cert = g_initable_new (g_tls_backend_get_certificate_type (backend), + NULL, error, + "pkcs11-uri", pkcs11_uri, + "private-key-pkcs11-uri", private_key_pkcs11_uri, + NULL); + + if (cert != NULL) + { + gchar *objects_uri; + + /* Old implementations might not override this property */ + g_object_get (cert, "pkcs11-uri", &objects_uri, NULL); + if (objects_uri == NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This GTlsBackend does not support creating PKCS #11 certificates")); + g_object_unref (cert); + return NULL; + } + g_free (objects_uri); + } + + return G_TLS_CERTIFICATE (cert); +} + /** * g_tls_certificate_list_new_from_file: * @file: (type filename): file containing PEM-encoded certificates to import @@ -658,7 +784,7 @@ g_tls_certificate_list_new_from_file (const gchar *file, * * Gets the #GTlsCertificate representing @cert's issuer, if known * - * Returns: (transfer none): The certificate of @cert's issuer, + * Returns: (nullable) (transfer none): The certificate of @cert's issuer, * or %NULL if @cert is self-signed or signed with an unknown * certificate. * diff --git a/gio/gtlscertificate.h b/gio/gtlscertificate.h index a064543c440691a0e7d4578ee32e607d0b11efc2..ead4f015e3b1909a1c26b238c851101e132fde4d 100644 --- a/gio/gtlscertificate.h +++ b/gio/gtlscertificate.h @@ -71,6 +71,11 @@ GLIB_AVAILABLE_IN_ALL GTlsCertificate *g_tls_certificate_new_from_files (const gchar *cert_file, const gchar *key_file, GError **error); +GLIB_AVAILABLE_IN_2_68 +GTlsCertificate *g_tls_certificate_new_from_pkcs11_uris (const gchar *pkcs11_uri, + const gchar *private_key_pkcs11_uri, + GError **error); + GLIB_AVAILABLE_IN_ALL GList *g_tls_certificate_list_new_from_file (const gchar *file, GError **error); diff --git a/gio/gtlsclientconnection.c b/gio/gtlsclientconnection.c index b38fad630f4e1b8e3c8ef659a51a12a48404c593..d0a740f4fe43b79f207468a3640dcce945267886 100644 --- a/gio/gtlsclientconnection.c +++ b/gio/gtlsclientconnection.c @@ -55,7 +55,7 @@ g_tls_client_connection_default_init (GTlsClientConnectionInterface *iface) * GTlsClientConnection:validation-flags: * * What steps to perform when validating a certificate received from - * a server. Server certificates that fail to validate in all of the + * a server. Server certificates that fail to validate in any of the * ways indicated here will be rejected unless the application * overrides the default via #GTlsConnection::accept-certificate. * @@ -103,14 +103,12 @@ g_tls_client_connection_default_init (GTlsClientConnectionInterface *iface) /** * GTlsClientConnection:use-ssl3: * - * If %TRUE, forces the connection to use a fallback version of TLS - * or SSL, rather than trying to negotiate the best version of TLS - * to use. See g_tls_client_connection_set_use_ssl3(). + * SSL 3.0 is no longer supported. See + * g_tls_client_connection_set_use_ssl3() for details. * * Since: 2.28 * - * Deprecated: 2.56: SSL 3.0 is insecure, and this property does not - * generally enable or disable it, despite its name. + * Deprecated: 2.56: SSL 3.0 is insecure. */ g_object_interface_install_property (iface, g_param_spec_boolean ("use-ssl3", @@ -226,7 +224,7 @@ g_tls_client_connection_set_validation_flags (GTlsClientConnection *conn, * * Gets @conn's expected server identity * - * Returns: (transfer none): a #GSocketConnectable describing the + * Returns: (nullable) (transfer none): a #GSocketConnectable describing the * expected server identity, or %NULL if the expected identity is not * known. * @@ -270,16 +268,14 @@ g_tls_client_connection_set_server_identity (GTlsClientConnection *conn, * g_tls_client_connection_get_use_ssl3: * @conn: the #GTlsClientConnection * - * Gets whether @conn will force the lowest-supported TLS protocol - * version rather than attempt to negotiate the highest mutually- - * supported version of TLS; see g_tls_client_connection_set_use_ssl3(). + * SSL 3.0 is no longer supported. See + * g_tls_client_connection_set_use_ssl3() for details. * - * Returns: whether @conn will use the lowest-supported TLS protocol version + * Returns: %FALSE * * Since: 2.28 * - * Deprecated: 2.56: SSL 3.0 is insecure, and this function does not - * actually indicate whether it is enabled. + * Deprecated: 2.56: SSL 3.0 is insecure. */ gboolean g_tls_client_connection_get_use_ssl3 (GTlsClientConnection *conn) @@ -289,32 +285,28 @@ g_tls_client_connection_get_use_ssl3 (GTlsClientConnection *conn) g_return_val_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn), 0); g_object_get (G_OBJECT (conn), "use-ssl3", &use_ssl3, NULL); - return use_ssl3; + return FALSE; } /** * g_tls_client_connection_set_use_ssl3: * @conn: the #GTlsClientConnection - * @use_ssl3: whether to use the lowest-supported protocol version - * - * Since 2.42.1, if @use_ssl3 is %TRUE, this forces @conn to use the - * lowest-supported TLS protocol version rather than trying to properly - * negotiate the highest mutually-supported protocol version with the - * peer. Be aware that SSL 3.0 is generally disabled by the - * #GTlsBackend, so the lowest-supported protocol version is probably - * not SSL 3.0. - * - * Since 2.58, this may additionally cause an RFC 7507 fallback SCSV to - * be sent to the server, causing modern TLS servers to immediately - * terminate the connection. You should generally only use this function - * if you need to connect to broken servers that exhibit TLS protocol - * version intolerance, and when an initial attempt to connect to a - * server normally has already failed. + * @use_ssl3: a #gboolean, ignored + * + * Since GLib 2.42.1, SSL 3.0 is no longer supported. + * + * From GLib 2.42.1 through GLib 2.62, this function could be used to + * force use of TLS 1.0, the lowest-supported TLS protocol version at + * the time. In the past, this was needed to connect to broken TLS + * servers that exhibited protocol version intolerance. Such servers + * are no longer common, and using TLS 1.0 is no longer considered + * acceptable. + * + * Since GLib 2.64, this function does nothing. * * Since: 2.28 * - * Deprecated: 2.56: SSL 3.0 is insecure, and this function does not - * generally enable or disable it, despite its name. + * Deprecated: 2.56: SSL 3.0 is insecure. */ void g_tls_client_connection_set_use_ssl3 (GTlsClientConnection *conn, @@ -322,7 +314,7 @@ g_tls_client_connection_set_use_ssl3 (GTlsClientConnection *conn, { g_return_if_fail (G_IS_TLS_CLIENT_CONNECTION (conn)); - g_object_set (G_OBJECT (conn), "use-ssl3", use_ssl3, NULL); + g_object_set (G_OBJECT (conn), "use-ssl3", FALSE, NULL); } /** @@ -359,12 +351,34 @@ g_tls_client_connection_get_accepted_cas (GTlsClientConnection *conn) * @conn: a #GTlsClientConnection * @source: a #GTlsClientConnection * - * Copies session state from one connection to another. This is - * not normally needed, but may be used when the same session - * needs to be used between different endpoints as is required - * by some protocols such as FTP over TLS. @source should have - * already completed a handshake, and @conn should not have - * completed a handshake. + * Possibly copies session state from one connection to another, for use + * in TLS session resumption. This is not normally needed, but may be + * used when the same session needs to be used between different + * endpoints, as is required by some protocols, such as FTP over TLS. + * @source should have already completed a handshake and, since TLS 1.3, + * it should have been used to read data at least once. @conn should not + * have completed a handshake. + * + * It is not possible to know whether a call to this function will + * actually do anything. Because session resumption is normally used + * only for performance benefit, the TLS backend might not implement + * this function. Even if implemented, it may not actually succeed in + * allowing @conn to resume @source's TLS session, because the server + * may not have sent a session resumption token to @source, or it may + * refuse to accept the token from @conn. There is no way to know + * whether a call to this function is actually successful. + * + * Using this function is not required to benefit from session + * resumption. If the TLS backend supports session resumption, the + * session will be resumed automatically if it is possible to do so + * without weakening the privacy guarantees normally provided by TLS, + * without need to call this function. For example, with TLS 1.3, + * a session ticket will be automatically copied from any + * #GTlsClientConnection that has previously received session tickets + * from the server, provided a ticket is available that has not + * previously been used for session resumption, since session ticket + * reuse would be a privacy weakness. Using this function causes the + * ticket to be copied without regard for privacy considerations. * * Since: 2.46 */ diff --git a/gio/gtlsconnection.c b/gio/gtlsconnection.c index 2e431ae7eb584db0fe888915d5aae3a51bafecfd..5654ca9ee9ab7c7a0f46447675ef87b6814739f3 100644 --- a/gio/gtlsconnection.c +++ b/gio/gtlsconnection.c @@ -139,9 +139,10 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED)); /** - * GTlsConnection:database: + * GTlsConnection:database: (nullable) * * The certificate database to use when verifying this TLS connection. * If no certificate database is set, then the default database will be @@ -157,7 +158,7 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** - * GTlsConnection:interaction: + * GTlsConnection:interaction: (nullable) * * A #GTlsInteraction object to be used when the connection or certificate * database need to interact with the user. This will be used to prompt the @@ -195,6 +196,8 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) * g_tls_connection_set_rehandshake_mode(). * * Since: 2.28 + * + * Deprecated: 2.60: The rehandshake mode is ignored. */ g_object_class_install_property (gobject_class, PROP_REHANDSHAKE_MODE, g_param_spec_enum ("rehandshake-mode", @@ -222,12 +225,11 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** - * GTlsConnection:peer-certificate: + * GTlsConnection:peer-certificate: (nullable) * * The connection's peer's certificate, after the TLS handshake has - * completed and the certificate has been accepted. Note in - * particular that this is not yet set during the emission of - * #GTlsConnection::accept-certificate. + * completed or failed. Note in particular that this is not yet set + * during the emission of #GTlsConnection::accept-certificate. * * (You can watch for a #GObject::notify signal on this property to * detect when a handshake has occurred.) @@ -244,7 +246,7 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) /** * GTlsConnection:peer-certificate-errors: * - * The errors noticed-and-ignored while verifying + * The errors noticed while verifying * #GTlsConnection:peer-certificate. Normally this should be 0, but * it may not be if #GTlsClientConnection:validation-flags is not * %G_TLS_CERTIFICATE_VALIDATE_ALL, or if @@ -262,7 +264,7 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /** - * GTlsConnection:advertised-protocols: + * GTlsConnection:advertised-protocols: (nullable) * * The list of application-layer protocols that the connection * advertises that it is willing to speak. See @@ -442,7 +444,7 @@ g_tls_connection_get_use_system_certdb (GTlsConnection *conn) /** * g_tls_connection_set_database: * @conn: a #GTlsConnection - * @database: a #GTlsDatabase + * @database: (nullable): a #GTlsDatabase * * Sets the certificate database that is used to verify peer certificates. * This is set to the default database by default. See @@ -474,7 +476,7 @@ g_tls_connection_set_database (GTlsConnection *conn, * Gets the certificate database that @conn uses to verify * peer certificates. See g_tls_connection_set_database(). * - * Returns: (transfer none): the certificate database that @conn uses or %NULL + * Returns: (transfer none) (nullable): the certificate database that @conn uses or %NULL * * Since: 2.30 */ @@ -536,7 +538,7 @@ g_tls_connection_set_certificate (GTlsConnection *conn, * Gets @conn's certificate, as set by * g_tls_connection_set_certificate(). * - * Returns: (transfer none): @conn's certificate, or %NULL + * Returns: (transfer none) (nullable): @conn's certificate, or %NULL * * Since: 2.28 */ @@ -586,7 +588,7 @@ g_tls_connection_set_interaction (GTlsConnection *conn, * for things like prompting the user for passwords. If %NULL is returned, then * no user interaction will occur for this connection. * - * Returns: (transfer none): The interaction object. + * Returns: (transfer none) (nullable): The interaction object. * * Since: 2.30 */ @@ -608,11 +610,11 @@ g_tls_connection_get_interaction (GTlsConnection *conn) * g_tls_connection_get_peer_certificate: * @conn: a #GTlsConnection * - * Gets @conn's peer's certificate after the handshake has completed. - * (It is not set during the emission of + * Gets @conn's peer's certificate after the handshake has completed + * or failed. (It is not set during the emission of * #GTlsConnection::accept-certificate.) * - * Returns: (transfer none): @conn's peer's certificate, or %NULL + * Returns: (transfer none) (nullable): @conn's peer's certificate, or %NULL * * Since: 2.28 */ @@ -635,8 +637,8 @@ g_tls_connection_get_peer_certificate (GTlsConnection *conn) * @conn: a #GTlsConnection * * Gets the errors associated with validating @conn's peer's - * certificate, after the handshake has completed. (It is not set - * during the emission of #GTlsConnection::accept-certificate.) + * certificate, after the handshake has completed or failed. (It is + * not set during the emission of #GTlsConnection::accept-certificate.) * * Returns: @conn's peer's certificate errors * @@ -730,27 +732,10 @@ g_tls_connection_get_require_close_notify (GTlsConnection *conn) * @conn: a #GTlsConnection * @mode: the rehandshaking mode * - * Sets how @conn behaves with respect to rehandshaking requests, when - * TLS 1.2 or older is in use. - * - * %G_TLS_REHANDSHAKE_NEVER means that it will never agree to - * rehandshake after the initial handshake is complete. (For a client, - * this means it will refuse rehandshake requests from the server, and - * for a server, this means it will close the connection with an error - * if the client attempts to rehandshake.) - * - * %G_TLS_REHANDSHAKE_SAFELY means that the connection will allow a - * rehandshake only if the other end of the connection supports the - * TLS `renegotiation_info` extension. This is the default behavior, - * but means that rehandshaking will not work against older - * implementations that do not support that extension. - * - * %G_TLS_REHANDSHAKE_UNSAFELY means that the connection will allow - * rehandshaking even without the `renegotiation_info` extension. On - * the server side in particular, this is not recommended, since it - * leaves the server open to certain attacks. However, this mode is - * necessary if you need to allow renegotiation with older client - * software. + * Since GLib 2.64, changing the rehandshake mode is no longer supported + * and will have no effect. With TLS 1.3, rehandshaking has been removed from + * the TLS protocol, replaced by separate post-handshake authentication and + * rekey operations. * * Since: 2.28 * @@ -766,7 +751,7 @@ g_tls_connection_set_rehandshake_mode (GTlsConnection *conn, g_return_if_fail (G_IS_TLS_CONNECTION (conn)); g_object_set (G_OBJECT (conn), - "rehandshake-mode", mode, + "rehandshake-mode", G_TLS_REHANDSHAKE_SAFELY, NULL); } G_GNUC_END_IGNORE_DEPRECATIONS @@ -778,7 +763,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS * Gets @conn rehandshaking mode. See * g_tls_connection_set_rehandshake_mode() for details. * - * Returns: @conn's rehandshaking mode + * Returns: %G_TLS_REHANDSHAKE_SAFELY * * Since: 2.28 * @@ -792,12 +777,15 @@ g_tls_connection_get_rehandshake_mode (GTlsConnection *conn) { GTlsRehandshakeMode mode; - g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), G_TLS_REHANDSHAKE_NEVER); + g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), G_TLS_REHANDSHAKE_SAFELY); + /* Continue to call g_object_get(), even though the return value is + * ignored, so that behavior doesn’t change for derived classes. + */ g_object_get (G_OBJECT (conn), "rehandshake-mode", &mode, NULL); - return mode; + return G_TLS_REHANDSHAKE_SAFELY; } G_GNUC_END_IGNORE_DEPRECATIONS @@ -877,6 +865,66 @@ g_tls_connection_get_negotiated_protocol (GTlsConnection *conn) return priv->negotiated_protocol; } +/** + * g_tls_channel_binding_error_quark: + * + * Gets the TLS channel binding error quark. + * + * Returns: a #GQuark. + * + * Since: 2.66 + */ +G_DEFINE_QUARK (g-tls-channel-binding-error-quark, g_tls_channel_binding_error) + +/** + * g_tls_connection_get_channel_binding_data: + * @conn: a #GTlsConnection + * @type: #GTlsChannelBindingType type of data to fetch + * @data: (out callee-allocates)(optional)(transfer none): #GByteArray is + * filled with the binding data, or %NULL + * @error: a #GError pointer, or %NULL + * + * Query the TLS backend for TLS channel binding data of @type for @conn. + * + * This call retrieves TLS channel binding data as specified in RFC + * [5056](https://tools.ietf.org/html/rfc5056), RFC + * [5929](https://tools.ietf.org/html/rfc5929), and related RFCs. The + * binding data is returned in @data. The @data is resized by the callee + * using #GByteArray buffer management and will be freed when the @data + * is destroyed by g_byte_array_unref(). If @data is %NULL, it will only + * check whether TLS backend is able to fetch the data (e.g. whether @type + * is supported by the TLS backend). It does not guarantee that the data + * will be available though. That could happen if TLS connection does not + * support @type or the binding data is not available yet due to additional + * negotiation or input required. + * + * Returns: %TRUE on success, %FALSE otherwise + * + * Since: 2.66 + */ +gboolean +g_tls_connection_get_channel_binding_data (GTlsConnection *conn, + GTlsChannelBindingType type, + GByteArray *data, + GError **error) +{ + GTlsConnectionClass *class; + + g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + class = G_TLS_CONNECTION_GET_CLASS (conn); + if (class->get_binding_data == NULL) + { + g_set_error_literal (error, G_TLS_CHANNEL_BINDING_ERROR, + G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED, + _("TLS backend does not implement TLS binding retrieval")); + return FALSE; + } + + return class->get_binding_data (conn, type, data, error); +} + /** * g_tls_connection_handshake: * @conn: a #GTlsConnection @@ -887,28 +935,30 @@ g_tls_connection_get_negotiated_protocol (GTlsConnection *conn) * * On the client side, it is never necessary to call this method; * although the connection needs to perform a handshake after - * connecting (or after sending a "STARTTLS"-type command) and may - * need to rehandshake later if the server requests it, + * connecting (or after sending a "STARTTLS"-type command), * #GTlsConnection will handle this for you automatically when you try - * to send or receive data on the connection. However, you can call - * g_tls_connection_handshake() manually if you want to know for sure - * whether the initial handshake succeeded or failed (as opposed to - * just immediately trying to write to @conn's output stream, in which - * case if it fails, it may not be possible to tell if it failed - * before or after completing the handshake). + * to send or receive data on the connection. You can call + * g_tls_connection_handshake() manually if you want to know whether + * the initial handshake succeeded or failed (as opposed to just + * immediately trying to use @conn to read or write, in which case, + * if it fails, it may not be possible to tell if it failed before or + * after completing the handshake), but beware that servers may reject + * client authentication after the handshake has completed, so a + * successful handshake does not indicate the connection will be usable. * * Likewise, on the server side, although a handshake is necessary at * the beginning of the communication, you do not need to call this * function explicitly unless you want clearer error reporting. * - * If TLS 1.2 or older is in use, you may call - * g_tls_connection_handshake() after the initial handshake to - * rehandshake; however, this usage is deprecated because rehandshaking - * is no longer part of the TLS protocol in TLS 1.3. Accordingly, the - * behavior of calling this function after the initial handshake is now - * undefined, except it is guaranteed to be reasonable and - * nondestructive so as to preserve compatibility with code written for - * older versions of GLib. + * Previously, calling g_tls_connection_handshake() after the initial + * handshake would trigger a rehandshake; however, this usage was + * deprecated in GLib 2.60 because rehandshaking was removed from the + * TLS protocol in TLS 1.3. Since GLib 2.64, calling this function after + * the initial handshake will no longer do anything. + * + * When using a #GTlsConnection created by #GSocketClient, the + * #GSocketClient performs the initial handshake, so calling this + * function manually is not recommended. * * #GTlsConnection::accept_certificate may be emitted during the * handshake. diff --git a/gio/gtlsconnection.h b/gio/gtlsconnection.h index be38dcf5c9b2723ec4ab803f496b48e17137b3d7..03722273373d3968ce495ce02e97cd5ddec2aa5a 100644 --- a/gio/gtlsconnection.h +++ b/gio/gtlsconnection.h @@ -66,9 +66,16 @@ struct _GTlsConnectionClass GAsyncResult *result, GError **error); +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gboolean ( *get_binding_data) (GTlsConnection *conn, + GTlsChannelBindingType type, + GByteArray *data, + GError **error); +G_GNUC_END_IGNORE_DEPRECATIONS + /*< private >*/ /* Padding for future expansion */ - gpointer padding[8]; + gpointer padding[7]; }; GLIB_AVAILABLE_IN_ALL @@ -124,6 +131,14 @@ void g_tls_connection_set_advertised_protocols (GTlsConnecti GLIB_AVAILABLE_IN_2_60 const gchar * g_tls_connection_get_negotiated_protocol (GTlsConnection *conn); +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +GLIB_AVAILABLE_IN_2_66 +gboolean g_tls_connection_get_channel_binding_data (GTlsConnection *conn, + GTlsChannelBindingType type, + GByteArray *data, + GError **error); +G_GNUC_END_IGNORE_DEPRECATIONS + GLIB_AVAILABLE_IN_ALL gboolean g_tls_connection_handshake (GTlsConnection *conn, GCancellable *cancellable, @@ -151,6 +166,18 @@ gboolean g_tls_connection_handshake_finish (GTlsConnecti GLIB_AVAILABLE_IN_ALL GQuark g_tls_error_quark (void); +/** + * G_TLS_CHANNEL_BINDING_ERROR: + * + * Error domain for TLS channel binding. Errors in this domain will be from the + * #GTlsChannelBindingError enumeration. See #GError for more information on error + * domains. + * + * Since: 2.66 + */ +#define G_TLS_CHANNEL_BINDING_ERROR (g_tls_channel_binding_error_quark ()) +GLIB_AVAILABLE_IN_2_66 +GQuark g_tls_channel_binding_error_quark (void); /*< protected >*/ GLIB_AVAILABLE_IN_ALL diff --git a/gio/gtlsdatabase.c b/gio/gtlsdatabase.c index f06dabf0a7ca609f48589b42a964b8c48fcefe26..d7dcf4bbe189c0109ed7ce3f4975c7fd36cc0060 100644 --- a/gio/gtlsdatabase.c +++ b/gio/gtlsdatabase.c @@ -186,6 +186,7 @@ g_tls_database_real_verify_chain_async (GTlsDatabase *self, task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_verify_chain_async); + g_task_set_name (task, "[gio] verify TLS chain"); g_task_set_task_data (task, args, async_verify_chain_free); g_task_run_in_thread (task, async_verify_chain_thread); g_object_unref (task); @@ -264,6 +265,7 @@ g_tls_database_real_lookup_certificate_for_handle_async (GTlsDatabase task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_lookup_certificate_for_handle_async); + g_task_set_name (task, "[gio] lookup TLS certificate"); g_task_set_task_data (task, args, async_lookup_certificate_for_handle_free); g_task_run_in_thread (task, async_lookup_certificate_for_handle_thread); g_object_unref (task); @@ -338,6 +340,7 @@ g_tls_database_real_lookup_certificate_issuer_async (GTlsDatabase *sel task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_lookup_certificate_issuer_async); + g_task_set_name (task, "[gio] lookup certificate issuer"); g_task_set_task_data (task, args, async_lookup_certificate_issuer_free); g_task_run_in_thread (task, async_lookup_certificate_issuer_thread); g_object_unref (task); @@ -419,6 +422,7 @@ g_tls_database_real_lookup_certificates_issued_by_async (GTlsDatabase task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_lookup_certificates_issued_by_async); + g_task_set_name (task, "[gio] lookup certificates issued by"); g_task_set_task_data (task, args, async_lookup_certificates_issued_by_free); g_task_run_in_thread (task, async_lookup_certificates_issued_by_thread); g_object_unref (task); @@ -473,9 +477,13 @@ g_tls_database_class_init (GTlsDatabaseClass *klass) * which means that the certificate is being used to authenticate a server * (and we are acting as the client). * - * The @identity is used to check for pinned certificates (trust exceptions) - * in the database. These will override the normal verification process on a - * host by host basis. + * The @identity is used to ensure the server certificate is valid for + * the expected peer identity. If the identity does not match the + * certificate, %G_TLS_CERTIFICATE_BAD_IDENTITY will be set in the + * return value. If @identity is %NULL, that bit will never be set in + * the return value. The peer identity may also be used to check for + * pinned certificates (trust exceptions) in the database. These may + * override the normal verification process on a host-by-host basis. * * Currently there are no @flags, and %G_TLS_DATABASE_VERIFY_NONE should be * used. @@ -508,8 +516,6 @@ g_tls_database_verify_chain (GTlsDatabase *self, GError **error) { g_return_val_if_fail (G_IS_TLS_DATABASE (self), G_TLS_CERTIFICATE_GENERIC_ERROR); - g_return_val_if_fail (G_IS_TLS_DATABASE (self), - G_TLS_CERTIFICATE_GENERIC_ERROR); g_return_val_if_fail (G_IS_TLS_CERTIFICATE (chain), G_TLS_CERTIFICATE_GENERIC_ERROR); g_return_val_if_fail (purpose, G_TLS_CERTIFICATE_GENERIC_ERROR); diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c index f5e02a1a880a33a1d69e8dcd5e04b3bb4755ef5e..948e812df5a4d621dc972a49e827b47263d3521f 100644 --- a/gio/gtlspassword.c +++ b/gio/gtlspassword.c @@ -290,7 +290,7 @@ g_tls_password_set_value (GTlsPassword *password, { /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ gsize length_unsigned = strlen ((gchar *) value); - g_return_if_fail (length_unsigned > G_MAXSSIZE); + g_return_if_fail (length_unsigned <= G_MAXSSIZE); length = (gssize) length_unsigned; } diff --git a/gio/gtrashportal.c b/gio/gtrashportal.c index 9922be21fb0db77776eb731cb4b037efa0073ec4..03c933297972e0625ce6086af5279541609f4b08 100644 --- a/gio/gtrashportal.c +++ b/gio/gtrashportal.c @@ -74,8 +74,9 @@ g_trash_portal_trash_file (GFile *file, GUnixFDList *fd_list = NULL; int fd, fd_in, errsv; gboolean ret = FALSE; + guint portal_result = 0; GXdpTrash *proxy; - + proxy = ensure_trash_portal (); if (proxy == NULL) { @@ -114,11 +115,17 @@ g_trash_portal_trash_file (GFile *file, ret = gxdp_trash_call_trash_file_sync (proxy, g_variant_new_handle (fd_in), fd_list, - NULL, + &portal_result, NULL, NULL, error); + if (ret && portal_result != 1) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Trash portal failed on %s", path); + ret = FALSE; + } + out: g_clear_object (&fd_list); g_free (path); diff --git a/gio/gunionvolumemonitor.c b/gio/gunionvolumemonitor.c index 93b74e5248c0e0b1d43c5ff6ad7884f3c709b979..c0173037595083b56dcb3c4aa3de3099591956c2 100644 --- a/gio/gunionvolumemonitor.c +++ b/gio/gunionvolumemonitor.c @@ -546,7 +546,7 @@ _g_mount_get_for_mount_path (const gchar *mount_path, /* TODO: How do we know this succeeded? Keep in mind that the native * volume monitor may fail (e.g. not being able to connect to - * hald). Is the get_mount_for_mount_path() method allowed to + * udisks). Is the get_mount_for_mount_path() method allowed to * return NULL? Seems like it is ... probably the method needs * to take a boolean and write if it succeeds or not.. Messy. * Very messy. diff --git a/gio/gunixcredentialsmessage.c b/gio/gunixcredentialsmessage.c index 02d59c858250374b9956c2a35301fdf18e8d26d4..9e5c7d32e93621add2a2b3b9eaf6d568f89e2919 100644 --- a/gio/gunixcredentialsmessage.c +++ b/gio/gunixcredentialsmessage.c @@ -96,6 +96,7 @@ g_unix_credentials_message_get_msg_type (GSocketControlMessage *message) #elif G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED #error "G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED is set but there is no msg_type defined for this platform" #else + /* includes G_CREDENTIALS_USE_APPLE_XUCRED */ return 0; #endif } diff --git a/gio/gunixinputstream.c b/gio/gunixinputstream.c index c63e4e50ef597fb669202201474e5037359fb291..8c2ce6233e0262cd407003057a440fdae9730405 100644 --- a/gio/gunixinputstream.c +++ b/gio/gunixinputstream.c @@ -20,12 +20,9 @@ #include "config.h" -#include -#include #include #include #include -#include #include #include @@ -36,6 +33,7 @@ #include "gasynchelper.h" #include "gfiledescriptorbased.h" #include "glibintl.h" +#include "giounix-private.h" /** @@ -64,7 +62,7 @@ enum { struct _GUnixInputStreamPrivate { int fd; guint close_fd : 1; - guint is_pipe_or_socket : 1; + guint can_poll : 1; }; static void g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface); @@ -103,14 +101,6 @@ static void g_unix_input_stream_skip_async (GInputStream *stream, static gssize g_unix_input_stream_skip_finish (GInputStream *stream, GAsyncResult *result, GError **error); -static void g_unix_input_stream_close_async (GInputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gboolean g_unix_input_stream_close_finish (GInputStream *stream, - GAsyncResult *result, - GError **error); static gboolean g_unix_input_stream_pollable_can_poll (GPollableInputStream *stream); static gboolean g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream); @@ -134,8 +124,6 @@ g_unix_input_stream_class_init (GUnixInputStreamClass *klass) stream_class->skip_async = g_unix_input_stream_skip_async; stream_class->skip_finish = g_unix_input_stream_skip_finish; } - stream_class->close_async = g_unix_input_stream_close_async; - stream_class->close_finish = g_unix_input_stream_close_finish; /** * GUnixInputStream:fd: @@ -196,10 +184,7 @@ g_unix_input_stream_set_property (GObject *object, { case PROP_FD: unix_stream->priv->fd = g_value_get_int (value); - if (lseek (unix_stream->priv->fd, 0, SEEK_CUR) == -1 && errno == ESPIPE) - unix_stream->priv->is_pipe_or_socket = TRUE; - else - unix_stream->priv->is_pipe_or_socket = FALSE; + unix_stream->priv->can_poll = _g_fd_is_pollable (unix_stream->priv->fd); break; case PROP_CLOSE_FD: unix_stream->priv->close_fd = g_value_get_boolean (value); @@ -347,7 +332,7 @@ g_unix_input_stream_read (GInputStream *stream, poll_fds[0].fd = unix_stream->priv->fd; poll_fds[0].events = G_IO_IN; - if (unix_stream->priv->is_pipe_or_socket && + if (unix_stream->priv->can_poll && g_cancellable_make_pollfd (cancellable, &poll_fds[1])) nfds = 2; else @@ -452,41 +437,10 @@ g_unix_input_stream_skip_finish (GInputStream *stream, /* TODO: Not implemented */ } -static void -g_unix_input_stream_close_async (GInputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GError *error = NULL; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, g_unix_input_stream_close_async); - g_task_set_priority (task, io_priority); - - if (g_unix_input_stream_close (stream, cancellable, &error)) - g_task_return_boolean (task, TRUE); - else - g_task_return_error (task, error); - g_object_unref (task); -} - -static gboolean -g_unix_input_stream_close_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); - - return g_task_propagate_boolean (G_TASK (result), error); -} - static gboolean g_unix_input_stream_pollable_can_poll (GPollableInputStream *stream) { - return G_UNIX_INPUT_STREAM (stream)->priv->is_pipe_or_socket; + return G_UNIX_INPUT_STREAM (stream)->priv->can_poll; } static gboolean diff --git a/gio/gunixmount.c b/gio/gunixmount.c index 0a6d7f3bfa44ba27a8abad4925c3d58703376b6f..acfebffdd7a695016f77f5170e9015cef4bcb351 100644 --- a/gio/gunixmount.c +++ b/gio/gunixmount.c @@ -302,7 +302,8 @@ eject_unmount_do (GMount *mount, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, - char **argv) + char **argv, + const gchar *task_name) { GUnixMount *unix_mount = G_UNIX_MOUNT (mount); GTask *task; @@ -310,6 +311,7 @@ eject_unmount_do (GMount *mount, task = g_task_new (mount, cancellable, callback, user_data); g_task_set_source_tag (task, eject_unmount_do); + g_task_set_name (task, task_name); g_task_set_task_data (task, g_strdupv (argv), (GDestroyNotify) g_strfreev); if (unix_mount->volume_monitor != NULL) @@ -337,7 +339,7 @@ g_unix_mount_unmount (GMount *mount, else argv[1] = unix_mount->device_path; - eject_unmount_do (mount, cancellable, callback, user_data, argv); + eject_unmount_do (mount, cancellable, callback, user_data, argv, "[gio] unmount mount"); } static gboolean @@ -363,7 +365,7 @@ g_unix_mount_eject (GMount *mount, else argv[1] = unix_mount->device_path; - eject_unmount_do (mount, cancellable, callback, user_data, argv); + eject_unmount_do (mount, cancellable, callback, user_data, argv, "[gio] eject mount"); } static gboolean diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index 1880d9926b77de996d34993ccc0b577810273c7e..32b9362599ca5125f5daf0a4a7f819d5bf8b6ad2 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -64,10 +64,10 @@ #endif #include "gunixmounts.h" -#include "glocalfileprivate.h" #include "gfile.h" #include "gfilemonitor.h" #include "glibintl.h" +#include "glocalfile.h" #include "gthemedicon.h" #include "gcontextspecificgroup.h" @@ -421,7 +421,7 @@ guess_system_internal (const char *mountpoint, * to not mengle those mounts with the "regular" mounts (i.e. which points to * the root). But because those mounts usually just duplicate other mounts and * are completely ignored with mntend-based implementation, let's mark them as - * system internal. Given the different approches it doesn't mean that all + * system internal. Given the different approaches it doesn't mean that all * mounts which were ignored will be system internal now, but this should work * in most cases. For more info, see g_unix_mount_get_root_path() annotation, * comment in mntent-based _g_get_unix_mounts() implementation and the @@ -956,6 +956,23 @@ _g_get_unix_mounts (void) return return_list; } +/* QNX {{{2 */ +#elif defined (HAVE_QNX) + +static char * +get_mtab_monitor_file (void) +{ + /* TODO: Not implemented */ + return NULL; +} + +static GList * +_g_get_unix_mounts (void) +{ + /* TODO: Not implemented */ + return NULL; +} + /* Common code {{{2 */ #else #error No _g_get_unix_mounts() implementation for system @@ -1479,6 +1496,14 @@ _g_get_unix_mount_points (void) return _g_get_unix_mounts (); } +/* QNX {{{2 */ +#elif defined (HAVE_QNX) +static GList * +_g_get_unix_mount_points (void) +{ + return _g_get_unix_mounts (); +} + /* Common code {{{2 */ #else #error No g_get_mount_table() implementation for system @@ -1660,6 +1685,52 @@ g_unix_mount_points_get (guint64 *time_read) return _g_get_unix_mount_points (); } +/** + * g_unix_mount_point_at: + * @mount_path: (type filename): path for a possible unix mount point. + * @time_read: (out) (optional): guint64 to contain a timestamp. + * + * Gets a #GUnixMountPoint for a given mount path. If @time_read is set, it + * will be filled with a unix timestamp for checking if the mount points have + * changed since with g_unix_mount_points_changed_since(). + * + * If more mount points have the same mount path, the last matching mount point + * is returned. + * + * Returns: (transfer full) (nullable): a #GUnixMountPoint, or %NULL if no match + * is found. + * + * Since: 2.66 + **/ +GUnixMountPoint * +g_unix_mount_point_at (const char *mount_path, + guint64 *time_read) +{ + GList *mount_points, *l; + GUnixMountPoint *mount_point, *found; + + mount_points = g_unix_mount_points_get (time_read); + + found = NULL; + for (l = mount_points; l != NULL; l = l->next) + { + mount_point = l->data; + + if (strcmp (mount_path, mount_point->mount_path) == 0) + { + if (found != NULL) + g_unix_mount_point_free (found); + + found = mount_point; + } + else + g_unix_mount_point_free (mount_point); + } + g_list_free (mount_points); + + return found; +} + /** * g_unix_mounts_changed_since: * @time: guint64 to contain a timestamp. @@ -2445,7 +2516,7 @@ g_unix_mount_point_get_fs_type (GUnixMountPoint *mount_point) * * Gets the options for the mount point. * - * Returns: a string containing the options. + * Returns: (nullable): a string containing the options. * * Since: 2.32 */ diff --git a/gio/gunixmounts.h b/gio/gunixmounts.h index fe8e241603793969b112d654d3b500d30de1c48e..2553e1ca17eb5b2906d32c6d89cd2f8bbe6e64db 100644 --- a/gio/gunixmounts.h +++ b/gio/gunixmounts.h @@ -132,6 +132,9 @@ GIcon * g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint *mount GLIB_AVAILABLE_IN_ALL GList * g_unix_mount_points_get (guint64 *time_read); +GLIB_AVAILABLE_IN_2_66 +GUnixMountPoint *g_unix_mount_point_at (const char *mount_path, + guint64 *time_read); GLIB_AVAILABLE_IN_ALL GList * g_unix_mounts_get (guint64 *time_read); GLIB_AVAILABLE_IN_ALL diff --git a/gio/gunixoutputstream.c b/gio/gunixoutputstream.c index 506e09a8c575468d7a2e38243e6fa3fad825953f..f4843a8ff65f8d4dccd43b3d7c89df94618ebbb9 100644 --- a/gio/gunixoutputstream.c +++ b/gio/gunixoutputstream.c @@ -20,12 +20,9 @@ #include "config.h" -#include -#include #include #include #include -#include #include #include @@ -38,6 +35,7 @@ #include "gfiledescriptorbased.h" #include "glibintl.h" #include "gioprivate.h" +#include "giounix-private.h" /** @@ -66,7 +64,7 @@ enum { struct _GUnixOutputStreamPrivate { int fd; guint close_fd : 1; - guint is_pipe_or_socket : 1; + guint can_poll : 1; }; static void g_unix_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface); @@ -102,14 +100,6 @@ static gboolean g_unix_output_stream_writev (GOutputStream *stream, static gboolean g_unix_output_stream_close (GOutputStream *stream, GCancellable *cancellable, GError **error); -static void g_unix_output_stream_close_async (GOutputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer data); -static gboolean g_unix_output_stream_close_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error); static gboolean g_unix_output_stream_pollable_can_poll (GPollableOutputStream *stream); static gboolean g_unix_output_stream_pollable_is_writable (GPollableOutputStream *stream); @@ -133,8 +123,6 @@ g_unix_output_stream_class_init (GUnixOutputStreamClass *klass) stream_class->write_fn = g_unix_output_stream_write; stream_class->writev_fn = g_unix_output_stream_writev; stream_class->close_fn = g_unix_output_stream_close; - stream_class->close_async = g_unix_output_stream_close_async; - stream_class->close_finish = g_unix_output_stream_close_finish; /** * GUnixOutputStream:fd: @@ -196,10 +184,7 @@ g_unix_output_stream_set_property (GObject *object, { case PROP_FD: unix_stream->priv->fd = g_value_get_int (value); - if (lseek (unix_stream->priv->fd, 0, SEEK_CUR) == -1 && errno == ESPIPE) - unix_stream->priv->is_pipe_or_socket = TRUE; - else - unix_stream->priv->is_pipe_or_socket = FALSE; + unix_stream->priv->can_poll = _g_fd_is_pollable (unix_stream->priv->fd); break; case PROP_CLOSE_FD: unix_stream->priv->close_fd = g_value_get_boolean (value); @@ -349,7 +334,7 @@ g_unix_output_stream_write (GOutputStream *stream, poll_fds[0].events = G_IO_OUT; nfds++; - if (unix_stream->priv->is_pipe_or_socket && + if (unix_stream->priv->can_poll && g_cancellable_make_pollfd (cancellable, &poll_fds[1])) nfds++; @@ -403,9 +388,9 @@ g_unix_output_stream_write (GOutputStream *stream, /* Macro to check if struct iovec and GOutputVector have the same ABI */ #define G_OUTPUT_VECTOR_IS_IOVEC (sizeof (struct iovec) == sizeof (GOutputVector) && \ - sizeof ((struct iovec *) 0)->iov_base == sizeof ((GOutputVector *) 0)->buffer && \ + G_SIZEOF_MEMBER (struct iovec, iov_base) == G_SIZEOF_MEMBER (GOutputVector, buffer) && \ G_STRUCT_OFFSET (struct iovec, iov_base) == G_STRUCT_OFFSET (GOutputVector, buffer) && \ - sizeof ((struct iovec *) 0)->iov_len == sizeof((GOutputVector *) 0)->size && \ + G_SIZEOF_MEMBER (struct iovec, iov_len) == G_SIZEOF_MEMBER (GOutputVector, size) && \ G_STRUCT_OFFSET (struct iovec, iov_len) == G_STRUCT_OFFSET (GOutputVector, size)) static gboolean @@ -456,7 +441,7 @@ g_unix_output_stream_writev (GOutputStream *stream, poll_fds[0].events = G_IO_OUT; nfds++; - if (unix_stream->priv->is_pipe_or_socket && + if (unix_stream->priv->can_poll && g_cancellable_make_pollfd (cancellable, &poll_fds[1])) nfds++; @@ -539,41 +524,10 @@ g_unix_output_stream_close (GOutputStream *stream, return res != -1; } -static void -g_unix_output_stream_close_async (GOutputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - GError *error = NULL; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, g_unix_output_stream_close_async); - g_task_set_priority (task, io_priority); - - if (g_unix_output_stream_close (stream, cancellable, &error)) - g_task_return_boolean (task, TRUE); - else - g_task_return_error (task, error); - g_object_unref (task); -} - -static gboolean -g_unix_output_stream_close_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); - - return g_task_propagate_boolean (G_TASK (result), error); -} - static gboolean g_unix_output_stream_pollable_can_poll (GPollableOutputStream *stream) { - return G_UNIX_OUTPUT_STREAM (stream)->priv->is_pipe_or_socket; + return G_UNIX_OUTPUT_STREAM (stream)->priv->can_poll; } static gboolean diff --git a/gio/gunixsocketaddress.c b/gio/gunixsocketaddress.c index 27e195e4707bbb0bde481ac432713daa0fea20b0..0ab1a62e94c6bdc076e94275118fe296618908af 100644 --- a/gio/gunixsocketaddress.c +++ b/gio/gunixsocketaddress.c @@ -67,7 +67,7 @@ enum }; #ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX sizeof (((struct sockaddr_un *) 0)->sun_path) +#define UNIX_PATH_MAX G_SIZEOF_MEMBER (struct sockaddr_un, sun_path) #endif struct _GUnixSocketAddressPrivate diff --git a/gio/gunixvolume.c b/gio/gunixvolume.c index a3768e11d0c25400da963528a5bc5828ce1e5fcf..60ae628a287f80075ff42f65a532778c1ec8c3c9 100644 --- a/gio/gunixvolume.c +++ b/gio/gunixvolume.c @@ -305,7 +305,8 @@ eject_mount_do (GVolume *volume, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, - const gchar * const *argv) + const gchar * const *argv, + const gchar *task_name) { GSubprocess *subprocess; GError *error = NULL; @@ -313,6 +314,7 @@ eject_mount_do (GVolume *volume, task = g_task_new (volume, cancellable, callback, user_data); g_task_set_source_tag (task, eject_mount_do); + g_task_set_name (task, task_name); if (g_task_return_error_if_cancelled (task)) { @@ -344,7 +346,7 @@ g_unix_volume_mount (GVolume *volume, else argv[1] = unix_volume->device_path; - eject_mount_do (volume, cancellable, callback, user_data, argv); + eject_mount_do (volume, cancellable, callback, user_data, argv, "[gio] mount volume"); } static gboolean @@ -369,7 +371,7 @@ g_unix_volume_eject (GVolume *volume, argv[1] = unix_volume->device_path; - eject_mount_do (volume, cancellable, callback, user_data, argv); + eject_mount_do (volume, cancellable, callback, user_data, argv, "[gio] eject volume"); } static gboolean diff --git a/gio/gvdb/gvdb-builder.c b/gio/gvdb/gvdb-builder.c index 2383e6002916b06ef5be376722df43b49f4b238d..64d8201dc9ba81f9cd60804ea8d3067995332381 100644 --- a/gio/gvdb/gvdb-builder.c +++ b/gio/gvdb/gvdb-builder.c @@ -206,7 +206,7 @@ item_to_index (GvdbItem *item) if (item != NULL) return item->assigned_index; - return guint32_to_le (-1u); + return guint32_to_le ((guint32) -1); } typedef struct @@ -234,7 +234,7 @@ file_builder_allocate (FileBuilder *fb, if (size == 0) return NULL; - fb->offset += (-fb->offset) & (alignment - 1); + fb->offset += (guint64) (-fb->offset) & (alignment - 1); chunk = g_slice_new (FileChunk); chunk->offset = fb->offset; chunk->size = size; @@ -339,9 +339,11 @@ file_builder_allocate_for_hash (FileBuilder *fb, #undef chunk memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le)); + memset (*hash_buckets, 0, n_buckets * sizeof (guint32_le)); + memset (*hash_items, 0, n_items * sizeof (struct gvdb_hash_item)); /* NOTE - the code to actually fill in the bloom filter here is missing. - * Patches welcome! + * Patches welcome! * * http://en.wikipedia.org/wiki/Bloom_filter * http://0pointer.de/blog/projects/bloom.html @@ -450,13 +452,22 @@ file_builder_new (gboolean byteswap) return builder; } +static void +file_builder_free (FileBuilder *fb) +{ + g_queue_free (fb->chunks); + g_slice_free (FileBuilder, fb); +} + static GString * file_builder_serialise (FileBuilder *fb, struct gvdb_pointer root) { - struct gvdb_header header = { { 0, }, }; + struct gvdb_header header = { { 0, 0 }, { 0 }, { 0 }, { { 0 }, { 0 } } }; GString *result; + memset (&header, 0, sizeof (header)); + if (fb->byteswap) { header.signature[0] = GVDB_SWAPPED_SIGNATURE0; @@ -494,9 +505,6 @@ file_builder_serialise (FileBuilder *fb, g_slice_free (FileChunk, chunk); } - g_queue_free (fb->chunks); - g_slice_free (FileBuilder, fb); - return result; } @@ -511,12 +519,118 @@ gvdb_table_write_contents (GHashTable *table, FileBuilder *fb; GString *str; + g_return_val_if_fail (table != NULL, FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + fb = file_builder_new (byteswap); file_builder_add_hash (fb, table, &root); str = file_builder_serialise (fb, root); + file_builder_free (fb); status = g_file_set_contents (filename, str->str, str->len, error); g_string_free (str, TRUE); return status; } + +typedef struct { + GBytes *contents; /* (owned) */ + GFile *file; /* (owned) */ +} WriteContentsData; + +static WriteContentsData * +write_contents_data_new (GBytes *contents, + GFile *file) +{ + WriteContentsData *data; + + data = g_slice_new (WriteContentsData); + data->contents = g_bytes_ref (contents); + data->file = g_object_ref (file); + + return data; +} + +static void +write_contents_data_free (WriteContentsData *data) +{ + g_bytes_unref (data->contents); + g_object_unref (data->file); + g_slice_free (WriteContentsData, data); +} + +static void +replace_contents_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = user_data; + WriteContentsData *data = g_task_get_task_data (task); + GError *error = NULL; + + g_return_if_fail (g_task_get_source_tag (task) == gvdb_table_write_contents_async); + + if (!g_file_replace_contents_finish (data->file, result, NULL, &error)) + g_task_return_error (task, g_steal_pointer (&error)); + else + g_task_return_boolean (task, TRUE); + + g_object_unref (task); +} + +void +gvdb_table_write_contents_async (GHashTable *table, + const gchar *filename, + gboolean byteswap, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + struct gvdb_pointer root; + FileBuilder *fb; + WriteContentsData *data; + GString *str; + GBytes *bytes; + GFile *file; + GTask *task; + + g_return_if_fail (table != NULL); + g_return_if_fail (filename != NULL); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + fb = file_builder_new (byteswap); + file_builder_add_hash (fb, table, &root); + str = file_builder_serialise (fb, root); + bytes = g_string_free_to_bytes (str); + file_builder_free (fb); + + file = g_file_new_for_path (filename); + data = write_contents_data_new (bytes, file); + + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_task_data (task, data, (GDestroyNotify)write_contents_data_free); + g_task_set_source_tag (task, gvdb_table_write_contents_async); + + g_file_replace_contents_async (file, + g_bytes_get_data (bytes, NULL), + g_bytes_get_size (bytes), + NULL, FALSE, + G_FILE_CREATE_PRIVATE, + cancellable, replace_contents_cb, g_steal_pointer (&task)); + + g_bytes_unref (bytes); + g_object_unref (file); +} + +gboolean +gvdb_table_write_contents_finish (GHashTable *table, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (table != NULL, FALSE); + g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} diff --git a/gio/gvdb/gvdb-builder.h b/gio/gvdb/gvdb-builder.h index b4815f0d07166822bc388edb2f3ef2b524216edf..30757d039d521b897ff7b6071dfa30a623ce8cdd 100644 --- a/gio/gvdb/gvdb-builder.h +++ b/gio/gvdb/gvdb-builder.h @@ -51,5 +51,16 @@ gboolean gvdb_table_write_contents (GHashTa const gchar *filename, gboolean byteswap, GError **error); +G_GNUC_INTERNAL +void gvdb_table_write_contents_async (GHashTable *table, + const gchar *filename, + gboolean byteswap, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +G_GNUC_INTERNAL +gboolean gvdb_table_write_contents_finish (GHashTable *table, + GAsyncResult *result, + GError **error); #endif /* __gvdb_builder_h__ */ diff --git a/gio/gvdb/gvdb-reader.c b/gio/gvdb/gvdb-reader.c index 83ad2ac1985a669c10196f19976d0459da0b1dd2..820ce4c3d72688d1e1e15f097b0da6d4b06de6cb 100644 --- a/gio/gvdb/gvdb-reader.c +++ b/gio/gvdb/gvdb-reader.c @@ -351,10 +351,10 @@ gvdb_table_get_names (GvdbTable *table, gsize *length) { gchar **names; - gint n_names; - gint filled; - gint total; - gint i; + guint n_names; + guint filled; + guint total; + guint i; /* We generally proceed by iterating over the list of items in the * hash table (in order of appearance) recording them into an array. @@ -379,7 +379,7 @@ gvdb_table_get_names (GvdbTable *table, * a pass that fills in no additional items. * * This takes an O(n) algorithm and turns it into O(n*m) where m is - * the depth of the tree, but in all sane cases the tree won't be very + * the depth of the tree, but typically the tree won't be very * deep and the constant factor of this algorithm is lower (and the * complexity of coding it, as well). */ diff --git a/gio/gvfs.c b/gio/gvfs.c index 3475624cf984dffd1c6d6cfe024fe278e6c85064..6e2dcf060764ffa8ea5c48e0d90343c613ed5499 100644 --- a/gio/gvfs.c +++ b/gio/gvfs.c @@ -337,21 +337,34 @@ g_vfs_parse_name (GVfs *vfs, return (* class->parse_name) (vfs, parse_name); } +static GVfs *vfs_default_singleton = NULL; /* (owned) (atomic) */ + /** * g_vfs_get_default: * * Gets the default #GVfs for the system. * - * Returns: (transfer none): a #GVfs. + * Returns: (not nullable) (transfer none): a #GVfs, which will be the local + * file system #GVfs if no other implementation is available. */ GVfs * g_vfs_get_default (void) { if (GLIB_PRIVATE_CALL (g_check_setuid) ()) return g_vfs_get_local (); - return _g_io_module_get_default (G_VFS_EXTENSION_POINT_NAME, - "GIO_USE_VFS", - (GIOModuleVerifyFunc)g_vfs_is_active); + + if (g_once_init_enter (&vfs_default_singleton)) + { + GVfs *singleton; + + singleton = _g_io_module_get_default (G_VFS_EXTENSION_POINT_NAME, + "GIO_USE_VFS", + (GIOModuleVerifyFunc) g_vfs_is_active); + + g_once_init_leave (&vfs_default_singleton, singleton); + } + + return vfs_default_singleton; } /** diff --git a/gio/gvolumemonitor.c b/gio/gvolumemonitor.c index 65ec955a9c9f40e140dff42f9bd9c70780ac4791..056999f6aca4a43ee349b05c510d26bc5d04f005 100644 --- a/gio/gvolumemonitor.c +++ b/gio/gvolumemonitor.c @@ -353,7 +353,7 @@ g_volume_monitor_get_mounts (GVolumeMonitor *volume_monitor) * * Finds a #GVolume object by its UUID (see g_volume_get_uuid()) * - * Returns: (transfer full): a #GVolume or %NULL if no such volume is available. + * Returns: (nullable) (transfer full): a #GVolume or %NULL if no such volume is available. * Free the returned object with g_object_unref(). **/ GVolume * @@ -377,7 +377,7 @@ g_volume_monitor_get_volume_for_uuid (GVolumeMonitor *volume_monitor, * * Finds a #GMount object by its UUID (see g_mount_get_uuid()) * - * Returns: (transfer full): a #GMount or %NULL if no such mount is available. + * Returns: (nullable) (transfer full): a #GMount or %NULL if no such mount is available. * Free the returned object with g_object_unref(). **/ GMount * diff --git a/gio/gwin32api-application-activation-manager.h b/gio/gwin32api-application-activation-manager.h new file mode 100644 index 0000000000000000000000000000000000000000..cf44b93e6b5e9f43a021d40ad38890ed48dc3088 --- /dev/null +++ b/gio/gwin32api-application-activation-manager.h @@ -0,0 +1,126 @@ +#if NTDDI_VERSION < NTDDI_WIN8 +/* The following code is copied verbatim from MinGW-w64 shobjidl.h */ +/* + * IApplicationActivationManager interface + */ +typedef enum ACTIVATEOPTIONS { + AO_NONE = 0x0, + AO_DESIGNMODE = 0x1, + AO_NOERRORUI = 0x2, + AO_NOSPLASHSCREEN = 0x4 +} ACTIVATEOPTIONS; + +DEFINE_ENUM_FLAG_OPERATORS(ACTIVATEOPTIONS) + +#ifndef __IApplicationActivationManager_INTERFACE_DEFINED__ +#define __IApplicationActivationManager_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_IApplicationActivationManager, 0x2e941141, 0x7f97, 0x4756, 0xba,0x1d, 0x9d,0xec,0xde,0x89,0x4a,0x3d); +#if defined(__cplusplus) && !defined(CINTERFACE) +MIDL_INTERFACE("2e941141-7f97-4756-ba1d-9decde894a3d") +IApplicationActivationManager : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE ActivateApplication( + LPCWSTR appUserModelId, + LPCWSTR arguments, + ACTIVATEOPTIONS options, + DWORD *processId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ActivateForFile( + LPCWSTR appUserModelId, + IShellItemArray *itemArray, + LPCWSTR verb, + DWORD *processId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ActivateForProtocol( + LPCWSTR appUserModelId, + IShellItemArray *itemArray, + DWORD *processId) = 0; + +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IApplicationActivationManager, 0x2e941141, 0x7f97, 0x4756, 0xba,0x1d, 0x9d,0xec,0xde,0x89,0x4a,0x3d) +#endif +#else +typedef struct IApplicationActivationManagerVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IApplicationActivationManager *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IApplicationActivationManager *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IApplicationActivationManager *This); + + /*** IApplicationActivationManager methods ***/ + HRESULT (STDMETHODCALLTYPE *ActivateApplication)( + IApplicationActivationManager *This, + LPCWSTR appUserModelId, + LPCWSTR arguments, + ACTIVATEOPTIONS options, + DWORD *processId); + + HRESULT (STDMETHODCALLTYPE *ActivateForFile)( + IApplicationActivationManager *This, + LPCWSTR appUserModelId, + IShellItemArray *itemArray, + LPCWSTR verb, + DWORD *processId); + + HRESULT (STDMETHODCALLTYPE *ActivateForProtocol)( + IApplicationActivationManager *This, + LPCWSTR appUserModelId, + IShellItemArray *itemArray, + DWORD *processId); + + END_INTERFACE +} IApplicationActivationManagerVtbl; + +interface IApplicationActivationManager { + CONST_VTBL IApplicationActivationManagerVtbl* lpVtbl; +}; + +#ifdef COBJMACROS +#ifndef WIDL_C_INLINE_WRAPPERS +/*** IUnknown methods ***/ +#define IApplicationActivationManager_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IApplicationActivationManager_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IApplicationActivationManager_Release(This) (This)->lpVtbl->Release(This) +/*** IApplicationActivationManager methods ***/ +#define IApplicationActivationManager_ActivateApplication(This,appUserModelId,arguments,options,processId) (This)->lpVtbl->ActivateApplication(This,appUserModelId,arguments,options,processId) +#define IApplicationActivationManager_ActivateForFile(This,appUserModelId,itemArray,verb,processId) (This)->lpVtbl->ActivateForFile(This,appUserModelId,itemArray,verb,processId) +#define IApplicationActivationManager_ActivateForProtocol(This,appUserModelId,itemArray,processId) (This)->lpVtbl->ActivateForProtocol(This,appUserModelId,itemArray,processId) +#else +/*** IUnknown methods ***/ +static FORCEINLINE HRESULT IApplicationActivationManager_QueryInterface(IApplicationActivationManager* This,REFIID riid,void **ppvObject) { + return This->lpVtbl->QueryInterface(This,riid,ppvObject); +} +static FORCEINLINE ULONG IApplicationActivationManager_AddRef(IApplicationActivationManager* This) { + return This->lpVtbl->AddRef(This); +} +static FORCEINLINE ULONG IApplicationActivationManager_Release(IApplicationActivationManager* This) { + return This->lpVtbl->Release(This); +} +/*** IApplicationActivationManager methods ***/ +static FORCEINLINE HRESULT IApplicationActivationManager_ActivateApplication(IApplicationActivationManager* This,LPCWSTR appUserModelId,LPCWSTR arguments,ACTIVATEOPTIONS options,DWORD *processId) { + return This->lpVtbl->ActivateApplication(This,appUserModelId,arguments,options,processId); +} +static FORCEINLINE HRESULT IApplicationActivationManager_ActivateForFile(IApplicationActivationManager* This,LPCWSTR appUserModelId,IShellItemArray *itemArray,LPCWSTR verb,DWORD *processId) { + return This->lpVtbl->ActivateForFile(This,appUserModelId,itemArray,verb,processId); +} +static FORCEINLINE HRESULT IApplicationActivationManager_ActivateForProtocol(IApplicationActivationManager* This,LPCWSTR appUserModelId,IShellItemArray *itemArray,DWORD *processId) { + return This->lpVtbl->ActivateForProtocol(This,appUserModelId,itemArray,processId); +} +#endif +#endif + +#endif + + +#endif /* __IApplicationActivationManager_INTERFACE_DEFINED__ */ +#endif /* NTDDI_VERSION < NTDDI_WIN8 */ \ No newline at end of file diff --git a/gio/gwin32api-iterator.h b/gio/gwin32api-iterator.h new file mode 100644 index 0000000000000000000000000000000000000000..d4df8a7b815cb716a9547fba1aaa221ce6fc47f6 --- /dev/null +++ b/gio/gwin32api-iterator.h @@ -0,0 +1,125 @@ +typedef interface IIterator IIterator; +typedef interface IIterable IIterable; + +/* IIterator */ +typedef struct IIteratorVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IIterator *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IIterator *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IIterator *This); + + /*** IInspectable methods ***/ + HRESULT (STDMETHODCALLTYPE *GetIids)( + IIterator *This, + UINT32 *count, + IID **ids); + + HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)( + IIterator *This, + HSTRING *className); + + HRESULT (STDMETHODCALLTYPE *GetTrustLevel)( + IIterator *This, + TrustLevel *trustLevel); + + /*** IIterator methods ***/ + HRESULT (STDMETHODCALLTYPE *get_Current)( + IIterator *This, + IUnknown **current); + + HRESULT (STDMETHODCALLTYPE *get_HasCurrent)( + IIterator *This, + CHAR *hasCurrent); + + HRESULT (STDMETHODCALLTYPE *MoveNext)( + IIterator *This, + CHAR *hasCurrent); + + HRESULT (STDMETHODCALLTYPE *GetMany)( + IIterator *This, + UINT capacity, + void *value, + UINT *actual); + + END_INTERFACE +} IIteratorVtbl; + +interface IIterator { + CONST_VTBL IIteratorVtbl* lpVtbl; +}; + +/*** IUnknown methods ***/ +#define IIterator_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IIterator_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IIterator_Release(This) (This)->lpVtbl->Release(This) +/*** IInspectable methods ***/ +#define IIterator_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids) +#define IIterator_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name) +#define IIterator_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level) +/*** IIterator methods ***/ +#define IIterator_get_Current(This,current) (This)->lpVtbl->get_Current(This,current) +#define IIterator_get_HasCurrent(This,hasCurrent) (This)->lpVtbl->get_HasCurrent(This,hasCurrent) +#define IIterator_MoveNext(This,hasCurrent) (This)->lpVtbl->MoveNext(This,hasCurrent) +#define IIterator_GetMany(This,capacity,value,actual) (This)->lpVtbl->GetMany(This,capacity,value,actual) + +/* IIterable */ +typedef struct IIterableVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IIterable *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IIterable *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IIterable *This); + + /*** IInspectable methods ***/ + HRESULT (STDMETHODCALLTYPE *GetIids)( + IIterable *This, + UINT32 *count, + IID **ids); + + HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)( + IIterable *This, + HSTRING *className); + + HRESULT (STDMETHODCALLTYPE *GetTrustLevel)( + IIterable *This, + TrustLevel *trustLevel); + + /*** IIterable methods ***/ + HRESULT (STDMETHODCALLTYPE *First)( + IIterable *This, + IIterator **first); + + END_INTERFACE +} IIterableVtbl; + +interface IIterable { + CONST_VTBL IIterableVtbl* lpVtbl; +}; + +/*** IUnknown methods ***/ +#define IIterable_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IIterable_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IIterable_Release(This) (This)->lpVtbl->Release(This) +/*** IInspectable methods ***/ +#define IIterable_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids) +#define IIterable_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name) +#define IIterable_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level) +/*** IIterable methods ***/ +#define IIterable_First(This,retval) (This)->lpVtbl->First(This,retval) diff --git a/gio/gwin32api-misc.h b/gio/gwin32api-misc.h new file mode 100644 index 0000000000000000000000000000000000000000..2b45d9abd18ca5e2715583ae2cb6ef4b790ef18b --- /dev/null +++ b/gio/gwin32api-misc.h @@ -0,0 +1 @@ +typedef interface IProcessorArchitecture IProcessorArchitecture; diff --git a/gio/gwin32api-package.h b/gio/gwin32api-package.h new file mode 100644 index 0000000000000000000000000000000000000000..9842a86fa35facffff226cc6991fdd296b354331 --- /dev/null +++ b/gio/gwin32api-package.h @@ -0,0 +1,264 @@ +typedef interface IPackageManager IPackageManager; +typedef interface IPackage IPackage; +typedef interface IPackageId IPackageId; +typedef interface IPackageVersion IPackageVersion; + +DEFINE_GUID(IID_IPackageManager, 0x9A7D4B65, 0x5E8F, 0x4FC7, 0xA2, 0xE5, 0x7F, 0x69, 0x25, 0xCB, 0x8B, 0x53); +DEFINE_GUID(IID_IPackage, 0x163C792F, 0xBD75, 0x413C, 0xBF, 0x23, 0xB1, 0xFE, 0x7B, 0x95, 0xD8, 0x25); + +/* IPackageManager */ +typedef struct IPackageManagerVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IPackageManager *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IPackageManager *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IPackageManager *This); + + /*** IInspectable methods ***/ + HRESULT (STDMETHODCALLTYPE *GetIids)( + IPackageManager *This, + UINT32 *count, + IID **ids); + + HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)( + IPackageManager *This, + HSTRING *className); + + HRESULT (STDMETHODCALLTYPE *GetTrustLevel)( + IPackageManager *This, + TrustLevel *trustLevel); + + /*** IPackageManager methods ***/ + HRESULT (STDMETHODCALLTYPE *stub_AddPackageAsync)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_UpdatePackageAsync)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_RemovePackageAsync)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_StagePackageAsync)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_RegisterPackageAsync)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *FindPackages)( + IPackageManager *This, + IIterable **retval); + + HRESULT (STDMETHODCALLTYPE *FindPackagesByUserSecurityId)( + IPackageManager *This, + HSTRING userSecurityId, + IIterable **retval); + + HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByNamePublisher)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByUserSecurityIdNamePublisher)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_FindUsers)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_SetPackageState)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_FindPackageByPackageFullName)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_CleanupPackageForUserAsync)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByPackageFamilyName)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByUserSecurityIdPackageFamilyName)( + IPackageManager *This); + + HRESULT (STDMETHODCALLTYPE *stub_FindPackageByUserSecurityIdPackageFullName)( + IPackageManager *This); + + END_INTERFACE +} IPackageManagerVtbl; + +interface IPackageManager { + CONST_VTBL IPackageManagerVtbl* lpVtbl; +}; + +/*** IUnknown methods ***/ +#define IPackageManager_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IPackageManager_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IPackageManager_Release(This) (This)->lpVtbl->Release(This) +/*** IInspectable methods ***/ +#define IPackageManager_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids) +#define IPackageManager_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name) +#define IPackageManager_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level) +/*** IPackageManager methods ***/ +#define IPackageManager_FindPackages(This,retval) (This)->lpVtbl->FindPackages(This,retval) +#define IPackageManager_FindPackagesByUserSecurityId(This,userSecurityId,retval) (This)->lpVtbl->FindPackagesByUserSecurityId(This,userSecurityId,retval) + +/* IPackageId */ +typedef struct IPackageIdVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IPackageId *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IPackageId *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IPackageId *This); + + /*** IInspectable methods ***/ + HRESULT (STDMETHODCALLTYPE *GetIids)( + IPackageId *This, + UINT32 *count, + IID **ids); + + HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)( + IPackageId *This, + HSTRING *className); + + HRESULT (STDMETHODCALLTYPE *GetTrustLevel)( + IPackageId *This, + TrustLevel *trustLevel); + + /*** IPackageId methods ***/ + HRESULT (STDMETHODCALLTYPE *get_Name)( + IPackageId *This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_Version)( + IPackageId *This, + IPackageVersion *value); + + HRESULT (STDMETHODCALLTYPE *get_Architecture)( + IPackageId *This, + IProcessorArchitecture *value); + + HRESULT (STDMETHODCALLTYPE *get_ResourceId)( + IPackageId *This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_Publisher)( + IPackageId *This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_PublisherId)( + IPackageId *This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_FullName)( + IPackageId *This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_FamilyName)( + IPackageId *This, + HSTRING *value); + + END_INTERFACE +} IPackageIdVtbl; + +interface IPackageId { + CONST_VTBL IPackageIdVtbl* lpVtbl; +}; + +/*** IUnknown methods ***/ +#define IPackageId_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IPackageId_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IPackageId_Release(This) (This)->lpVtbl->Release(This) +/*** IInspectable methods ***/ +#define IPackageId_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids) +#define IPackageId_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name) +#define IPackageId_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level) +/*** IPackageId methods ***/ +#define IPackageId_get_Name(This,value) (This)->lpVtbl->get_Name(This,value) +#define IPackageId_get_Version(This,value) (This)->lpVtbl->get_Version(This,value) +#define IPackageId_get_Architecture(This,value) (This)->lpVtbl->get_Architecture(This,value) +#define IPackageId_get_ResourceId(This,value) (This)->lpVtbl->get_ResourceId(This,value) +#define IPackageId_get_Publisher(This,value) (This)->lpVtbl->get_Publisher(This,value) +#define IPackageId_get_PublisherId(This,value) (This)->lpVtbl->get_PublisherId(This,value) +#define IPackageId_get_FullName(This,value) (This)->lpVtbl->get_FullName(This,value) +#define IPackageId_get_FamilyName(This,value) (This)->lpVtbl->get_FamilyName(This,value) + +/* IPackage */ +typedef struct IPackageVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IPackage *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IPackage *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IPackage *This); + + /*** IInspectable methods ***/ + HRESULT (STDMETHODCALLTYPE *GetIids)( + IPackage *This, + UINT32 *count, + IID **ids); + + HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)( + IPackage *This, + HSTRING *className); + + HRESULT (STDMETHODCALLTYPE *GetTrustLevel)( + IPackage *This, + TrustLevel *trustLevel); + + /*** IPackage methods ***/ + HRESULT (STDMETHODCALLTYPE *get_Id)( + IPackage *This, + IPackageId **value); + + HRESULT (STDMETHODCALLTYPE *get_InstalledLocation)( + IPackage *This, + IUnknown **value); + + HRESULT (STDMETHODCALLTYPE *get_IsFramework)( + IPackage *This, + CHAR *value); + + HRESULT (STDMETHODCALLTYPE *get_Dependencies)( + IPackage *This, + void **value); + + END_INTERFACE +} IPackageVtbl; + +interface IPackage { + CONST_VTBL IPackageVtbl* lpVtbl; +}; + +/*** IUnknown methods ***/ +#define IPackage_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IPackage_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IPackage_Release(This) (This)->lpVtbl->Release(This) +/*** IInspectable methods ***/ +#define IPackage_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids) +#define IPackage_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name) +#define IPackage_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level) +/*** IPackage methods ***/ +#define IPackage_get_Id(This,value) (This)->lpVtbl->get_Id(This,value) +#define IPackage_get_InstalledLocation(This,value) (This)->lpVtbl->get_InstalledLocation(This,value) +#define IPackage_get_IsFramework(This,value) (This)->lpVtbl->get_IsFramework(This,value) +#define IPackage_get_Dependencies(This,value) (This)->lpVtbl->get_Dependencies(This,value) diff --git a/gio/gwin32api-storage.h b/gio/gwin32api-storage.h new file mode 100644 index 0000000000000000000000000000000000000000..716a0a7a1c40348967a1db8e8d42c2f59192e898 --- /dev/null +++ b/gio/gwin32api-storage.h @@ -0,0 +1,339 @@ +struct DateTime; + +typedef struct DateTime { + UINT64 UniversalTime; +} DateTime; + +/* The following is copied verbatim from MinGW-w64 windows.storage.h */ +enum StorageItemTypes; +enum FileAttributes; +enum NameCollisionOption; +enum StorageDeleteOption; + +typedef enum NameCollisionoption { + NameCollisionoption_GenerateUniqueName = 0, + NameCollisionoption_ReplaceExisting = 1, + NameCollisionoption_FailIfExists = 2 +} NameCollisionOption; + +typedef enum FileAttributes { + FileAttributes_Normal = 0, + FileAttributes_ReadOnly = 1, + FileAttributes_Directory = 2, + FileAttributes_Archive = 3, + FileAttributes_Temporary = 4 +} FileAttributes; + +typedef enum StorageItemTypes { + StorageItemTypes_None = 0, + StorageItemTypes_File = 1, + StorageItemTypes_Folder = 2 +} StorageItemTypes; + +typedef enum StorageDeleteOption { + StorageDeleteOption_Default = 0, + StorageDeleteOption_PermanentDelete = 1 +} StorageDeleteOption; + +#ifndef __IStorageItem_FWD_DEFINED__ +#define __IStorageItem_FWD_DEFINED__ +typedef interface IStorageItem IStorageItem; +#endif + +/* + * IStorageItem interface + */ +#ifndef __IStorageItem_INTERFACE_DEFINED__ +#define __IStorageItem_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_IStorageItem, 0x4207a996, 0xca2f, 0x42f7, 0xbd,0xe8, 0x8b,0x10,0x45,0x7a,0x7f,0x30); +#if defined(__cplusplus) && !defined(CINTERFACE) +MIDL_INTERFACE("4207a996-ca2f-42f7-bde8-8b10457a7f30") +IStorageItem : public IInspectable +{ + virtual HRESULT STDMETHODCALLTYPE RenameAsyncOverloadDefaultOptions( + HSTRING desiredName, + IInspectable **action) = 0; + + virtual HRESULT STDMETHODCALLTYPE RenameAsync( + HSTRING desiredName, + NameCollisionOption option, + IInspectable **action) = 0; + + virtual HRESULT STDMETHODCALLTYPE DeleteAsyncOverloadDefaultOptions( + IInspectable **action) = 0; + + virtual HRESULT STDMETHODCALLTYPE DeleteAsync( + StorageDeleteOption option, + IInspectable **action) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBasicPropertiesAsync( + IInspectable **action) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_Name( + HSTRING *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_Path( + HSTRING *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_Attributes( + FileAttributes *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_DateCreated( + DateTime *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsOfType( + StorageItemTypes itemType, + boolean *value) = 0; + +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IStorageItem, 0x4207a996, 0xca2f, 0x42f7, 0xbd,0xe8, 0x8b,0x10,0x45,0x7a,0x7f,0x30) +#endif +#else +typedef struct IStorageItemVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IStorageItem* This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IStorageItem* This); + + ULONG (STDMETHODCALLTYPE *Release)( + IStorageItem* This); + + /*** IInspectable methods ***/ + HRESULT (STDMETHODCALLTYPE *GetIids)( + IStorageItem* This, + ULONG *iidCount, + IID **iids); + + HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)( + IStorageItem* This, + HSTRING *className); + + HRESULT (STDMETHODCALLTYPE *GetTrustLevel)( + IStorageItem* This, + TrustLevel *trustLevel); + + /*** IStorageItem methods ***/ + HRESULT (STDMETHODCALLTYPE *RenameAsyncOverloadDefaultOptions)( + IStorageItem* This, + HSTRING desiredName, + IInspectable **action); + + HRESULT (STDMETHODCALLTYPE *RenameAsync)( + IStorageItem* This, + HSTRING desiredName, + NameCollisionOption option, + IInspectable **action); + + HRESULT (STDMETHODCALLTYPE *DeleteAsyncOverloadDefaultOptions)( + IStorageItem* This, + IInspectable **action); + + HRESULT (STDMETHODCALLTYPE *DeleteAsync)( + IStorageItem* This, + StorageDeleteOption option, + IInspectable **action); + + HRESULT (STDMETHODCALLTYPE *GetBasicPropertiesAsync)( + IStorageItem* This, + IInspectable **action); + + HRESULT (STDMETHODCALLTYPE *get_Name)( + IStorageItem* This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_Path)( + IStorageItem* This, + HSTRING *value); + + HRESULT (STDMETHODCALLTYPE *get_Attributes)( + IStorageItem* This, + FileAttributes *value); + + HRESULT (STDMETHODCALLTYPE *get_DateCreated)( + IStorageItem* This, + DateTime *value); + + HRESULT (STDMETHODCALLTYPE *IsOfType)( + IStorageItem* This, + StorageItemTypes itemType, + boolean *value); + + END_INTERFACE +} IStorageItemVtbl; +interface IStorageItem { + CONST_VTBL IStorageItemVtbl* lpVtbl; +}; + +#ifdef COBJMACROS +#ifndef WIDL_C_INLINE_WRAPPERS +/*** IUnknown methods ***/ +#define IStorageItem_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IStorageItem_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IStorageItem_Release(This) (This)->lpVtbl->Release(This) +/*** IInspectable methods ***/ +#define IStorageItem_GetIids(This,iidCount,iids) (This)->lpVtbl->GetIids(This,iidCount,iids) +#define IStorageItem_GetRuntimeClassName(This,className) (This)->lpVtbl->GetRuntimeClassName(This,className) +#define IStorageItem_GetTrustLevel(This,trustLevel) (This)->lpVtbl->GetTrustLevel(This,trustLevel) +/*** IStorageItem methods ***/ +#define IStorageItem_RenameAsyncOverloadDefaultOptions(This,desiredName,action) (This)->lpVtbl->RenameAsyncOverloadDefaultOptions(This,desiredName,action) +#define IStorageItem_RenameAsync(This,desiredName,option,action) (This)->lpVtbl->RenameAsync(This,desiredName,option,action) +#define IStorageItem_DeleteAsyncOverloadDefaultOptions(This,action) (This)->lpVtbl->DeleteAsyncOverloadDefaultOptions(This,action) +#define IStorageItem_DeleteAsync(This,option,action) (This)->lpVtbl->DeleteAsync(This,option,action) +#define IStorageItem_GetBasicPropertiesAsync(This,action) (This)->lpVtbl->GetBasicPropertiesAsync(This,action) +#define IStorageItem_get_Name(This,value) (This)->lpVtbl->get_Name(This,value) +#define IStorageItem_get_Path(This,value) (This)->lpVtbl->get_Path(This,value) +#define IStorageItem_get_Attributes(This,value) (This)->lpVtbl->get_Attributes(This,value) +#define IStorageItem_get_DateCreated(This,value) (This)->lpVtbl->get_DateCreated(This,value) +#define IStorageItem_IsOfType(This,itemType,value) (This)->lpVtbl->IsOfType(This,itemType,value) +#else +/*** IUnknown methods ***/ +static FORCEINLINE HRESULT IStorageItem_QueryInterface(IStorageItem* This,REFIID riid,void **ppvObject) { + return This->lpVtbl->QueryInterface(This,riid,ppvObject); +} +static FORCEINLINE ULONG IStorageItem_AddRef(IStorageItem* This) { + return This->lpVtbl->AddRef(This); +} +static FORCEINLINE ULONG IStorageItem_Release(IStorageItem* This) { + return This->lpVtbl->Release(This); +} +/*** IInspectable methods ***/ +static FORCEINLINE HRESULT IStorageItem_GetIids(IStorageItem* This,ULONG *iidCount,IID **iids) { + return This->lpVtbl->GetIids(This,iidCount,iids); +} +static FORCEINLINE HRESULT IStorageItem_GetRuntimeClassName(IStorageItem* This,HSTRING *className) { + return This->lpVtbl->GetRuntimeClassName(This,className); +} +static FORCEINLINE HRESULT IStorageItem_GetTrustLevel(IStorageItem* This,TrustLevel *trustLevel) { + return This->lpVtbl->GetTrustLevel(This,trustLevel); +} +/*** IStorageItem methods ***/ +static FORCEINLINE HRESULT IStorageItem_RenameAsyncOverloadDefaultOptions(IStorageItem* This,HSTRING desiredName,IInspectable **action) { + return This->lpVtbl->RenameAsyncOverloadDefaultOptions(This,desiredName,action); +} +static FORCEINLINE HRESULT IStorageItem_RenameAsync(IStorageItem* This,HSTRING desiredName,NameCollisionOption option,IInspectable **action) { + return This->lpVtbl->RenameAsync(This,desiredName,option,action); +} +static FORCEINLINE HRESULT IStorageItem_DeleteAsyncOverloadDefaultOptions(IStorageItem* This,IInspectable **action) { + return This->lpVtbl->DeleteAsyncOverloadDefaultOptions(This,action); +} +static FORCEINLINE HRESULT IStorageItem_DeleteAsync(IStorageItem* This,StorageDeleteOption option,IInspectable **action) { + return This->lpVtbl->DeleteAsync(This,option,action); +} +static FORCEINLINE HRESULT IStorageItem_GetBasicPropertiesAsync(IStorageItem* This,IInspectable **action) { + return This->lpVtbl->GetBasicPropertiesAsync(This,action); +} +static FORCEINLINE HRESULT IStorageItem_get_Name(IStorageItem* This,HSTRING *value) { + return This->lpVtbl->get_Name(This,value); +} +static FORCEINLINE HRESULT IStorageItem_get_Path(IStorageItem* This,HSTRING *value) { + return This->lpVtbl->get_Path(This,value); +} +static FORCEINLINE HRESULT IStorageItem_get_Attributes(IStorageItem* This,FileAttributes *value) { + return This->lpVtbl->get_Attributes(This,value); +} +static FORCEINLINE HRESULT IStorageItem_get_DateCreated(IStorageItem* This,DateTime *value) { + return This->lpVtbl->get_DateCreated(This,value); +} +static FORCEINLINE HRESULT IStorageItem_IsOfType(IStorageItem* This,StorageItemTypes itemType,boolean *value) { + return This->lpVtbl->IsOfType(This,itemType,value); +} +#endif +#endif + +#endif + +HRESULT STDMETHODCALLTYPE IStorageItem_RenameAsyncOverloadDefaultOptions_Proxy( + IStorageItem* This, + HSTRING desiredName, + IInspectable **action); +void __RPC_STUB IStorageItem_RenameAsyncOverloadDefaultOptions_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_RenameAsync_Proxy( + IStorageItem* This, + HSTRING desiredName, + NameCollisionOption option, + IInspectable **action); +void __RPC_STUB IStorageItem_RenameAsync_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_DeleteAsyncOverloadDefaultOptions_Proxy( + IStorageItem* This, + IInspectable **action); +void __RPC_STUB IStorageItem_DeleteAsyncOverloadDefaultOptions_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_DeleteAsync_Proxy( + IStorageItem* This, + StorageDeleteOption option, + IInspectable **action); +void __RPC_STUB IStorageItem_DeleteAsync_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_GetBasicPropertiesAsync_Proxy( + IStorageItem* This, + IInspectable **action); +void __RPC_STUB IStorageItem_GetBasicPropertiesAsync_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_get_Name_Proxy( + IStorageItem* This, + HSTRING *value); +void __RPC_STUB IStorageItem_get_Name_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_get_Path_Proxy( + IStorageItem* This, + HSTRING *value); +void __RPC_STUB IStorageItem_get_Path_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_get_Attributes_Proxy( + IStorageItem* This, + FileAttributes *value); +void __RPC_STUB IStorageItem_get_Attributes_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_get_DateCreated_Proxy( + IStorageItem* This, + DateTime *value); +void __RPC_STUB IStorageItem_get_DateCreated_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); +HRESULT STDMETHODCALLTYPE IStorageItem_IsOfType_Proxy( + IStorageItem* This, + StorageItemTypes itemType, + boolean *value); +void __RPC_STUB IStorageItem_IsOfType_Stub( + IRpcStubBuffer* This, + IRpcChannelBuffer* pRpcChannelBuffer, + PRPC_MESSAGE pRpcMessage, + DWORD* pdwStubPhase); + +#endif /* __IStorageItem_INTERFACE_DEFINED__ */ diff --git a/gio/gwin32appinfo.c b/gio/gwin32appinfo.c index 9f335b37017b6c8e2637d9e914c263e1ccc15b2c..5403225e2a95ac2cdd905c7e5bd7173d805e06e4 100644 --- a/gio/gwin32appinfo.c +++ b/gio/gwin32appinfo.c @@ -22,6 +22,8 @@ #include "config.h" +#define COBJMACROS + #include #include "gcontenttype.h" @@ -32,8 +34,20 @@ #include #include "glibintl.h" #include +#include +/* Contains the definitions from shlobj.h that are + * guarded as Windows8-or-newer and are unavailable + * to GLib, being only Windows7-or-newer. + */ +#include "gwin32api-application-activation-manager.h" #include +/* For SHLoadIndirectString() */ +#include + +#include +#include "giowin32-priv.h" +#include "glib-private.h" /* We need to watch 8 places: * 0) HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations @@ -55,15 +69,73 @@ * 7) HKEY_CLASSES_ROOT (only its subkeys) * On change: re-enumerate subkeys, try to filter out wrong names. * + * + * About verbs. A registry key (the name of that key is known as ProgID) + * can contain a "shell" subkey, which can then contain a number of verb + * subkeys (the most common being the "open" verb), and each of these + * contains a "command" subkey, which has a default string value that + * is the command to be run. + * Most ProgIDs are in HKEY_CLASSES_ROOT, but some are nested deeper in + * the registry (such as HKEY_CURRENT_USER\\Software\\). + * + * Verb selection works like this (according to https://docs.microsoft.com/en-us/windows/win32/shell/context ): + * 1) If "open" verb is available, that verb is used. + * 2) If the Shell subkey has a default string value, and if a verb subkey + * with that name exists, that verb is used. + * 3) The first subkey found in the list of verb subkeys is used. + * 4) The "openwith" verb is used + * + * Testing suggests that Windows never reaches the point 4 in any realistic + * circumstances. If a "command" subkey is missing for a verb, or if it has + * an empty string as its default value, the app launch fails + * (the "openwith" verb is not used, even if it's present). + * If the command is present, but is not valid (runs nonexisting executable, + * for example), then other verbs are not checked. + * It seems that when the documentation said "openwith verb", it meant + * that Windows invokes the default "Open with..." dialog (it does not + * look at the "openwith" verb subkey, even if it's there). + * If a verb subkey that is supposed to be used is present, but it lacks + * a command subkey, an error message is shown and nothing else happens. + */ + +#define _verb_idx(array,index) ((GWin32AppInfoShellVerb *) g_ptr_array_index (array, index)) + +#define _lookup_by_verb(array, verb, dst, itemtype) do { \ + gsize _index; \ + itemtype *_v; \ + for (_index = 0; array && _index < array->len; _index++) \ + { \ + _v = (itemtype *) g_ptr_array_index (array, _index); \ + if (_wcsicmp (_v->verb_name, (verb)) == 0) \ + { \ + *(dst) = _v; \ + break; \ + } \ + } \ + if (array == NULL || _index >= array->len) \ + *(dst) = NULL; \ +} while (0) + +#define _verb_lookup(array, verb, dst) _lookup_by_verb (array, verb, dst, GWin32AppInfoShellVerb) + +/* Because with subcommands a verb would have + * a name like "foo\\bar", but the key its command + * should be looked for is "shell\\foo\\shell\\bar\\command" */ +typedef struct _reg_verb { + gunichar2 *name; + gunichar2 *shellpath; +} reg_verb; typedef struct _GWin32AppInfoURLSchema GWin32AppInfoURLSchema; typedef struct _GWin32AppInfoFileExtension GWin32AppInfoFileExtension; +typedef struct _GWin32AppInfoShellVerb GWin32AppInfoShellVerb; typedef struct _GWin32AppInfoHandler GWin32AppInfoHandler; typedef struct _GWin32AppInfoApplication GWin32AppInfoApplication; typedef struct _GWin32AppInfoURLSchemaClass GWin32AppInfoURLSchemaClass; typedef struct _GWin32AppInfoFileExtensionClass GWin32AppInfoFileExtensionClass; +typedef struct _GWin32AppInfoShellVerbClass GWin32AppInfoShellVerbClass; typedef struct _GWin32AppInfoHandlerClass GWin32AppInfoHandlerClass; typedef struct _GWin32AppInfoApplicationClass GWin32AppInfoApplicationClass; @@ -87,6 +159,11 @@ struct _GWin32AppInfoApplicationClass GObjectClass parent_class; }; +struct _GWin32AppInfoShellVerbClass +{ + GObjectClass parent_class; +}; + struct _GWin32AppInfoURLSchema { GObject parent_instance; @@ -97,52 +174,83 @@ struct _GWin32AppInfoURLSchema { gchar *schema_u8; /* url schema (stuff before ':'), in UTF-8, folded */ - gchar *schema_folded; + gchar *schema_u8_folded; - /* Handler currently selected for this schema */ + /* Handler currently selected for this schema. Can be NULL. */ GWin32AppInfoHandler *chosen_handler; - /* Maps folded handler IDs -> to other handlers for this schema */ + /* Maps folded handler IDs -> to GWin32AppInfoHandlers for this schema. + * Includes the chosen handler, if any. + */ GHashTable *handlers; }; struct _GWin32AppInfoHandler { GObject parent_instance; - /* Class name in HKCR */ + /* Usually a class name in HKCR */ gunichar2 *handler_id; - /* Handler registry key (HKCR\\handler_id). Can be used to watch this handler. */ + /* Registry object obtained by opening @handler_id. + * Can be used to watch this handler. + * May be %NULL (for fake handlers that we made up). + */ GWin32RegistryKey *key; - /* Class name in HKCR, UTF-8, folded */ + /* @handler_id, in UTF-8, folded */ gchar *handler_id_folded; - /* shell/open/command default value for the class named by class_id */ - gunichar2 *handler_command; + /* Icon of the application for this handler */ + GIcon *icon; + + /* Verbs that this handler supports */ + GPtrArray *verbs; /* of GWin32AppInfoShellVerb */ - /* If handler_id class has no command, it might point to another class */ - gunichar2 *proxy_id; + /* AppUserModelID for a UWP application. When this is not NULL, + * this handler launches a UWP application. + * UWP applications are launched using a COM interface and have no commandlines, + * and the verbs will reflect that too. + */ + gunichar2 *uwp_aumid; +}; - /* Proxy registry key (HKCR\\proxy_id). Can be used to watch handler's proxy. */ - GWin32RegistryKey *proxy_key; +struct _GWin32AppInfoShellVerb { + GObject parent_instance; - /* shell/open/command default value for the class named by proxy_id */ - gunichar2 *proxy_command; + /* The verb that is used to invoke this handler. */ + gunichar2 *verb_name; - /* Executable of the program (for matching, in folded form; UTF-8) */ - gchar *executable_folded; + /* User-friendly (localized) verb name. */ + gchar *verb_displayname; + + /* %TRUE if this verb is for a UWP app. + * It means that @command, @executable and @dll_function are %NULL. + */ + gboolean is_uwp; + + /* shell/verb/command */ + gunichar2 *command; + + /* Same as @command, but in UTF-8 */ + gchar *command_utf8; /* Executable of the program (UTF-8) */ gchar *executable; + /* Executable of the program (for matching, in folded form; UTF-8) */ + gchar *executable_folded; + /* Pointer to a location within @executable */ gchar *executable_basename; - /* Icon of the application for this handler */ - GIcon *icon; + /* If not NULL, then @executable and its derived fields contain the name + * of a DLL file (without the name of the function that rundll32.exe should + * invoke), and this field contains the name of the function to be invoked. + * The application is then invoked as 'rundll32.exe "dll_path",dll_function other_arguments...'. + */ + gchar *dll_function; - /* The application that is linked to this handler. */ + /* The application that is linked to this verb. */ GWin32AppInfoApplication *app; }; @@ -155,28 +263,35 @@ struct _GWin32AppInfoFileExtension { /* File extension (with leading '.'), in UTF-8 */ gchar *extension_u8; - /* handler currently selected for this extension */ + /* handler currently selected for this extension. Can be NULL. */ GWin32AppInfoHandler *chosen_handler; - /* Maps folded handler IDs -> to other handlers for this extension */ + /* Maps folded handler IDs -> to GWin32AppInfoHandlers for this extension. + * Includes the chosen handler, if any. + */ GHashTable *handlers; - - /* Maps folded app exename -> to apps that support this extension. - * ONLY for apps that are not reachable via handlers (i.e. apps from - * the HKCR/Applications, which have no handlers). */ - GHashTable *other_apps; }; struct _GWin32AppInfoApplication { GObject parent_instance; - /* Canonical name (used for key names). Can be NULL. */ + /* Canonical name (used for key names). + * For applications tracked by id this is the root registry + * key path for the application. + * For applications tracked by executable name this is the + * basename of the executable. + * For UWP apps this is the AppUserModelID. + * For fake applications this is the full filename of the + * executable (as far as it can be inferred from a command line, + * meaning that it can also be a basename, if that's + * all that a commandline happen to give us). + */ gunichar2 *canonical_name; - /* Canonical name (used for key names), in UTF-8. Can be NULL. */ + /* @canonical_name, in UTF-8 */ gchar *canonical_name_u8; - /* Canonical name (used for key names), in UTF-8, folded. Can be NULL. */ + /* @canonical_name, in UTF-8, folded */ gchar *canonical_name_folded; /* Human-readable name in English. Can be NULL */ @@ -197,30 +312,17 @@ struct _GWin32AppInfoApplication { /* Description, could be in user's language, UTF-8. Can be NULL */ gchar *description_u8; - /* shell/open/command for the application. Can be NULL (see executable). */ - gunichar2 *command; - - /* shell/open/command for the application. Can be NULL (see executable). */ - gchar *command_u8; - - /* Executable of the program (for matching, in folded form; - * UTF-8). Never NULL. */ - gchar *executable_folded; - - /* Executable of the program (UTF-8). Never NULL. */ - gchar *executable; - - /* Pointer to a location within @executable */ - gchar *executable_basename; + /* Verbs that this application supports */ + GPtrArray *verbs; /* of GWin32AppInfoShellVerb */ /* Explicitly supported URLs, hashmap from map-owned gchar ptr (schema, - * UTF-8, folded) -> a GWin32AppInfoHandler + * UTF-8, folded) -> to a GWin32AppInfoHandler * Schema can be used as a key in the urls hashmap. */ GHashTable *supported_urls; /* Explicitly supported extensions, hashmap from map-owned gchar ptr - * (.extension, UTF-8, folded) -> a GWin32AppInfoHandler + * (.extension, UTF-8, folded) -> to a GWin32AppInfoHandler * Extension can be used as a key in the extensions hashmap. */ GHashTable *supported_exts; @@ -244,6 +346,9 @@ struct _GWin32AppInfoApplication { /* Set to TRUE for applications that are machine-wide defaults (i.e. default * browser) */ gboolean default_app; + + /* Set to TRUE for UWP applications */ + gboolean is_uwp; }; #define G_TYPE_WIN32_APPINFO_URL_SCHEMA (g_win32_appinfo_url_schema_get_type ()) @@ -258,13 +363,18 @@ struct _GWin32AppInfoApplication { #define G_TYPE_WIN32_APPINFO_APPLICATION (g_win32_appinfo_application_get_type ()) #define G_WIN32_APPINFO_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_WIN32_APPINFO_APPLICATION, GWin32AppInfoApplication)) +#define G_TYPE_WIN32_APPINFO_SHELL_VERB (g_win32_appinfo_shell_verb_get_type ()) +#define G_WIN32_APPINFO_SHELL_VERB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_WIN32_APPINFO_SHELL_VERB, GWin32AppInfoShellVerb)) + GType g_win32_appinfo_url_schema_get_type (void) G_GNUC_CONST; GType g_win32_appinfo_file_extension_get_type (void) G_GNUC_CONST; +GType g_win32_appinfo_shell_verb_get_type (void) G_GNUC_CONST; GType g_win32_appinfo_handler_get_type (void) G_GNUC_CONST; GType g_win32_appinfo_application_get_type (void) G_GNUC_CONST; G_DEFINE_TYPE (GWin32AppInfoURLSchema, g_win32_appinfo_url_schema, G_TYPE_OBJECT) G_DEFINE_TYPE (GWin32AppInfoFileExtension, g_win32_appinfo_file_extension, G_TYPE_OBJECT) +G_DEFINE_TYPE (GWin32AppInfoShellVerb, g_win32_appinfo_shell_verb, G_TYPE_OBJECT) G_DEFINE_TYPE (GWin32AppInfoHandler, g_win32_appinfo_handler, G_TYPE_OBJECT) G_DEFINE_TYPE (GWin32AppInfoApplication, g_win32_appinfo_application, G_TYPE_OBJECT) @@ -275,7 +385,7 @@ g_win32_appinfo_url_schema_dispose (GObject *object) g_clear_pointer (&url->schema, g_free); g_clear_pointer (&url->schema_u8, g_free); - g_clear_pointer (&url->schema_folded, g_free); + g_clear_pointer (&url->schema_u8_folded, g_free); g_clear_object (&url->chosen_handler); g_clear_pointer (&url->handlers, g_hash_table_destroy); G_OBJECT_CLASS (g_win32_appinfo_url_schema_parent_class)->dispose (object); @@ -289,15 +399,10 @@ g_win32_appinfo_handler_dispose (GObject *object) g_clear_pointer (&handler->handler_id, g_free); g_clear_pointer (&handler->handler_id_folded, g_free); - g_clear_pointer (&handler->handler_command, g_free); - g_clear_pointer (&handler->proxy_id, g_free); - g_clear_pointer (&handler->proxy_command, g_free); - g_clear_pointer (&handler->executable_folded, g_free); - g_clear_pointer (&handler->executable, g_free); g_clear_object (&handler->key); - g_clear_object (&handler->proxy_key); g_clear_object (&handler->icon); - g_clear_object (&handler->app); + g_clear_pointer (&handler->verbs, g_ptr_array_unref); + g_clear_pointer (&handler->uwp_aumid, g_free); G_OBJECT_CLASS (g_win32_appinfo_handler_parent_class)->dispose (object); } @@ -310,10 +415,25 @@ g_win32_appinfo_file_extension_dispose (GObject *object) g_clear_pointer (&ext->extension_u8, g_free); g_clear_object (&ext->chosen_handler); g_clear_pointer (&ext->handlers, g_hash_table_destroy); - g_clear_pointer (&ext->other_apps, g_hash_table_destroy); G_OBJECT_CLASS (g_win32_appinfo_file_extension_parent_class)->dispose (object); } +static void +g_win32_appinfo_shell_verb_dispose (GObject *object) +{ + GWin32AppInfoShellVerb *shverb = G_WIN32_APPINFO_SHELL_VERB (object); + + g_clear_pointer (&shverb->verb_name, g_free); + g_clear_pointer (&shverb->verb_displayname, g_free); + g_clear_pointer (&shverb->command, g_free); + g_clear_pointer (&shverb->command_utf8, g_free); + g_clear_pointer (&shverb->executable_folded, g_free); + g_clear_pointer (&shverb->executable, g_free); + g_clear_pointer (&shverb->dll_function, g_free); + g_clear_object (&shverb->app); + G_OBJECT_CLASS (g_win32_appinfo_shell_verb_parent_class)->dispose (object); +} + static void g_win32_appinfo_application_dispose (GObject *object) { @@ -325,19 +445,28 @@ g_win32_appinfo_application_dispose (GObject *object) g_clear_pointer (&app->pretty_name, g_free); g_clear_pointer (&app->localized_pretty_name, g_free); g_clear_pointer (&app->description, g_free); - g_clear_pointer (&app->command, g_free); g_clear_pointer (&app->pretty_name_u8, g_free); g_clear_pointer (&app->localized_pretty_name_u8, g_free); g_clear_pointer (&app->description_u8, g_free); - g_clear_pointer (&app->command_u8, g_free); - g_clear_pointer (&app->executable_folded, g_free); - g_clear_pointer (&app->executable, g_free); g_clear_pointer (&app->supported_urls, g_hash_table_destroy); g_clear_pointer (&app->supported_exts, g_hash_table_destroy); g_clear_object (&app->icon); + g_clear_pointer (&app->verbs, g_ptr_array_unref); G_OBJECT_CLASS (g_win32_appinfo_application_parent_class)->dispose (object); } +static const gchar * +g_win32_appinfo_application_get_some_name (GWin32AppInfoApplication *app) +{ + if (app->localized_pretty_name_u8) + return app->localized_pretty_name_u8; + + if (app->pretty_name_u8) + return app->pretty_name_u8; + + return app->canonical_name_u8; +} + static void g_win32_appinfo_url_schema_class_init (GWin32AppInfoURLSchemaClass *klass) { @@ -354,6 +483,14 @@ g_win32_appinfo_file_extension_class_init (GWin32AppInfoFileExtensionClass *klas gobject_class->dispose = g_win32_appinfo_file_extension_dispose; } +static void +g_win32_appinfo_shell_verb_class_init (GWin32AppInfoShellVerbClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = g_win32_appinfo_shell_verb_dispose; +} + static void g_win32_appinfo_handler_class_init (GWin32AppInfoHandlerClass *klass) { @@ -379,6 +516,11 @@ g_win32_appinfo_url_schema_init (GWin32AppInfoURLSchema *self) g_object_unref); } +static void +g_win32_appinfo_shell_verb_init (GWin32AppInfoShellVerb *self) +{ +} + static void g_win32_appinfo_file_extension_init (GWin32AppInfoFileExtension *self) { @@ -386,15 +528,12 @@ g_win32_appinfo_file_extension_init (GWin32AppInfoFileExtension *self) g_str_equal, g_free, g_object_unref); - self->other_apps = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); } static void g_win32_appinfo_handler_init (GWin32AppInfoHandler *self) { + self->verbs = g_ptr_array_new_with_free_func (g_object_unref); } static void @@ -408,9 +547,29 @@ g_win32_appinfo_application_init (GWin32AppInfoApplication *self) g_str_equal, g_free, g_object_unref); + self->verbs = g_ptr_array_new_with_free_func (g_object_unref); } -G_LOCK_DEFINE_STATIC (gio_win32_appinfo); +/* The AppInfo threadpool that does asynchronous AppInfo tree rebuilds */ +static GThreadPool *gio_win32_appinfo_threadpool; + +/* This mutex is held by a thread that reads or writes the AppInfo tree. + * (tree object references can be obtained and later read without + * holding this mutex, since objects are practically immutable). + */ +static GMutex gio_win32_appinfo_mutex; + +/* Any thread wanting to access AppInfo can wait on this condition */ +static GCond gio_win32_appinfo_cond; + +/* Increased to indicate that AppInfo tree does needs to be rebuilt. + * AppInfo thread checks this to see if it needs to + * do a tree re-build. If the value changes during a rebuild, + * another rebuild is triggered after that. + * Other threads check this to see if they need + * to wait for a tree re-build to finish. + */ +static gint gio_win32_appinfo_update_counter = 0; /* Map of owned ".ext" (with '.', UTF-8, folded) * to GWin32AppInfoFileExtension ptr @@ -423,23 +582,35 @@ static GHashTable *extensions = NULL; static GHashTable *urls = NULL; /* Map of owned "appID" (UTF-8, folded) to - * GWin32AppInfoApplication ptr + * a GWin32AppInfoApplication */ static GHashTable *apps_by_id = NULL; /* Map of owned "app.exe" (UTF-8, folded) to - * GWin32AppInfoApplication ptr. + * a GWin32AppInfoApplication. * This map and its values are separate from apps_by_id. The fact that an app * with known ID has the same executable [base]name as an app in this map does * not mean that they are the same application. */ static GHashTable *apps_by_exe = NULL; +/* Map of owned "path:\to\app.exe" (UTF-8, folded) to + * a GWin32AppInfoApplication. + * The app objects in this map are fake - they are linked to + * handlers that do not have any apps associated with them. + */ +static GHashTable *fake_apps = NULL; + /* Map of owned "handler id" (UTF-8, folded) - * to GWin32AppInfoHandler ptr + * to a GWin32AppInfoHandler */ static GHashTable *handlers = NULL; +/* Temporary (only exists while the registry is being scanned) table + * that maps GWin32RegistryKey objects (keeps a ref) to owned AUMId wchar strings. + */ +static GHashTable *uwp_handler_table = NULL; + /* Watch this whole subtree */ static GWin32RegistryKey *url_associations_key; @@ -464,17 +635,6 @@ static GWin32RegistryKey *applications_key; /* Watch this key */ static GWin32RegistryKey *classes_root_key; -static gunichar2 * -g_wcsdup (const gunichar2 *str, gssize str_size) -{ - if (str_size == -1) - { - str_size = wcslen (str) + 1; - str_size *= sizeof (gunichar2); - } - return g_memdup (str, str_size); -} - #define URL_ASSOCIATIONS L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\" #define USER_CHOICE L"\\UserChoice" #define OPEN_WITH_PROGIDS L"\\OpenWithProgids" @@ -482,134 +642,111 @@ g_wcsdup (const gunichar2 *str, gssize str_size) #define HKCR L"HKEY_CLASSES_ROOT\\" #define HKCU L"HKEY_CURRENT_USER\\" #define HKLM L"HKEY_LOCAL_MACHINE\\" -#define SHELL_OPEN_COMMAND L"\\shell\\open\\command" #define REG_PATH_MAX 256 #define REG_PATH_MAX_SIZE (REG_PATH_MAX * sizeof (gunichar2)) -static gunichar2 * -read_resource_string (gunichar2 *res) -{ - gunichar2 *id_str; - gunichar2 *id_str_end; - gunichar2 *filename_str; - unsigned long id; - HMODULE resource_module; - gunichar2 *buffer; - int string_length; - int buffer_length; - - if (res == NULL || res[0] != L'@') - return res; - - id_str = wcsrchr (res, L'-'); - - if (id_str == NULL || id_str[-1] != L',') - return res; - - id_str += 1; - - id = wcstoul (id_str, &id_str_end, 10); +/* for g_wcsdup(), + * _g_win32_extract_executable(), + * _g_win32_fixup_broken_microsoft_rundll_commandline() + */ +#include "giowin32-private.c" - if (id_str_end == id_str || id_str_end[0] != L'\0' || id == ULONG_MAX) - return res; +/* for g_win32_package_parser_enum_packages() */ +#include "gwin32packageparser.h" - filename_str = &res[1]; - id_str[-2] = L'\0'; +static void +read_handler_icon (GWin32RegistryKey *key, + GIcon **icon_out) +{ + GWin32RegistryKey *icon_key; + GWin32RegistryValueType default_type; + gchar *default_value; - resource_module = LoadLibraryExW (filename_str, - 0, - LOAD_LIBRARY_AS_DATAFILE | - LOAD_LIBRARY_AS_IMAGE_RESOURCE); + g_assert (icon_out); - g_free (res); + *icon_out = NULL; - if (resource_module == NULL) - return NULL; + icon_key = g_win32_registry_key_get_child_w (key, L"DefaultIcon", NULL); - buffer_length = 256; - string_length = buffer_length - 1; + if (icon_key == NULL) + return; - while (TRUE) + if (g_win32_registry_key_get_value (icon_key, + NULL, + TRUE, + "", + &default_type, + (gpointer *) &default_value, + NULL, + NULL)) { - buffer = g_malloc (buffer_length * sizeof (gunichar2)); - string_length = LoadStringW (resource_module, id, buffer, buffer_length); - - if (string_length != 0 && string_length == buffer_length - 1) - { - g_free (buffer); - buffer_length *= 2; - } - else - { - if (string_length == 0) - g_clear_pointer (&buffer, g_free); + /* TODO: For UWP handlers this string is usually in @{...} form, + * see grab_registry_string() below. Right now this + * string is read as-is and the icon would silently fail to load. + * Also, right now handler icon is not used anywhere + * (only app icon is used). + */ + if (default_type == G_WIN32_REGISTRY_VALUE_STR && + default_value[0] != '\0') + *icon_out = g_themed_icon_new (default_value); - break; - } - } - - FreeLibrary (resource_module); - - if (buffer) - { - gunichar2 *result = g_wcsdup (buffer, -1); - g_free (buffer); - return result; + g_clear_pointer (&default_value, g_free); } - return NULL; + g_object_unref (icon_key); } static void -read_handler_icon (GWin32RegistryKey *proxy_key, - GWin32RegistryKey *program_key, - GIcon **icon_out) +reg_verb_free (gpointer p) { - gint counter; - GWin32RegistryKey *key; - - *icon_out = NULL; - - for (counter = 0; counter < 2; counter++) - { - GWin32RegistryKey *icon_key; - - if (counter == 0) - key = proxy_key; - else - key = program_key; - - if (!key) - continue; + if (p == NULL) + return; - icon_key = g_win32_registry_key_get_child_w (key, L"DefaultIcon", NULL); + g_free (((reg_verb *) p)->name); + g_free (((reg_verb *) p)->shellpath); + g_free (p); +} - if (icon_key != NULL) - { - GWin32RegistryValueType default_type; - gchar *default_value; +#define is_open(x) ( \ + ((x)[0] == L'o' || (x)[0] == L'O') && \ + ((x)[1] == L'p' || (x)[1] == L'P') && \ + ((x)[2] == L'e' || (x)[2] == L'E') && \ + ((x)[3] == L'n' || (x)[3] == L'N') && \ + ((x)[4] == L'\0') \ +) + +/* default verb (if any) comes first, + * then "open", then the rest of the verbs + * are sorted alphabetically + */ +static gint +compare_verbs (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + const reg_verb *ca = (const reg_verb *) a; + const reg_verb *cb = (const reg_verb *) b; + const gunichar2 *def = (const gunichar2 *) user_data; + gboolean is_open_ca; + gboolean is_open_cb; - if (g_win32_registry_key_get_value (icon_key, - TRUE, - "", - &default_type, - (gpointer *) &default_value, - NULL, - NULL)) - { - if (default_type == G_WIN32_REGISTRY_VALUE_STR || - default_value[0] != '\0') - *icon_out = g_themed_icon_new (default_value); + if (def != NULL) + { + if (_wcsicmp (ca->name, def) == 0) + return -1; + else if (_wcsicmp (cb->name, def) == 0) + return 1; + } - g_clear_pointer (&default_value, g_free); - } + is_open_ca = is_open (ca->name); + is_open_cb = is_open (cb->name); - g_object_unref (icon_key); - } + if (is_open_ca && !is_open_cb) + return -1; + else if (is_open_ca && !is_open_cb) + return 1; - if (*icon_out) - break; - } + return _wcsicmp (ca->name, cb->name); } static gboolean build_registry_path (gunichar2 *output, gsize output_size, ...) G_GNUC_NULL_TERMINATED; @@ -617,6 +754,80 @@ static gboolean build_registry_pathv (gunichar2 *output, gsize output_size, va_l static GWin32RegistryKey *_g_win32_registry_key_build_and_new_w (GError **error, ...) G_GNUC_NULL_TERMINATED; +/* Called by process_verbs_commands. + * @verb is a verb name + * @command_line is the commandline of that verb + * @command_line_utf8 is the UTF-8 version of @command_line + * @verb_displayname is the prettier display name of the verb (might be NULL) + * @verb_is_preferred is TRUE if the verb is the preferred one + * @invent_new_verb_name is TRUE when the verb should be added + * even if a verb with such + * name already exists (in which case + * a new name is invented), unless + * the existing verb runs exactly the same + * commandline. + */ +typedef void (*verb_command_func) (gpointer handler_data1, + gpointer handler_data2, + const gunichar2 *verb, + const gunichar2 *command_line, + const gchar *command_line_utf8, + const gchar *verb_displayname, + gboolean verb_is_preferred, + gboolean invent_new_verb_name); + +static gunichar2 * decide_which_id_to_use (const gunichar2 *program_id, + GWin32RegistryKey **return_key, + gchar **return_handler_id_u8, + gchar **return_handler_id_u8_folded, + gunichar2 **return_uwp_aumid); + +static GWin32AppInfoURLSchema * get_schema_object (const gunichar2 *schema, + const gchar *schema_u8, + const gchar *schema_u8_folded); + +static GWin32AppInfoHandler * get_handler_object (const gchar *handler_id_u8_folded, + GWin32RegistryKey *handler_key, + const gunichar2 *handler_id, + const gunichar2 *uwp_aumid); + +static GWin32AppInfoFileExtension *get_ext_object (const gunichar2 *ext, + const gchar *ext_u8, + const gchar *ext_u8_folded); + + +static void process_verbs_commands (GList *verbs, + const reg_verb *preferred_verb, + const gunichar2 *path_to_progid, + const gunichar2 *progid, + gboolean autoprefer_first_verb, + verb_command_func handler, + gpointer handler_data1, + gpointer handler_data2); + +static void handler_add_verb (gpointer handler_data1, + gpointer handler_data2, + const gunichar2 *verb, + const gunichar2 *command_line, + const gchar *command_line_utf8, + const gchar *verb_displayname, + gboolean verb_is_preferred, + gboolean invent_new_verb_name); + +static void process_uwp_verbs (GList *verbs, + const reg_verb *preferred_verb, + const gunichar2 *path_to_progid, + const gunichar2 *progid, + gboolean autoprefer_first_verb, + GWin32AppInfoHandler *handler_rec, + GWin32AppInfoApplication *app); + +static void uwp_handler_add_verb (GWin32AppInfoHandler *handler_rec, + GWin32AppInfoApplication *app, + const gunichar2 *verb, + const gchar *verb_displayname, + gboolean verb_is_preferred); + /* output_size is in *bytes*, not gunichar2s! */ static gboolean build_registry_path (gunichar2 *output, gsize output_size, ...) @@ -694,703 +905,1093 @@ _g_win32_registry_key_build_and_new_w (GError **error, ...) return key; } - -static gboolean -utf8_and_fold (const gunichar2 *str, - gchar **str_u8, - gchar **str_u8_folded) -{ - gchar *u8; - gchar *folded; - u8 = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL); - - if (u8 == NULL) - return FALSE; - - folded = g_utf8_casefold (u8, -1); - - if (folded == NULL) - { - g_free (u8); - return FALSE; - } - - if (str_u8) - *str_u8 = u8; - else - g_free (u8); - - if (str_u8_folded) - *str_u8_folded = folded; - else - g_free (folded); - - return TRUE; -} - - +/* Gets the list of shell verbs (a GList of reg_verb, put into @verbs) + * from the @program_id_key. + * If one of the verbs should be preferred, + * a pointer to this verb (in the GList) will be + * put into @preferred_verb. + * Does not automatically assume that the first verb + * is preferred (when no other preferences exist). + * @verbname_prefix is prefixed to the name of the verb + * (this is used for subcommands) and is initially an + * empty string. + * @verbshell_prefix is the subkey of @program_id_key + * that contains the verbs. It is "Shell" initially, + * but grows with recursive invocations (for subcommands). + * @is_uwp points to a boolean, which + * indicates whether the function is being called for a UWP app. + * It might be switched from %TRUE to %FALSE on return, + * if the application turns out to not to be UWP on closer inspection. + * If the application is already known not to be UWP before the + * call, this pointer can be %NULL instead. + * Returns TRUE on success, FALSE on failure. + */ static gboolean -follow_class_chain_to_handler (const gunichar2 *program_id, - gsize program_id_size, - gunichar2 **program_command, - GWin32RegistryKey **program_key, - gunichar2 **proxy_id, - gunichar2 **proxy_command, - GWin32RegistryKey **proxy_key, - gchar **program_id_u8, - gchar **program_id_folded) +get_verbs (GWin32RegistryKey *program_id_key, + const reg_verb **preferred_verb, + GList **verbs, + const gunichar2 *verbname_prefix, + const gunichar2 *verbshell_prefix, + gboolean *is_uwp) { + GWin32RegistrySubkeyIter iter; GWin32RegistryKey *key; GWin32RegistryValueType val_type; - gsize proxy_id_size; - gboolean got_value; + gunichar2 *default_verb; + gsize verbshell_prefix_len; + gsize verbname_prefix_len; + GList *i; - g_assert (program_id && program_command && proxy_id && proxy_command); + g_assert (program_id_key && verbs && preferred_verb); - *program_command = NULL; - *proxy_id = NULL; - *proxy_command = NULL; + *verbs = NULL; + *preferred_verb = NULL; - if (program_key) - *program_key = NULL; + key = g_win32_registry_key_get_child_w (program_id_key, + verbshell_prefix, + NULL); + + if (key == NULL) + return FALSE; - if (proxy_key) - *proxy_key = NULL; + if (!g_win32_registry_subkey_iter_init (&iter, key, NULL)) + { + g_object_unref (key); + return FALSE; + } - key = _g_win32_registry_key_build_and_new_w (NULL, HKCR, program_id, - SHELL_OPEN_COMMAND, NULL); + verbshell_prefix_len = g_utf16_len (verbshell_prefix); + verbname_prefix_len = g_utf16_len (verbname_prefix); - if (key != NULL) + while (g_win32_registry_subkey_iter_next (&iter, TRUE, NULL)) { - got_value = g_win32_registry_key_get_value_w (key, - TRUE, - L"", - &val_type, - (void **) program_command, - NULL, - NULL); - if (got_value && val_type == G_WIN32_REGISTRY_VALUE_STR) + const gunichar2 *name; + gsize name_len; + GWin32RegistryKey *subkey; + gboolean has_subcommands; + const reg_verb *tmp; + GWin32RegistryValueType subc_type; + reg_verb *rverb; + const gunichar2 *shell = L"Shell"; + const gsize shell_len = g_utf16_len (shell); + + if (!g_win32_registry_subkey_iter_get_name_w (&iter, &name, &name_len, NULL)) + continue; + + subkey = g_win32_registry_key_get_child_w (key, + name, + NULL); + + g_assert (subkey != NULL); + /* The key we're looking at is "/Shell/", + * where "Shell" is verbshell_prefix. + * If it has a value named 'Subcommands' (doesn't matter what its data is), + * it means that this key has its own Shell subkey, the subkeys + * of which are shell commands (i.e. /Shell//Shell/). + * To handle that, create new, extended nameprefix and shellprefix, + * and call the function recursively. + * name prefix "" -> "\\" + * shell prefix "Shell" -> "Shell\\\\Shell" + * The root, program_id_key, remains the same in all invocations. + * Essentially, we're flattening the command tree into a list. + */ + has_subcommands = FALSE; + if ((is_uwp == NULL || !(*is_uwp)) && /* Assume UWP apps don't have subcommands */ + g_win32_registry_key_get_value_w (subkey, + NULL, + TRUE, + L"Subcommands", + &subc_type, + NULL, + NULL, + NULL) && + subc_type == G_WIN32_REGISTRY_VALUE_STR) { - if ((program_id_u8 != NULL || program_id_folded != NULL) && - !utf8_and_fold (program_id, program_id_u8, program_id_folded)) - { - g_object_unref (key); - g_free (program_command); + gboolean dummy = FALSE; + gunichar2 *new_nameprefix = g_new (gunichar2, verbname_prefix_len + name_len + 1 + 1); + gunichar2 *new_shellprefix = g_new (gunichar2, verbshell_prefix_len + 1 + name_len + 1 + shell_len + 1); + memcpy (&new_shellprefix[0], verbshell_prefix, verbshell_prefix_len * sizeof (gunichar2)); + new_shellprefix[verbshell_prefix_len] = L'\\'; + memcpy (&new_shellprefix[verbshell_prefix_len + 1], name, name_len * sizeof (gunichar2)); + new_shellprefix[verbshell_prefix_len + 1 + name_len] = L'\\'; + memcpy (&new_shellprefix[verbshell_prefix_len + 1 + name_len + 1], shell, shell_len * sizeof (gunichar2)); + new_shellprefix[verbshell_prefix_len + 1 + name_len + 1 + shell_len] = 0; + + memcpy (&new_nameprefix[0], verbname_prefix, verbname_prefix_len * sizeof (gunichar2)); + memcpy (&new_nameprefix[verbname_prefix_len], name, (name_len) * sizeof (gunichar2)); + new_nameprefix[verbname_prefix_len + name_len] = L'\\'; + new_nameprefix[verbname_prefix_len + name_len + 1] = 0; + has_subcommands = get_verbs (program_id_key, &tmp, verbs, new_nameprefix, new_shellprefix, &dummy); + g_free (new_shellprefix); + g_free (new_nameprefix); + } - return FALSE; - } - if (program_key == NULL) - g_object_unref (key); - else - *program_key = key; + /* Presence of subcommands means that this key itself is not a command-key */ + if (has_subcommands) + { + g_clear_object (&subkey); + continue; + } - return TRUE; + if (is_uwp != NULL && *is_uwp && + !g_win32_registry_key_get_value_w (subkey, + NULL, + TRUE, + L"ActivatableClassId", + &subc_type, + NULL, + NULL, + NULL)) + { + /* We expected a UWP app, but it lacks ActivatableClassId + * on a verb, which means that it does not behave like + * a UWP app should (msedge being an example - it's UWP, + * but has its own launchable exe file and a simple ID), + * so we have to treat it like a normal app. + */ + *is_uwp = FALSE; } - else if (got_value) - g_clear_pointer (program_command, g_free); - g_object_unref (key); + g_clear_object (&subkey); + + /* We don't look at the command sub-key and its value (the actual command line) here. + * We save the registry path instead, and use it later in process_verbs_commands(). + * The name of the verb is also saved. + * verbname_prefix is prefixed to the verb name (it's either an empty string + * or already ends with a '\\', so no extra separators needed). + * verbshell_prefix is prefixed to the verb key path (this one needs a separator, + * because it never has one - all verbshell prefixes end with "Shell", not "Shell\\") + */ + rverb = g_new0 (reg_verb, 1); + rverb->name = g_new (gunichar2, verbname_prefix_len + name_len + 1); + memcpy (&rverb->name[0], verbname_prefix, verbname_prefix_len * sizeof (gunichar2)); + memcpy (&rverb->name[verbname_prefix_len], name, name_len * sizeof (gunichar2)); + rverb->name[verbname_prefix_len + name_len] = 0; + rverb->shellpath = g_new (gunichar2, verbshell_prefix_len + 1 + name_len + 1); + memcpy (&rverb->shellpath[0], verbshell_prefix, verbshell_prefix_len * sizeof (gunichar2)); + memcpy (&rverb->shellpath[verbshell_prefix_len], L"\\", sizeof (gunichar2)); + memcpy (&rverb->shellpath[verbshell_prefix_len + 1], name, name_len * sizeof (gunichar2)); + rverb->shellpath[verbshell_prefix_len + 1 + name_len] = 0; + *verbs = g_list_append (*verbs, rverb); } - key = _g_win32_registry_key_build_and_new_w (NULL, HKCR, program_id, NULL); + g_win32_registry_subkey_iter_clear (&iter); - if (key == NULL) - return FALSE; - - got_value = g_win32_registry_key_get_value_w (key, - TRUE, - L"", - &val_type, - (void **) proxy_id, - &proxy_id_size, - NULL); - if (!got_value || - (val_type != G_WIN32_REGISTRY_VALUE_STR)) + if (*verbs == NULL) { g_object_unref (key); - g_clear_pointer (proxy_id, g_free); + return FALSE; } - if (proxy_key) - *proxy_key = key; - else - g_object_unref (key); - - key = _g_win32_registry_key_build_and_new_w (NULL, HKCR, *proxy_id, - SHELL_OPEN_COMMAND, NULL); + default_verb = NULL; - if (key == NULL) - { - g_clear_pointer (proxy_id, g_free); - if (proxy_key) - g_clear_object (proxy_key); - return FALSE; - } + if (g_win32_registry_key_get_value_w (key, + NULL, + TRUE, + L"", + &val_type, + (void **) &default_verb, + NULL, + NULL) && + (val_type != G_WIN32_REGISTRY_VALUE_STR || + g_utf16_len (default_verb) <= 0)) + g_clear_pointer (&default_verb, g_free); - got_value = g_win32_registry_key_get_value_w (key, - TRUE, - L"", - &val_type, - (void **) proxy_command, - NULL, - NULL); g_object_unref (key); - if (!got_value || - val_type != G_WIN32_REGISTRY_VALUE_STR || - ((program_id_u8 != NULL || program_id_folded != NULL) && - !utf8_and_fold (program_id, program_id_u8, program_id_folded))) + /* Only sort at the top level */ + if (verbname_prefix[0] == 0) { - g_clear_pointer (proxy_id, g_free); - g_clear_pointer (proxy_command, g_free); - if (proxy_key) - g_clear_object (proxy_key); - return FALSE; + *verbs = g_list_sort_with_data (*verbs, compare_verbs, default_verb); + + for (i = *verbs; default_verb && *preferred_verb == NULL && i; i = i->next) + if (_wcsicmp (default_verb, ((const reg_verb *) i->data)->name) == 0) + *preferred_verb = (const reg_verb *) i->data; } + g_clear_pointer (&default_verb, g_free); + return TRUE; } - +/* Grabs a URL association (from HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\ + * or from an application with Capabilities, or just a schema subkey in HKCR). + * @program_id is a ProgID of the handler for the URL. + * @schema is the schema for the URL. + * @schema_u8 and @schema_u8_folded are UTF-8 and folded UTF-8 + * respectively. + * @app is the app to which the URL handler belongs (can be NULL). + * @is_user_choice is TRUE if this association is clearly preferred + */ static void -extract_executable (gunichar2 *commandline, - gchar **ex_out, - gchar **ex_basename_out, - gchar **ex_folded_out, - gchar **ex_folded_basename_out) +get_url_association (const gunichar2 *program_id, + const gunichar2 *schema, + const gchar *schema_u8, + const gchar *schema_u8_folded, + GWin32AppInfoApplication *app, + gboolean is_user_choice) { - gchar *ex; - gchar *ex_folded; - gunichar2 *p; - gboolean quoted; - size_t len; - size_t execlen; - gunichar2 *exepart; - gboolean found; - - quoted = FALSE; - execlen = 0; - found = FALSE; - len = wcslen (commandline); - p = commandline; - - while (p < &commandline[len]) - { - switch (p[0]) - { - case L'"': - quoted = !quoted; - break; - case L' ': - if (!quoted) - { - execlen = p - commandline; - p = &commandline[len]; - found = TRUE; - } - break; - default: - break; - } - p += 1; - } - - if (!found) - execlen = len; - - exepart = g_wcsdup (commandline, (execlen + 1) * sizeof (gunichar2)); - exepart[execlen] = L'\0'; + GWin32AppInfoURLSchema *schema_rec; + GWin32AppInfoHandler *handler_rec; + gunichar2 *handler_id; + GList *verbs; + const reg_verb *preferred_verb; + gchar *handler_id_u8; + gchar *handler_id_u8_folded; + gunichar2 *uwp_aumid; + gboolean is_uwp; + GWin32RegistryKey *handler_key; + + if ((handler_id = decide_which_id_to_use (program_id, + &handler_key, + &handler_id_u8, + &handler_id_u8_folded, + &uwp_aumid)) == NULL) + return; - p = &exepart[0]; + is_uwp = uwp_aumid != NULL; - while (execlen > 0 && exepart[0] == L'"' && exepart[execlen - 1] == L'"') + if (!get_verbs (handler_key, &preferred_verb, &verbs, L"", L"Shell", &is_uwp)) { - p = &exepart[1]; - exepart[execlen - 1] = L'\0'; - execlen -= 2; - } - - if (!utf8_and_fold (p, &ex, &ex_folded)) - /* Currently no code to handle this case. It shouldn't happen though... */ - g_assert_not_reached (); + g_clear_pointer (&handler_id, g_free); + g_clear_pointer (&handler_id_u8, g_free); + g_clear_pointer (&handler_id_u8_folded, g_free); + g_clear_object (&handler_key); + g_clear_pointer (&uwp_aumid, g_free); - g_free (exepart); + return; + } - if (ex_out) - { - *ex_out = ex; + if (!is_uwp && uwp_aumid != NULL) + g_clear_pointer (&uwp_aumid, g_free); - if (ex_basename_out) - { - *ex_basename_out = &ex[strlen (ex) - 1]; + schema_rec = get_schema_object (schema, + schema_u8, + schema_u8_folded); - while (*ex_basename_out > ex) - { - if ((*ex_basename_out)[0] == '/' || - (*ex_basename_out)[0] == '\\') - { - *ex_basename_out += 1; - break; - } + handler_rec = get_handler_object (handler_id_u8_folded, + handler_key, + handler_id, + uwp_aumid); - *ex_basename_out -= 1; - } - } - } - else - { - g_free (ex); - } + if (is_user_choice || schema_rec->chosen_handler == NULL) + g_set_object (&schema_rec->chosen_handler, handler_rec); - if (ex_folded_out) - { - *ex_folded_out = ex_folded; + g_hash_table_insert (schema_rec->handlers, + g_strdup (handler_id_u8_folded), + g_object_ref (handler_rec)); - if (ex_folded_basename_out) - { - *ex_folded_basename_out = &ex_folded[strlen (ex_folded) - 1]; + g_clear_object (&handler_key); - while (*ex_folded_basename_out > ex_folded) - { - if ((*ex_folded_basename_out)[0] == '/' || - (*ex_folded_basename_out)[0] == '\\') - { - *ex_folded_basename_out += 1; - break; - } + if (app) + g_hash_table_insert (app->supported_urls, + g_strdup (schema_rec->schema_u8_folded), + g_object_ref (handler_rec)); - *ex_folded_basename_out -= 1; - } - } - } + if (uwp_aumid == NULL) + process_verbs_commands (g_steal_pointer (&verbs), + preferred_verb, + HKCR, + handler_id, + TRUE, + handler_add_verb, + handler_rec, + app); else - { - g_free (ex_folded); - } + process_uwp_verbs (g_steal_pointer (&verbs), + preferred_verb, + HKCR, + handler_id, + TRUE, + handler_rec, + app); + + + g_clear_pointer (&handler_id_u8, g_free); + g_clear_pointer (&handler_id_u8_folded, g_free); + g_clear_pointer (&handler_id, g_free); + g_clear_pointer (&uwp_aumid, g_free); } +/* Grabs a file extension association (from HKCR\.ext or similar). + * @program_id is a ProgID of the handler for the extension. + * @file_extension is the extension (with the leading '.') + * @app is the app to which the extension handler belongs (can be NULL). + * @is_user_choice is TRUE if this is clearly the preferred association + */ static void -get_url_association (const gunichar2 *schema) +get_file_ext (const gunichar2 *program_id, + const gunichar2 *file_extension, + GWin32AppInfoApplication *app, + gboolean is_user_choice) { - GWin32AppInfoURLSchema *schema_rec; GWin32AppInfoHandler *handler_rec; - GWin32AppInfoHandler *handler_rec_in_url; - gchar *schema_u8; - gchar *schema_folded; - GWin32RegistryKey *user_choice; - GWin32RegistryValueType val_type; - gunichar2 *program_id; - gsize program_id_size; - gunichar2 *program_command; - gunichar2 *proxy_id; - gunichar2 *proxy_command; - gchar *program_id_u8; - gchar *program_id_folded; - GWin32RegistryKey *program_key; - GWin32RegistryKey *proxy_key; - - user_choice = _g_win32_registry_key_build_and_new_w (NULL, URL_ASSOCIATIONS, - schema, USER_CHOICE, - NULL); - - if (user_choice == NULL) + gunichar2 *handler_id; + const reg_verb *preferred_verb; + GList *verbs; + gchar *handler_id_u8; + gchar *handler_id_u8_folded; + gunichar2 *uwp_aumid; + gboolean is_uwp; + GWin32RegistryKey *handler_key; + GWin32AppInfoFileExtension *file_extn; + gchar *file_extension_u8; + gchar *file_extension_u8_folded; + + if ((handler_id = decide_which_id_to_use (program_id, + &handler_key, + &handler_id_u8, + &handler_id_u8_folded, + &uwp_aumid)) == NULL) return; - if (!utf8_and_fold (schema, &schema_u8, &schema_folded)) + if (!g_utf16_to_utf8_and_fold (file_extension, + -1, + &file_extension_u8, + &file_extension_u8_folded)) { - g_object_unref (user_choice); + g_clear_pointer (&handler_id, g_free); + g_clear_pointer (&handler_id_u8, g_free); + g_clear_pointer (&handler_id_u8_folded, g_free); + g_clear_pointer (&uwp_aumid, g_free); + g_clear_object (&handler_key); + return; } - schema_rec = g_hash_table_lookup (urls, schema_folded); + is_uwp = uwp_aumid != NULL; - if (!g_win32_registry_key_get_value_w (user_choice, - TRUE, - L"Progid", - &val_type, - (void **) &program_id, - &program_id_size, - NULL)) + if (!get_verbs (handler_key, &preferred_verb, &verbs, L"", L"Shell", &is_uwp)) { - g_free (schema_u8); - g_free (schema_folded); - g_object_unref (user_choice); - return; - } + g_clear_pointer (&handler_id, g_free); + g_clear_pointer (&handler_id_u8, g_free); + g_clear_pointer (&handler_id_u8_folded, g_free); + g_clear_object (&handler_key); + g_clear_pointer (&file_extension_u8, g_free); + g_clear_pointer (&file_extension_u8_folded, g_free); + g_clear_pointer (&uwp_aumid, g_free); - if (val_type != G_WIN32_REGISTRY_VALUE_STR) - { - g_free (schema_u8); - g_free (schema_folded); - g_free (program_id); - g_object_unref (user_choice); return; } - program_key = proxy_key = NULL; - program_command = proxy_id = proxy_command = NULL; - - if (!follow_class_chain_to_handler (program_id, - program_id_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &program_id_u8, - &program_id_folded)) + if (!is_uwp && uwp_aumid != NULL) + g_clear_pointer (&uwp_aumid, g_free); + + file_extn = get_ext_object (file_extension, file_extension_u8, file_extension_u8_folded); + + handler_rec = get_handler_object (handler_id_u8_folded, + handler_key, + handler_id, + uwp_aumid); + + if (is_user_choice || file_extn->chosen_handler == NULL) + g_set_object (&file_extn->chosen_handler, handler_rec); + + g_hash_table_insert (file_extn->handlers, + g_strdup (handler_id_u8_folded), + g_object_ref (handler_rec)); + + if (app) + g_hash_table_insert (app->supported_exts, + g_strdup (file_extension_u8_folded), + g_object_ref (handler_rec)); + + g_clear_pointer (&file_extension_u8, g_free); + g_clear_pointer (&file_extension_u8_folded, g_free); + g_clear_object (&handler_key); + + if (uwp_aumid == NULL) + process_verbs_commands (g_steal_pointer (&verbs), + preferred_verb, + HKCR, + handler_id, + TRUE, + handler_add_verb, + handler_rec, + app); + else + process_uwp_verbs (g_steal_pointer (&verbs), + preferred_verb, + HKCR, + handler_id, + TRUE, + handler_rec, + app); + + g_clear_pointer (&handler_id, g_free); + g_clear_pointer (&handler_id_u8, g_free); + g_clear_pointer (&handler_id_u8_folded, g_free); + g_clear_pointer (&uwp_aumid, g_free); +} + +/* Returns either a @program_id or the string from + * the default value of the program_id key (which is a name + * of a proxy class), or NULL. + * Does not check that proxy represents a valid + * record, just checks that it exists. + * Can return the class key (HKCR/program_id or HKCR/proxy_id). + * Can convert returned value to UTF-8 and fold it. + */ +static gunichar2 * +decide_which_id_to_use (const gunichar2 *program_id, + GWin32RegistryKey **return_key, + gchar **return_handler_id_u8, + gchar **return_handler_id_u8_folded, + gunichar2 **return_uwp_aumid) +{ + GWin32RegistryKey *key; + GWin32RegistryKey *uwp_key; + GWin32RegistryValueType val_type; + gunichar2 *proxy_id; + gunichar2 *return_id; + gunichar2 *uwp_aumid; + gboolean got_value; + gchar *handler_id_u8; + gchar *handler_id_u8_folded; + g_assert (program_id); + + if (return_key) + *return_key = NULL; + + if (return_uwp_aumid) + *return_uwp_aumid = NULL; + + key = g_win32_registry_key_get_child_w (classes_root_key, program_id, NULL); + + if (key == NULL) + return NULL; + + /* Check for UWP first */ + uwp_aumid = NULL; + uwp_key = g_win32_registry_key_get_child_w (key, L"Application", NULL); + + if (uwp_key != NULL) { - g_free (schema_u8); - g_free (schema_folded); - g_free (program_id); - g_object_unref (user_choice); - return; + got_value = g_win32_registry_key_get_value_w (uwp_key, + NULL, + TRUE, + L"AppUserModelID", + &val_type, + (void **) &uwp_aumid, + NULL, + NULL); + if (got_value && val_type != G_WIN32_REGISTRY_VALUE_STR) + g_clear_pointer (&uwp_aumid, g_free); + + /* Other values in the Application key contain useful information + * (description, name, icon), but it's inconvenient to read + * it here (we don't have an app object *yet*). Store the key + * in a table instead, and look at it later. + */ + if (uwp_aumid == NULL) + g_debug ("ProgramID %S looks like a UWP application, but isn't", + program_id); + else + g_hash_table_insert (uwp_handler_table, g_object_ref (uwp_key), g_wcsdup (uwp_aumid, -1)); + + g_object_unref (uwp_key); } - handler_rec = g_hash_table_lookup (handlers, program_id_folded); + /* Then check for proxy */ + proxy_id = NULL; - if (handler_rec == NULL) + if (uwp_aumid == NULL) { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); - - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = g_wcsdup (program_id, program_id_size); - handler_rec->handler_id_folded = - g_strdup (program_id_folded); - handler_rec->handler_command = - program_command ? g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, program_key, &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (program_id_folded), - handler_rec); + got_value = g_win32_registry_key_get_value_w (key, + NULL, + TRUE, + L"", + &val_type, + (void **) &proxy_id, + NULL, + NULL); + if (got_value && val_type != G_WIN32_REGISTRY_VALUE_STR) + g_clear_pointer (&proxy_id, g_free); } - else + + return_id = NULL; + + if (proxy_id) { - g_clear_object (&program_key); - g_clear_object (&proxy_key); + GWin32RegistryKey *proxy_key; + proxy_key = g_win32_registry_key_get_child_w (classes_root_key, proxy_id, NULL); + + if (proxy_key) + { + if (return_key) + *return_key = g_steal_pointer (&proxy_key); + g_clear_object (&proxy_key); + + return_id = g_steal_pointer (&proxy_id); + } + + g_clear_pointer (&proxy_id, g_free); } - if (schema_rec == NULL) + if ((return_handler_id_u8 || + return_handler_id_u8_folded) && + !g_utf16_to_utf8_and_fold (return_id == NULL ? program_id : return_id, + -1, + &handler_id_u8, + &handler_id_u8_folded)) { - schema_rec = g_object_new (G_TYPE_WIN32_APPINFO_URL_SCHEMA, NULL); - schema_rec->schema = g_wcsdup (schema, -1); - schema_rec->schema_u8 = g_strdup (schema_u8); - schema_rec->schema_folded = g_strdup (schema_folded); - schema_rec->chosen_handler = g_object_ref (handler_rec); - g_hash_table_insert (urls, g_strdup (schema_folded), schema_rec); + g_clear_object (&key); + if (return_key) + g_clear_object (return_key); + g_clear_pointer (&return_id, g_free); + + return NULL; } - if (schema_rec->chosen_handler == NULL) - schema_rec->chosen_handler = g_object_ref (handler_rec); + if (return_handler_id_u8) + *return_handler_id_u8 = g_steal_pointer (&handler_id_u8); + g_clear_pointer (&handler_id_u8, g_free); + if (return_handler_id_u8_folded) + *return_handler_id_u8_folded = g_steal_pointer (&handler_id_u8_folded); + g_clear_pointer (&handler_id_u8_folded, g_free); + if (return_uwp_aumid) + *return_uwp_aumid = g_steal_pointer (&uwp_aumid); + g_clear_pointer (&uwp_aumid, g_free); - handler_rec_in_url = g_hash_table_lookup (schema_rec->handlers, - program_id_folded); + if (return_id == NULL && return_key) + *return_key = g_steal_pointer (&key); + g_clear_object (&key); - if (handler_rec_in_url == NULL && schema_rec->chosen_handler != handler_rec) - g_hash_table_insert (schema_rec->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); + if (return_id == NULL) + return g_wcsdup (program_id, -1); - g_free (schema_u8); - g_free (schema_folded); - g_free (program_id); - g_free (program_id_u8); - g_free (program_id_folded); - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); - g_object_unref (user_choice); + return return_id; } +/* Grabs the command for each verb from @verbs, + * and invokes @handler for it. Consumes @verbs. + * @path_to_progid and @progid are concatenated to + * produce a path to the key where Shell/verb/command + * subkeys are looked up. + * @preferred_verb, if not NULL, will be used to inform + * the @handler that a verb is preferred. + * @autoprefer_first_verb will automatically make the first + * verb to be preferred, if @preferred_verb is NULL. + * @handler_data1 and @handler_data2 are passed to @handler as-is. + */ static void -get_file_ext (const gunichar2 *ext) +process_verbs_commands (GList *verbs, + const reg_verb *preferred_verb, + const gunichar2 *path_to_progid, + const gunichar2 *progid, + gboolean autoprefer_first_verb, + verb_command_func handler, + gpointer handler_data1, + gpointer handler_data2) { - GWin32AppInfoFileExtension *file_extn; - gboolean file_ext_known; - GWin32AppInfoHandler *handler_rec; - GWin32AppInfoHandler *handler_rec_in_ext; - gchar *ext_u8; - gchar *ext_folded; - GWin32RegistryKey *user_choice; - GWin32RegistryKey *open_with_progids; - GWin32RegistryValueType val_type; - gsize program_id_size; - gboolean found_handler; - gunichar2 *program_id; - gunichar2 *proxy_id; - gchar *program_id_u8; - gchar *program_id_folded; - GWin32RegistryKey *program_key; - GWin32RegistryKey *proxy_key; - gunichar2 *program_command; - gunichar2 *proxy_command; - - open_with_progids = _g_win32_registry_key_build_and_new_w (NULL, FILE_EXTS, - ext, - OPEN_WITH_PROGIDS, - NULL); - - user_choice = _g_win32_registry_key_build_and_new_w (NULL, FILE_EXTS, ext, - USER_CHOICE, NULL); + GList *i; + gboolean got_value; - if (user_choice == NULL && open_with_progids == NULL) - return; + g_assert (handler != NULL); + g_assert (verbs != NULL); + g_assert (progid != NULL); - if (!utf8_and_fold (ext, &ext_u8, &ext_folded)) + for (i = verbs; i; i = i->next) { - g_clear_object (&user_choice); - g_clear_object (&open_with_progids); - return; - } + const reg_verb *verb = (const reg_verb *) i->data; + GWin32RegistryKey *key; + GWin32RegistryKey *verb_key; + gunichar2 *command_value; + gchar *command_value_utf8; + GWin32RegistryValueType val_type; + gunichar2 *verb_displayname; + gchar *verb_displayname_u8; + + key = _g_win32_registry_key_build_and_new_w (NULL, path_to_progid, progid, + L"\\", verb->shellpath, L"\\command", NULL); + + if (key == NULL) + { + g_debug ("%S%S\\shell\\%S does not have a \"command\" subkey", + path_to_progid, progid, verb->shellpath); + continue; + } - file_extn = NULL; - file_ext_known = g_hash_table_lookup_extended (extensions, - ext_folded, - NULL, - (void **) &file_extn); + command_value = NULL; + got_value = g_win32_registry_key_get_value_w (key, + NULL, + TRUE, + L"", + &val_type, + (void **) &command_value, + NULL, + NULL); + g_clear_object (&key); - if (!file_ext_known) - file_extn = g_object_new (G_TYPE_WIN32_APPINFO_FILE_EXTENSION, NULL); + if (!got_value || + val_type != G_WIN32_REGISTRY_VALUE_STR || + (command_value_utf8 = g_utf16_to_utf8 (command_value, + -1, + NULL, + NULL, + NULL)) == NULL) + { + g_clear_pointer (&command_value, g_free); + continue; + } - found_handler = FALSE; + verb_displayname = NULL; + verb_displayname_u8 = NULL; + verb_key = _g_win32_registry_key_build_and_new_w (NULL, path_to_progid, progid, + L"\\", verb->shellpath, NULL); - if (user_choice != NULL) - { - if (g_win32_registry_key_get_value_w (user_choice, - TRUE, - L"Progid", - &val_type, - (void **) &program_id, - &program_id_size, - NULL)) + if (verb_key) { - program_key = proxy_key = NULL; - - if (val_type == G_WIN32_REGISTRY_VALUE_STR && - follow_class_chain_to_handler (program_id, - program_id_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &program_id_u8, - &program_id_folded)) - { - handler_rec = g_hash_table_lookup (handlers, - program_id_folded); + gsize verb_displayname_len; - if (handler_rec == NULL) - { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, - NULL); - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = - g_wcsdup (program_id, program_id_size); - handler_rec->handler_id_folded = - g_strdup (program_id_folded); - handler_rec->handler_command = - program_command ? g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = - proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, - program_key, - &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (program_id_folded), - handler_rec); - } - else - { - g_clear_object (&program_key); - g_clear_object (&proxy_key); - } + got_value = g_win32_registry_key_get_value_w (verb_key, + g_win32_registry_get_os_dirs_w (), + TRUE, + L"MUIVerb", + &val_type, + (void **) &verb_displayname, + &verb_displayname_len, + NULL); - found_handler = TRUE; + if (got_value && + val_type == G_WIN32_REGISTRY_VALUE_STR && + verb_displayname_len > sizeof (gunichar2)) + verb_displayname_u8 = g_utf16_to_utf8 (verb_displayname, -1, NULL, NULL, NULL); - handler_rec_in_ext = g_hash_table_lookup (file_extn->handlers, - program_id_folded); + g_clear_pointer (&verb_displayname, g_free); - if (file_extn->chosen_handler == NULL) - { - g_hash_table_insert (file_extn->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - } - else if (handler_rec_in_ext == NULL) - { - if (file_extn->chosen_handler->handler_id_folded && - strcmp (file_extn->chosen_handler->handler_id_folded, - program_id_folded) != 0) - g_hash_table_insert (file_extn->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - } + if (verb_displayname_u8 == NULL) + { + got_value = g_win32_registry_key_get_value_w (verb_key, + NULL, + TRUE, + L"", + &val_type, + (void **) &verb_displayname, + &verb_displayname_len, + NULL); - g_free (program_id_u8); - g_free (program_id_folded); - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); + if (got_value && + val_type == G_WIN32_REGISTRY_VALUE_STR && + verb_displayname_len > sizeof (gunichar2)) + verb_displayname_u8 = g_utf16_to_utf8 (verb_displayname, -1, NULL, NULL, NULL); } - g_free (program_id); + g_clear_pointer (&verb_displayname, g_free); + g_clear_object (&verb_key); } - g_object_unref (user_choice); + handler (handler_data1, handler_data2, verb->name, command_value, command_value_utf8, + verb_displayname_u8, + (preferred_verb && _wcsicmp (verb->name, preferred_verb->name) == 0) || + (!preferred_verb && autoprefer_first_verb && i == verbs), + FALSE); + + g_clear_pointer (&command_value, g_free); + g_clear_pointer (&command_value_utf8, g_free); + g_clear_pointer (&verb_displayname_u8, g_free); } - if (open_with_progids != NULL) + g_list_free_full (verbs, reg_verb_free); +} + +static void +process_uwp_verbs (GList *verbs, + const reg_verb *preferred_verb, + const gunichar2 *path_to_progid, + const gunichar2 *progid, + gboolean autoprefer_first_verb, + GWin32AppInfoHandler *handler_rec, + GWin32AppInfoApplication *app) +{ + GList *i; + + g_assert (verbs != NULL); + + for (i = verbs; i; i = i->next) { - GWin32RegistryValueIter iter; + const reg_verb *verb = (const reg_verb *) i->data; + GWin32RegistryKey *key; + gboolean got_value; + GWin32RegistryValueType val_type; + gunichar2 *acid; + gsize acid_len; + + key = _g_win32_registry_key_build_and_new_w (NULL, path_to_progid, progid, + L"\\", verb->shellpath, NULL); - if (g_win32_registry_value_iter_init (&iter, open_with_progids, NULL)) + if (key == NULL) { - gunichar2 *value_name; - gunichar2 *value_data; - gsize value_name_len; - gsize value_data_size; - GWin32RegistryValueType value_type; + g_debug ("%S%S\\%S does not exist", + path_to_progid, progid, verb->shellpath); + continue; + } - while (g_win32_registry_value_iter_next (&iter, TRUE, NULL)) - { - gsize value_name_size; - program_key = proxy_key = NULL; + got_value = g_win32_registry_key_get_value_w (key, + g_win32_registry_get_os_dirs_w (), + TRUE, + L"ActivatableClassId", + &val_type, + (void **) &acid, + &acid_len, + NULL); - if ((!g_win32_registry_value_iter_get_value_type (&iter, - &value_type, - NULL)) || - ((val_type != G_WIN32_REGISTRY_VALUE_STR) && - (val_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR)) || - (!g_win32_registry_value_iter_get_name_w (&iter, &value_name, - &value_name_len, - NULL)) || - (value_name_len <= 0) || - (!g_win32_registry_value_iter_get_data_w (&iter, TRUE, - (void **) &value_data, - &value_data_size, - NULL)) || - (value_data_size < sizeof (gunichar2)) || - (value_data[0] == L'\0')) - continue; + if (got_value && + val_type == G_WIN32_REGISTRY_VALUE_STR && + acid_len > sizeof (gunichar2)) + { + /* TODO: default value of a shell subkey, if not empty, + * migh contain something like @{Some.Identifier_1234.456.678.789_some_words?ms-resource://Arbitrary.Path/Pointing/Somewhere} + * and it might be possible to turn it into a nice displayname. + */ + uwp_handler_add_verb (handler_rec, + app, + verb->name, + NULL, + (preferred_verb && _wcsicmp (verb->name, preferred_verb->name) == 0) || + (!preferred_verb && autoprefer_first_verb && i == verbs)); + } + else + { + g_debug ("%S%S\\%S does not have an ActivatableClassId string value", + path_to_progid, progid, verb->shellpath); + } - value_name_size = sizeof (gunichar2) * (value_name_len + 1); - - if (!follow_class_chain_to_handler (value_name, - value_name_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &program_id_u8, - &program_id_folded)) - continue; + g_clear_pointer (&acid, g_free); + g_clear_object (&key); + } - handler_rec = g_hash_table_lookup (handlers, - program_id_folded); + g_list_free_full (verbs, reg_verb_free); +} - if (handler_rec == NULL) - { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); - - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = - g_wcsdup (value_name, value_name_size); - handler_rec->handler_id_folded = - g_strdup (program_id_folded); - handler_rec->handler_command = - program_command ? g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = - proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, - program_key, - &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (program_id_folded), - handler_rec); - } - else - { - g_clear_object (&program_key); - g_clear_object (&proxy_key); - } +/* Looks up a schema object identified by + * @schema_u8_folded in the urls hash table. + * If such object doesn't exist, + * creates it and puts it into the urls hash table. + * Returns the object. + */ +static GWin32AppInfoURLSchema * +get_schema_object (const gunichar2 *schema, + const gchar *schema_u8, + const gchar *schema_u8_folded) +{ + GWin32AppInfoURLSchema *schema_rec; - found_handler = TRUE; + schema_rec = g_hash_table_lookup (urls, schema_u8_folded); - handler_rec_in_ext = g_hash_table_lookup (file_extn->handlers, - program_id_folded); + if (schema_rec != NULL) + return schema_rec; - if (handler_rec_in_ext == NULL) - { - if (file_extn->chosen_handler == NULL) - g_hash_table_insert (file_extn->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - else if (file_extn->chosen_handler->handler_id_folded && - strcmp (file_extn->chosen_handler->handler_id_folded, - program_id_folded) != 0) - g_hash_table_insert (file_extn->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - } + schema_rec = g_object_new (G_TYPE_WIN32_APPINFO_URL_SCHEMA, NULL); + schema_rec->schema = g_wcsdup (schema, -1); + schema_rec->schema_u8 = g_strdup (schema_u8); + schema_rec->schema_u8_folded = g_strdup (schema_u8_folded); + g_hash_table_insert (urls, g_strdup (schema_rec->schema_u8_folded), schema_rec); - g_free (program_id_u8); - g_free (program_id_folded); - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); - } + return schema_rec; +} - g_win32_registry_value_iter_clear (&iter); - } +/* Looks up a handler object identified by + * @handler_id_u8_folded in the handlers hash table. + * If such object doesn't exist, + * creates it and puts it into the handlers hash table. + * Returns the object. + */ +static GWin32AppInfoHandler * +get_handler_object (const gchar *handler_id_u8_folded, + GWin32RegistryKey *handler_key, + const gunichar2 *handler_id, + const gunichar2 *uwp_aumid) +{ + GWin32AppInfoHandler *handler_rec; - g_object_unref (open_with_progids); - } + handler_rec = g_hash_table_lookup (handlers, handler_id_u8_folded); - if (!found_handler) - { - if (!file_ext_known) - g_object_unref (file_extn); - } - else if (!file_ext_known) + if (handler_rec != NULL) + return handler_rec; + + handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); + if (handler_key) + handler_rec->key = g_object_ref (handler_key); + handler_rec->handler_id = g_wcsdup (handler_id, -1); + handler_rec->handler_id_folded = g_strdup (handler_id_u8_folded); + if (uwp_aumid) + handler_rec->uwp_aumid = g_wcsdup (uwp_aumid, -1); + if (handler_key) + read_handler_icon (handler_key, &handler_rec->icon); + g_hash_table_insert (handlers, g_strdup (handler_id_u8_folded), handler_rec); + + return handler_rec; +} + +static void +handler_add_verb (gpointer handler_data1, + gpointer handler_data2, + const gunichar2 *verb, + const gunichar2 *command_line, + const gchar *command_line_utf8, + const gchar *verb_displayname, + gboolean verb_is_preferred, + gboolean invent_new_verb_name) +{ + GWin32AppInfoHandler *handler_rec = (GWin32AppInfoHandler *) handler_data1; + GWin32AppInfoApplication *app_rec = (GWin32AppInfoApplication *) handler_data2; + GWin32AppInfoShellVerb *shverb; + + _verb_lookup (handler_rec->verbs, verb, &shverb); + + if (shverb != NULL) + return; + + shverb = g_object_new (G_TYPE_WIN32_APPINFO_SHELL_VERB, NULL); + shverb->verb_name = g_wcsdup (verb, -1); + shverb->verb_displayname = g_strdup (verb_displayname); + shverb->command = g_wcsdup (command_line, -1); + shverb->command_utf8 = g_strdup (command_line_utf8); + shverb->is_uwp = FALSE; /* This function is for non-UWP verbs only */ + if (app_rec) + shverb->app = g_object_ref (app_rec); + + _g_win32_extract_executable (shverb->command, + &shverb->executable, + &shverb->executable_basename, + &shverb->executable_folded, + NULL, + &shverb->dll_function); + + if (shverb->dll_function != NULL) + _g_win32_fixup_broken_microsoft_rundll_commandline (shverb->command); + + if (!verb_is_preferred) + g_ptr_array_add (handler_rec->verbs, shverb); + else + g_ptr_array_insert (handler_rec->verbs, 0, shverb); +} + +/* Tries to generate a new name for a verb that looks + * like "verb (%x)", where %x is an integer in range of [0;255). + * On success puts new verb (and new verb displayname) into + * @new_verb and @new_displayname and return TRUE. + * On failure puts NULL into both and returns FALSE. + */ +static gboolean +generate_new_verb_name (GPtrArray *verbs, + const gunichar2 *verb, + const gchar *verb_displayname, + gunichar2 **new_verb, + gchar **new_displayname) +{ + gsize counter; + GWin32AppInfoShellVerb *shverb; + gsize orig_len = g_utf16_len (verb); + gsize new_verb_name_len = orig_len + strlen (" ()") + 2 + 1; + gunichar2 *new_verb_name = g_new (gunichar2, new_verb_name_len); + + *new_verb = NULL; + *new_displayname = NULL; + + memcpy (new_verb_name, verb, orig_len * sizeof (gunichar2)); + for (counter = 0; counter < 255; counter++) + { + _snwprintf (&new_verb_name[orig_len], new_verb_name_len, L" (%zx)", counter); + _verb_lookup (verbs, new_verb_name, &shverb); + + if (shverb == NULL) + { + *new_verb = new_verb_name; + if (verb_displayname != NULL) + *new_displayname = g_strdup_printf ("%s (%zx)", verb_displayname, counter); + + return TRUE; + } + } + + return FALSE; +} + +static void +app_add_verb (gpointer handler_data1, + gpointer handler_data2, + const gunichar2 *verb, + const gunichar2 *command_line, + const gchar *command_line_utf8, + const gchar *verb_displayname, + gboolean verb_is_preferred, + gboolean invent_new_verb_name) +{ + gunichar2 *new_verb = NULL; + gchar *new_displayname = NULL; + GWin32AppInfoApplication *app_rec = (GWin32AppInfoApplication *) handler_data2; + GWin32AppInfoShellVerb *shverb; + + _verb_lookup (app_rec->verbs, verb, &shverb); + + /* Special logic for fake apps - do our best to + * collate all possible verbs in the app, + * including the verbs that have the same name but + * different commandlines, in which case a new + * verb name has to be invented. + */ + if (shverb != NULL) { - file_extn->extension = g_wcsdup (ext, -1); - file_extn->extension_u8 = g_strdup (ext_u8); - g_hash_table_insert (extensions, g_strdup (ext_folded), file_extn); + gsize vi; + + if (!invent_new_verb_name) + return; + + for (vi = 0; vi < app_rec->verbs->len; vi++) + { + GWin32AppInfoShellVerb *app_verb; + + app_verb = _verb_idx (app_rec->verbs, vi); + + if (_wcsicmp (command_line, app_verb->command) == 0) + break; + } + + if (vi < app_rec->verbs->len || + !generate_new_verb_name (app_rec->verbs, + verb, + verb_displayname, + &new_verb, + &new_displayname)) + return; } - g_free (ext_u8); - g_free (ext_folded); + shverb = g_object_new (G_TYPE_WIN32_APPINFO_SHELL_VERB, NULL); + if (new_verb == NULL) + shverb->verb_name = g_wcsdup (verb, -1); + else + shverb->verb_name = g_steal_pointer (&new_verb); + if (new_displayname == NULL) + shverb->verb_displayname = g_strdup (verb_displayname); + else + shverb->verb_displayname = g_steal_pointer (&new_displayname); + + shverb->command = g_wcsdup (command_line, -1); + shverb->command_utf8 = g_strdup (command_line_utf8); + shverb->app = g_object_ref (app_rec); + + _g_win32_extract_executable (shverb->command, + &shverb->executable, + &shverb->executable_basename, + &shverb->executable_folded, + NULL, + &shverb->dll_function); + + if (shverb->dll_function != NULL) + _g_win32_fixup_broken_microsoft_rundll_commandline (shverb->command); + + if (!verb_is_preferred) + g_ptr_array_add (app_rec->verbs, shverb); + else + g_ptr_array_insert (app_rec->verbs, 0, shverb); +} + +static void +uwp_app_add_verb (GWin32AppInfoApplication *app_rec, + const gunichar2 *verb, + const gchar *verb_displayname) +{ + GWin32AppInfoShellVerb *shverb; + + _verb_lookup (app_rec->verbs, verb, &shverb); + + if (shverb != NULL) + return; + + shverb = g_object_new (G_TYPE_WIN32_APPINFO_SHELL_VERB, NULL); + shverb->verb_name = g_wcsdup (verb, -1); + shverb->app = g_object_ref (app_rec); + shverb->verb_displayname = g_strdup (verb_displayname); + + shverb->is_uwp = TRUE; + + /* Strictly speaking, this is unnecessary, but + * let's make it clear that UWP verbs have no + * commands and executables. + */ + shverb->command = NULL; + shverb->command_utf8 = NULL; + shverb->executable = NULL; + shverb->executable_basename = NULL; + shverb->executable_folded = NULL; + shverb->dll_function = NULL; + + g_ptr_array_add (app_rec->verbs, shverb); +} + +static void +uwp_handler_add_verb (GWin32AppInfoHandler *handler_rec, + GWin32AppInfoApplication *app, + const gunichar2 *verb, + const gchar *verb_displayname, + gboolean verb_is_preferred) +{ + GWin32AppInfoShellVerb *shverb; + + _verb_lookup (handler_rec->verbs, verb, &shverb); + + if (shverb != NULL) + return; + + shverb = g_object_new (G_TYPE_WIN32_APPINFO_SHELL_VERB, NULL); + shverb->verb_name = g_wcsdup (verb, -1); + shverb->verb_displayname = g_strdup (verb_displayname); + + shverb->is_uwp = TRUE; + + if (app) + shverb->app = g_object_ref (app); + + shverb->command = NULL; + shverb->command_utf8 = NULL; + shverb->executable = NULL; + shverb->executable_basename = NULL; + shverb->executable_folded = NULL; + shverb->dll_function = NULL; + + if (!verb_is_preferred) + g_ptr_array_add (handler_rec->verbs, shverb); + else + g_ptr_array_insert (handler_rec->verbs, 0, shverb); +} + +/* Looks up a file extension object identified by + * @ext_u8_folded in the extensions hash table. + * If such object doesn't exist, + * creates it and puts it into the extensions hash table. + * Returns the object. + */ +static GWin32AppInfoFileExtension * +get_ext_object (const gunichar2 *ext, + const gchar *ext_u8, + const gchar *ext_u8_folded) +{ + GWin32AppInfoFileExtension *file_extn; + + if (g_hash_table_lookup_extended (extensions, + ext_u8_folded, + NULL, + (void **) &file_extn)) + return file_extn; + + file_extn = g_object_new (G_TYPE_WIN32_APPINFO_FILE_EXTENSION, NULL); + file_extn->extension = g_wcsdup (ext, -1); + file_extn->extension_u8 = g_strdup (ext_u8); + g_hash_table_insert (extensions, g_strdup (ext_u8_folded), file_extn); + + return file_extn; } +/* Iterates over HKCU\\Software\\Clients or HKLM\\Software\\Clients, + * (depending on @user_registry being TRUE or FALSE), + * collecting applications listed there. + * Puts the path to the client key for each client into @priority_capable_apps + * (only for clients with file or URL associations). + */ static void collect_capable_apps_from_clients (GPtrArray *capable_apps, GPtrArray *priority_capable_apps, @@ -1399,7 +2000,7 @@ collect_capable_apps_from_clients (GPtrArray *capable_apps, GWin32RegistryKey *clients; GWin32RegistrySubkeyIter clients_iter; - gunichar2 *client_type_name; + const gunichar2 *client_type_name; gsize client_type_name_len; @@ -1427,7 +2028,7 @@ collect_capable_apps_from_clients (GPtrArray *capable_apps, GWin32RegistryKey *system_client_type; GWin32RegistryValueType default_type; gunichar2 *default_value = NULL; - gunichar2 *client_name; + const gunichar2 *client_name; gsize client_name_len; if (!g_win32_registry_subkey_iter_get_name_w (&clients_iter, @@ -1444,6 +2045,7 @@ collect_capable_apps_from_clients (GPtrArray *capable_apps, continue; if (g_win32_registry_key_get_value_w (system_client_type, + NULL, TRUE, L"", &default_type, @@ -1531,11 +2133,17 @@ collect_capable_apps_from_clients (GPtrArray *capable_apps, g_object_unref (clients); } +/* Iterates over HKCU\\Software\\RegisteredApplications or HKLM\\Software\\RegisteredApplications, + * (depending on @user_registry being TRUE or FALSE), + * collecting applications listed there. + * Puts the path to the app key for each app into @capable_apps. + */ static void collect_capable_apps_from_registered_apps (GPtrArray *capable_apps, gboolean user_registry) { GWin32RegistryValueIter iter; + const gunichar2 *reg_path; gunichar2 *value_data; gsize value_data_size; @@ -1543,13 +2151,12 @@ collect_capable_apps_from_registered_apps (GPtrArray *capable_apps, GWin32RegistryKey *registered_apps; if (user_registry) - registered_apps = - g_win32_registry_key_new_w (L"HKEY_CURRENT_USER\\Software\\RegisteredApplications", - NULL); + reg_path = L"HKEY_CURRENT_USER\\Software\\RegisteredApplications"; else - registered_apps = - g_win32_registry_key_new_w (L"HKEY_LOCAL_MACHINE\\Software\\RegisteredApplications", - NULL); + reg_path = L"HKEY_LOCAL_MACHINE\\Software\\RegisteredApplications"; + + registered_apps = + g_win32_registry_key_new_w (reg_path, NULL); if (!registered_apps) return; @@ -1557,13 +2164,15 @@ collect_capable_apps_from_registered_apps (GPtrArray *capable_apps, if (!g_win32_registry_value_iter_init (&iter, registered_apps, NULL)) { g_object_unref (registered_apps); + return; } while (g_win32_registry_value_iter_next (&iter, TRUE, NULL)) { gunichar2 possible_location[REG_PATH_MAX_SIZE + 1]; - GWin32RegistryKey *location = NULL; + GWin32RegistryKey *location; + gunichar2 *p; if ((!g_win32_registry_value_iter_get_value_type (&iter, &value_type, @@ -1577,51 +2186,83 @@ collect_capable_apps_from_registered_apps (GPtrArray *capable_apps, (value_data[0] == L'\0')) continue; - if (build_registry_path (possible_location, sizeof (possible_location), - HKCU, value_data, NULL)) - location = g_win32_registry_key_new_w (possible_location, NULL); - - if (location) - { - gunichar2 *p = wcsrchr (possible_location, L'\\'); - - if (p) - *p = L'\0'; - - g_ptr_array_add (capable_apps, g_wcsdup (possible_location, -1)); - g_object_unref (location); - continue; - } - if (!build_registry_path (possible_location, sizeof (possible_location), user_registry ? HKCU : HKLM, value_data, NULL)) continue; location = g_win32_registry_key_new_w (possible_location, NULL); - if (location) + if (location == NULL) + continue; + + p = wcsrchr (possible_location, L'\\'); + + if (p) { - gunichar2 *p = wcsrchr (possible_location, L'\\'); - if (p) - *p = L'\0'; + *p = L'\0'; g_ptr_array_add (capable_apps, g_wcsdup (possible_location, -1)); - g_object_unref (location); } + + g_object_unref (location); } g_win32_registry_value_iter_clear (&iter); g_object_unref (registered_apps); } +/* Looks up an app object identified by + * @canonical_name_folded in the @app_hashmap. + * If such object doesn't exist, + * creates it and puts it into the @app_hashmap. + * Returns the object. + */ +static GWin32AppInfoApplication * +get_app_object (GHashTable *app_hashmap, + const gunichar2 *canonical_name, + const gchar *canonical_name_u8, + const gchar *canonical_name_folded, + gboolean user_specific, + gboolean default_app, + gboolean is_uwp) +{ + GWin32AppInfoApplication *app; + + app = g_hash_table_lookup (app_hashmap, canonical_name_folded); + + if (app != NULL) + return app; + + app = g_object_new (G_TYPE_WIN32_APPINFO_APPLICATION, NULL); + app->canonical_name = g_wcsdup (canonical_name, -1); + app->canonical_name_u8 = g_strdup (canonical_name_u8); + app->canonical_name_folded = g_strdup (canonical_name_folded); + app->no_open_with = FALSE; + app->user_specific = user_specific; + app->default_app = default_app; + app->is_uwp = is_uwp; + g_hash_table_insert (app_hashmap, + g_strdup (canonical_name_folded), + app); + + return app; +} + +/* Grabs an application that has Capabilities. + * @app_key_path is the path to the application key + * (which must have a "Capabilities" subkey). + * @default_app is TRUE if the app has priority + */ static void -read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolean default_app) +read_capable_app (const gunichar2 *app_key_path, + gboolean user_specific, + gboolean default_app) { GWin32AppInfoApplication *app; - gunichar2 *app_key_path; - gunichar2 *canonical_name; - gchar *canonical_name_u8; - gchar *canonical_name_folded; - GWin32RegistryKey *appkey; + gchar *canonical_name_u8 = NULL; + gchar *canonical_name_folded = NULL; + gchar *app_key_path_u8 = NULL; + gchar *app_key_path_u8_folded = NULL; + GWin32RegistryKey *appkey = NULL; gunichar2 *fallback_friendly_name; GWin32RegistryValueType vtype; gboolean success; @@ -1631,130 +2272,58 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea gunichar2 *icon_source; GWin32RegistryKey *capabilities; GWin32RegistryKey *default_icon_key; - GWin32RegistryKey *shell_open_command_key; - gunichar2 *shell_open_command; - gchar *app_executable; - gchar *app_executable_basename; - gchar *app_executable_folded; - gchar *app_executable_folded_basename; GWin32RegistryKey *associations; - - app_key_path = g_wcsdup (input_app_key_path, -1); - - canonical_name = wcsrchr (app_key_path, L'\\'); - - if (canonical_name == NULL) - { - /* The key must have at least one '\\' */ - g_free (app_key_path); - return; - } - - canonical_name += 1; - - if (!utf8_and_fold (canonical_name, &canonical_name_u8, &canonical_name_folded)) - { - g_free (app_key_path); - return; - } - - appkey = g_win32_registry_key_new_w (app_key_path, NULL); - - if (appkey == NULL) - { - g_free (canonical_name_u8); - g_free (canonical_name_folded); - g_free (app_key_path); - return; - } - - capabilities = - g_win32_registry_key_get_child_w (appkey, L"Capabilities", NULL); - - if (capabilities == NULL) + const reg_verb *preferred_verb; + GList *verbs = NULL; + gboolean verbs_in_root_key = TRUE; + + appkey = NULL; + capabilities = NULL; + + if (!g_utf16_to_utf8_and_fold (app_key_path, + -1, + &canonical_name_u8, + &canonical_name_folded) || + !g_utf16_to_utf8_and_fold (app_key_path, + -1, + &app_key_path_u8, + &app_key_path_u8_folded) || + (appkey = g_win32_registry_key_new_w (app_key_path, NULL)) == NULL || + (capabilities = g_win32_registry_key_get_child_w (appkey, L"Capabilities", NULL)) == NULL || + !(get_verbs (appkey, &preferred_verb, &verbs, L"", L"Shell", NULL) || + (verbs_in_root_key = FALSE) || + get_verbs (capabilities, &preferred_verb, &verbs, L"", L"Shell", NULL))) { - /* Must have capabilities */ - g_free (canonical_name_u8); - g_free (canonical_name_folded); - g_free (app_key_path); - return; - } - - shell_open_command_key = - g_win32_registry_key_get_child_w (appkey, - L"shell\\open\\command", - NULL); - - if (shell_open_command_key == NULL) - { - g_object_unref (capabilities); - g_free (canonical_name_u8); - g_free (canonical_name_folded); - g_free (app_key_path); - g_object_unref (appkey); - return ; - } - - shell_open_command = NULL; + g_clear_pointer (&canonical_name_u8, g_free); + g_clear_pointer (&canonical_name_folded, g_free); + g_clear_object (&appkey); + g_clear_object (&capabilities); + g_clear_pointer (&app_key_path_u8, g_free); + g_clear_pointer (&app_key_path_u8_folded, g_free); - success = g_win32_registry_key_get_value_w (shell_open_command_key, - TRUE, - L"", - &vtype, - (gpointer *) &shell_open_command, - NULL, - NULL); - - if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) - { - /* Must have a command */ - g_clear_pointer (&shell_open_command, g_free); - g_object_unref (capabilities); - g_free (canonical_name_u8); - g_free (canonical_name_folded); - g_free (app_key_path); - g_object_unref (appkey); return; } - extract_executable (shell_open_command, - &app_executable, - &app_executable_basename, - &app_executable_folded, - &app_executable_folded_basename); - - app = g_hash_table_lookup (apps_by_id, canonical_name_folded); - - if (app == NULL) - { - app = g_object_new (G_TYPE_WIN32_APPINFO_APPLICATION, NULL); - - app->canonical_name = g_wcsdup (canonical_name, -1); - app->canonical_name_u8 = g_strdup (canonical_name_u8); - app->canonical_name_folded = - g_strdup (canonical_name_folded); - - app->command = g_wcsdup (shell_open_command, -1); - app->command_u8 = - g_utf16_to_utf8 (shell_open_command, -1, NULL, NULL, NULL); - app->executable = g_strdup (app_executable); - app->executable_basename = - &app->executable[app_executable_basename - app_executable]; - app->executable_folded = - g_strdup (app_executable_folded); - - app->no_open_with = FALSE; - - app->user_specific = user_specific; - app->default_app = default_app; - - g_hash_table_insert (apps_by_id, - g_strdup (canonical_name_folded), - app); - } + app = get_app_object (apps_by_id, + app_key_path, + canonical_name_u8, + canonical_name_folded, + user_specific, + default_app, + FALSE); + + process_verbs_commands (g_steal_pointer (&verbs), + preferred_verb, + L"", /* [ab]use the fact that two strings are simply concatenated */ + verbs_in_root_key ? app_key_path : g_win32_registry_key_get_path_w (capabilities), + FALSE, + app_add_verb, + app, + app); fallback_friendly_name = NULL; success = g_win32_registry_key_get_value_w (appkey, + NULL, TRUE, L"", &vtype, @@ -1765,7 +2334,8 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) g_clear_pointer (&fallback_friendly_name, g_free); - if (fallback_friendly_name && app->pretty_name == NULL) + if (fallback_friendly_name && + app->pretty_name == NULL) { app->pretty_name = g_wcsdup (fallback_friendly_name, -1); g_clear_pointer (&app->pretty_name_u8, g_free); @@ -1778,6 +2348,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea friendly_name = NULL; success = g_win32_registry_key_get_value_w (capabilities, + g_win32_registry_get_os_dirs_w (), TRUE, L"LocalizedString", &vtype, @@ -1785,12 +2356,12 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea NULL, NULL); - if (success && (vtype != G_WIN32_REGISTRY_VALUE_STR || friendly_name[0] != L'@')) + if (success && + vtype != G_WIN32_REGISTRY_VALUE_STR) g_clear_pointer (&friendly_name, g_free); - friendly_name = read_resource_string (friendly_name); - - if (friendly_name && app->localized_pretty_name == NULL) + if (friendly_name && + app->localized_pretty_name == NULL) { app->localized_pretty_name = g_wcsdup (friendly_name, -1); g_clear_pointer (&app->localized_pretty_name_u8, g_free); @@ -1803,6 +2374,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea description = NULL; success = g_win32_registry_key_get_value_w (capabilities, + g_win32_registry_get_os_dirs_w (), TRUE, L"ApplicationDescription", &vtype, @@ -1813,8 +2385,6 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) g_clear_pointer (&description, g_free); - description = read_resource_string (description); - if (description && app->description == NULL) { app->description = g_wcsdup (description, -1); @@ -1831,6 +2401,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea if (default_icon_key != NULL) { success = g_win32_registry_key_get_value_w (default_icon_key, + NULL, TRUE, L"", &vtype, @@ -1838,7 +2409,8 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea NULL, NULL); - if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) + if (success && + vtype != G_WIN32_REGISTRY_VALUE_STR) g_clear_pointer (&icon_source, g_free); g_object_unref (default_icon_key); @@ -1847,6 +2419,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea if (icon_source == NULL) { success = g_win32_registry_key_get_value_w (capabilities, + NULL, TRUE, L"ApplicationIcon", &vtype, @@ -1854,11 +2427,13 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea NULL, NULL); - if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) + if (success && + vtype != G_WIN32_REGISTRY_VALUE_STR) g_clear_pointer (&icon_source, g_free); } - if (icon_source && app->icon == NULL) + if (icon_source && + app->icon == NULL) { gchar *name = g_utf16_to_utf8 (icon_source, -1, NULL, NULL, NULL); app->icon = g_themed_icon_new (name); @@ -1867,6 +2442,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea narrow_application_name = NULL; success = g_win32_registry_key_get_value_w (capabilities, + g_win32_registry_get_os_dirs_w (), TRUE, L"ApplicationName", &vtype, @@ -1877,15 +2453,17 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) g_clear_pointer (&narrow_application_name, g_free); - narrow_application_name = read_resource_string (narrow_application_name); - - /* TODO: do something with the narrow name. Maybe make a kind of sub-app? - * Narrow name is a more precise name of the application in given context. - * I.e. Thunderbird's name is "Thunderbird", whereas its narrow name is - * "Thunderbird (news)" when registering it as a news client. - * Maybe we should consider applications with different narrow names as - * different applications altogether? - */ + if (narrow_application_name && + app->localized_pretty_name == NULL) + { + app->localized_pretty_name = g_wcsdup (narrow_application_name, -1); + g_clear_pointer (&app->localized_pretty_name_u8, g_free); + app->localized_pretty_name_u8 = g_utf16_to_utf8 (narrow_application_name, + -1, + NULL, + NULL, + NULL); + } associations = g_win32_registry_key_get_child_w (capabilities, L"FileAssociations", @@ -1905,19 +2483,6 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea while (g_win32_registry_value_iter_next (&iter, TRUE, NULL)) { - GWin32AppInfoHandler *handler_rec; - GWin32AppInfoHandler *handler_rec_in_ext; - GWin32AppInfoFileExtension *ext; - gunichar2 *program_command; - gunichar2 *proxy_id; - gunichar2 *proxy_command; - GWin32RegistryKey *program_key; - GWin32RegistryKey *proxy_key; - gchar *program_id_u8; - gchar *program_id_folded; - gchar *file_extension_u8; - gchar *file_extension_folded; - if ((!g_win32_registry_value_iter_get_value_type (&iter, &value_type, NULL)) || @@ -1936,106 +2501,7 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea (extension_handler[0] == L'\0')) continue; - if (!follow_class_chain_to_handler (extension_handler, - extension_handler_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &program_id_u8, - &program_id_folded)) - continue; - - handler_rec = g_hash_table_lookup (handlers, - program_id_folded); - - if (handler_rec == NULL) - { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); - - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = - g_wcsdup (extension_handler,extension_handler_size); - handler_rec->handler_id_folded = - g_strdup (program_id_folded); - handler_rec->handler_command = - program_command ? g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = - proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, - program_key, - &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (program_id_folded), - handler_rec); - } - else - { - g_clear_object (&program_key); - g_clear_object (&proxy_key); - } - - if (utf8_and_fold (file_extension, - &file_extension_u8, - &file_extension_folded)) - { - ext = g_hash_table_lookup (extensions, - file_extension_folded); - - if (ext == NULL) - { - ext = g_object_new (G_TYPE_WIN32_APPINFO_FILE_EXTENSION, NULL); - - ext->extension = g_wcsdup (file_extension, -1); - ext->extension_u8 = g_strdup (file_extension_u8); - g_hash_table_insert (extensions, g_strdup (file_extension_folded), ext); - } - - handler_rec_in_ext = - g_hash_table_lookup (ext->handlers, - program_id_folded); - - if (handler_rec_in_ext == NULL) - { - if (ext->chosen_handler == NULL) - g_hash_table_insert (ext->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - else if (ext->chosen_handler->handler_id_folded && - strcmp (ext->chosen_handler->handler_id_folded, - program_id_folded) != 0) - g_hash_table_insert (ext->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - } - - handler_rec_in_ext = - g_hash_table_lookup (app->supported_exts, - file_extension_folded); - - if (handler_rec_in_ext == NULL) - g_hash_table_insert (app->supported_exts, - g_strdup (file_extension_folded), - g_object_ref (handler_rec)); - - g_free (file_extension_u8); - g_free (file_extension_folded); - } - - g_free (program_id_u8); - g_free (program_id_folded); - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); + get_file_ext (extension_handler, file_extension, app, FALSE); } g_win32_registry_value_iter_clear (&iter); @@ -2060,18 +2526,8 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea while (g_win32_registry_value_iter_next (&iter, TRUE, NULL)) { - GWin32AppInfoHandler *handler_rec; - GWin32AppInfoHandler *handler_rec_in_url; - GWin32AppInfoURLSchema *schema; - gunichar2 *program_command; - gunichar2 *proxy_id; - gunichar2 *proxy_command; - GWin32RegistryKey *program_key; - GWin32RegistryKey *proxy_key; - gchar *program_id_u8; - gchar *program_id_folded; gchar *schema_u8; - gchar *schema_folded; + gchar *schema_u8_folded; if ((!g_win32_registry_value_iter_get_value_type (&iter, &value_type, @@ -2092,101 +2548,16 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea (schema_handler[0] == L'\0')) continue; - if (!follow_class_chain_to_handler (schema_handler, - schema_handler_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &program_id_u8, - &program_id_folded)) - continue; - - handler_rec = g_hash_table_lookup (handlers, program_id_folded); - if (handler_rec == NULL) - { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); - - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = - g_wcsdup (schema_handler, schema_handler_size); - handler_rec->handler_id_folded = - g_strdup (program_id_folded); - handler_rec->handler_command = program_command ? - g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = - proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, - program_key, - &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (program_id_folded), - handler_rec); - } - else - { - g_clear_object (&program_key); - g_clear_object (&proxy_key); - } + if (g_utf16_to_utf8_and_fold (url_schema, + url_schema_len, + &schema_u8, + &schema_u8_folded)) + get_url_association (schema_handler, url_schema, schema_u8, schema_u8_folded, app, FALSE); - if (utf8_and_fold (url_schema, - &schema_u8, - &schema_folded)) - { - schema = g_hash_table_lookup (urls, - schema_folded); - - if (schema == NULL) - { - schema = g_object_new (G_TYPE_WIN32_APPINFO_URL_SCHEMA, NULL); - - schema->schema = g_wcsdup (url_schema, -1); - schema->schema_u8 = g_strdup (schema_u8); - schema->schema_folded = - g_strdup (schema_folded); - g_hash_table_insert (urls, - g_strdup (schema_folded), - schema); - } - - handler_rec_in_url = - g_hash_table_lookup (schema->handlers, - program_id_folded); - - if (handler_rec_in_url == NULL) - g_hash_table_insert (schema->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - - handler_rec_in_url = - g_hash_table_lookup (app->supported_urls, - schema_folded); - - if (handler_rec_in_url == NULL) - g_hash_table_insert (app->supported_urls, - g_strdup (schema_folded), - g_object_ref (handler_rec)); - - g_free (schema_u8); - g_free (schema_folded); - } - - g_free (program_id_u8); - g_free (program_id_folded); - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); + g_clear_pointer (&schema_u8, g_free); + g_clear_pointer (&schema_u8_folded, g_free); } g_win32_registry_value_iter_clear (&iter); @@ -2195,28 +2566,26 @@ read_capable_app (gunichar2 *input_app_key_path, gboolean user_specific, gboolea g_object_unref (associations); } - g_clear_pointer (&app_executable, g_free); - g_clear_pointer (&app_executable_folded, g_free); g_clear_pointer (&fallback_friendly_name, g_free); g_clear_pointer (&description, g_free); g_clear_pointer (&icon_source, g_free); g_clear_pointer (&narrow_application_name, g_free); - g_clear_pointer (&shell_open_command, g_free); g_object_unref (appkey); - g_object_unref (shell_open_command_key); g_object_unref (capabilities); - g_free (canonical_name_u8); - g_free (canonical_name_folded); - g_free (app_key_path); + g_clear_pointer (&app_key_path_u8, g_free); + g_clear_pointer (&app_key_path_u8_folded, g_free); + g_clear_pointer (&canonical_name_u8, g_free); + g_clear_pointer (&canonical_name_folded, g_free); } +/* Iterates over subkeys in HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\ + * and calls get_url_association() for each one that has a user-chosen handler. + */ static void read_urls (GWin32RegistryKey *url_associations) { GWin32RegistrySubkeyIter url_iter; - gunichar2 *url_schema; - gsize url_schema_len; if (url_associations == NULL) return; @@ -2226,280 +2595,260 @@ read_urls (GWin32RegistryKey *url_associations) while (g_win32_registry_subkey_iter_next (&url_iter, TRUE, NULL)) { - if (!g_win32_registry_subkey_iter_get_name_w (&url_iter, - &url_schema, - &url_schema_len, - NULL)) - continue; - - get_url_association (url_schema); + gchar *schema_u8 = NULL; + gchar *schema_u8_folded = NULL; + const gunichar2 *url_schema = NULL; + gunichar2 *program_id = NULL; + GWin32RegistryKey *user_choice = NULL; + gsize url_schema_len; + GWin32RegistryValueType val_type; + + if (g_win32_registry_subkey_iter_get_name_w (&url_iter, + &url_schema, + &url_schema_len, + NULL) && + g_utf16_to_utf8_and_fold (url_schema, + url_schema_len, + &schema_u8, + &schema_u8_folded) && + (user_choice = _g_win32_registry_key_build_and_new_w (NULL, URL_ASSOCIATIONS, + url_schema, USER_CHOICE, + NULL)) != NULL && + g_win32_registry_key_get_value_w (user_choice, + NULL, + TRUE, + L"Progid", + &val_type, + (void **) &program_id, + NULL, + NULL) && + val_type == G_WIN32_REGISTRY_VALUE_STR) + get_url_association (program_id, url_schema, schema_u8, schema_u8_folded, NULL, TRUE); + + g_clear_pointer (&program_id, g_free); + g_clear_pointer (&user_choice, g_object_unref); + g_clear_pointer (&schema_u8, g_free); + g_clear_pointer (&schema_u8_folded, g_free); } g_win32_registry_subkey_iter_clear (&url_iter); } +/* Reads an application that is only registered by the basename of its + * executable (and doesn't have Capabilities subkey). + * @incapable_app is the registry key for the app. + * @app_exe_basename is the basename of its executable. + */ static void -read_exeapps (void) +read_incapable_app (GWin32RegistryKey *incapable_app, + const gunichar2 *app_exe_basename, + const gchar *app_exe_basename_u8, + const gchar *app_exe_basename_u8_folded) { - GWin32RegistryKey *applications_key; - GWin32RegistrySubkeyIter app_iter; - gunichar2 *app_exe_basename; - gsize app_exe_basename_len; - - applications_key = - g_win32_registry_key_new_w (L"HKEY_CLASSES_ROOT\\Applications", NULL); + GWin32RegistryValueIter sup_iter; + GWin32AppInfoApplication *app; + GList *verbs; + const reg_verb *preferred_verb; + gunichar2 *friendly_app_name; + gboolean success; + GWin32RegistryValueType vtype; + gboolean no_open_with; + GWin32RegistryKey *default_icon_key; + gunichar2 *icon_source; + GIcon *icon = NULL; + GWin32RegistryKey *supported_key; - if (applications_key == NULL) + if (!get_verbs (incapable_app, &preferred_verb, &verbs, L"", L"Shell", NULL)) return; - if (!g_win32_registry_subkey_iter_init (&app_iter, applications_key, NULL)) - { - g_object_unref (applications_key); - return; - } - - while (g_win32_registry_subkey_iter_next (&app_iter, TRUE, NULL)) - { - GWin32RegistryKey *incapable_app; - gunichar2 *friendly_app_name; - gboolean success; - gboolean no_open_with; - GWin32RegistryValueType vtype; - GWin32RegistryKey *default_icon_key; - gunichar2 *icon_source; - GIcon *icon = NULL; - gchar *appexe; - gchar *appexe_basename; - gchar *appexe_folded; - gchar *appexe_folded_basename; - GWin32AppInfoApplication *app; - GWin32RegistryKey *shell_open_command_key; - gunichar2 *shell_open_command; - GWin32RegistryKey *supported_key; - - if (!g_win32_registry_subkey_iter_get_name_w (&app_iter, - &app_exe_basename, - &app_exe_basename_len, - NULL)) - continue; + app = get_app_object (apps_by_exe, + app_exe_basename, + app_exe_basename_u8, + app_exe_basename_u8_folded, + FALSE, + FALSE, + FALSE); + + process_verbs_commands (g_steal_pointer (&verbs), + preferred_verb, + L"HKEY_CLASSES_ROOT\\Applications\\", + app_exe_basename, + TRUE, + app_add_verb, + app, + app); + + friendly_app_name = NULL; + success = g_win32_registry_key_get_value_w (incapable_app, + g_win32_registry_get_os_dirs_w (), + TRUE, + L"FriendlyAppName", + &vtype, + (void **) &friendly_app_name, + NULL, + NULL); - incapable_app = - g_win32_registry_key_get_child_w (applications_key, - app_exe_basename, - NULL); + if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) + g_clear_pointer (&friendly_app_name, g_free); + + no_open_with = g_win32_registry_key_get_value_w (incapable_app, + NULL, + TRUE, + L"NoOpenWith", + &vtype, + NULL, + NULL, + NULL); - if (incapable_app == NULL) - continue; + default_icon_key = + g_win32_registry_key_get_child_w (incapable_app, + L"DefaultIcon", + NULL); - extract_executable (app_exe_basename, - &appexe, - &appexe_basename, - &appexe_folded, - &appexe_folded_basename); + icon_source = NULL; - shell_open_command_key = - g_win32_registry_key_get_child_w (incapable_app, - L"shell\\open\\command", + if (default_icon_key != NULL) + { + success = + g_win32_registry_key_get_value_w (default_icon_key, + NULL, + TRUE, + L"", + &vtype, + (void **) &icon_source, + NULL, NULL); - shell_open_command = NULL; - - if (shell_open_command_key != NULL) - { - success = g_win32_registry_key_get_value_w (shell_open_command_key, - TRUE, - L"", - &vtype, - (gpointer *) &shell_open_command, - NULL, - NULL); - - if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) - { - g_clear_pointer (&shell_open_command, g_free); - } - - g_object_unref (shell_open_command_key); - } - - friendly_app_name = NULL; - success = g_win32_registry_key_get_value_w (incapable_app, - TRUE, - L"FriendlyAppName", - &vtype, - (void **) &friendly_app_name, - NULL, - NULL); - if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) - g_clear_pointer (&friendly_app_name, g_free); - - friendly_app_name = read_resource_string (friendly_app_name); + g_clear_pointer (&icon_source, g_free); - no_open_with = FALSE; - success = g_win32_registry_key_get_value_w (incapable_app, - TRUE, - L"NoOpenWith", - &vtype, - NULL, - NULL, - NULL); + g_object_unref (default_icon_key); + } - if (success) - no_open_with = TRUE; + if (icon_source) + { + gchar *name = g_utf16_to_utf8 (icon_source, -1, NULL, NULL, NULL); + if (name != NULL) + icon = g_themed_icon_new (name); + g_free (name); + } - default_icon_key = - g_win32_registry_key_get_child_w (incapable_app, - L"DefaultIcon", - NULL); + app->no_open_with = no_open_with; - icon_source = NULL; + if (friendly_app_name && + app->localized_pretty_name == NULL) + { + app->localized_pretty_name = g_wcsdup (friendly_app_name, -1); + g_clear_pointer (&app->localized_pretty_name_u8, g_free); + app->localized_pretty_name_u8 = + g_utf16_to_utf8 (friendly_app_name, -1, NULL, NULL, NULL); + } - if (default_icon_key != NULL) - { - success = - g_win32_registry_key_get_value_w (default_icon_key, - TRUE, - L"", - &vtype, - (void **) &icon_source, - NULL, - NULL); + if (icon && app->icon == NULL) + app->icon = g_object_ref (icon); - if (success && vtype != G_WIN32_REGISTRY_VALUE_STR) - g_clear_pointer (&icon_source, g_free); + supported_key = + g_win32_registry_key_get_child_w (incapable_app, + L"SupportedTypes", + NULL); - g_object_unref (default_icon_key); - } + if (supported_key && + g_win32_registry_value_iter_init (&sup_iter, supported_key, NULL)) + { + gunichar2 *ext_name; + gsize ext_name_len; - if (icon_source) + while (g_win32_registry_value_iter_next (&sup_iter, TRUE, NULL)) { - gchar *name = g_utf16_to_utf8 (icon_source, -1, NULL, NULL, NULL); - icon = g_themed_icon_new (name); - g_free (name); - } + if ((!g_win32_registry_value_iter_get_name_w (&sup_iter, + &ext_name, + &ext_name_len, + NULL)) || + (ext_name_len <= 0) || + (ext_name[0] != L'.')) + continue; - app = g_hash_table_lookup (apps_by_exe, appexe_folded_basename); + get_file_ext (ext_name, ext_name, app, FALSE); + } - if (app == NULL) - { - app = g_object_new (G_TYPE_WIN32_APPINFO_APPLICATION, NULL); + g_win32_registry_value_iter_clear (&sup_iter); + } - app->command = - shell_open_command ? g_wcsdup (shell_open_command, -1) : NULL; + g_clear_object (&supported_key); + g_free (friendly_app_name); + g_free (icon_source); - if (shell_open_command) - app->command_u8 = g_utf16_to_utf8 (shell_open_command, -1, NULL, NULL, NULL); + g_clear_object (&icon); +} - app->executable = g_strdup (appexe); - app->executable_basename = &app->executable[appexe_basename - appexe]; - app->executable_folded = g_strdup (appexe_folded); +/* Iterates over subkeys of HKEY_CLASSES_ROOT\\Applications + * and calls read_incapable_app() for each one. + */ +static void +read_exeapps (void) +{ + GWin32RegistryKey *applications_key; + GWin32RegistrySubkeyIter app_iter; - app->no_open_with = no_open_with; + applications_key = + g_win32_registry_key_new_w (L"HKEY_CLASSES_ROOT\\Applications", NULL); - if (friendly_app_name) - { - app->localized_pretty_name = g_wcsdup (friendly_app_name, -1); - g_clear_pointer (&app->localized_pretty_name_u8, g_free); - app->localized_pretty_name_u8 = - g_utf16_to_utf8 (friendly_app_name, -1, NULL, NULL, NULL); - } + if (applications_key == NULL) + return; - if (icon) - app->icon = g_object_ref (icon); + if (!g_win32_registry_subkey_iter_init (&app_iter, applications_key, NULL)) + { + g_object_unref (applications_key); + return; + } - app->user_specific = FALSE; - app->default_app = FALSE; + while (g_win32_registry_subkey_iter_next (&app_iter, TRUE, NULL)) + { + const gunichar2 *app_exe_basename; + gsize app_exe_basename_len; + GWin32RegistryKey *incapable_app; + gchar *app_exe_basename_u8; + gchar *app_exe_basename_u8_folded; - g_hash_table_insert (apps_by_exe, - g_strdup (appexe_folded_basename), - app); - } + if (!g_win32_registry_subkey_iter_get_name_w (&app_iter, + &app_exe_basename, + &app_exe_basename_len, + NULL) || + !g_utf16_to_utf8_and_fold (app_exe_basename, + app_exe_basename_len, + &app_exe_basename_u8, + &app_exe_basename_u8_folded)) + continue; - supported_key = - g_win32_registry_key_get_child_w (incapable_app, - L"SupportedTypes", + incapable_app = + g_win32_registry_key_get_child_w (applications_key, + app_exe_basename, NULL); - if (supported_key) - { - GWin32RegistryValueIter sup_iter; - if (g_win32_registry_value_iter_init (&sup_iter, supported_key, NULL)) - { - gunichar2 *ext_name; - gsize ext_name_len; - - while (g_win32_registry_value_iter_next (&sup_iter, TRUE, NULL)) - { - gchar *ext_u8; - gchar *ext_folded; - GWin32AppInfoFileExtension *file_extn; - gboolean file_ext_known; - - if ((!g_win32_registry_value_iter_get_name_w (&sup_iter, - &ext_name, - &ext_name_len, - NULL)) || - (ext_name_len <= 0) || - (ext_name[0] != L'.') || - (!utf8_and_fold (ext_name, - &ext_u8, - &ext_folded))) - continue; - - file_extn = NULL; - file_ext_known = - g_hash_table_lookup_extended (extensions, - ext_folded, - NULL, - (void **) &file_extn); - - if (!file_ext_known) - { - file_extn = - g_object_new (G_TYPE_WIN32_APPINFO_FILE_EXTENSION, NULL); - file_extn->extension = g_wcsdup (ext_name, -1); - file_extn->extension_u8 = g_strdup (ext_u8); - g_hash_table_insert (extensions, - g_strdup (ext_folded), - file_extn); - } - - g_hash_table_insert (file_extn->other_apps, - g_strdup (appexe_folded), - g_object_ref (app)); - - g_free (ext_u8); - g_free (ext_folded); - } - - g_win32_registry_value_iter_clear (&sup_iter); - } - - g_object_unref (supported_key); - } + if (incapable_app != NULL) + read_incapable_app (incapable_app, + app_exe_basename, + app_exe_basename_u8, + app_exe_basename_u8_folded); - - g_free (appexe); - g_free (appexe_folded); - g_free (shell_open_command); - g_free (friendly_app_name); - g_free (icon_source); - - g_clear_object (&icon); g_clear_object (&incapable_app); + g_clear_pointer (&app_exe_basename_u8, g_free); + g_clear_pointer (&app_exe_basename_u8_folded, g_free); } g_win32_registry_subkey_iter_clear (&app_iter); g_object_unref (applications_key); } - +/* Iterates over subkeys of HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\ + * and calls get_file_ext() for each associated handler + * (starting with user-chosen handler, if any) + */ static void read_exts (GWin32RegistryKey *file_exts) { GWin32RegistrySubkeyIter ext_iter; - gunichar2 *file_extension; + const gunichar2 *file_extension; gsize file_extension_len; if (file_exts == NULL) @@ -2510,256 +2859,89 @@ read_exts (GWin32RegistryKey *file_exts) while (g_win32_registry_subkey_iter_next (&ext_iter, TRUE, NULL)) { + GWin32RegistryKey *open_with_progids; + gunichar2 *program_id; + GWin32RegistryValueIter iter; + gunichar2 *value_name; + gsize value_name_len; + GWin32RegistryValueType value_type; + GWin32RegistryKey *user_choice; + if (!g_win32_registry_subkey_iter_get_name_w (&ext_iter, &file_extension, &file_extension_len, NULL)) continue; - get_file_ext (file_extension); - } + program_id = NULL; + user_choice = _g_win32_registry_key_build_and_new_w (NULL, FILE_EXTS, file_extension, + USER_CHOICE, NULL); + if (user_choice && + g_win32_registry_key_get_value_w (user_choice, + NULL, + TRUE, + L"Progid", + &value_type, + (void **) &program_id, + NULL, + NULL) && + value_type == G_WIN32_REGISTRY_VALUE_STR) + { + /* Note: program_id could be "ProgramID" or "Applications\\program.exe". + * The code still works, but handler_id might have a backslash + * in it - that might trip us up later on. + * Even though in that case this is logically an "application" + * registry entry, we don't treat it in any special way. + * We do scan that registry branch anyway, just not here. + */ + get_file_ext (program_id, file_extension, NULL, TRUE); + } - g_win32_registry_subkey_iter_clear (&ext_iter); -} - -static void -read_class_extension (GWin32RegistryKey *classes_root, - gunichar2 *class_name, - gsize class_name_len) -{ - gchar *ext_u8; - gchar *ext_folded; - GWin32AppInfoFileExtension *file_extn; - GWin32AppInfoHandler *handler_rec; - GWin32AppInfoHandler *handler_rec_in_ext; - GWin32RegistryKey *class_key; - gsize program_id_size; - gunichar2 *program_id; - gunichar2 *proxy_id; - GWin32RegistryKey *program_key; - GWin32RegistryKey *proxy_key; - gunichar2 *program_command; - gunichar2 *proxy_command; - - class_key = g_win32_registry_key_get_child_w (classes_root, class_name, NULL); - - if (class_key == NULL) - return; - - program_id = class_name; - program_id_size = (class_name_len + 1) * sizeof (gunichar2); - program_key = proxy_key = NULL; - program_command = proxy_command = NULL; - - if (!follow_class_chain_to_handler (program_id, - program_id_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &ext_u8, - &ext_folded)) - { - g_object_unref (class_key); - return; - } - - - file_extn = g_hash_table_lookup (extensions, ext_folded); - handler_rec = g_hash_table_lookup (handlers, ext_folded); - - if (file_extn == NULL) - { - file_extn = g_object_new (G_TYPE_WIN32_APPINFO_FILE_EXTENSION, NULL); - file_extn->extension = g_wcsdup (class_name, -1); - file_extn->extension_u8 = g_strdup (ext_u8); - g_hash_table_insert (extensions, g_strdup (ext_folded), file_extn); - } - - if (handler_rec == NULL) - { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); - - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = g_wcsdup (program_id, program_id_size); - handler_rec->handler_id_folded = g_strdup (ext_folded); - handler_rec->handler_command = - program_command ? g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, program_key, &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (ext_folded), - handler_rec); - } - else - { - g_clear_object (&program_key); - g_clear_object (&proxy_key); - } - - handler_rec_in_ext = g_hash_table_lookup (file_extn->handlers, - ext_folded); - - if (file_extn->chosen_handler == NULL) - g_hash_table_insert (file_extn->handlers, - g_strdup (ext_folded), - g_object_ref (handler_rec)); - else if (handler_rec_in_ext == NULL) - { - if (file_extn->chosen_handler->handler_id_folded && - strcmp (file_extn->chosen_handler->handler_id_folded, - ext_folded) != 0) - g_hash_table_insert (file_extn->handlers, - g_strdup (ext_folded), - g_object_ref (handler_rec)); - } - - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); - g_free (ext_u8); - g_free (ext_folded); - g_object_unref (class_key); -} - -static void -read_class_url (GWin32RegistryKey *classes_root, - gunichar2 *class_name, - gsize class_name_len) -{ - GWin32RegistryKey *class_key; - gboolean success; - GWin32RegistryValueType vtype; - GWin32AppInfoURLSchema *schema_rec; - GWin32AppInfoHandler *handler_rec; - GWin32AppInfoHandler *handler_rec_in_url; - gunichar2 *program_id; - gsize program_id_size; - gunichar2 *program_command; - gunichar2 *proxy_id; - gunichar2 *proxy_command; - gchar *program_id_u8; - gchar *program_id_folded; - GWin32RegistryKey *program_key; - GWin32RegistryKey *proxy_key; - - class_key = g_win32_registry_key_get_child_w (classes_root, class_name, NULL); - - if (class_key == NULL) - return; + g_clear_object (&user_choice); + g_clear_pointer (&program_id, g_free); - success = g_win32_registry_key_get_value_w (class_key, - TRUE, - L"URL Protocol", - &vtype, - NULL, - NULL, - NULL); + open_with_progids = _g_win32_registry_key_build_and_new_w (NULL, FILE_EXTS, + file_extension, + OPEN_WITH_PROGIDS, + NULL); - if (!success || - vtype != G_WIN32_REGISTRY_VALUE_STR) - { - g_object_unref (class_key); - return; - } + if (open_with_progids == NULL) + continue; - program_id = class_name; - program_id_size = (class_name_len + 1) * sizeof (gunichar2); - proxy_key = program_key = NULL; - program_command = proxy_id = proxy_command = NULL; - - if (!follow_class_chain_to_handler (program_id, - program_id_size, - &program_command, - &program_key, - &proxy_id, - &proxy_command, - &proxy_key, - &program_id_u8, - &program_id_folded)) - { - g_object_unref (class_key); - return; - } + if (!g_win32_registry_value_iter_init (&iter, open_with_progids, NULL)) + { + g_clear_object (&open_with_progids); + continue; + } - schema_rec = g_hash_table_lookup (urls, program_id_folded); - handler_rec = g_hash_table_lookup (handlers, program_id_folded); + while (g_win32_registry_value_iter_next (&iter, TRUE, NULL)) + { + if (!g_win32_registry_value_iter_get_name_w (&iter, &value_name, + &value_name_len, + NULL) || + (value_name_len == 0)) + continue; - if (handler_rec == NULL) - { - handler_rec = g_object_new (G_TYPE_WIN32_APPINFO_HANDLER, NULL); - - handler_rec->proxy_key = proxy_key; - handler_rec->key = program_key; - handler_rec->handler_id = g_wcsdup (program_id, program_id_size); - handler_rec->handler_id_folded = - g_strdup (program_id_folded); - handler_rec->handler_command = - program_command ? g_wcsdup (program_command, -1) : NULL; - handler_rec->proxy_id = proxy_id ? g_wcsdup (proxy_id, -1) : NULL; - handler_rec->proxy_command = - proxy_command ? g_wcsdup (proxy_command, -1) : NULL; - extract_executable (proxy_command ? proxy_command : program_command, - &handler_rec->executable, - &handler_rec->executable_basename, - &handler_rec->executable_folded, - NULL); - read_handler_icon (proxy_key, program_key, &handler_rec->icon); - g_hash_table_insert (handlers, - g_strdup (program_id_folded), - handler_rec); - } - else - { - g_clear_object (&program_key); - g_clear_object (&proxy_key); - } + get_file_ext (value_name, file_extension, NULL, FALSE); + } - if (schema_rec == NULL) - { - schema_rec = g_object_new (G_TYPE_WIN32_APPINFO_URL_SCHEMA, NULL); - schema_rec->schema = g_wcsdup (class_name, -1); - schema_rec->schema_u8 = g_strdup (program_id_u8); - schema_rec->schema_folded = g_strdup (program_id_folded); - schema_rec->chosen_handler = g_object_ref (handler_rec); - g_hash_table_insert (urls, - g_strdup (program_id_folded), - schema_rec); + g_win32_registry_value_iter_clear (&iter); + g_clear_object (&open_with_progids); } - if (schema_rec->chosen_handler == NULL) - schema_rec->chosen_handler = g_object_ref (handler_rec); - - handler_rec_in_url = g_hash_table_lookup (schema_rec->handlers, - program_id_folded); - - if (handler_rec_in_url == NULL && schema_rec->chosen_handler != handler_rec) - g_hash_table_insert (schema_rec->handlers, - g_strdup (program_id_folded), - g_object_ref (handler_rec)); - - g_free (program_id_u8); - g_free (program_id_folded); - g_free (program_command); - g_free (proxy_id); - g_free (proxy_command); - g_object_unref (class_key); + g_win32_registry_subkey_iter_clear (&ext_iter); } +/* Iterates over subkeys in HKCR, calls + * get_file_ext() for any subkey that starts with ".", + * or get_url_association() for any subkey that could + * be a URL schema and has a "URL Protocol" value. + */ static void read_classes (GWin32RegistryKey *classes_root) { GWin32RegistrySubkeyIter class_iter; - gunichar2 *class_name; + const gunichar2 *class_name; gsize class_name_len; if (classes_root == NULL) @@ -2778,411 +2960,745 @@ read_classes (GWin32RegistryKey *classes_root) continue; if (class_name[0] == L'.') - read_class_extension (classes_root, class_name, class_name_len); + { + GWin32RegistryKey *class_key; + GWin32RegistryValueIter iter; + GWin32RegistryKey *open_with_progids; + gunichar2 *value_name; + gsize value_name_len; + + /* Read the data from the HKCR\\.ext (usually proxied + * to another HKCR subkey) + */ + get_file_ext (class_name, class_name, NULL, FALSE); + + class_key = g_win32_registry_key_get_child_w (classes_root, class_name, NULL); + + if (class_key == NULL) + continue; + + open_with_progids = g_win32_registry_key_get_child_w (class_key, L"OpenWithProgids", NULL); + g_clear_object (&class_key); + + if (open_with_progids == NULL) + continue; + + if (!g_win32_registry_value_iter_init (&iter, open_with_progids, NULL)) + { + g_clear_object (&open_with_progids); + continue; + } + + /* Read the data for other handlers for this extension */ + while (g_win32_registry_value_iter_next (&iter, TRUE, NULL)) + { + if (!g_win32_registry_value_iter_get_name_w (&iter, &value_name, + &value_name_len, + NULL) || + (value_name_len == 0)) + continue; + + get_file_ext (value_name, class_name, NULL, FALSE); + } + + g_win32_registry_value_iter_clear (&iter); + g_clear_object (&open_with_progids); + } else { gsize i; + GWin32RegistryKey *class_key; + gboolean success; + GWin32RegistryValueType vtype; + gchar *schema_u8; + gchar *schema_u8_folded; for (i = 0; i < class_name_len; i++) if (!iswalpha (class_name[i])) break; - if (i == class_name_len) - read_class_url (classes_root, class_name, class_name_len); + if (i != class_name_len) + continue; + + class_key = g_win32_registry_key_get_child_w (classes_root, class_name, NULL); + + if (class_key == NULL) + continue; + + success = g_win32_registry_key_get_value_w (class_key, + NULL, + TRUE, + L"URL Protocol", + &vtype, + NULL, + NULL, + NULL); + g_clear_object (&class_key); + + if (!success || + vtype != G_WIN32_REGISTRY_VALUE_STR) + continue; + + if (!g_utf16_to_utf8_and_fold (class_name, -1, &schema_u8, &schema_u8_folded)) + continue; + + get_url_association (class_name, class_name, schema_u8, schema_u8_folded, NULL, FALSE); + + g_clear_pointer (&schema_u8, g_free); + g_clear_pointer (&schema_u8_folded, g_free); } } g_win32_registry_subkey_iter_clear (&class_iter); } +/* Iterates over all handlers and over all apps, + * and links handler verbs to apps if a handler + * runs the same executable as one of the app verbs. + */ static void -link_chosen_handlers (void) +link_handlers_to_unregistered_apps (void) { GHashTableIter iter; - GHashTableIter handler_iter; - gchar *schema_folded; - GWin32AppInfoURLSchema *schema; - gchar *handler_id_folded; + GHashTableIter app_iter; GWin32AppInfoHandler *handler; - gchar *ext_folded; - GWin32AppInfoFileExtension *ext; - - g_hash_table_iter_init (&iter, urls); + gchar *handler_id_fld; + GWin32AppInfoApplication *app; + gchar *canonical_name_fld; + gchar *appexe_fld_basename; + g_hash_table_iter_init (&iter, handlers); while (g_hash_table_iter_next (&iter, - (gpointer *) &schema_folded, - (gpointer *) &schema)) + (gpointer *) &handler_id_fld, + (gpointer *) &handler)) { - if (schema->chosen_handler != NULL) - continue; + gsize vi; - g_hash_table_iter_init (&handler_iter, schema->handlers); + if (handler->uwp_aumid != NULL) + continue; - while (g_hash_table_iter_next (&handler_iter, - (gpointer *) &handler_id_folded, - (gpointer *) &handler)) + for (vi = 0; vi < handler->verbs->len; vi++) { - gchar *proxy_id_folded; + GWin32AppInfoShellVerb *handler_verb; + const gchar *handler_exe_basename; + enum + { + SH_UNKNOWN, + GOT_SH_INFO, + ERROR_GETTING_SH_INFO, + } have_stat_handler = SH_UNKNOWN; + GWin32PrivateStat handler_verb_exec_info; - if (schema->chosen_handler != NULL) - break; + handler_verb = _verb_idx (handler->verbs, vi); - if (strcmp (handler_id_folded, schema_folded) != 0) + if (handler_verb->app != NULL) continue; - if (handler->proxy_command && - handler->proxy_id && - utf8_and_fold (handler->proxy_id, - NULL, - &proxy_id_folded)) + handler_exe_basename = g_utf8_find_basename (handler_verb->executable_folded, -1); + g_hash_table_iter_init (&app_iter, apps_by_id); + + while (g_hash_table_iter_next (&app_iter, + (gpointer *) &canonical_name_fld, + (gpointer *) &app)) { - GWin32AppInfoHandler *proxy; + GWin32AppInfoShellVerb *app_verb; + gsize ai; - proxy = g_hash_table_lookup (handlers, proxy_id_folded); + if (app->is_uwp) + continue; - if (proxy) + for (ai = 0; ai < app->verbs->len; ai++) { - schema->chosen_handler = g_object_ref (proxy); - g_debug ("Linking schema %s to proxy handler %c ? \"%S\" : %S\n", - schema->schema_u8, - schema->chosen_handler->proxy_id ? 'P' : 'T', - schema->chosen_handler->proxy_id ? schema->chosen_handler->proxy_id : schema->chosen_handler->handler_id, - schema->chosen_handler->proxy_command ? schema->chosen_handler->proxy_command : schema->chosen_handler->handler_command); - } + GWin32PrivateStat app_verb_exec_info; + const gchar *app_exe_basename; + app_verb = _verb_idx (app->verbs, ai); + + app_exe_basename = g_utf8_find_basename (app_verb->executable_folded, -1); + + /* First check that the executable paths are identical */ + if (g_strcmp0 (app_verb->executable_folded, handler_verb->executable_folded) != 0) + { + /* If not, check the basenames. If they are different, don't bother + * with further checks. + */ + if (g_strcmp0 (app_exe_basename, handler_exe_basename) != 0) + continue; + + /* Get filesystem IDs for both files. + * For the handler that is attempted only once. + */ + if (have_stat_handler == SH_UNKNOWN) + { + if (GLIB_PRIVATE_CALL (g_win32_stat_utf8) (handler_verb->executable_folded, + &handler_verb_exec_info) == 0) + have_stat_handler = GOT_SH_INFO; + else + have_stat_handler = ERROR_GETTING_SH_INFO; + } + + if (have_stat_handler != GOT_SH_INFO || + (GLIB_PRIVATE_CALL (g_win32_stat_utf8) (app_verb->executable_folded, + &app_verb_exec_info) != 0) || + app_verb_exec_info.file_index != handler_verb_exec_info.file_index) + continue; + } - g_free (proxy_id_folded); + handler_verb->app = g_object_ref (app); + break; + } } - if (schema->chosen_handler == NULL) + if (handler_verb->app != NULL) + continue; + + g_hash_table_iter_init (&app_iter, apps_by_exe); + + while (g_hash_table_iter_next (&app_iter, + (gpointer *) &appexe_fld_basename, + (gpointer *) &app)) { - schema->chosen_handler = g_object_ref (handler); - g_debug ("Linking schema %s to handler %c ? \"%S\" : %S\n", - schema->schema_u8, - schema->chosen_handler->proxy_id ? 'P' : 'T', - schema->chosen_handler->proxy_id ? schema->chosen_handler->proxy_id : schema->chosen_handler->handler_id, - schema->chosen_handler->proxy_command ? schema->chosen_handler->proxy_command : schema->chosen_handler->handler_command); + if (app->is_uwp) + continue; + + /* Use basename because apps_by_exe only has basenames */ + if (g_strcmp0 (handler_exe_basename, appexe_fld_basename) != 0) + continue; + + handler_verb->app = g_object_ref (app); + break; } } } +} - g_hash_table_iter_init (&iter, extensions); +/* Finds all .ext and schema: handler verbs that have no app linked to them, + * creates a "fake app" object and links these verbs to these + * objects. Objects are identified by the full path to + * the executable being run, thus multiple different invocations + * get grouped in a more-or-less natural way. + * The iteration goes separately over .ext and schema: handlers + * (instead of the global handlers hashmap) to allow us to + * put the handlers into supported_urls or supported_exts as + * needed (handler objects themselves have no knowledge of extensions + * and/or URLs they are associated with). + */ +static void +link_handlers_to_fake_apps (void) +{ + GHashTableIter iter; + GHashTableIter handler_iter; + gchar *extension_utf8_folded; + GWin32AppInfoFileExtension *file_extn; + gchar *handler_id_fld; + GWin32AppInfoHandler *handler; + gchar *url_utf8_folded; + GWin32AppInfoURLSchema *schema; + g_hash_table_iter_init (&iter, extensions); while (g_hash_table_iter_next (&iter, - (gpointer *) &ext_folded, - (gpointer *) &ext)) + (gpointer *) &extension_utf8_folded, + (gpointer *) &file_extn)) { - if (ext->chosen_handler != NULL) - continue; - - g_hash_table_iter_init (&handler_iter, ext->handlers); - + g_hash_table_iter_init (&handler_iter, file_extn->handlers); while (g_hash_table_iter_next (&handler_iter, - (gpointer *) &handler_id_folded, + (gpointer *) &handler_id_fld, (gpointer *) &handler)) { - gchar *proxy_id_folded; + gsize vi; - if (ext->chosen_handler != NULL) - break; - - if (strcmp (handler_id_folded, ext_folded) != 0) + if (handler->uwp_aumid != NULL) continue; - if (handler->proxy_command && - handler->proxy_id && - utf8_and_fold (handler->proxy_id, - NULL, - &proxy_id_folded)) + for (vi = 0; vi < handler->verbs->len; vi++) { - GWin32AppInfoHandler *proxy; + GWin32AppInfoShellVerb *handler_verb; + GWin32AppInfoApplication *app; + gunichar2 *exename_utf16; + handler_verb = _verb_idx (handler->verbs, vi); - proxy = g_hash_table_lookup (handlers, proxy_id_folded); + if (handler_verb->app != NULL) + continue; - if (proxy) - { - ext->chosen_handler = g_object_ref (proxy); - g_debug ("Linking ext %s to proxy handler %c ? \"%S\" : %S\n", - ext->extension_u8, - ext->chosen_handler->proxy_id ? 'P' : 'T', - ext->chosen_handler->proxy_id ? ext->chosen_handler->proxy_id : ext->chosen_handler->handler_id, - ext->chosen_handler->proxy_command ? ext->chosen_handler->proxy_command : ext->chosen_handler->handler_command); - } + exename_utf16 = g_utf8_to_utf16 (handler_verb->executable, -1, NULL, NULL, NULL); + if (exename_utf16 == NULL) + continue; - g_free (proxy_id_folded); + app = get_app_object (fake_apps, + exename_utf16, + handler_verb->executable, + handler_verb->executable_folded, + FALSE, + FALSE, + FALSE); + g_clear_pointer (&exename_utf16, g_free); + handler_verb->app = g_object_ref (app); + + app_add_verb (app, + app, + handler_verb->verb_name, + handler_verb->command, + handler_verb->command_utf8, + handler_verb->verb_displayname, + TRUE, + TRUE); + g_hash_table_insert (app->supported_exts, + g_strdup (extension_utf8_folded), + g_object_ref (handler)); } + } + } - if (ext->chosen_handler == NULL) + g_hash_table_iter_init (&iter, urls); + while (g_hash_table_iter_next (&iter, + (gpointer *) &url_utf8_folded, + (gpointer *) &schema)) + { + g_hash_table_iter_init (&handler_iter, schema->handlers); + while (g_hash_table_iter_next (&handler_iter, + (gpointer *) &handler_id_fld, + (gpointer *) &handler)) + { + gsize vi; + + if (handler->uwp_aumid != NULL) + continue; + + for (vi = 0; vi < handler->verbs->len; vi++) { - ext->chosen_handler = g_object_ref (handler); - g_debug ("Linking ext %s to handler %c ? \"%S\" : %S\n", - ext->extension_u8, - ext->chosen_handler->proxy_id ? 'P' : 'T', - ext->chosen_handler->proxy_id ? ext->chosen_handler->proxy_id : ext->chosen_handler->handler_id, - ext->chosen_handler->proxy_command ? ext->chosen_handler->proxy_command : ext->chosen_handler->handler_command); + GWin32AppInfoShellVerb *handler_verb; + GWin32AppInfoApplication *app; + gchar *command_utf8_folded; + handler_verb = _verb_idx (handler->verbs, vi); + + if (handler_verb->app != NULL) + continue; + + command_utf8_folded = g_utf8_casefold (handler_verb->command_utf8, -1); + app = get_app_object (fake_apps, + handler_verb->command, + handler_verb->command_utf8, + command_utf8_folded, + FALSE, + FALSE, + FALSE); + g_clear_pointer (&command_utf8_folded, g_free); + handler_verb->app = g_object_ref (app); + + app_add_verb (app, + app, + handler_verb->verb_name, + handler_verb->command, + handler_verb->command_utf8, + handler_verb->verb_displayname, + TRUE, + TRUE); + g_hash_table_insert (app->supported_urls, + g_strdup (url_utf8_folded), + g_object_ref (handler)); } } } } -static void -link_handlers_to_registered_apps (void) +static GWin32AppInfoHandler * +find_uwp_handler_for_ext (GWin32AppInfoFileExtension *file_extn, + const gunichar2 *app_user_model_id) { - GHashTableIter iter; - GHashTableIter sup_iter; - gchar *app_id_folded; - GWin32AppInfoApplication *app; - gchar *schema_folded; - GWin32AppInfoURLSchema *schema; - gchar *ext_folded; - GWin32AppInfoFileExtension *ext; - gsize unhandled_exts; + GHashTableIter handler_iter; + gchar *handler_id_fld; + GWin32AppInfoHandler *handler; - g_hash_table_iter_init (&sup_iter, urls); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &schema_folded, - (gpointer *) &schema)) + g_hash_table_iter_init (&handler_iter, file_extn->handlers); + while (g_hash_table_iter_next (&handler_iter, + (gpointer *) &handler_id_fld, + (gpointer *) &handler)) { - if (schema->chosen_handler == NULL) - g_debug ("WARNING: schema %s has no chosen handler\n", schema->schema_u8); + if (handler->uwp_aumid == NULL) + continue; + + if (_wcsicmp (handler->uwp_aumid, app_user_model_id) == 0) + return handler; } - unhandled_exts= 0; - g_hash_table_iter_init (&sup_iter, extensions); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &ext_folded, - (gpointer *) &ext)) + + return NULL; +} + +static GWin32AppInfoHandler * +find_uwp_handler_for_schema (GWin32AppInfoURLSchema *schema, + const gunichar2 *app_user_model_id) +{ + GHashTableIter handler_iter; + gchar *handler_id_fld; + GWin32AppInfoHandler *handler; + + g_hash_table_iter_init (&handler_iter, schema->handlers); + while (g_hash_table_iter_next (&handler_iter, + (gpointer *) &handler_id_fld, + (gpointer *) &handler)) { - if (ext->chosen_handler == NULL) - { - g_debug ("WARNING: extension %s has no chosen handler\n", - ext->extension_u8); - unhandled_exts += 1; - } + if (handler->uwp_aumid == NULL) + continue; + + if (_wcsicmp (handler->uwp_aumid, app_user_model_id) == 0) + return handler; } - g_hash_table_iter_init (&iter, apps_by_id); - while (g_hash_table_iter_next (&iter, - (gpointer *) &app_id_folded, - (gpointer *) &app)) + return NULL; +} + +static gboolean +uwp_package_cb (gpointer user_data, + const gunichar2 *full_package_name, + const gunichar2 *package_name, + const gunichar2 *app_user_model_id, + gboolean show_in_applist, + GPtrArray *supported_extgroups, + GPtrArray *supported_protocols) +{ + gint i, i_verb, i_ext; + gint extensions_considered; + GWin32AppInfoApplication *app; + gchar *app_user_model_id_u8; + gchar *app_user_model_id_u8_folded; + GHashTableIter iter; + GWin32AppInfoHandler *ext; + GWin32AppInfoHandler *url; + + if (!g_utf16_to_utf8_and_fold (app_user_model_id, + -1, + &app_user_model_id_u8, + &app_user_model_id_u8_folded)) + return TRUE; + + app = get_app_object (apps_by_id, + app_user_model_id, + app_user_model_id_u8, + app_user_model_id_u8_folded, + TRUE, + FALSE, + TRUE); + + extensions_considered = 0; + + for (i = 0; i < supported_extgroups->len; i++) { - if (app->supported_urls) - { - GWin32AppInfoHandler *handler; + GWin32PackageExtGroup *grp = (GWin32PackageExtGroup *) g_ptr_array_index (supported_extgroups, i); - g_hash_table_iter_init (&sup_iter, app->supported_urls); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &schema_folded, - (gpointer *) &handler)) - { - schema = g_hash_table_lookup (urls, schema_folded); + extensions_considered += grp->extensions->len; + + for (i_ext = 0; i_ext < grp->extensions->len; i_ext++) + { + wchar_t *ext = (wchar_t *) g_ptr_array_index (grp->extensions, i_ext); + gchar *ext_u8; + gchar *ext_u8_folded; + GWin32AppInfoFileExtension *file_extn; + GWin32AppInfoHandler *handler_rec; + + if (!g_utf16_to_utf8_and_fold (ext, + -1, + &ext_u8, + &ext_u8_folded)) + continue; - g_assert (schema != NULL); + file_extn = get_ext_object (ext, ext_u8, ext_u8_folded); + g_free (ext_u8); + handler_rec = find_uwp_handler_for_ext (file_extn, app_user_model_id); - if (schema->chosen_handler != NULL && - schema->chosen_handler->app == NULL) - { - schema->chosen_handler->app = g_object_ref (app); - g_debug ("Linking %S", app->canonical_name); - - if (app->localized_pretty_name) - g_debug (" '%S'", app->localized_pretty_name); - else if (app->pretty_name) - g_debug (" '%S'", app->pretty_name); - else - g_debug (" '%s'", app->executable); - - if (app->command) - g_debug (" %S", app->command); - - g_debug ("\n to schema %s handler %c ? \"%S\" : %S\n", - schema->schema_u8, - schema->chosen_handler->proxy_id ? 'P' : 'T', - schema->chosen_handler->proxy_id ? schema->chosen_handler->proxy_id : schema->chosen_handler->handler_id, - schema->chosen_handler->proxy_command ? schema->chosen_handler->proxy_command : schema->chosen_handler->handler_command); - } + if (handler_rec == NULL) + { + /* Use AppUserModelId as the ID of the new fake handler */ + handler_rec = get_handler_object (app_user_model_id_u8_folded, + NULL, + app_user_model_id, + app_user_model_id); + g_hash_table_insert (file_extn->handlers, + g_strdup (app_user_model_id_u8_folded), + g_object_ref (handler_rec)); } - g_hash_table_iter_init (&sup_iter, app->supported_urls); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &schema_folded, - (gpointer *) &handler)) + if (file_extn->chosen_handler == NULL) + g_set_object (&file_extn->chosen_handler, handler_rec); + + /* This is somewhat wasteful, but for 100% correct handling + * we need to remember which extensions (handlers) support + * which verbs, and each handler gets its own copy of the + * verb object, since our design is handler-centric, + * not verb-centric. The app also gets a list of verbs, + * but without handlers it would have no idea which + * verbs can be used with which extensions. + */ + for (i_verb = 0; i_verb < grp->verbs->len; i_verb++) { - if (handler->app == NULL) - { - handler->app = g_object_ref (app); - g_debug ("Linking %S", app->canonical_name); - - if (app->localized_pretty_name) - g_debug (" '%S'", app->localized_pretty_name); - else if (app->pretty_name) - g_debug (" '%S'", app->pretty_name); - else - g_debug (" '%s'", app->executable); - - if (app->command) - g_debug (" %S", app->command); - - g_debug ("\n directly to schema handler to %c ? \"%S\" : %S\n", - handler->proxy_id ? 'P' : 'T', - handler->proxy_id ? handler->proxy_id : handler->handler_id, - handler->proxy_command ? handler->proxy_command : handler->handler_command); - } + wchar_t *verb = NULL; + + verb = (wchar_t *) g_ptr_array_index (grp->verbs, i_verb); + /* *_add_verb() functions are no-ops when a verb already exists, + * so we're free to call them as many times as we want. + */ + uwp_handler_add_verb (handler_rec, + app, + verb, + NULL, + FALSE); } + + g_hash_table_insert (app->supported_exts, + g_steal_pointer (&ext_u8_folded), + g_object_ref (handler_rec)); } + } - if (app->supported_exts) + g_hash_table_iter_init (&iter, app->supported_exts); + + /* Pile up all handler verbs into the app too, + * for cases when we don't have a ref to a handler. + */ + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &ext)) + { + gint i_hverb; + + if (!ext) + continue; + + for (i_hverb = 0; i_hverb < ext->verbs->len; i_hverb++) { - GWin32AppInfoHandler *handler; + GWin32AppInfoShellVerb *handler_verb; - g_hash_table_iter_init (&sup_iter, app->supported_exts); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &ext_folded, - (gpointer *) &handler)) - { - ext = g_hash_table_lookup (extensions, ext_folded); + handler_verb = _verb_idx (ext->verbs, i_hverb); + uwp_app_add_verb (app, handler_verb->verb_name, handler_verb->verb_displayname); + if (handler_verb->app == NULL && handler_verb->is_uwp) + handler_verb->app = g_object_ref (app); + } + } - g_assert (ext != NULL); + if (app->verbs->len == 0 && extensions_considered > 0) + g_warning ("Unexpectedly, UWP app `%S' (AUMId `%s') supports %d extensions but has no verbs", + full_package_name, app_user_model_id_u8, extensions_considered); - if (ext->chosen_handler != NULL && - ext->chosen_handler->app == NULL) - { - ext->chosen_handler->app = g_object_ref (app); - g_debug ("Linking %S", app->canonical_name); - - if (app->localized_pretty_name) - g_debug (" '%S'", app->localized_pretty_name); - else if (app->pretty_name) - g_debug (" '%S'", app->pretty_name); - else - g_debug (" '%s'", app->executable); - - if (app->command) - g_debug (" %S", app->command); - - g_debug ("\n to ext %s handler %c ? \"%S\" : %S\n", - ext->extension_u8, - ext->chosen_handler->proxy_id ? 'P' : 'T', - ext->chosen_handler->proxy_id ? ext->chosen_handler->proxy_id : ext->chosen_handler->handler_id, - ext->chosen_handler->proxy_command ? ext->chosen_handler->proxy_command : ext->chosen_handler->handler_command); - } - } + for (i = 0; i < supported_protocols->len; i++) + { + wchar_t *proto = (wchar_t *) g_ptr_array_index (supported_protocols, i); + gchar *proto_u8; + gchar *proto_u8_folded; + GWin32AppInfoURLSchema *schema_rec; + GWin32AppInfoHandler *handler_rec; - g_hash_table_iter_init (&sup_iter, app->supported_exts); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &ext_folded, - (gpointer *) &handler)) - { - if (handler->app == NULL) - { - handler->app = g_object_ref (app); - g_debug ("Linking %S", app->canonical_name); - - if (app->localized_pretty_name) - g_debug (" '%S'", app->localized_pretty_name); - else if (app->pretty_name) - g_debug (" '%S'", app->pretty_name); - else - g_debug (" '%s'", app->executable); - - if (app->command) - g_debug (" %S", app->command); - - g_debug ("\n directly to ext handler %c ? \"%S\" : %S\n", - handler->proxy_id ? 'P' : 'T', - handler->proxy_id ? handler->proxy_id : handler->handler_id, - handler->proxy_command ? handler->proxy_command : handler->handler_command); - } - } + if (!g_utf16_to_utf8_and_fold (proto, + -1, + &proto_u8, + &proto_u8_folded)) + continue; + + schema_rec = get_schema_object (proto, + proto_u8, + proto_u8_folded); + + g_free (proto_u8); + + handler_rec = find_uwp_handler_for_schema (schema_rec, app_user_model_id); + + if (handler_rec == NULL) + { + /* Use AppUserModelId as the ID of the new fake handler */ + handler_rec = get_handler_object (app_user_model_id_u8_folded, + NULL, + app_user_model_id, + app_user_model_id); + + g_hash_table_insert (schema_rec->handlers, + g_strdup (app_user_model_id_u8_folded), + g_object_ref (handler_rec)); } + + if (schema_rec->chosen_handler == NULL) + g_set_object (&schema_rec->chosen_handler, handler_rec); + + /* Technically, UWP apps don't use verbs for URIs, + * but we only store an app field in verbs, + * so each UWP URI handler has to have one. + * Let's call it "open". + */ + uwp_handler_add_verb (handler_rec, + app, + L"open", + NULL, + TRUE); + + g_hash_table_insert (app->supported_urls, + g_steal_pointer (&proto_u8_folded), + g_object_ref (handler_rec)); } - g_debug ("%" G_GSIZE_FORMAT "undefhandled extensions\n", unhandled_exts); - unhandled_exts= 0; - g_hash_table_iter_init (&sup_iter, extensions); - while (g_hash_table_iter_next (&sup_iter, - (gpointer *) &ext_folded, - (gpointer *) &ext)) + g_hash_table_iter_init (&iter, app->supported_urls); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &url)) { - if (ext->chosen_handler == NULL) + gint i_hverb; + + if (!url) + continue; + + for (i_hverb = 0; i_hverb < url->verbs->len; i_hverb++) + { + GWin32AppInfoShellVerb *handler_verb; + + handler_verb = _verb_idx (url->verbs, i_hverb); + uwp_app_add_verb (app, handler_verb->verb_name, handler_verb->verb_displayname); + if (handler_verb->app == NULL && handler_verb->is_uwp) + handler_verb->app = g_object_ref (app); + } + } + + g_free (app_user_model_id_u8); + g_free (app_user_model_id_u8_folded); + + return TRUE; +} + +/* Calls SHLoadIndirectString() in a loop to resolve + * a string in @{...} format (also supports other indirect + * strings, but we aren't using it for those). + * Consumes the input, but may return it unmodified + * (not an indirect string). May return %NULL (the string + * is indirect, but the OS failed to load it). + */ +static gunichar2 * +resolve_string (gunichar2 *at_string) +{ + HRESULT hr; + gunichar2 *result = NULL; + gsize result_size; + /* This value is arbitrary */ + const gsize reasonable_size_limit = 8192; + + if (at_string == NULL || at_string[0] != L'@') + return at_string; + + /* In case of a no-op @at_string will be copied into the output, + * buffer so allocate at least that much. + */ + result_size = wcslen (at_string) + 1; + + while (TRUE) + { + result = g_renew (gunichar2, result, result_size); + /* Since there's no built-in way to detect too small buffer size, + * we do so by putting a sentinel at the end of the buffer. + * If it's 0 (result is always 0-terminated, even if the buffer + * is too small), then try larger buffer. + */ + result[result_size - 1] = 0xff; + /* This string accepts size in characters, not bytes. */ + hr = SHLoadIndirectString (at_string, result, result_size, NULL); + if (!SUCCEEDED (hr)) + { + g_free (result); + g_free (at_string); + return NULL; + } + else if (result[result_size - 1] != 0 || + result_size >= reasonable_size_limit) { - g_debug ("WARNING: extension %s has no chosen handler\n", - ext->extension_u8); - unhandled_exts += 1; + /* Now that the length is known, allocate the exact amount */ + gunichar2 *copy = g_wcsdup (result, -1); + g_free (result); + g_free (at_string); + return copy; } + + result_size *= 2; } - g_debug ("%" G_GSIZE_FORMAT "undefhandled extensions\n", unhandled_exts); + + g_assert_not_reached (); + + return at_string; } static void -link_handlers_to_unregistered_apps (void) +grab_registry_string (GWin32RegistryKey *handler_appkey, + const gunichar2 *value_name, + gunichar2 **destination, + gchar **destination_u8) { - GHashTableIter iter; - GHashTableIter app_iter; - GWin32AppInfoHandler *handler; - gchar *handler_id_fc; - GWin32AppInfoApplication *app; - gchar *canonical_name_fc; - gchar *appexe_fc_basename; + gunichar2 *value; + gsize value_size; + GWin32RegistryValueType vtype; + const gunichar2 *ms_resource_prefix = L"ms-resource:"; + gsize ms_resource_prefix_len = wcslen (ms_resource_prefix); - g_hash_table_iter_init (&iter, handlers); - while (g_hash_table_iter_next (&iter, - (gpointer *) &handler_id_fc, - (gpointer *) &handler)) - { - gchar *hndexe_fc_basename; + /* Right now this function is not used without destination, + * enforce this. destination_u8 is optional. + */ + g_assert (destination != NULL); - if ((handler->app != NULL) || - (handler->executable_folded == NULL)) - continue; + if (*destination != NULL) + return; - hndexe_fc_basename = g_utf8_casefold (handler->executable_basename, -1); + if (g_win32_registry_key_get_value_w (handler_appkey, + NULL, + TRUE, + value_name, + &vtype, + (void **) &value, + &value_size, + NULL) && + vtype != G_WIN32_REGISTRY_VALUE_STR) + g_clear_pointer (&value, g_free); - if (hndexe_fc_basename == NULL) - continue; + /* There's no way for us to resolve "ms-resource:..." strings */ + if (value != NULL && + value_size >= ms_resource_prefix_len && + memcmp (value, + ms_resource_prefix, + ms_resource_prefix_len * sizeof (gunichar2)) == 0) + g_clear_pointer (&value, g_free); - g_hash_table_iter_init (&app_iter, apps_by_id); + if (value == NULL) + return; - while (g_hash_table_iter_next (&app_iter, - (gpointer *) &canonical_name_fc, - (gpointer *) &app)) - { - if (app->executable_folded == NULL) - continue; + *destination = resolve_string (g_steal_pointer (&value)); - if (strcmp (app->executable_folded, - handler->executable_folded) != 0) - continue; + if (*destination == NULL) + return; - handler->app = app; - break; - } + if (destination_u8) + *destination_u8 = g_utf16_to_utf8 (*destination, -1, NULL, NULL, NULL); +} - if (handler->app != NULL) - continue; +static void +read_uwp_handler_info (void) +{ + GHashTableIter iter; + GWin32RegistryKey *handler_appkey; + gunichar2 *aumid; - g_hash_table_iter_init (&app_iter, apps_by_exe); + g_hash_table_iter_init (&iter, uwp_handler_table); - while ((hndexe_fc_basename != NULL) && - (g_hash_table_iter_next (&app_iter, - (gpointer *) &appexe_fc_basename, - (gpointer *) &app))) - { - /* Use basename because apps_by_exe only has basenames */ - if (strcmp (hndexe_fc_basename, appexe_fc_basename) != 0) - continue; + while (g_hash_table_iter_next (&iter, (gpointer *) &handler_appkey, (gpointer *) &aumid)) + { + gchar *aumid_u8_folded; + GWin32AppInfoApplication *app; - handler->app = app; - break; - } + if (!g_utf16_to_utf8_and_fold (aumid, + -1, + NULL, + &aumid_u8_folded)) + continue; + + app = g_hash_table_lookup (apps_by_id, aumid_u8_folded); + g_clear_pointer (&aumid_u8_folded, g_free); - g_free (hndexe_fc_basename); + if (app == NULL) + continue; - if (handler->app == NULL) - g_debug ("WARNING: handler that runs %s has no corresponding app\n", - handler->executable); + grab_registry_string (handler_appkey, L"ApplicationDescription", &app->description, &app->description_u8); + grab_registry_string (handler_appkey, L"ApplicationName", &app->localized_pretty_name, &app->localized_pretty_name_u8); + /* TODO: ApplicationIcon value (usually also @{...}) resolves into + * an image (PNG only?) with implicit multiple variants (scale, size, etc). + */ } } - static void update_registry_data (void) { @@ -3193,7 +3709,8 @@ update_registry_data (void) GWin32RegistryKey *url_associations; GWin32RegistryKey *file_exts; GWin32RegistryKey *classes_root; - DWORD collect_start, collect_end, alloc_end, capable_end, url_end, ext_end, exeapp_end, classes_end, postproc_end; + DWORD collect_start, collect_end, alloc_end, capable_end, url_end, ext_end, exeapp_end, classes_end, uwp_end, postproc_end; + GError *error = NULL; url_associations = g_win32_registry_key_new_w (L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations", @@ -3209,6 +3726,7 @@ update_registry_data (void) g_clear_pointer (&apps_by_id, g_hash_table_destroy); g_clear_pointer (&apps_by_exe, g_hash_table_destroy); + g_clear_pointer (&fake_apps, g_hash_table_destroy); g_clear_pointer (&urls, g_hash_table_destroy); g_clear_pointer (&extensions, g_hash_table_destroy); g_clear_pointer (&handlers, g_hash_table_destroy); @@ -3230,12 +3748,16 @@ update_registry_data (void) g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); apps_by_exe = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + fake_apps = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); urls = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); extensions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + uwp_handler_table = + g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, g_free); alloc_end = GetTickCount (); for (i = 0; i < priority_capable_apps_keys->len; i++) @@ -3260,9 +3782,18 @@ update_registry_data (void) exeapp_end = GetTickCount (); read_classes (classes_root); classes_end = GetTickCount (); - link_chosen_handlers (); - link_handlers_to_registered_apps (); + + if (!g_win32_package_parser_enum_packages (uwp_package_cb, NULL, &error)) + { + g_debug ("Unable to get UWP apps: %s", error->message); + g_clear_error (&error); + } + + read_uwp_handler_info (); + + uwp_end = GetTickCount (); link_handlers_to_unregistered_apps (); + link_handlers_to_fake_apps (); postproc_end = GetTickCount (); g_debug ("Collecting capable appnames: %lums\n" @@ -3272,8 +3803,9 @@ update_registry_data (void) "Reading extension assocs: %lums\n" "Reading exe-only apps:...... %lums\n" "Reading classes: %lums\n" + "Reading UWP apps: %lums\n" "Postprocessing:..............%lums\n" - "TOTAL: %lums\n", + "TOTAL: %lums", collect_end - collect_start, alloc_end - collect_end, capable_end - alloc_end, @@ -3281,7 +3813,8 @@ update_registry_data (void) ext_end - url_end, exeapp_end - ext_end, classes_end - exeapp_end, - postproc_end - classes_end, + uwp_end - classes_end, + postproc_end - uwp_end, postproc_end - collect_start); g_clear_object (&classes_root); @@ -3290,10 +3823,24 @@ update_registry_data (void) g_ptr_array_free (capable_apps_keys, TRUE); g_ptr_array_free (user_capable_apps_keys, TRUE); g_ptr_array_free (priority_capable_apps_keys, TRUE); + g_hash_table_unref (uwp_handler_table); return; } +/* This function is called when any of our registry watchers detect + * changes in the registry. + */ +static void +keys_updated (GWin32RegistryKey *key, + gpointer user_data) +{ + /* Indicate the tree as not up-to-date, push a new job for the AppInfo thread */ + g_atomic_int_inc (&gio_win32_appinfo_update_counter); + /* We don't use the data pointer, but it must be non-NULL */ + g_thread_pool_push (gio_win32_appinfo_threadpool, (gpointer) keys_updated, NULL); +} + static void watch_keys (void) { @@ -3303,7 +3850,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3313,7 +3860,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3323,7 +3870,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3333,7 +3880,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3343,7 +3890,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3353,7 +3900,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3363,7 +3910,7 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); @@ -3373,19 +3920,52 @@ watch_keys (void) G_WIN32_REGISTRY_WATCH_NAME | G_WIN32_REGISTRY_WATCH_ATTRIBUTES | G_WIN32_REGISTRY_WATCH_VALUES, - NULL, + keys_updated, NULL, NULL); } - +/* This is the main function of the AppInfo thread */ static void -g_win32_appinfo_init (void) +gio_win32_appinfo_thread_func (gpointer data, + gpointer user_data) +{ + gint saved_counter; + g_mutex_lock (&gio_win32_appinfo_mutex); + saved_counter = g_atomic_int_get (&gio_win32_appinfo_update_counter); + + if (saved_counter > 0) + update_registry_data (); + /* If the counter didn't change while we were working, then set it to zero. + * Otherwise we need to rebuild the tree again, so keep it greater than zero. + * Numeric value doesn't matter - even if we're asked to rebuild N times, + * we just need to rebuild once, and as long as there were no new rebuild + * requests while we were working, we're done. + */ + if (g_atomic_int_compare_and_exchange (&gio_win32_appinfo_update_counter, + saved_counter, + 0)) + g_cond_broadcast (&gio_win32_appinfo_cond); + + g_mutex_unlock (&gio_win32_appinfo_mutex); +} + +/* Initializes Windows AppInfo. Creates the registry watchers, + * the AppInfo thread, and initiates an update of the AppInfo tree. + * Called with do_wait = `FALSE` at startup to prevent it from + * blocking until the tree is updated. All subsequent calls + * from everywhere else are made with do_wait = `TRUE`, blocking + * until the tree is re-built (if needed). + */ +void +gio_win32_appinfo_init (gboolean do_wait) { static gsize initialized; if (g_once_init_enter (&initialized)) { + HMODULE gio_dll_extra; + url_associations_key = g_win32_registry_key_new_w (L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations", NULL); @@ -3413,24 +3993,44 @@ g_win32_appinfo_init (void) watch_keys (); - update_registry_data (); + /* We don't really require an exclusive pool, but the implementation + * details might cause the g_thread_pool_push() call below to block + * if the pool is not exclusive (specifically - for POSIX threads backend + * lacking thread scheduler settings). + */ + gio_win32_appinfo_threadpool = g_thread_pool_new (gio_win32_appinfo_thread_func, + NULL, + 1, + TRUE, + NULL); + g_mutex_init (&gio_win32_appinfo_mutex); + g_cond_init (&gio_win32_appinfo_cond); + g_atomic_int_set (&gio_win32_appinfo_update_counter, 1); + /* Trigger initial tree build. Fake data pointer. */ + g_thread_pool_push (gio_win32_appinfo_threadpool, (gpointer) keys_updated, NULL); + /* Increment the DLL refcount */ + GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, + (const char *) gio_win32_appinfo_init, + &gio_dll_extra); + /* gio DLL cannot be unloaded now */ g_once_init_leave (&initialized, TRUE); } - if ((url_associations_key && g_win32_registry_key_has_changed (url_associations_key)) || - (file_exts_key && g_win32_registry_key_has_changed (file_exts_key)) || - (user_clients_key && g_win32_registry_key_has_changed (user_clients_key)) || - (system_clients_key && g_win32_registry_key_has_changed (system_clients_key)) || - (applications_key && g_win32_registry_key_has_changed (applications_key)) || - (user_registered_apps_key && g_win32_registry_key_has_changed (user_registered_apps_key)) || - (system_registered_apps_key && g_win32_registry_key_has_changed (system_registered_apps_key)) || - (classes_root_key && g_win32_registry_key_has_changed (classes_root_key))) + if (!do_wait) + return; + + /* Previously, we checked each of the watched keys here. + * Now we just look at the update counter, because each key + * has a change callback keys_updated, which increments this counter. + */ + if (g_atomic_int_get (&gio_win32_appinfo_update_counter) > 0) { - G_LOCK (gio_win32_appinfo); - update_registry_data (); + g_mutex_lock (&gio_win32_appinfo_mutex); + while (g_atomic_int_get (&gio_win32_appinfo_update_counter) > 0) + g_cond_wait (&gio_win32_appinfo_cond, &gio_win32_appinfo_mutex); watch_keys (); - G_UNLOCK (gio_win32_appinfo); + g_mutex_unlock (&gio_win32_appinfo_mutex); } } @@ -3463,7 +4063,7 @@ g_win32_app_info_finalize (GObject *object) info = G_WIN32_APP_INFO (object); - g_clear_pointer (&info->supported_types, g_free); + g_clear_pointer (&info->supported_types, g_strfreev); g_clear_object (&info->app); g_clear_object (&info->handler); @@ -3496,8 +4096,8 @@ g_win32_app_info_new_from_app (GWin32AppInfoApplication *app, new_info->app = g_object_ref (app); - g_win32_appinfo_init (); - G_LOCK (gio_win32_appinfo); + gio_win32_appinfo_init (TRUE); + g_mutex_lock (&gio_win32_appinfo_mutex); i = 0; g_hash_table_iter_init (&iter, new_info->app->supported_exts); @@ -3508,7 +4108,7 @@ g_win32_app_info_new_from_app (GWin32AppInfoApplication *app, i += 1; } - new_info->supported_types = g_malloc (sizeof (gchar *) * (i + 1)); + new_info->supported_types = g_new (gchar *, i + 1); i = 0; g_hash_table_iter_init (&iter, new_info->app->supported_exts); @@ -3518,11 +4118,11 @@ g_win32_app_info_new_from_app (GWin32AppInfoApplication *app, if (!ext) continue; - new_info->supported_types[i] = (gchar *) ext; + new_info->supported_types[i] = g_strdup ((gchar *) ext); i += 1; } - G_UNLOCK (gio_win32_appinfo); + g_mutex_unlock (&gio_win32_appinfo_mutex); new_info->supported_types[i] = NULL; @@ -3555,7 +4155,7 @@ g_win32_app_info_dup (GAppInfo *appinfo) for (i = 0; info->supported_types[i]; i++) break; - new_info->supported_types = g_malloc (sizeof (gchar *) * (i + 1)); + new_info->supported_types = g_new (gchar *, i + 1); for (i = 0; info->supported_types[i]; i++) new_info->supported_types[i] = g_strdup (info->supported_types[i]); @@ -3570,30 +4170,41 @@ static gboolean g_win32_app_info_equal (GAppInfo *appinfo1, GAppInfo *appinfo2) { + GWin32AppInfoShellVerb *shverb1 = NULL; + GWin32AppInfoShellVerb *shverb2 = NULL; GWin32AppInfo *info1 = G_WIN32_APP_INFO (appinfo1); GWin32AppInfo *info2 = G_WIN32_APP_INFO (appinfo2); + GWin32AppInfoApplication *app1 = info1->app; + GWin32AppInfoApplication *app2 = info2->app; - if (info1->app == NULL || - info2->app == NULL) + if (app1 == NULL || + app2 == NULL) return info1 == info2; - if (info1->app->canonical_name_folded != NULL && - info2->app->canonical_name_folded != NULL) - return (strcmp (info1->app->canonical_name_folded, - info2->app->canonical_name_folded)) == 0; + if (app1->canonical_name_folded != NULL && + app2->canonical_name_folded != NULL) + return (g_strcmp0 (app1->canonical_name_folded, + app2->canonical_name_folded)) == 0; - if (info1->app->executable_folded != NULL && - info2->app->executable_folded != NULL) - return (strcmp (info1->app->executable_folded, - info2->app->executable_folded)) == 0; + if (app1->verbs->len > 0 && + app2->verbs->len > 0) + { + shverb1 = _verb_idx (app1->verbs, 0); + shverb2 = _verb_idx (app2->verbs, 0); + if (shverb1->executable_folded != NULL && + shverb2->executable_folded != NULL) + return (g_strcmp0 (shverb1->executable_folded, + shverb2->executable_folded)) == 0; + } - return info1->app == info2->app; + return app1 == app2; } static const char * g_win32_app_info_get_id (GAppInfo *appinfo) { GWin32AppInfo *info = G_WIN32_APP_INFO (appinfo); + GWin32AppInfoShellVerb *shverb; if (info->app == NULL) return NULL; @@ -3601,8 +4212,9 @@ g_win32_app_info_get_id (GAppInfo *appinfo) if (info->app->canonical_name_u8) return info->app->canonical_name_u8; - if (info->app->executable_basename) - return info->app->executable_basename; + if (info->app->verbs->len > 0 && + (shverb = _verb_idx (info->app->verbs, 0))->executable_basename != NULL) + return shverb->executable_basename; return NULL; } @@ -3612,7 +4224,9 @@ g_win32_app_info_get_name (GAppInfo *appinfo) { GWin32AppInfo *info = G_WIN32_APP_INFO (appinfo); - if (info->app && info->app->canonical_name_u8) + if (info->app && info->app->pretty_name_u8) + return info->app->pretty_name_u8; + else if (info->app && info->app->canonical_name_u8) return info->app->canonical_name_u8; else return P_("Unnamed"); @@ -3653,7 +4267,10 @@ g_win32_app_info_get_executable (GAppInfo *appinfo) if (info->app == NULL) return NULL; - return info->app->executable; + if (info->app->verbs->len > 0 && !info->app->is_uwp) + return _verb_idx (info->app->verbs, 0)->executable; + + return NULL; } static const char * @@ -3664,7 +4281,10 @@ g_win32_app_info_get_commandline (GAppInfo *appinfo) if (info->app == NULL) return NULL; - return info->app->command_u8; + if (info->app->verbs->len > 0 && !info->app->is_uwp) + return _verb_idx (info->app->verbs, 0)->command_utf8; + + return NULL; } static GIcon * @@ -3968,14 +4588,6 @@ expand_application_parameters (GWin32AppInfo *info, gboolean res; gchar *a_char; - if (exec_line == NULL) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - P_("Application registry did not specify" - " a shell\\open\\command")); - return FALSE; - } - expanded_exec = g_string_new (NULL); res = FALSE; @@ -4023,47 +4635,93 @@ expand_application_parameters (GWin32AppInfo *info, static gchar * -get_appath_for_exe (gunichar2 *exe_basename) +get_appath_for_exe (const gchar *exe_basename) { GWin32RegistryKey *apppath_key = NULL; GWin32RegistryValueType val_type; - gunichar2 *appath = NULL; + gchar *appath = NULL; gboolean got_value; - gchar *result = NULL; + gchar *key_path = g_strdup_printf ("HKEY_LOCAL_MACHINE\\" + "SOFTWARE\\" + "Microsoft\\" + "Windows\\" + "CurrentVersion\\" + "App Paths\\" + "%s", exe_basename); - apppath_key = _g_win32_registry_key_build_and_new_w (NULL, L"HKEY_LOCAL_MACHINE\\" - L"\\SOFTWARE" - L"\\Microsoft" - L"\\Windows" - L"\\CurrentVersion" - L"\\App Paths\\", - exe_basename, NULL); + apppath_key = g_win32_registry_key_new (key_path, NULL); + g_clear_pointer (&key_path, g_free); if (apppath_key == NULL) return NULL; - got_value = g_win32_registry_key_get_value_w (apppath_key, - TRUE, - L"Path", - &val_type, - (void **) &appath, - NULL, - NULL); + got_value = g_win32_registry_key_get_value (apppath_key, + NULL, + TRUE, + "Path", + &val_type, + (void **) &appath, + NULL, + NULL); g_object_unref (apppath_key); - if (got_value && val_type == G_WIN32_REGISTRY_VALUE_STR) - result = g_utf16_to_utf8 (appath, -1, NULL,NULL, NULL); + if (got_value && + val_type == G_WIN32_REGISTRY_VALUE_STR) + return appath; g_clear_pointer (&appath, g_free); + return appath; +} + + +static gboolean +g_win32_app_info_launch_uwp_internal (GWin32AppInfo *info, + gboolean for_files, + IShellItemArray *items, + GWin32AppInfoShellVerb *shverb, + GError **error) +{ + DWORD pid; + IApplicationActivationManager* paam = NULL; + gboolean result = TRUE; + HRESULT hr; + + hr = CoCreateInstance (&CLSID_ApplicationActivationManager, NULL, CLSCTX_INPROC_SERVER, &IID_IApplicationActivationManager, (void **) &paam); + if (FAILED (hr)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to create ApplicationActivationManager: 0x%lx", hr); + return FALSE; + } + + if (items == NULL) + hr = IApplicationActivationManager_ActivateApplication (paam, (const wchar_t *) info->app->canonical_name, NULL, AO_NONE, &pid); + else if (for_files) + hr = IApplicationActivationManager_ActivateForFile (paam, (const wchar_t *) info->app->canonical_name, items, shverb->verb_name, &pid); + else + hr = IApplicationActivationManager_ActivateForProtocol (paam, (const wchar_t *) info->app->canonical_name, items, &pid); + + if (FAILED (hr)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "The app %s failed to launch: 0x%lx", + g_win32_appinfo_application_get_some_name (info->app), hr); + result = FALSE; + } + + IApplicationActivationManager_Release (paam); + return result; } static gboolean g_win32_app_info_launch_internal (GWin32AppInfo *info, - GList *objs, + GList *objs, /* non-UWP only */ + gboolean for_files, /* UWP only */ + IShellItemArray *items, /* UWP only */ GAppLaunchContext *launch_context, GSpawnFlags spawn_flags, GError **error) @@ -4071,66 +4729,53 @@ g_win32_app_info_launch_internal (GWin32AppInfo *info, gboolean completed = FALSE; char **argv, **envp; int argc; - gchar *command; + const gchar *command; gchar *apppath; - gunichar2 *exe_basename; + GWin32AppInfoShellVerb *shverb; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (info->app != NULL, FALSE); argv = NULL; + shverb = NULL; - if (launch_context) - envp = g_app_launch_context_get_environment (launch_context); - else - envp = g_get_environ (); - - command = NULL; - exe_basename = NULL; + if (!info->app->is_uwp && + info->handler != NULL && + info->handler->verbs->len > 0) + shverb = _verb_idx (info->handler->verbs, 0); + else if (info->app->verbs->len > 0) + shverb = _verb_idx (info->app->verbs, 0); - if (info->handler) + if (shverb == NULL) { - if (info->handler->handler_command) - { - command = g_utf16_to_utf8 (info->handler->handler_command, - -1, - NULL, - NULL, - NULL); - exe_basename = g_utf8_to_utf16 (info->handler->executable_basename, - -1, - NULL, - NULL, - NULL); - } - else if (info->handler->proxy_command) - { - command = g_utf16_to_utf8 (info->handler->proxy_command, - -1, - NULL, - NULL, - NULL); - exe_basename = g_utf8_to_utf16 (info->handler->executable_basename, - -1, - NULL, - NULL, - NULL); - } - } + if (info->app->is_uwp || info->handler == NULL) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + P_("The app ‘%s’ in the application object has no verbs"), + g_win32_appinfo_application_get_some_name (info->app)); + else if (info->handler->verbs->len == 0) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + P_("The app ‘%s’ and the handler ‘%s’ in the application object have no verbs"), + g_win32_appinfo_application_get_some_name (info->app), + info->handler->handler_id_folded); - if (command == NULL) - { - command = g_strdup (info->app->command_u8); - exe_basename = g_utf8_to_utf16 (info->app->executable_basename, - -1, - NULL, - NULL, - NULL); + return FALSE; } - apppath = get_appath_for_exe (exe_basename); + if (info->app->is_uwp) + return g_win32_app_info_launch_uwp_internal (info, + for_files, + items, + shverb, + error); + + if (launch_context) + envp = g_app_launch_context_get_environment (launch_context); + else + envp = g_get_environ (); - g_free (exe_basename); + g_assert (shverb->command_utf8 != NULL); + command = shverb->command_utf8; + apppath = get_appath_for_exe (shverb->executable_basename); if (apppath) { @@ -4220,7 +4865,6 @@ g_win32_app_info_launch_internal (GWin32AppInfo *info, out: g_strfreev (argv); g_strfreev (envp); - g_free (command); return completed; } @@ -4276,6 +4920,95 @@ g_win32_app_info_supports_files (GAppInfo *appinfo) } +static IShellItemArray * +make_item_array (gboolean for_files, + GList *files_or_uris, + GError **error) +{ + ITEMIDLIST **item_ids; + IShellItemArray *items; + GList *p; + gsize count; + gsize i; + HRESULT hr; + + count = g_list_length (files_or_uris); + + items = NULL; + item_ids = g_new (ITEMIDLIST*, count); + + for (i = 0, p = files_or_uris; p != NULL; p = p->next, i++) + { + wchar_t *file_or_uri_utf16; + + if (!for_files) + file_or_uri_utf16 = g_utf8_to_utf16 ((gchar *) p->data, -1, NULL, NULL, error); + else + file_or_uri_utf16 = g_utf8_to_utf16 (g_file_peek_path (G_FILE (p->data)), -1, NULL, NULL, error); + + if (file_or_uri_utf16 == NULL) + break; + + if (for_files) + { + wchar_t *c; + gsize len; + gsize len_tail; + + len = wcslen (file_or_uri_utf16); + /* Filenames *MUST* use single backslashes, else the call + * will fail. First convert all slashes to backslashes, + * then remove duplicates. + */ + for (c = file_or_uri_utf16; for_files && *c != 0; c++) + { + if (*c == L'/') + *c = L'\\'; + } + for (len_tail = 0, c = &file_or_uri_utf16[len - 1]; + for_files && c > file_or_uri_utf16; + c--, len_tail++) + { + if (c[0] != L'\\' || c[-1] != L'\\') + continue; + + memmove (&c[-1], &c[0], len_tail * sizeof (wchar_t)); + } + } + + hr = SHParseDisplayName (file_or_uri_utf16, NULL, &item_ids[i], 0, NULL); + g_free (file_or_uri_utf16); + + if (FAILED (hr)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "File or URI `%S' cannot be parsed by SHParseDisplayName: 0x%lx", file_or_uri_utf16, hr); + break; + } + } + + if (i == count) + { + hr = SHCreateShellItemArrayFromIDLists (count, (const ITEMIDLIST **) item_ids, &items); + if (FAILED (hr)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "SHCreateShellItemArrayFromIDLists() failed: 0x%lx", hr); + items = NULL; + } + } + + count = i; + + for (i = 0; i < count; i++) + CoTaskMemFree (item_ids[i]); + + g_free (item_ids); + + return items; +} + + static gboolean g_win32_app_info_launch_uris (GAppInfo *appinfo, GList *uris, @@ -4285,6 +5018,26 @@ g_win32_app_info_launch_uris (GAppInfo *appinfo, gboolean res = FALSE; gboolean do_files; GList *objs; + GWin32AppInfo *info = G_WIN32_APP_INFO (appinfo); + + if (info->app != NULL && info->app->is_uwp) + { + IShellItemArray *items = NULL; + + if (uris) + { + items = make_item_array (FALSE, uris, error); + if (items == NULL) + return res; + } + + res = g_win32_app_info_launch_internal (info, NULL, FALSE, items, launch_context, 0, error); + + if (items != NULL) + IShellItemArray_Release (items); + + return res; + } do_files = g_win32_app_info_supports_files (appinfo); @@ -4313,8 +5066,10 @@ g_win32_app_info_launch_uris (GAppInfo *appinfo, objs = g_list_reverse (objs); - res = g_win32_app_info_launch_internal (G_WIN32_APP_INFO (appinfo), + res = g_win32_app_info_launch_internal (info, objs, + FALSE, + NULL, launch_context, G_SPAWN_SEARCH_PATH, error); @@ -4333,6 +5088,26 @@ g_win32_app_info_launch (GAppInfo *appinfo, gboolean res = FALSE; gboolean do_uris; GList *objs; + GWin32AppInfo *info = G_WIN32_APP_INFO (appinfo); + + if (info->app != NULL && info->app->is_uwp) + { + IShellItemArray *items = NULL; + + if (files) + { + items = make_item_array (TRUE, files, error); + if (items == NULL) + return res; + } + + res = g_win32_app_info_launch_internal (info, NULL, TRUE, items, launch_context, 0, error); + + if (items != NULL) + IShellItemArray_Release (items); + + return res; + } do_uris = g_win32_app_info_supports_uris (appinfo); @@ -4352,8 +5127,10 @@ g_win32_app_info_launch (GAppInfo *appinfo, objs = g_list_reverse (objs); - res = g_win32_app_info_launch_internal (G_WIN32_APP_INFO (appinfo), + res = g_win32_app_info_launch_internal (info, objs, + TRUE, + NULL, launch_context, G_SPAWN_SEARCH_PATH, error); @@ -4379,13 +5156,22 @@ g_app_info_create_from_commandline (const char *commandline, { GWin32AppInfo *info; GWin32AppInfoApplication *app; + gunichar2 *app_command; g_return_val_if_fail (commandline, NULL); - info = g_object_new (G_TYPE_WIN32_APP_INFO, NULL); + app_command = g_utf8_to_utf16 (commandline, -1, NULL, NULL, NULL); + + if (app_command == NULL) + return NULL; + info = g_object_new (G_TYPE_WIN32_APP_INFO, NULL); app = g_object_new (G_TYPE_WIN32_APPINFO_APPLICATION, NULL); + app->no_open_with = FALSE; + app->user_specific = FALSE; + app->default_app = FALSE; + if (application_name) { app->canonical_name = g_utf8_to_utf16 (application_name, @@ -4397,19 +5183,16 @@ g_app_info_create_from_commandline (const char *commandline, app->canonical_name_folded = g_utf8_casefold (application_name, -1); } - app->command = g_utf8_to_utf16 (commandline, -1, NULL, NULL, NULL); - app->command_u8 = g_strdup (commandline); - - extract_executable (app->command, - &app->executable, - &app->executable_basename, - &app->executable_folded, - NULL); - - app->no_open_with = FALSE; - app->user_specific = FALSE; - app->default_app = FALSE; + app_add_verb (app, + app, + L"open", + app_command, + commandline, + "open", + TRUE, + FALSE); + g_clear_pointer (&app_command, g_free); info->app = app; info->handler = NULL; @@ -4449,9 +5232,10 @@ g_win32_app_info_iface_init (GAppInfoIface *iface) GAppInfo * g_app_info_get_default_for_uri_scheme (const char *uri_scheme) { - GWin32AppInfoURLSchema *scheme; + GWin32AppInfoURLSchema *scheme = NULL; char *scheme_down; GAppInfo *result; + GWin32AppInfoShellVerb *shverb; scheme_down = g_utf8_casefold (uri_scheme, -1); @@ -4461,30 +5245,28 @@ g_app_info_get_default_for_uri_scheme (const char *uri_scheme) if (strcmp (scheme_down, "file") == 0) { g_free (scheme_down); + return NULL; } - g_win32_appinfo_init (); - G_LOCK (gio_win32_appinfo); + gio_win32_appinfo_init (TRUE); + g_mutex_lock (&gio_win32_appinfo_mutex); - scheme = g_hash_table_lookup (urls, scheme_down); + g_set_object (&scheme, g_hash_table_lookup (urls, scheme_down)); g_free (scheme_down); - if (scheme) - g_object_ref (scheme); - - G_UNLOCK (gio_win32_appinfo); + g_mutex_unlock (&gio_win32_appinfo_mutex); result = NULL; if (scheme != NULL && scheme->chosen_handler != NULL && - scheme->chosen_handler->app != NULL) - result = g_win32_app_info_new_from_app (scheme->chosen_handler->app, + scheme->chosen_handler->verbs->len > 0 && + (shverb = _verb_idx (scheme->chosen_handler->verbs, 0))->app != NULL) + result = g_win32_app_info_new_from_app (shverb->app, scheme->chosen_handler); - if (scheme) - g_object_unref (scheme); + g_clear_object (&scheme); return result; } @@ -4493,72 +5275,61 @@ GAppInfo * g_app_info_get_default_for_type (const char *content_type, gboolean must_support_uris) { - GWin32AppInfoFileExtension *ext; + GWin32AppInfoFileExtension *ext = NULL; char *ext_down; - GWin32AppInfoHandler *handler; GAppInfo *result; - GWin32AppInfoApplication *app; - GHashTableIter iter; + GWin32AppInfoShellVerb *shverb; ext_down = g_utf8_casefold (content_type, -1); if (!ext_down) return NULL; - g_win32_appinfo_init (); - G_LOCK (gio_win32_appinfo); + gio_win32_appinfo_init (TRUE); + g_mutex_lock (&gio_win32_appinfo_mutex); /* Assuming that "content_type" is a file extension, not a MIME type */ - ext = g_hash_table_lookup (extensions, ext_down); + g_set_object (&ext, g_hash_table_lookup (extensions, ext_down)); g_free (ext_down); - result = NULL; + g_mutex_unlock (&gio_win32_appinfo_mutex); - if (ext != NULL) - g_object_ref (ext); + if (ext == NULL) + return NULL; - G_UNLOCK (gio_win32_appinfo); + result = NULL; - if (ext != NULL) + if (ext->chosen_handler != NULL && + ext->chosen_handler->verbs->len > 0 && + (shverb = _verb_idx (ext->chosen_handler->verbs, 0))->app != NULL && + (!must_support_uris || + g_win32_app_supports_uris (shverb->app))) + result = g_win32_app_info_new_from_app (shverb->app, + ext->chosen_handler); + else { - if (ext->chosen_handler != NULL && - ext->chosen_handler->app != NULL && - (!must_support_uris || - g_win32_app_supports_uris (ext->chosen_handler->app))) - result = g_win32_app_info_new_from_app (ext->chosen_handler->app, - ext->chosen_handler); - else + GHashTableIter iter; + GWin32AppInfoHandler *handler; + + g_hash_table_iter_init (&iter, ext->handlers); + + while (result == NULL && + g_hash_table_iter_next (&iter, NULL, (gpointer *) &handler)) { - g_hash_table_iter_init (&iter, ext->handlers); + if (handler->verbs->len == 0) + continue; - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &handler)) - { - if (handler->app && - (!must_support_uris || - g_win32_app_supports_uris (ext->chosen_handler->app))) - { - result = g_win32_app_info_new_from_app (handler->app, handler); - break; - } - } + shverb = _verb_idx (handler->verbs, 0); - if (result == NULL) - { - g_hash_table_iter_init (&iter, ext->other_apps); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app)) - { - if (!must_support_uris || - g_win32_app_supports_uris (ext->chosen_handler->app)) - { - result = g_win32_app_info_new_from_app (app, NULL); - break; - } - } - } + if (shverb->app && + (!must_support_uris || + g_win32_app_supports_uris (shverb->app))) + result = g_win32_app_info_new_from_app (shverb->app, handler); } - g_object_unref (ext); } + g_clear_object (&ext); + return result; } @@ -4571,15 +5342,15 @@ g_app_info_get_all (void) GList *apps; GList *apps_i; - g_win32_appinfo_init (); - G_LOCK (gio_win32_appinfo); + gio_win32_appinfo_init (TRUE); + g_mutex_lock (&gio_win32_appinfo_mutex); apps = NULL; g_hash_table_iter_init (&iter, apps_by_id); while (g_hash_table_iter_next (&iter, NULL, &value)) apps = g_list_prepend (apps, g_object_ref (G_OBJECT (value))); - G_UNLOCK (gio_win32_appinfo); + g_mutex_unlock (&gio_win32_appinfo_mutex); infos = NULL; for (apps_i = apps; apps_i; apps_i = apps_i->next) @@ -4594,62 +5365,69 @@ g_app_info_get_all (void) GList * g_app_info_get_all_for_type (const char *content_type) { - GWin32AppInfoFileExtension *ext; + GWin32AppInfoFileExtension *ext = NULL; char *ext_down; GWin32AppInfoHandler *handler; - GWin32AppInfoApplication *app; GHashTableIter iter; + GHashTable *apps = NULL; GList *result; + GWin32AppInfoShellVerb *shverb; ext_down = g_utf8_casefold (content_type, -1); if (!ext_down) return NULL; - g_win32_appinfo_init (); - G_LOCK (gio_win32_appinfo); + gio_win32_appinfo_init (TRUE); + g_mutex_lock (&gio_win32_appinfo_mutex); /* Assuming that "content_type" is a file extension, not a MIME type */ - ext = g_hash_table_lookup (extensions, ext_down); + g_set_object (&ext, g_hash_table_lookup (extensions, ext_down)); g_free (ext_down); - result = NULL; - - if (ext != NULL) - g_object_ref (ext); - - G_UNLOCK (gio_win32_appinfo); + g_mutex_unlock (&gio_win32_appinfo_mutex); if (ext == NULL) return NULL; + result = NULL; + /* Used as a set to ensure uniqueness */ + apps = g_hash_table_new (g_direct_hash, g_direct_equal); + if (ext->chosen_handler != NULL && - ext->chosen_handler->app != NULL) - result = g_list_prepend (result, - g_win32_app_info_new_from_app (ext->chosen_handler->app, - ext->chosen_handler)); + ext->chosen_handler->verbs->len > 0 && + (shverb = _verb_idx (ext->chosen_handler->verbs, 0))->app != NULL) + { + g_hash_table_add (apps, shverb->app); + result = g_list_prepend (result, + g_win32_app_info_new_from_app (shverb->app, + ext->chosen_handler)); + } g_hash_table_iter_init (&iter, ext->handlers); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &handler)) { - if (handler->app && - (ext->chosen_handler == NULL || ext->chosen_handler->app != handler->app)) - result = g_list_prepend (result, - g_win32_app_info_new_from_app (handler->app, - handler)); - } + gsize vi; - g_hash_table_iter_init (&iter, ext->other_apps); + for (vi = 0; vi < handler->verbs->len; vi++) + { + shverb = _verb_idx (handler->verbs, vi); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app)) - { - result = g_list_prepend (result, g_win32_app_info_new_from_app (app, NULL)); - } + if (shverb->app == NULL || + g_hash_table_contains (apps, shverb->app)) + continue; - g_object_unref (ext); + g_hash_table_add (apps, shverb->app); + result = g_list_prepend (result, + g_win32_app_info_new_from_app (shverb->app, + handler)); + } + } + g_clear_object (&ext); result = g_list_reverse (result); + g_hash_table_unref (apps); return result; } diff --git a/gio/gwin32file-sync-stream.c b/gio/gwin32file-sync-stream.c new file mode 100644 index 0000000000000000000000000000000000000000..bc3b6069444b30c15cf682bfa5b99d957466ed6c --- /dev/null +++ b/gio/gwin32file-sync-stream.c @@ -0,0 +1,508 @@ +/* gwin32file-sync-stream.c - a simple IStream implementation + * + * Copyright 2020 Руслан Ижбулатов + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +/* A COM object that implements an IStream backed by a file HANDLE. + * Works just like `SHCreateStreamOnFileEx()`, but does not + * support locking, and doesn't force us to link to libshlwapi. + * Only supports synchronous access. + */ +#include "config.h" +#define COBJMACROS +#define INITGUID +#include + +#include "gwin32file-sync-stream.h" + +static HRESULT STDMETHODCALLTYPE _file_sync_stream_query_interface (IStream *self_ptr, + REFIID ref_interface_guid, + LPVOID *output_object_ptr); +static ULONG STDMETHODCALLTYPE _file_sync_stream_release (IStream *self_ptr); +static ULONG STDMETHODCALLTYPE _file_sync_stream_add_ref (IStream *self_ptr); + +static HRESULT STDMETHODCALLTYPE _file_sync_stream_read (IStream *self_ptr, + void *output_data, + ULONG bytes_to_read, + ULONG *output_bytes_read); + +static HRESULT STDMETHODCALLTYPE _file_sync_stream_write (IStream *self_ptr, + const void *data, + ULONG bytes_to_write, + ULONG *output_bytes_written); + + +static HRESULT STDMETHODCALLTYPE _file_sync_stream_clone (IStream *self_ptr, + IStream **output_clone_ptr); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_commit (IStream *self_ptr, + DWORD commit_flags); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_copy_to (IStream *self_ptr, + IStream *output_stream, + ULARGE_INTEGER bytes_to_copy, + ULARGE_INTEGER *output_bytes_read, + ULARGE_INTEGER *output_bytes_written); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_lock_region (IStream *self_ptr, + ULARGE_INTEGER lock_offset, + ULARGE_INTEGER lock_bytes, + DWORD lock_type); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_revert (IStream *self_ptr); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_seek (IStream *self_ptr, + LARGE_INTEGER move_distance, + DWORD origin, + ULARGE_INTEGER *output_new_position); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_set_size (IStream *self_ptr, + ULARGE_INTEGER new_size); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_stat (IStream *self_ptr, + STATSTG *output_stat, + DWORD flags); +static HRESULT STDMETHODCALLTYPE _file_sync_stream_unlock_region (IStream *self_ptr, + ULARGE_INTEGER lock_offset, + ULARGE_INTEGER lock_bytes, + DWORD lock_type); + +static void _file_sync_stream_free (GWin32FileSyncStream *self); + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_query_interface (IStream *self_ptr, + REFIID ref_interface_guid, + LPVOID *output_object_ptr) +{ + *output_object_ptr = NULL; + + if (IsEqualGUID (ref_interface_guid, &IID_IUnknown)) + { + IUnknown_AddRef ((IUnknown *) self_ptr); + *output_object_ptr = self_ptr; + return S_OK; + } + else if (IsEqualGUID (ref_interface_guid, &IID_IStream)) + { + IStream_AddRef (self_ptr); + *output_object_ptr = self_ptr; + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE +_file_sync_stream_add_ref (IStream *self_ptr) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + + return ++self->ref_count; +} + +static ULONG STDMETHODCALLTYPE +_file_sync_stream_release (IStream *self_ptr) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + + int ref_count = --self->ref_count; + + if (ref_count == 0) + _file_sync_stream_free (self); + + return ref_count; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_read (IStream *self_ptr, + void *output_data, + ULONG bytes_to_read, + ULONG *output_bytes_read) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + DWORD bytes_read; + + if (!ReadFile (self->file_handle, output_data, bytes_to_read, &bytes_read, NULL)) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + if (output_bytes_read) + *output_bytes_read = bytes_read; + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_write (IStream *self_ptr, + const void *data, + ULONG bytes_to_write, + ULONG *output_bytes_written) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + DWORD bytes_written; + + if (!WriteFile (self->file_handle, data, bytes_to_write, &bytes_written, NULL)) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + if (output_bytes_written) + *output_bytes_written = bytes_written; + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_seek (IStream *self_ptr, + LARGE_INTEGER move_distance, + DWORD origin, + ULARGE_INTEGER *output_new_position) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + LARGE_INTEGER new_position; + DWORD move_method; + + switch (origin) + { + case STREAM_SEEK_SET: + move_method = FILE_BEGIN; + break; + case STREAM_SEEK_CUR: + move_method = FILE_CURRENT; + break; + case STREAM_SEEK_END: + move_method = FILE_END; + break; + default: + return E_INVALIDARG; + } + + if (!SetFilePointerEx (self->file_handle, move_distance, &new_position, move_method)) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + (*output_new_position).QuadPart = new_position.QuadPart; + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_set_size (IStream *self_ptr, + ULARGE_INTEGER new_size) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + FILE_END_OF_FILE_INFO info; + + info.EndOfFile.QuadPart = new_size.QuadPart; + + if (SetFileInformationByHandle (self->file_handle, FileEndOfFileInfo, &info, sizeof (info))) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_copy_to (IStream *self_ptr, + IStream *output_stream, + ULARGE_INTEGER bytes_to_copy, + ULARGE_INTEGER *output_bytes_read, + ULARGE_INTEGER *output_bytes_written) +{ + ULARGE_INTEGER counter; + ULARGE_INTEGER written_counter; + ULARGE_INTEGER read_counter; + + counter.QuadPart = bytes_to_copy.QuadPart; + written_counter.QuadPart = 0; + read_counter.QuadPart = 0; + + while (counter.QuadPart > 0) + { + HRESULT hr; + ULONG bytes_read; + ULONG bytes_written; + ULONG bytes_index; +#define _INTERNAL_BUFSIZE 1024 + BYTE buffer[_INTERNAL_BUFSIZE]; +#undef _INTERNAL_BUFSIZE + ULONG buffer_size = sizeof (buffer); + ULONG to_read = buffer_size; + + if (counter.QuadPart < buffer_size) + to_read = (ULONG) counter.QuadPart; + + /* Because MS SDK has a function IStream_Read() with 3 arguments */ + hr = self_ptr->lpVtbl->Read (self_ptr, buffer, to_read, &bytes_read); + if (!SUCCEEDED (hr)) + return hr; + + read_counter.QuadPart += bytes_read; + + if (bytes_read == 0) + break; + + bytes_index = 0; + + while (bytes_index < bytes_read) + { + /* Because MS SDK has a function IStream_Write() with 3 arguments */ + hr = output_stream->lpVtbl->Write (output_stream, &buffer[bytes_index], bytes_read - bytes_index, &bytes_written); + if (!SUCCEEDED (hr)) + return hr; + + if (bytes_written == 0) + return __HRESULT_FROM_WIN32 (ERROR_WRITE_FAULT); + + bytes_index += bytes_written; + written_counter.QuadPart += bytes_written; + } + } + + if (output_bytes_read) + output_bytes_read->QuadPart = read_counter.QuadPart; + if (output_bytes_written) + output_bytes_written->QuadPart = written_counter.QuadPart; + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_commit (IStream *self_ptr, + DWORD commit_flags) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + + if (!FlushFileBuffers (self->file_handle)) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_revert (IStream *self_ptr) +{ + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_lock_region (IStream *self_ptr, + ULARGE_INTEGER lock_offset, + ULARGE_INTEGER lock_bytes, + DWORD lock_type) +{ + return STG_E_INVALIDFUNCTION; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_unlock_region (IStream *self_ptr, + ULARGE_INTEGER lock_offset, + ULARGE_INTEGER lock_bytes, + DWORD lock_type) +{ + return STG_E_INVALIDFUNCTION; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_stat (IStream *self_ptr, + STATSTG *output_stat, + DWORD flags) +{ + GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr; + BOOL get_name = FALSE; + FILE_BASIC_INFO bi; + FILE_STANDARD_INFO si; + + if (output_stat == NULL) + return STG_E_INVALIDPOINTER; + + switch (flags) + { + case STATFLAG_DEFAULT: + get_name = TRUE; + break; + case STATFLAG_NONAME: + get_name = FALSE; + break; + default: + return STG_E_INVALIDFLAG; + } + + if (!GetFileInformationByHandleEx (self->file_handle, FileBasicInfo, &bi, sizeof (bi)) || + !GetFileInformationByHandleEx (self->file_handle, FileStandardInfo, &si, sizeof (si))) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + output_stat->type = STGTY_STREAM; + output_stat->mtime.dwLowDateTime = bi.LastWriteTime.LowPart; + output_stat->mtime.dwHighDateTime = bi.LastWriteTime.HighPart; + output_stat->ctime.dwLowDateTime = bi.CreationTime.LowPart; + output_stat->ctime.dwHighDateTime = bi.CreationTime.HighPart; + output_stat->atime.dwLowDateTime = bi.LastAccessTime.LowPart; + output_stat->atime.dwHighDateTime = bi.LastAccessTime.HighPart; + output_stat->grfLocksSupported = 0; + memset (&output_stat->clsid, 0, sizeof (CLSID)); + output_stat->grfStateBits = 0; + output_stat->reserved = 0; + output_stat->cbSize.QuadPart = si.EndOfFile.QuadPart; + output_stat->grfMode = self->stgm_mode; + + if (get_name) + { + DWORD tries; + wchar_t *buffer; + + /* Nothing in the documentation guarantees that the name + * won't change between two invocations (one - to get the + * buffer size, the other - to fill the buffer). + * Re-try up to 5 times in case the required buffer size + * doesn't match. + */ + for (tries = 5; tries > 0; tries--) + { + DWORD buffer_size; + DWORD buffer_size2; + DWORD error; + + buffer_size = GetFinalPathNameByHandleW (self->file_handle, NULL, 0, 0); + + if (buffer_size == 0) + { + DWORD error = GetLastError (); + return __HRESULT_FROM_WIN32 (error); + } + + buffer = CoTaskMemAlloc (buffer_size); + buffer[buffer_size - 1] = 0; + buffer_size2 = GetFinalPathNameByHandleW (self->file_handle, buffer, buffer_size, 0); + + if (buffer_size2 < buffer_size) + break; + + error = GetLastError (); + CoTaskMemFree (buffer); + if (buffer_size2 == 0) + return __HRESULT_FROM_WIN32 (error); + } + + if (tries == 0) + return __HRESULT_FROM_WIN32 (ERROR_BAD_LENGTH); + + output_stat->pwcsName = buffer; + } + else + output_stat->pwcsName = NULL; + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE +_file_sync_stream_clone (IStream *self_ptr, + IStream **output_clone_ptr) +{ + return E_NOTIMPL; +} + +static IStreamVtbl _file_sync_stream_vtbl = { + _file_sync_stream_query_interface, + _file_sync_stream_add_ref, + _file_sync_stream_release, + _file_sync_stream_read, + _file_sync_stream_write, + _file_sync_stream_seek, + _file_sync_stream_set_size, + _file_sync_stream_copy_to, + _file_sync_stream_commit, + _file_sync_stream_revert, + _file_sync_stream_lock_region, + _file_sync_stream_unlock_region, + _file_sync_stream_stat, + _file_sync_stream_clone, +}; + +static void +_file_sync_stream_free (GWin32FileSyncStream *self) +{ + if (self->owns_handle) + CloseHandle (self->file_handle); + + g_free (self); +} + +/** + * g_win32_file_sync_stream_new: + * @handle: a Win32 HANDLE for a file. + * @owns_handle: %TRUE if newly-created stream owns the handle + * (and closes it when destroyed) + * @stgm_mode: a combination of [STGM constants](https://docs.microsoft.com/en-us/windows/win32/stg/stgm-constants) + * that specify the mode with which the stream + * is opened. + * @output_hresult: (out) (optional): a HRESULT from the internal COM calls. + * Will be `S_OK` on success. + * + * Creates an IStream object backed by a HANDLE. + * + * @stgm_mode should match the mode of the @handle, otherwise the stream might + * attempt to perform operations that the @handle does not allow. The implementation + * itself ignores these flags completely, they are only used to report + * the mode of the stream to third parties. + * + * The stream only does synchronous access and will never return `E_PENDING` on I/O. + * + * The returned stream object should be treated just like any other + * COM object, and released via `IUnknown_Release()`. + * its elements have been unreffed with g_object_unref(). + * + * Returns: (nullable) (transfer full): a new IStream object on success, %NULL on failure. + **/ +IStream * +g_win32_file_sync_stream_new (HANDLE file_handle, + gboolean owns_handle, + DWORD stgm_mode, + HRESULT *output_hresult) +{ + GWin32FileSyncStream *new_stream; + IStream *result; + HRESULT hr; + + new_stream = g_new0 (GWin32FileSyncStream, 1); + new_stream->self.lpVtbl = &_file_sync_stream_vtbl; + + hr = IUnknown_QueryInterface ((IUnknown *) new_stream, &IID_IStream, (void **) &result); + if (!SUCCEEDED (hr)) + { + g_free (new_stream); + + if (output_hresult) + *output_hresult = hr; + + return NULL; + } + + new_stream->stgm_mode = stgm_mode; + new_stream->file_handle = file_handle; + new_stream->owns_handle = owns_handle; + + if (output_hresult) + *output_hresult = S_OK; + + return result; +} diff --git a/gio/gio-launch-desktop.c b/gio/gwin32file-sync-stream.h similarity index 47% rename from gio/gio-launch-desktop.c rename to gio/gwin32file-sync-stream.h index 03845df28d9a3766931b94e223db928a232f3769..8e7f5fd59268053bc7b547b68d0e1a5fc7205a15 100644 --- a/gio/gio-launch-desktop.c +++ b/gio/gwin32file-sync-stream.h @@ -1,6 +1,6 @@ /* GIO - GLib Input, Output and Streaming Library * - * Copyright (C) 2018 Endless Mobile, Inc. + * Copyright (C) 2020 Руслан Ижбулатов * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -15,38 +15,30 @@ * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, see . * - * Author: Daniel Drake */ +#ifndef __G_WIN32_FILE_SYNC_STREAM_H__ +#define __G_WIN32_FILE_SYNC_STREAM_H__ -/* - * gio-launch-desktop: GDesktopAppInfo helper - * Executable wrapper to set GIO_LAUNCHED_DESKTOP_FILE_PID - * There are complications when doing this in a fork()/exec() codepath, - * and it cannot otherwise be done with posix_spawn(). - * This wrapper is designed to be minimal and lightweight. - * It does not even link against glib. - */ +#include -#include -#include -#include -#include +#ifdef G_PLATFORM_WIN32 -int -main (int argc, char *argv[]) -{ - pid_t pid = getpid (); - char buf[50]; - int r; +typedef struct _GWin32FileSyncStream GWin32FileSyncStream; - if (argc < 2) - return -1; +struct _GWin32FileSyncStream +{ + IStream self; + ULONG ref_count; + HANDLE file_handle; + gboolean owns_handle; + DWORD stgm_mode; +}; - r = snprintf (buf, sizeof (buf), "GIO_LAUNCHED_DESKTOP_FILE_PID=%ld", (long) pid); - if (r >= sizeof (buf)) - return -1; +IStream *g_win32_file_sync_stream_new (HANDLE file_handle, + gboolean owns_handle, + DWORD stgm_mode, + HRESULT *output_hresult); - putenv (buf); +#endif /* G_PLATFORM_WIN32 */ - return execvp (argv[1], argv + 1); -} +#endif /* __G_WIN32_FILE_SYNC_STREAM_H__ */ \ No newline at end of file diff --git a/gio/gwin32mount.c b/gio/gwin32mount.c index 5b4847a9d769cb2d881cf0ec067ec3b66776f86c..83d8695a1b4411d0f4c31b6986f9b42726cf88dd 100644 --- a/gio/gwin32mount.c +++ b/gio/gwin32mount.c @@ -131,6 +131,9 @@ _g_win32_mount_new (GVolumeMonitor *volume_monitor, { GWin32Mount *mount; const gchar *drive = path; //fixme + WCHAR *drive_utf16; + + drive_utf16 = g_utf8_to_utf16 (drive, -1, NULL, NULL, NULL); #if 0 /* No volume for mount: Ignore internal things */ @@ -141,7 +144,7 @@ _g_win32_mount_new (GVolumeMonitor *volume_monitor, mount = g_object_new (G_TYPE_WIN32_MOUNT, NULL); mount->volume_monitor = volume_monitor != NULL ? g_object_ref (volume_monitor) : NULL; mount->mount_path = g_strdup (path); - mount->drive_type = GetDriveType (drive); + mount->drive_type = GetDriveTypeW (drive_utf16); mount->can_eject = FALSE; /* TODO */ mount->name = _win32_get_displayname (drive); @@ -151,6 +154,9 @@ _g_win32_mount_new (GVolumeMonitor *volume_monitor, if (volume != NULL) _g_win32_volume_set_mount (volume, mount); #endif + + g_free (drive_utf16); + return mount; } diff --git a/gio/gwin32packageparser.c b/gio/gwin32packageparser.c new file mode 100644 index 0000000000000000000000000000000000000000..ad530227020bd4fe158cafbed142d6644686af42 --- /dev/null +++ b/gio/gwin32packageparser.c @@ -0,0 +1,818 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2020 Руслан Ижбулатов + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + */ + +/* Queries the system (Windows 8 or newer) for the list + * of UWP packages, parses their manifests and invokes + * a user-provided callback with the needed application + * info. + */ + +#include "config.h" + +#define COBJMACROS +#define INITGUID +#include +#include +#include +#include +#include + +#include "gwin32api-storage.h" +#include "gwin32api-misc.h" +#include "gwin32api-iterator.h" +#include "gwin32api-package.h" + +#include + +#include + +#include "gwin32file-sync-stream.h" +#include "gwin32packageparser.h" + +#ifdef G_WINAPI_ONLY_APP +#define LoadedRoActivateInstance RoActivateInstance +#define LoadedWindowsCreateStringReference WindowsCreateStringReference +#define LoadedWindowsDeleteString WindowsDeleteString +#define sax_WindowsGetStringRawBuffer WindowsGetStringRawBuffer +#define LoadedWindowsGetStringRawBuffer WindowsGetStringRawBuffer +#define sax_CreateXmlReader CreateXmlReader +#else +typedef HRESULT (WINAPI *RoActivateInstance_func)(HSTRING activatableClassId, IInspectable **instance); +typedef HRESULT (WINAPI *WindowsCreateStringReference_func)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string); +typedef HRESULT (WINAPI *WindowsDeleteString_func)(HSTRING string); +typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_func)(HSTRING string, UINT32 *length); +typedef HRESULT (STDAPICALLTYPE *CreateXmlReader_func)(REFIID riid, void **ppvObject, IMalloc *pMalloc); +#define sax_WindowsGetStringRawBuffer sax->WindowsGetStringRawBuffer +#define sax_CreateXmlReader sax->CreateXmlReader +#endif + +static gsize +g_utf16_len (const gunichar2 *str) +{ + gsize result; + + for (result = 0; str[0] != 0; str++, result++) + ; + + return result; +} + +static gunichar2 * +g_wcsdup (const gunichar2 *str, gssize str_len) +{ + gsize str_len_unsigned; + gsize str_size; + + g_return_val_if_fail (str != NULL, NULL); + + if (str_len < 0) + str_len_unsigned = g_utf16_len (str); + else + str_len_unsigned = (gsize) str_len; + + g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); + str_size = (str_len_unsigned + 1) * sizeof (gunichar2); + + return g_memdup2 (str, str_size); +} + +static BOOL +WIN32_FROM_HRESULT (HRESULT hresult, + DWORD *win32_error_code) +{ + if ((hresult & 0xFFFF0000) == MAKE_HRESULT (SEVERITY_ERROR, FACILITY_WIN32, 0) || + hresult == S_OK) + { + *win32_error_code = HRESULT_CODE (hresult); + return TRUE; + } + + return FALSE; +} + +static GIOErrorEnum +gio_error_from_hresult (HRESULT hresult) +{ + DWORD error; + + if (WIN32_FROM_HRESULT (hresult, &error)) + return g_io_error_from_errno (error); + + return G_IO_ERROR_FAILED; +} + +static void +free_extgroup (GWin32PackageExtGroup *g) +{ + g_ptr_array_unref (g->verbs); + g_ptr_array_unref (g->extensions); + g_free (g); +} + +struct _xml_sax_state +{ +#ifndef G_WINAPI_ONLY_APP + WindowsGetStringRawBuffer_func WindowsGetStringRawBuffer; + CreateXmlReader_func CreateXmlReader; +#endif + + GWin32PackageParserCallback callback; + gpointer user_data; + + const wchar_t *manifest_filename; + gsize package_index; + const wchar_t *wcs_full_name; + const wchar_t *wcs_name; + HSTRING package_family; + + gboolean applist; + gboolean exit_early; + + UINT64 in_package; + UINT64 in_applications; + UINT64 in_application; + UINT64 in_extensions; + UINT64 in_extension_protocol; + UINT64 in_extension_fta; + UINT64 in_fta_group; + UINT64 in_sfp; + UINT64 in_filetype; + UINT64 in_sv; + GPtrArray *supported_extensions; + GPtrArray *supported_protocols; + GPtrArray *supported_verbs; + GPtrArray *supported_extgroups; + wchar_t *application_usermodelid; +}; + +static gboolean parse_manifest_file (struct _xml_sax_state *sax); +static gboolean xml_parser_iteration (struct _xml_sax_state *sax, + IXmlReader *xml_reader); +static gboolean xml_parser_get_current_state (struct _xml_sax_state *sax, + IXmlReader *xml_reader, + const wchar_t **local_name, + const wchar_t **prefix, + const wchar_t **value); + +gboolean +g_win32_package_parser_enum_packages (GWin32PackageParserCallback callback, + gpointer user_data, + GError **error) +{ + gboolean result = TRUE; + HRESULT hr; + HSTRING packagemanager_name = NULL; + HSTRING_HEADER packageanager_name_header; + const wchar_t *packman_id = L"Windows.Management.Deployment.PackageManager"; + IInspectable *ii_pm = NULL; + IPackageManager *pm = NULL; + IIterable *packages_iterable = NULL; + IIterator *packages_iterator = NULL; + CHAR has_current; + gsize package_index; + const wchar_t *bslash_appmanifest = L"\\AppxManifest.xml"; + struct _xml_sax_state sax_stack; + struct _xml_sax_state *sax = &sax_stack; + +#ifndef G_WINAPI_ONLY_APP + HMODULE xmllite = NULL; + HMODULE combase = NULL; + HMODULE winrt = NULL; + RoActivateInstance_func LoadedRoActivateInstance; + WindowsCreateStringReference_func LoadedWindowsCreateStringReference; + WindowsDeleteString_func LoadedWindowsDeleteString; + WindowsGetStringRawBuffer_func LoadedWindowsGetStringRawBuffer; + CreateXmlReader_func LoadedCreateXmlReader; + + winrt = LoadLibraryW (L"api-ms-win-core-winrt-l1-1-0.dll"); + if (winrt == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "Failed to load api-ms-win-core-winrt-l1-1-0.dll"); + goto cleanup; + } + + combase = LoadLibraryW (L"combase.dll"); + if (combase == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "Failed to load combase.dll"); + goto cleanup; + } + + xmllite = LoadLibraryW (L"xmllite.dll"); + if (xmllite == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "Failed to load xmllite.dll"); + goto cleanup; + } + + LoadedCreateXmlReader = (CreateXmlReader_func) GetProcAddress (xmllite, "CreateXmlReader"); + if (LoadedCreateXmlReader == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "CreateXmlReader entry point is not found in xmllite.dll"); + goto cleanup; + } + + LoadedRoActivateInstance = (RoActivateInstance_func) GetProcAddress (winrt, "RoActivateInstance"); + if (LoadedRoActivateInstance == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "RoActivateInstance entry point is not found in api-ms-win-core-winrt-l1-1-0.dll"); + goto cleanup; + } + + LoadedWindowsCreateStringReference = (WindowsCreateStringReference_func) GetProcAddress (combase, "WindowsCreateStringReference"); + if (LoadedWindowsCreateStringReference == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "WindowsCreateStringReference entry point is not found in combase.dll"); + goto cleanup; + } + + LoadedWindowsDeleteString = (WindowsDeleteString_func) GetProcAddress (combase, "WindowsDeleteString"); + if (LoadedWindowsDeleteString == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "WindowsDeleteString entry point is not found in combase.dll"); + goto cleanup; + } + + LoadedWindowsGetStringRawBuffer = (WindowsGetStringRawBuffer_func) GetProcAddress (combase, "WindowsGetStringRawBuffer"); + if (LoadedWindowsGetStringRawBuffer == NULL) + { + result = FALSE; + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()), + "WindowsGetStringRawBuffer entry point is not found in combase.dll"); + goto cleanup; + } +#endif + + /* This essentially locks current GLib thread into apartment COM model. */ + hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); + /* Can return S_FALSE if COM is already initialized, + * which is not an error, and we still need to uninitialize after that. + */ + if (hr != S_OK && hr != S_FALSE) + { + result = FALSE; + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, + "CoInitializeEx(COINIT_APARTMENTTHREADED) failed with code 0x%lx", hr); + goto cleanup; + } + +#define canned_com_error_handler(function_name_literal, where_to_go) \ + do \ + { \ + if (FAILED (hr)) \ + { \ + result = FALSE; \ + g_set_error (error, G_IO_ERROR, gio_error_from_hresult (hr), \ + function_name_literal " failed with code 0x%lx", hr); \ + goto where_to_go; \ + } \ + } while (0) + + hr = LoadedWindowsCreateStringReference (packman_id, wcslen (packman_id), &packageanager_name_header, &packagemanager_name); + canned_com_error_handler ("WindowsCreateStringReference()", cleanup); + + hr = LoadedRoActivateInstance (packagemanager_name, &ii_pm); + canned_com_error_handler ("RoActivateInstance()", cleanup); + + hr = IInspectable_QueryInterface (ii_pm, &IID_IPackageManager, (void**) &pm); + canned_com_error_handler ("IInspectable_QueryInterface()", cleanup); + + hr = IPackageManager_FindPackagesByUserSecurityId (pm, 0, &packages_iterable); + canned_com_error_handler ("IPackageManager_FindPackagesByUserSecurityId()", cleanup); + + hr = IIterable_First (packages_iterable, &packages_iterator); + canned_com_error_handler ("IIterable_First()", cleanup); + + hr = IIterator_get_HasCurrent (packages_iterator, &has_current); + canned_com_error_handler ("IIterator_get_HasCurrent()", cleanup); + + for (package_index = 0; SUCCEEDED (hr) && has_current; package_index++) + { + IUnknown *item = NULL; + IPackage *ipackage = NULL; + IPackageId *ipackageid = NULL; + IUnknown *package_install_location = NULL; + IStorageItem *storage_item = NULL; + HSTRING path = NULL; + HSTRING name = NULL; + HSTRING full_name = NULL; + HSTRING package_family = NULL; + size_t manifest_filename_size; + const wchar_t *wcs_path; + const wchar_t *wcs_full_name; + const wchar_t *wcs_name; + wchar_t *manifest_filename = NULL; + +#define canned_com_error_handler_pkg(function_name_literal, where_to_go) \ + do \ + { \ + if (FAILED (hr)) \ + { \ + result = FALSE; \ + g_set_error (error, G_IO_ERROR, gio_error_from_hresult (hr), \ + function_name_literal " for package #%zu failed with code 0x%lx", package_index, hr); \ + goto where_to_go; \ + } \ + } while (0) + + hr = IIterator_get_Current (packages_iterator, &item); + canned_com_error_handler_pkg ("IIterator_get_Current()", package_cleanup); + + hr = IUnknown_QueryInterface (item, &IID_IPackage, (void **) &ipackage); + canned_com_error_handler_pkg ("IUnknown_QueryInterface(IID_IPackage)", package_cleanup); + + hr = IPackage_get_Id (ipackage, &ipackageid); + canned_com_error_handler_pkg ("IPackage_get_Id()", package_cleanup); + + hr = IPackageId_get_FullName (ipackageid, &full_name); + canned_com_error_handler_pkg ("IPackageId_get_FullName()", package_cleanup); + + hr = IPackageId_get_Name (ipackageid, &name); + canned_com_error_handler_pkg ("IPackageId_get_Name()", package_cleanup); + + wcs_full_name = LoadedWindowsGetStringRawBuffer (full_name, NULL); + wcs_name = LoadedWindowsGetStringRawBuffer (name, NULL); + +#define canned_com_error_handler_pkg_named(function_name_literal, where_to_go) \ + do \ + { \ + if (FAILED (hr)) \ + { \ + result = FALSE; \ + g_set_error (error, G_IO_ERROR, gio_error_from_hresult (hr), \ + function_name_literal " for package #%zu (`%S') failed with code 0x%lx", package_index, wcs_full_name, hr); \ + goto where_to_go; \ + } \ + } while (0) + + hr = IPackage_get_InstalledLocation (ipackage, &package_install_location); + canned_com_error_handler_pkg_named ("IPackage_get_InstalledLocation()", package_cleanup); + + hr = IUnknown_QueryInterface (package_install_location, &IID_IStorageItem, (void **) &storage_item); + canned_com_error_handler_pkg_named ("IUnknown_QueryInterface(IID_IStorageItem)", package_cleanup); + + hr = IPackageId_get_FamilyName (ipackageid, &package_family); + canned_com_error_handler_pkg_named ("IPackageId_get_FamilyName()", package_cleanup); + + hr = IStorageItem_get_Path (storage_item, &path); + canned_com_error_handler_pkg_named ("IStorageItem_get_Path()", package_cleanup); + + wcs_path = LoadedWindowsGetStringRawBuffer (path, NULL); + manifest_filename_size = wcslen (wcs_path) + wcslen (bslash_appmanifest); + manifest_filename = g_new (wchar_t, manifest_filename_size + 1); + memcpy (manifest_filename, wcs_path, manifest_filename_size * sizeof (wchar_t)); + memcpy (&manifest_filename[wcslen (wcs_path)], bslash_appmanifest, (wcslen (bslash_appmanifest) + 1) * sizeof (wchar_t)); + + memset (sax, 0, sizeof (*sax)); + sax->callback = callback; + sax->user_data = user_data; + sax->manifest_filename = manifest_filename; + sax->package_index = package_index; + sax->wcs_full_name = wcs_full_name; + sax->wcs_name = wcs_name; + sax->package_family = package_family; + sax->applist = TRUE; + sax->exit_early = FALSE; +#ifndef G_WINAPI_ONLY_APP + sax->CreateXmlReader = LoadedCreateXmlReader; + sax->WindowsGetStringRawBuffer = LoadedWindowsGetStringRawBuffer; +#endif + /* Result isn't checked. If we fail to parse the manifest, + * just try the next package, no need to bail out. + */ + parse_manifest_file (sax); + + hr = IIterator_MoveNext (packages_iterator, &has_current); + canned_com_error_handler_pkg_named ("IIterator_MoveNext()", package_cleanup); + +#undef canned_com_error_handler_pkg_named +#undef canned_com_error_handler_pkg +#undef canned_com_error_handler + + package_cleanup: + g_clear_pointer (&manifest_filename, g_free); + + if (path) + LoadedWindowsDeleteString (path); + if (storage_item) + (void) IStorageItem_Release (storage_item); + if (package_install_location) + (void) IUnknown_Release (package_install_location); + if (ipackage) + (void) IPackage_Release (ipackage); + if (item) + (void) IUnknown_Release (item); + + if (package_family) + LoadedWindowsDeleteString (package_family); + if (name) + LoadedWindowsDeleteString (name); + if (full_name) + LoadedWindowsDeleteString (full_name); + + if (ipackageid) + (void) IPackageId_Release (ipackageid); + if (sax->exit_early) + break; + } + + cleanup: + if (packages_iterator) + (void) IIterator_Release (packages_iterator); + if (packages_iterable) + (void) IIterable_Release (packages_iterable); + if (pm) + (void) IPackageManager_Release (pm); + if (ii_pm) + (void) IInspectable_Release (ii_pm); + + CoUninitialize (); + +#ifndef G_WINAPI_ONLY_APP + if (xmllite) + (void) FreeLibrary (xmllite); + if (combase) + (void) FreeLibrary (combase); + if (winrt) + (void) FreeLibrary (winrt); +#endif + + return result; +} + +static gboolean +parse_manifest_file (struct _xml_sax_state *sax) +{ + HRESULT hr; + HANDLE file_handle = INVALID_HANDLE_VALUE; + IStream *file_stream = NULL; + gboolean result; + IXmlReader *xml_reader; + + file_handle = CreateFileW (sax->manifest_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_handle == INVALID_HANDLE_VALUE) + { + g_warning ("Failed to open application manifest `%S' for package #%zu (`%S'): error code 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, GetLastError ()); + return FALSE; + } + + file_stream = g_win32_file_sync_stream_new (file_handle, TRUE, STGM_READ | STGM_SHARE_DENY_WRITE, &hr); + if (file_stream == NULL) + { + g_warning ("Failed to create an IStream for application manifest `%S' for package #%zu (`%S'): HRESULT 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr); + CloseHandle (file_handle); + return FALSE; + } + + /* file_stream owns it now */ + file_handle = NULL; + + hr = sax_CreateXmlReader (&IID_IXmlReader, (void **) &xml_reader, NULL); + /* Slightly incorrect - xml reader is not created for any particular file, + * in theory we could re-use the same xml reader instance for all files. + */ + if (FAILED (hr)) + { + g_warning ("CreateXmlReader() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr); + (void) IStream_Release (file_stream); + return FALSE; + } + + hr = IXmlReader_SetInput (xml_reader, (IUnknown *) file_stream); + if (FAILED (hr)) + { + g_warning ("IXmlReader_SetInput() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr); + (void) IXmlReader_Release (xml_reader); + (void) IStream_Release (file_stream); + return FALSE; + } + + sax->supported_extensions = g_ptr_array_new_full (0, (GDestroyNotify) g_free); + sax->supported_protocols = g_ptr_array_new_full (0, (GDestroyNotify) g_free); + sax->supported_verbs = g_ptr_array_new_full (0, (GDestroyNotify) g_free); + sax->supported_extgroups = g_ptr_array_new_full (0, (GDestroyNotify) free_extgroup); + + result = TRUE; + + while (!sax->exit_early && result && !IXmlReader_IsEOF (xml_reader)) + result = xml_parser_iteration (sax, xml_reader); + + g_clear_pointer (&sax->application_usermodelid, g_free); + g_clear_pointer (&sax->supported_extensions, g_ptr_array_unref); + g_clear_pointer (&sax->supported_verbs, g_ptr_array_unref); + g_clear_pointer (&sax->supported_extgroups, g_ptr_array_unref); + g_clear_pointer (&sax->supported_protocols, g_ptr_array_unref); + + (void) IXmlReader_Release (xml_reader); + (void) IStream_Release (file_stream); + + return result; +} + +static gboolean +xml_parser_get_current_state (struct _xml_sax_state *sax, + IXmlReader *xml_reader, + const wchar_t **local_name, + const wchar_t **prefix, + const wchar_t **value) +{ + HRESULT hr; + UINT xml_line_number; + UINT xml_line_position; + + hr = IXmlReader_GetLineNumber (xml_reader, &xml_line_number); + if (FAILED (hr)) + { + g_warning ("IXmlReader_GetLineNumber() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr); + return FALSE; + } + + hr = IXmlReader_GetLinePosition (xml_reader, &xml_line_position); + if (FAILED (hr)) + { + g_warning ("IXmlReader_GetLinePosition() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr); + return FALSE; + } + + hr = IXmlReader_GetLocalName (xml_reader, local_name, NULL); + if (FAILED (hr)) + { + g_warning ("IXmlReader_GetLocalName() for application manifest `%S':%u (column %u) for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, xml_line_number, xml_line_position, sax->package_index, sax->wcs_full_name, hr); + return FALSE; + } + + hr = IXmlReader_GetPrefix (xml_reader, prefix, NULL); + if (FAILED (hr)) + { + g_warning ("IXmlReader_GetPrefix() for application manifest `%S':%u (column %u) for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, xml_line_number, xml_line_position, sax->package_index, sax->wcs_full_name, hr); + return FALSE; + } + + hr = IXmlReader_GetValue (xml_reader, value, NULL); + if (FAILED (hr)) + { + g_warning ("IXmlReader_GetValue() for application manifest `%S':%u (column %u) for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, xml_line_number, xml_line_position, sax->package_index, sax->wcs_full_name, hr); + return FALSE; + } + + return TRUE; +} + +static gboolean +xml_parser_iteration (struct _xml_sax_state *sax, + IXmlReader *xml_reader) +{ + HRESULT hr; + XmlNodeType xml_node_type; + const wchar_t *local_name; + const wchar_t *prefix; + const wchar_t *value; + BOOL is_visual_elements = FALSE; + BOOL is_extension = FALSE; + BOOL is_protocol = FALSE; + BOOL is_empty; + BOOL is_application = FALSE; + BOOL is_verb = FALSE; + + hr = IXmlReader_Read (xml_reader, &xml_node_type); + if (FAILED (hr)) + { + g_warning ("IXmlReader_Read() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx", + sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr); + return FALSE; + } + + if (!xml_parser_get_current_state (sax, xml_reader, &local_name, &prefix, &value)) + return FALSE; + + switch (xml_node_type) + { + case XmlNodeType_Element: + is_empty = IXmlReader_IsEmptyElement (xml_reader); + g_assert (local_name != NULL); + + if (!is_empty && + _wcsicmp (local_name, L"Package") == 0 && + prefix[0] == 0) + sax->in_package += 1; + else if (!is_empty && + sax->in_package == 1 && + _wcsicmp (local_name, L"Applications") == 0 && + prefix[0] == 0) + sax->in_applications += 1; + else if (!is_empty && + sax->in_applications == 1 && + _wcsicmp (local_name, L"Application") == 0 && + prefix[0] == 0) + { + sax->in_application += 1; + is_application = TRUE; + sax->applist = TRUE; + g_clear_pointer (&sax->application_usermodelid, g_free); + } + else if (sax->in_application == 1 && + _wcsicmp (local_name, L"VisualElements") == 0 && + (_wcsicmp (prefix, L"uap") == 0 || _wcsicmp (prefix, L"uap3") == 0)) + is_visual_elements = TRUE; + else if (!is_empty && + sax->in_application == 1 && + _wcsicmp (local_name, L"Extensions") == 0 && + prefix[0] == 0) + sax->in_extensions += 1; + else if (!is_empty && + sax->in_application == 1 && + _wcsicmp (local_name, L"Extension") == 0 && + _wcsicmp (prefix, L"uap") == 0) + is_extension = TRUE; + else if (sax->in_extension_protocol == 1 && + _wcsicmp (local_name, L"Protocol") == 0 && + _wcsicmp (prefix, L"uap") == 0) + is_protocol = TRUE; + else if (!is_empty && + sax->in_extension_fta == 1 && + _wcsicmp (local_name, L"FileTypeAssociation") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_fta_group += 1; + else if (!is_empty && + sax->in_fta_group == 1 && + _wcsicmp (local_name, L"SupportedFileTypes") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_sfp += 1; + else if (!is_empty && + sax->in_fta_group == 1 && + _wcsicmp (local_name, L"SupportedVerbs") == 0 && + _wcsicmp (prefix, L"uap2") == 0) + sax->in_sv += 1; + else if (!is_empty && + sax->in_sfp == 1 && + _wcsicmp (local_name, L"FileType") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_filetype += 1; + else if (!is_empty && + sax->in_sv == 1 && + _wcsicmp (local_name, L"Verb") == 0 && + _wcsicmp (prefix, L"uap3") == 0) + is_verb = TRUE; + + hr = IXmlReader_MoveToFirstAttribute (xml_reader); + while (hr == S_OK) + { + if (!xml_parser_get_current_state (sax, xml_reader, &local_name, &prefix, &value)) + return FALSE; + + g_assert (local_name != NULL); + g_assert (value != NULL); + g_assert (prefix != NULL); + + if (is_application && + sax->application_usermodelid == NULL && + _wcsicmp (local_name, L"Id") == 0) + { + size_t id_len = 0; + size_t value_len = wcslen (value); + const wchar_t *wcs_package_family; + size_t wcs_package_family_len; + + wcs_package_family = sax_WindowsGetStringRawBuffer (sax->package_family, NULL); + wcs_package_family_len = wcslen (wcs_package_family); + id_len += wcs_package_family_len + 1 + value_len; + sax->application_usermodelid = g_new (wchar_t, id_len + 1); + /* AppUserModelId = ! */ + memcpy (&sax->application_usermodelid[0], wcs_package_family, wcs_package_family_len * sizeof (wchar_t)); + memcpy (&sax->application_usermodelid[wcs_package_family_len], L"!", sizeof (wchar_t)); + memcpy (&sax->application_usermodelid[wcs_package_family_len + 1], value, (value_len + 1) * sizeof (wchar_t)); + } + else if (is_visual_elements && + _wcsicmp (local_name, L"AppListEntry") == 0 && + _wcsicmp (value, L"none") == 0) + sax->applist = FALSE; + else if (is_extension && + _wcsicmp (local_name, L"Category") == 0 && + _wcsicmp (value, L"windows.protocol") == 0) + sax->in_extension_protocol += 1; + else if (is_extension && + _wcsicmp (local_name, L"Category") == 0 && + _wcsicmp (value, L"windows.fileTypeAssociation") == 0) + sax->in_extension_fta += 1; + else if (is_protocol && + _wcsicmp (local_name, L"Name") == 0) + g_ptr_array_add (sax->supported_protocols, g_wcsdup (value, -1)); + else if (is_verb && + _wcsicmp (local_name, L"Id") == 0) + g_ptr_array_add (sax->supported_verbs, g_wcsdup (value, -1)); + + hr = IXmlReader_MoveToNextAttribute (xml_reader); + } + break; + case XmlNodeType_Text: + g_assert (value != NULL); + + if (sax->in_filetype && value[0] != 0) + g_ptr_array_add (sax->supported_extensions, g_wcsdup (value, -1)); + break; + case XmlNodeType_EndElement: + g_assert (local_name != NULL); + + if (_wcsicmp (local_name, L"Package") == 0 && + prefix[0] == 0) + sax->in_package -= 1; + else if (sax->in_package == 1 && + _wcsicmp (local_name, L"Applications") == 0 && + prefix[0] == 0) + sax->in_applications -= 1; + else if (sax->in_application == 1 && + _wcsicmp (local_name, L"Extensions") == 0 && + prefix[0] == 0) + sax->in_extensions -= 1; + else if (sax->in_extension_protocol == 1 && + _wcsicmp (local_name, L"Extension") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_extension_protocol -= 1; + else if (sax->in_extension_fta == 1 && + _wcsicmp (local_name, L"Extension") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_extension_fta -= 1; + else if (sax->in_fta_group == 1 && + _wcsicmp (local_name, L"SupportedFileTypes") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_sfp -= 1; + else if (sax->in_sfp == 1 && + _wcsicmp (local_name, L"FileType") == 0 && + _wcsicmp (prefix, L"uap") == 0) + sax->in_filetype -= 1; + else if (sax->in_fta_group == 1 && + _wcsicmp (local_name, L"SupportedVerbs") == 0 && + _wcsicmp (prefix, L"uap2") == 0) + sax->in_sv -= 1; + else if (sax->in_applications == 1 && + _wcsicmp (local_name, L"Application") == 0 && + prefix[0] == 0) + { + if (sax->application_usermodelid != NULL) + sax->exit_early = !sax->callback (sax->user_data, sax->wcs_full_name, sax->wcs_name, + sax->application_usermodelid, sax->applist, + sax->supported_extgroups, sax->supported_protocols); + g_clear_pointer (&sax->supported_extgroups, g_ptr_array_unref); + g_clear_pointer (&sax->supported_protocols, g_ptr_array_unref); + sax->supported_protocols = g_ptr_array_new_full (0, (GDestroyNotify) g_free); + sax->supported_extgroups = g_ptr_array_new_full (0, (GDestroyNotify) free_extgroup); + sax->in_application -= 1; + } + else if (sax->in_extension_fta == 1 && + _wcsicmp (local_name, L"FileTypeAssociation") == 0 && + _wcsicmp (prefix, L"uap") == 0) + { + GWin32PackageExtGroup *new_group = g_new0 (GWin32PackageExtGroup, 1); + new_group->extensions = g_steal_pointer (&sax->supported_extensions); + sax->supported_extensions = g_ptr_array_new_full (0, (GDestroyNotify) g_free); + new_group->verbs = g_steal_pointer (&sax->supported_verbs); + sax->supported_verbs = g_ptr_array_new_full (0, (GDestroyNotify) g_free); + g_ptr_array_add (sax->supported_extgroups, new_group); + sax->in_fta_group -= 1; + } + break; + default: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/gio/gwin32packageparser.h b/gio/gwin32packageparser.h new file mode 100644 index 0000000000000000000000000000000000000000..f55e30c3f41185b97efd1010a6faea71ed552be5 --- /dev/null +++ b/gio/gwin32packageparser.h @@ -0,0 +1,48 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2020 Руслан Ижбулатов + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + */ +#ifndef __G_WIN32_PACKAGE_PARSER_H__ +#define __G_WIN32_PACKAGE_PARSER_H__ + +#include + +#ifdef G_PLATFORM_WIN32 + +typedef struct _GWin32PackageExtGroup GWin32PackageExtGroup; + +struct _GWin32PackageExtGroup +{ + GPtrArray *verbs; + GPtrArray *extensions; +}; + +typedef gboolean (*GWin32PackageParserCallback)(gpointer user_data, + const gunichar2 *full_package_name, + const gunichar2 *package_name, + const gunichar2 *app_user_model_id, + gboolean show_in_applist, + GPtrArray *supported_extgroups, + GPtrArray *supported_protocols); + +gboolean g_win32_package_parser_enum_packages (GWin32PackageParserCallback callback, + gpointer user_data, + GError **error); + +#endif /* G_PLATFORM_WIN32 */ + +#endif /* __G_WIN32_PACKAGE_PARSER_H__ */ \ No newline at end of file diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c index c7d346655aee5e1f183e1c69014ed67b2ef0fbcc..398d8f45b8f1eb201b934691c34fb12e58727b4d 100644 --- a/gio/gwin32registrykey.c +++ b/gio/gwin32registrykey.c @@ -124,7 +124,7 @@ typedef enum G_WIN32_REGISTRY_UPDATED_NOTHING = 0, G_WIN32_REGISTRY_UPDATED_PATH = 1, } GWin32RegistryKeyUpdateFlag; - + static gsize g_utf16_len (const gunichar2 *str) { @@ -964,7 +964,7 @@ g_win32_registry_subkey_iter_next (GWin32RegistrySubkeyIter *iter, **/ gboolean g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter *iter, - gunichar2 **subkey_name, + const gunichar2 **subkey_name, gsize *subkey_name_len, GError **error) { @@ -1006,7 +1006,7 @@ g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter *iter, **/ gboolean g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter *iter, - gchar **subkey_name, + const gchar **subkey_name, gsize *subkey_name_len, GError **error) { @@ -1031,13 +1031,15 @@ g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter *iter, &subkey_name_len_glong, error); - if (iter->subkey_name_u8 != NULL) - { - *subkey_name_len = subkey_name_len_glong; - return TRUE; - } + if (iter->subkey_name_u8 == NULL) + return FALSE; - return FALSE; + *subkey_name = iter->subkey_name_u8; + + if (subkey_name_len) + *subkey_name_len = subkey_name_len_glong; + + return TRUE; } /** @@ -1856,9 +1858,119 @@ g_win32_registry_key_get_path_w (GWin32RegistryKey *key) return key->priv->absolute_path_w; } +/** + * g_win32_registry_get_os_dirs_w: + * + * Returns a list of directories for DLL lookups. + * Can be used with g_win32_registry_key_get_value_w(). + * + * Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of UTF-16 strings. + * + * Since: 2.66 + */ +const gunichar2 * const * +g_win32_registry_get_os_dirs_w (void) +{ + static gunichar2 **mui_os_dirs = NULL; + + if (g_once_init_enter (&mui_os_dirs)) + { + gunichar2 **new_mui_os_dirs; + gunichar2 *system32 = NULL; + gunichar2 *syswow64 = NULL; + UINT buffer_size; + gsize array_index = 0; + + buffer_size = GetSystemWow64DirectoryW (NULL, 0); + + if (buffer_size > 0) + { + UINT copied; + syswow64 = g_malloc (buffer_size * sizeof (gunichar2)); + copied = GetSystemWow64DirectoryW (syswow64, buffer_size); + if (copied <= 0) + g_clear_pointer (&syswow64, g_free); + } + + buffer_size = GetSystemDirectoryW (NULL, 0); + + if (buffer_size > 0) + { + UINT copied; + system32 = g_malloc (buffer_size * sizeof (gunichar2)); + copied = GetSystemDirectoryW (system32, buffer_size); + if (copied <= 0) + g_clear_pointer (&system32, g_free); + } + + new_mui_os_dirs = g_new0 (gunichar2 *, 3); + + if (system32 != NULL) + new_mui_os_dirs[array_index++] = system32; + + if (syswow64 != NULL) + new_mui_os_dirs[array_index++] = syswow64; + + new_mui_os_dirs[array_index++] = NULL; + + g_once_init_leave (&mui_os_dirs, new_mui_os_dirs); + } + + return (const gunichar2 * const *) mui_os_dirs; +} + +/** + * g_win32_registry_get_os_dirs: + * + * Returns a list of directories for DLL lookups. + * Can be used with g_win32_registry_key_get_value(). + * + * Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of UTF-8 strings. + * + * Since: 2.66 + */ +const gchar * const * +g_win32_registry_get_os_dirs (void) +{ + static gchar **mui_os_dirs = NULL; + + if (g_once_init_enter (&mui_os_dirs)) + { + gchar **new_mui_os_dirs; + gsize array_index; + gsize new_array_index; + const gunichar2 * const *mui_os_dirs_utf16 = g_win32_registry_get_os_dirs_w (); + + for (array_index = 0; mui_os_dirs_utf16[array_index] != NULL; array_index++) + ; + + new_mui_os_dirs = g_new0 (gchar *, array_index + 1); + + for (array_index = 0, new_array_index = 0; + mui_os_dirs_utf16[array_index] != NULL; + array_index++) + { + new_mui_os_dirs[new_array_index] = g_utf16_to_utf8 (mui_os_dirs_utf16[array_index], + -1, NULL, NULL, NULL); + if (new_mui_os_dirs[new_array_index] != NULL) + new_array_index += 1; + else + g_critical ("Failed to convert to a system directory #%zu to UTF-8", array_index); + } + + g_once_init_leave (&mui_os_dirs, new_mui_os_dirs); + } + + return (const gchar * const *) mui_os_dirs; +} + /** * g_win32_registry_key_get_value: * @key: (in) (transfer none): a #GWin32RegistryKey + * @mui_dll_dirs: (in) (transfer none) (array zero-terminated=1) (optional): a %NULL-terminated + * array of directory names where the OS + * should look for a DLL indicated in a MUI string, if the + * DLL path in the string is not absolute * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR * to G_WIN32_REGISTRY_VALUE_STR. * @value_name: (in) (transfer none): name of the value to get (in UTF-8). @@ -1872,12 +1984,32 @@ g_win32_registry_key_get_path_w (GWin32RegistryKey *key) * Get data from a value of a key. String data is guaranteed to be * appropriately terminated and will be in UTF-8. * + * When not %NULL, @mui_dll_dirs indicates that `RegLoadMUIStringW()` API + * should be used instead of the usual `RegQueryValueExW()`. This implies + * that the value being queried is of type `REG_SZ` or `REG_EXPAND_SZ` (if it is not, the function + * falls back to `RegQueryValueExW()`), and that this string must undergo special processing + * (see [`SHLoadIndirectString()` documentation](https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) for an explanation on what + * kinds of strings are processed) to get the result. + * + * If no specific MUI DLL directories need to be used, pass + * the return value of g_win32_registry_get_os_dirs() as @mui_dll_dirs + * (as an bonus, the value from g_win32_registry_get_os_dirs() + * does not add any extra UTF8->UTF16 conversion overhead). + * + * @auto_expand works with @mui_dll_dirs, but only affects the processed + * string, making it somewhat useless. The unprocessed string is always expanded + * internally, if its type is `REG_EXPAND_SZ` - there is no need to enable + * @auto_expand for this to work. + * + * The API for this function changed in GLib 2.66 to add the @mui_dll_dirs argument. + * * Returns: %TRUE on success, %FALSE on failure. * - * Since: 2.46 + * Since: 2.66 **/ gboolean g_win32_registry_key_get_value (GWin32RegistryKey *key, + const gchar * const *mui_dll_dirs, gboolean auto_expand, const gchar *value_name, GWin32RegistryValueType *value_type, @@ -1892,6 +2024,9 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key, gchar *value_data_u8; gsize value_data_u8_len; gboolean result; + gsize mui_dll_dirs_count; + gunichar2 **mui_dll_dirs_utf16; + const gchar * const *mui_os_dirs; g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE); g_return_val_if_fail (value_name != NULL, FALSE); @@ -1907,7 +2042,48 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key, if (value_name_w == NULL) return FALSE; + mui_dll_dirs_utf16 = NULL; + mui_os_dirs = g_win32_registry_get_os_dirs (); + + if (mui_dll_dirs != NULL && + mui_dll_dirs != mui_os_dirs) + { + gsize i; + + mui_dll_dirs_count = g_strv_length ((gchar **) mui_dll_dirs); + mui_dll_dirs_utf16 = g_new0 (gunichar2 *, mui_dll_dirs_count + 1); + + for (i = 0; mui_dll_dirs[i] != NULL; i++) + { + mui_dll_dirs_utf16[i] = g_utf8_to_utf16 (mui_dll_dirs[i], -1, NULL, NULL, error); + + if (mui_dll_dirs_utf16[i] == NULL) + break; + } + + if (mui_dll_dirs[i] != NULL) + { + g_prefix_error (error, + "A mui_dll_dirs string #%zu `%s' failed to convert: ", + i, mui_dll_dirs[i]); + + for (i = 0; i < mui_dll_dirs_count; i++) + g_free (mui_dll_dirs_utf16[i]); + + g_free (mui_dll_dirs_utf16); + g_free (value_name_w); + + return FALSE; + } + } + else if (mui_dll_dirs != NULL && + mui_dll_dirs == mui_os_dirs) + { + mui_dll_dirs_utf16 = (gunichar2 **) g_win32_registry_get_os_dirs_w (); + } + result = g_win32_registry_key_get_value_w (key, + (const gunichar2 * const *) mui_dll_dirs_utf16, auto_expand, value_name_w, &value_type_g, @@ -1916,6 +2092,14 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key, error); g_free (value_name_w); + if (mui_dll_dirs_utf16 != NULL && + mui_dll_dirs != mui_os_dirs) + { + gsize array_index; + for (array_index = 0; mui_dll_dirs_utf16[array_index] != NULL; array_index++) + g_free (mui_dll_dirs_utf16[array_index]); + g_free (mui_dll_dirs_utf16); + } if (!result) return FALSE; @@ -1962,9 +2146,98 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key, return TRUE; } +/* A wrapper that calls either RegQueryValueExW() or + * RegLoadMUIStringW() depending on the value of the + * last argument. + * Apart from the extra argument, the function behaves + * just like RegQueryValueExW(), with a few caveats. + */ +static LSTATUS +MuiRegQueryValueExW (HKEY hKey, + LPCWSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData, + const gunichar2 * const *mui_dll_dirs) +{ + gsize dir_index; + LSTATUS result = ERROR_PATH_NOT_FOUND; + DWORD bufsize; + DWORD data_size; + PVOID old_value; + + if (mui_dll_dirs == NULL) + return RegQueryValueExW (hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); + + bufsize = 0; + + if (lpcbData != NULL) + bufsize = *lpcbData; + + if (mui_dll_dirs[0] != NULL) + { + /* Optimization: check that the value actually exists, + * before we start trying different mui dll dirs + */ + result = RegQueryValueExW (hKey, lpValueName, NULL, NULL, NULL, 0); + + if (result == ERROR_FILE_NOT_FOUND) + return result; + } + + Wow64DisableWow64FsRedirection (&old_value); + + /* Try with NULL dir first */ + result = RegLoadMUIStringW (hKey, + lpValueName, + (wchar_t *) lpData, + bufsize, + &data_size, + 0, + NULL); + + /* Not a MUI value, load normally */ + if (result == ERROR_INVALID_DATA) + { + Wow64RevertWow64FsRedirection (old_value); + + return RegQueryValueExW (hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); + } + + for (dir_index = 0; + result == ERROR_FILE_NOT_FOUND && + mui_dll_dirs[dir_index] != NULL; + dir_index++) + result = RegLoadMUIStringW (hKey, + lpValueName, + (wchar_t *) lpData, + bufsize, + &data_size, + 0, + mui_dll_dirs[dir_index]); + + Wow64RevertWow64FsRedirection (old_value); + + if (lpcbData != NULL && + result == ERROR_MORE_DATA) + *lpcbData = data_size; + + if (lpType != NULL && + result != ERROR_INVALID_DATA && + result != ERROR_FILE_NOT_FOUND) + *lpType = REG_SZ; + + return result; +} + /** * g_win32_registry_key_get_value_w: * @key: (in) (transfer none): a #GWin32RegistryKey + * @mui_dll_dirs: (in) (transfer none) (array zero-terminated=1) (optional): a %NULL-terminated + * array of directory names where the OS + * should look for a DLL indicated in a MUI string, if the + * DLL path in the string is not absolute * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR * to G_WIN32_REGISTRY_VALUE_STR. * @value_name: (in) (transfer none): name of the value to get (in UTF-16). @@ -1975,23 +2248,39 @@ g_win32_registry_key_get_value (GWin32RegistryKey *key, * by @value_data. * @error: (nullable): a pointer to %NULL #GError, or %NULL * - * Get data from a value of a key. - * * Get data from a value of a key. String data is guaranteed to be * appropriately terminated and will be in UTF-16. * * When calling with value_data == NULL (to get data size without getting * the data itself) remember that returned size corresponds to possibly * unterminated string data (if value is some kind of string), because - * termination cannot be checked and fixed unless the data is retreived + * termination cannot be checked and fixed unless the data is retrieved * too. * + * When not %NULL, @mui_dll_dirs indicates that `RegLoadMUIStringW()` API + * should be used instead of the usual `RegQueryValueExW()`. This implies + * that the value being queried is of type `REG_SZ` or `REG_EXPAND_SZ` (if it is not, the function + * falls back to `RegQueryValueExW()`), and that this string must undergo special processing + * (see [`SHLoadIndirectString()` documentation](https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) for an explanation on what + * kinds of strings are processed) to get the result. + * + * If no specific MUI DLL directories need to be used, pass + * the return value of g_win32_registry_get_os_dirs_w() as @mui_dll_dirs. + * + * @auto_expand works with @mui_dll_dirs, but only affects the processed + * string, making it somewhat useless. The unprocessed string is always expanded + * internally, if its type is `REG_EXPAND_SZ` - there is no need to enable + * @auto_expand for this to work. + * + * The API for this function changed in GLib 2.66 to add the @mui_dll_dirs argument. + * * Returns: %TRUE on success, %FALSE on failure. * - * Since: 2.46 + * Since: 2.66 **/ gboolean g_win32_registry_key_get_value_w (GWin32RegistryKey *key, + const gunichar2 * const *mui_dll_dirs, gboolean auto_expand, const gunichar2 *value_name, GWin32RegistryValueType *value_type, @@ -2018,12 +2307,13 @@ g_win32_registry_key_get_value_w (GWin32RegistryKey *key, value_data_size != NULL, FALSE); req_value_data_size = 0; - status = RegQueryValueExW (key->priv->handle, - value_name, - NULL, - &value_type_w, - NULL, - &req_value_data_size); + status = MuiRegQueryValueExW (key->priv->handle, + value_name, + NULL, + &value_type_w, + NULL, + &req_value_data_size, + mui_dll_dirs); if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS) { @@ -2050,12 +2340,13 @@ g_win32_registry_key_get_value_w (GWin32RegistryKey *key, req_value_data = g_malloc (req_value_data_size + sizeof (gunichar2) * 2); req_value_data_size2 = req_value_data_size; - status = RegQueryValueExW (key->priv->handle, - value_name, - NULL, - &value_type_w2, - (gpointer) req_value_data, - &req_value_data_size2); + status = MuiRegQueryValueExW (key->priv->handle, + value_name, + NULL, + &value_type_w2, + (gpointer) req_value_data, + &req_value_data_size2, + mui_dll_dirs); if (status != ERROR_SUCCESS) { @@ -2211,7 +2502,7 @@ g_win32_registry_key_watch (GWin32RegistryKey *key, if (g_once_init_enter (&nt_notify_change_multiple_keys)) { NtNotifyChangeMultipleKeysFunc func; - HMODULE ntdll = GetModuleHandle ("ntdll.dll"); + HMODULE ntdll = GetModuleHandleW (L"ntdll.dll"); if (ntdll != NULL) func = (NtNotifyChangeMultipleKeysFunc) GetProcAddress (ntdll, "NtNotifyChangeMultipleKeys"); @@ -2352,8 +2643,6 @@ g_win32_registry_key_set_property (GObject *object, switch (prop_id) { case PROP_PATH: - g_assert (priv->absolute_path_w == NULL); - g_assert (priv->absolute_path == NULL); path = g_value_get_string (value); if (path == NULL) @@ -2364,20 +2653,21 @@ g_win32_registry_key_set_property (GObject *object, if (path_w == NULL) break; - g_free (priv->absolute_path_w); - g_free (priv->absolute_path); + /* Construct only */ + g_assert (priv->absolute_path_w == NULL); + g_assert (priv->absolute_path == NULL); priv->absolute_path_w = path_w; priv->absolute_path = g_value_dup_string (value); break; case PROP_PATH_UTF16: - g_assert (priv->absolute_path_w == NULL); - g_assert (priv->absolute_path == NULL); path_w = (gunichar2 *) g_value_get_pointer (value); if (path_w == NULL) break; + /* Construct only */ + g_assert (priv->absolute_path_w == NULL); priv->absolute_path_w = g_wcsdup (path_w, -1); break; diff --git a/gio/gwin32registrykey.h b/gio/gwin32registrykey.h index 52ccd5c0fdf77d57a3e36dcba02657bcb2b5fe5a..f92a10caf8ed219f241c1ca9ed0ea2cf9deb25fa 100644 --- a/gio/gwin32registrykey.h +++ b/gio/gwin32registrykey.h @@ -191,12 +191,12 @@ gboolean g_win32_registry_subkey_iter_next (GWin32RegistrySubk GError **error); GLIB_AVAILABLE_IN_2_46 gboolean g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter *iter, - gchar **subkey_name, + const gchar **subkey_name, gsize *subkey_name_len, GError **error); GLIB_AVAILABLE_IN_2_46 gboolean g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter *iter, - gunichar2 **subkey_name, + const gunichar2 **subkey_name, gsize *subkey_name_len, GError **error); @@ -239,8 +239,9 @@ gboolean g_win32_registry_value_iter_get_data_w (GWin32RegistryValu gsize *value_data_size, GError **error); -GLIB_AVAILABLE_IN_2_46 +GLIB_AVAILABLE_IN_2_66 gboolean g_win32_registry_key_get_value (GWin32RegistryKey *key, + const gchar * const *mui_dll_dirs, gboolean auto_expand, const gchar *value_name, GWin32RegistryValueType *value_type, @@ -248,8 +249,9 @@ gboolean g_win32_registry_key_get_value (GWin32RegistryKey gsize *value_data_size, GError **error); -GLIB_AVAILABLE_IN_2_46 +GLIB_AVAILABLE_IN_2_66 gboolean g_win32_registry_key_get_value_w (GWin32RegistryKey *key, + const gunichar2 * const *mui_dll_dirs, gboolean auto_expand, const gunichar2 *value_name, GWin32RegistryValueType *value_type, @@ -276,6 +278,12 @@ gboolean g_win32_registry_key_has_changed (GWin32RegistryKey GLIB_AVAILABLE_IN_2_46 void g_win32_registry_key_erase_change_indicator (GWin32RegistryKey *key); +GLIB_AVAILABLE_IN_2_66 +const gunichar2 * const *g_win32_registry_get_os_dirs_w (void); + +GLIB_AVAILABLE_IN_2_66 +const gchar * const *g_win32_registry_get_os_dirs (void); + G_END_DECLS #endif /* G_PLATFORM_WIN32 */ diff --git a/gio/gwin32volumemonitor.c b/gio/gwin32volumemonitor.c index 5124718346b24aef6e8456696d76cf75e29297cc..c6657a357d64029ba13e8bbc7c4380fb0ba0d6fb 100644 --- a/gio/gwin32volumemonitor.c +++ b/gio/gwin32volumemonitor.c @@ -68,13 +68,13 @@ get_viewable_logical_drives (void) DWORD no_drives; gboolean hklm_present = FALSE; - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "Software\\Microsoft\\Windows\\" - "CurrentVersion\\Policies\\Explorer", - 0, KEY_READ, &key) == ERROR_SUCCESS) + if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows\\" + L"CurrentVersion\\Policies\\Explorer", + 0, KEY_READ, &key) == ERROR_SUCCESS) { - if (RegQueryValueEx (key, "NoDrives", NULL, &var_type, - (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) + if (RegQueryValueExW (key, L"NoDrives", NULL, &var_type, + (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) { /* We need the bits that are set in viewable_drives, and * unset in no_drives. @@ -88,13 +88,13 @@ get_viewable_logical_drives (void) /* If the key is present in HKLM then the one in HKCU should be ignored */ if (!hklm_present) { - if (RegOpenKeyEx (HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\" - "CurrentVersion\\Policies\\Explorer", - 0, KEY_READ, &key) == ERROR_SUCCESS) + if (RegOpenKeyExW (HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\" + L"CurrentVersion\\Policies\\Explorer", + 0, KEY_READ, &key) == ERROR_SUCCESS) { - if (RegQueryValueEx (key, "NoDrives", NULL, &var_type, - (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) + if (RegQueryValueExW (key, L"NoDrives", NULL, &var_type, + (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) { viewable_drives = viewable_drives & ~no_drives; } @@ -105,7 +105,7 @@ get_viewable_logical_drives (void) return viewable_drives; } -/* deliver accesible (aka 'mounted') volumes */ +/* deliver accessible (aka 'mounted') volumes */ static GList * get_mounts (GVolumeMonitor *volume_monitor) { @@ -237,7 +237,7 @@ g_win32_volume_monitor_class_init (GWin32VolumeMonitorClass *klass) static void g_win32_volume_monitor_init (GWin32VolumeMonitor *win32_monitor) { - /* maybe we shoud setup a callback window to listern for WM_DEVICECHANGE ? */ + /* maybe we should setup a callback window to listen for WM_DEVICECHANGE ? */ #if 0 unix_monitor->mount_monitor = g_win32_mount_monitor_new (); diff --git a/gio/gzlibcompressor.c b/gio/gzlibcompressor.c index 53f3e4745f10cbef585ca9f85fd662f88a5e5781..b68f8823ab602de5ecaa1b6dbb0186680f4e63c9 100644 --- a/gio/gzlibcompressor.c +++ b/gio/gzlibcompressor.c @@ -296,7 +296,7 @@ g_zlib_compressor_new (GZlibCompressorFormat format, * * Returns the #GZlibCompressor:file-info property. * - * Returns: (transfer none): a #GFileInfo, or %NULL + * Returns: (nullable) (transfer none): a #GFileInfo, or %NULL * * Since: 2.26 */ diff --git a/gio/gzlibdecompressor.c b/gio/gzlibdecompressor.c index cf2542ef8a84c82848fdf6129d71cf6d984d3d67..e3f225150fcbc998b2b17b9a07c4dc11a1804cdc 100644 --- a/gio/gzlibdecompressor.c +++ b/gio/gzlibdecompressor.c @@ -282,7 +282,7 @@ g_zlib_decompressor_new (GZlibCompressorFormat format) * or the header data was not fully processed yet, or it not present in the * data stream at all. * - * Returns: (transfer none): a #GFileInfo, or %NULL + * Returns: (nullable) (transfer none): a #GFileInfo, or %NULL * * Since: 2.26 */ diff --git a/gio/inotify/inotify-helper.c b/gio/inotify/inotify-helper.c index d944587530be6909b452aaf3bc4e62272e417932..c2b98b167073320b0c9cccb5a1d39a80ea91c160 100644 --- a/gio/inotify/inotify-helper.c +++ b/gio/inotify/inotify-helper.c @@ -193,7 +193,7 @@ ih_event_callback (ik_event_t *event, * properly. If not, the assumption we have made about event->mask * only ever having a single bit set (apart from IN_ISDIR) is false. * The kernel documentation is lacking here. */ - g_assert (event_flags != -1); + g_assert ((int) event_flags != -1); interesting = g_file_monitor_source_handle_event (sub->user_data, event_flags, event->name, NULL, other, event->timestamp); @@ -201,7 +201,7 @@ ih_event_callback (ik_event_t *event, g_object_unref (other); } } - else if (event_flags != -1) + else if ((int) event_flags != -1) /* unpaired event -- no 'other' field */ interesting = g_file_monitor_source_handle_event (sub->user_data, event_flags, event->name, NULL, NULL, event->timestamp); diff --git a/gio/inotify/inotify-kernel.c b/gio/inotify/inotify-kernel.c index 05cdcb1aa6fd27c6a76dfdf29345d106423256c1..1a30fc84dad16f172a2834b59d159713106d74d9 100644 --- a/gio/inotify/inotify-kernel.c +++ b/gio/inotify/inotify-kernel.c @@ -372,8 +372,8 @@ ik_source_new (gboolean (* callback) (ik_event_t *event)) { static GSourceFuncs source_funcs = { NULL, NULL, - ik_source_dispatch - /* should have a finalize, but it will never happen */ + ik_source_dispatch, + NULL, NULL, NULL }; InotifyKernelSource *iks; GSource *source; diff --git a/gio/kqueue/dep-list.c b/gio/kqueue/dep-list.c index 3e79765392b1f952f5a79020e6e319dff30a789f..0a46aa8509728f15c44e5e688a9150a125e82d79 100644 --- a/gio/kqueue/dep-list.c +++ b/gio/kqueue/dep-list.c @@ -231,7 +231,7 @@ error: * * @param[in,out] before A pointer to a pointer to a list. Will contain items * which were not found in the 'after' list. - * @param[in,out] after A pointer to a pointer to a list. Will containt items + * @param[in,out] after A pointer to a pointer to a list. Will contain items * which were not found in the 'before' list. **/ void @@ -356,7 +356,7 @@ G_STMT_START { \ * Detect and notify about moves in the watched directory. * * A move is what happens when you rename a file in a directory, and - * a new name is unique, i.e. you didnt overwrite any existing files + * a new name is unique, i.e. you didn't overwrite any existing files * with this one. * * @param[in,out] removed A list of the removed files in the directory. @@ -387,7 +387,7 @@ dl_detect_moves (dep_list **removed, /** * Detect and notify about replacements in the watched directory. * - * Consider you are watching a directory foo with the folloing files + * Consider you are watching a directory foo with the following files * insinde: * * foo/bar @@ -534,4 +534,3 @@ dl_calculate (dep_list *before, dl_shallow_free (pre); dl_shallow_free (was); } - diff --git a/gio/kqueue/gkqueuefilemonitor.c b/gio/kqueue/gkqueuefilemonitor.c index c6e4ec4b8e2ba8d9569b1324b4a7dc780509be19..f69f98e1cfbb565565e3139f3574bdafe8164dc7 100644 --- a/gio/kqueue/gkqueuefilemonitor.c +++ b/gio/kqueue/gkqueuefilemonitor.c @@ -354,7 +354,7 @@ g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_d * rescan of missing files immediately so we don't have to wait for * 4 seconds for discovering missing files. We pass the sub_file * corresponding to the GKqueueFileMonitor to 'check_this_sub_only' - * argument to prevent _km_scan_missing from emiting 'CREATED' + * argument to prevent _km_scan_missing from emitting 'CREATED' * events because _kh_dir_diff will do it for us. */ if (sub->mon->sub_file != NULL && sub->mon->sub_file->fd == -1) _km_scan_missing (sub->mon->sub_file); diff --git a/gio/kqueue/kqueue-helper.c b/gio/kqueue/kqueue-helper.c index 36a5b58a78110cd9b5ff18ce7afc345c9f324ffe..b3e42a24fb5cce6dcbcd5f765b8d8162731de1b3 100644 --- a/gio/kqueue/kqueue-helper.c +++ b/gio/kqueue/kqueue-helper.c @@ -194,5 +194,3 @@ _kh_dir_diff (kqueue_sub *sub, gboolean handle_deleted) dl_free (was); } - - diff --git a/gio/kqueue/kqueue-missing.c b/gio/kqueue/kqueue-missing.c index 37af82e5b01da742932b75b9d30ffc78c9c7f441..d1ffdf4bd7c31cdea587d2192b50f0fa59d43b51 100644 --- a/gio/kqueue/kqueue-missing.c +++ b/gio/kqueue/kqueue-missing.c @@ -34,7 +34,7 @@ static gboolean km_debug_enabled = FALSE; static GSList *missing_subs_list = NULL; G_LOCK_DEFINE_STATIC (missing_lock); -static volatile gboolean scan_missing_running = FALSE; +static gboolean scan_missing_running = FALSE; /* must be accessed under @missing_lock */ static gboolean @@ -62,7 +62,6 @@ _km_add_missing (kqueue_sub *sub) KM_W ("adding %s to missing list\n", sub->filename); missing_subs_list = g_slist_prepend (missing_subs_list, sub); - G_UNLOCK (missing_lock); if (!scan_missing_running) { @@ -73,6 +72,8 @@ _km_add_missing (kqueue_sub *sub) g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ()); g_source_unref (source); } + + G_UNLOCK (missing_lock); } /** diff --git a/gio/meson.build b/gio/meson.build index 3535788abf18a893f4ecc7f05b2eb41a79f9036a..49a37a7bdd928509823128e02a0618169930b3a5 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -2,6 +2,7 @@ gio_c_args = [ '-DG_LOG_DOMAIN="GLib-GIO"', '-DGIO_COMPILATION', '-DGIO_MODULE_DIR="@0@"'.format(glib_giomodulesdir), + '-DLOCALSTATEDIR="@0@"'.format(glib_localstatedir), ] gio_c_args += glib_hidden_visibility_args @@ -10,15 +11,9 @@ gio_c_args += glib_hidden_visibility_args gnetworking_h_conf = configuration_data() -gnetworking_h_wspiapi_include = '' gnetworking_h_nameser_compat_include = '' -if host_system == 'windows' - # in the Windows SDK and in mingw-w64 has wrappers for - # inline workarounds for getaddrinfo, getnameinfo and freeaddrinfo if - # they aren't present at run-time (on Windows 2000). - gnetworking_h_wspiapi_include = '#include ' -elif not host_system.contains('android') +if host_system not in ['windows', 'android'] # Don't check for C_IN on Android since it does not define it in public # headers, we define it ourselves wherever necessary if not cc.compiles('''#include @@ -56,6 +51,9 @@ if host_system != 'windows' elif cc.links(res_query_test, args : '-lbind', name : 'res_query() in -lbind') network_libs += [ cc.find_library('bind') ] network_args += [ '-lbind' ] + elif cc.links(res_query_test, args : '-lsocket', name : 'res_query() in -lsocket') + network_libs += [ cc.find_library('socket') ] + network_args += [ '-lsocket' ] else error('Could not find res_query()') endif @@ -154,7 +152,7 @@ if host_system != 'windows' endif -if host_system.contains('android') +if host_system == 'android' # struct ip_mreq_source definition is broken on Android NDK <= r16 # See https://bugzilla.gnome.org/show_bug.cgi?id=740791 if not cc.compiles('''#include @@ -168,7 +166,6 @@ if host_system.contains('android') endif endif -gnetworking_h_conf.set('WSPIAPI_INCLUDE', gnetworking_h_wspiapi_include) gnetworking_h_conf.set('NAMESER_COMPAT_INCLUDE', gnetworking_h_nameser_compat_include) gnetworking_h = configure_file(input : 'gnetworking.h.in', @@ -247,16 +244,6 @@ xdp_dbus_generated = custom_target('xdp-dbus', '--output-directory', '@OUTDIR@', '--generate-c-code', 'xdp-dbus', '--c-namespace', 'GXdp', - '--annotate', 'org.freedesktop.portal.Documents.Add()', - 'org.gtk.GDBus.C.UnixFD', 'true', - '--annotate', 'org.freedesktop.portal.Documents.AddNamed()', - 'org.gtk.GDBus.C.UnixFD', 'true', - '--annotate', 'org.freedesktop.portal.Documents.AddFull()', - 'org.gtk.GDBus.C.UnixFD', 'true', - '--annotate', 'org.freedesktop.portal.OpenURI.OpenFile()', - 'org.gtk.GDBus.C.UnixFD', 'true', - '--annotate', 'org.freedesktop.portal.Trash.TrashFile()', - 'org.gtk.GDBus.C.UnixFD', 'true', '@INPUT@']) # Generate gdbus-generated.{c,h} @@ -375,6 +362,7 @@ gdbus_daemon_sources = [ if host_system != 'windows' unix_sources = files( 'gfiledescriptorbased.c', + 'giounix-private.c', 'gunixconnection.c', 'gunixcredentialsmessage.c', 'gunixfdlist.c', @@ -393,6 +381,7 @@ if host_system != 'windows' portal_sources = [files( 'gdocumentportal.c', 'gopenuriportal.c', + 'gmemorymonitorportal.c', 'gnetworkmonitorportal.c', 'gproxyresolverportal.c', 'gtrashportal.c', @@ -425,12 +414,6 @@ if host_system != 'windows' contenttype_sources += files('gcontenttype.c') appinfo_sources += files('gdesktopappinfo.c') gio_unix_include_headers += files('gdesktopappinfo.h') - - executable('gio-launch-desktop', 'gio-launch-desktop.c', - install : true, - c_args : gio_c_args, - # intl.lib is not compatible with SAFESEH - link_args : noseh_link_args) endif subdir('xdgmime') @@ -452,12 +435,16 @@ else cc.find_library('dnsapi'), iphlpapi_dep, winsock2] + platform_deps += uwp_gio_deps + win32_sources += files( 'gwin32registrykey.c', 'gwin32mount.c', 'gwin32volumemonitor.c', 'gwin32inputstream.c', 'gwin32outputstream.c', + 'gwin32file-sync-stream.c', + 'gwin32packageparser.c', 'gwin32networkmonitor.c', 'gwin32networkmonitor.h', 'gwin32notificationbackend.c', @@ -528,6 +515,8 @@ gio_sources = files( 'gloadableicon.c', 'gmarshal-internal.c', 'gmount.c', + 'gmemorymonitor.c', + 'gmemorymonitordbus.c', 'gmemoryinputstream.c', 'gmemoryoutputstream.c', 'gmountoperation.c', @@ -597,6 +586,7 @@ gio_sources = files( 'gzlibdecompressor.c', 'glistmodel.c', 'gliststore.c', + '../glib/gtrace.c', ) gio_sources += appinfo_sources @@ -670,6 +660,7 @@ gio_headers = files( 'gloadableicon.h', 'gmount.h', 'gmemoryinputstream.h', + 'gmemorymonitor.h', 'gmemoryoutputstream.h', 'gmountoperation.h', 'gnativesocketaddress.h', @@ -780,6 +771,17 @@ if host_system == 'windows' endif if have_bash + bash_comp_inst_dir = '' + if bash_comp_dep.found() + bash_comp_dir_override = bash_comp_dep.version().version_compare('>= 2.10') ? ['datadir', get_option('datadir')] : ['prefix', get_option('prefix')] + bash_comp_inst_dir = bash_comp_dep.get_pkgconfig_variable('completionsdir', define_variable: bash_comp_dir_override) + endif + + if bash_comp_inst_dir == '' + message('Found bash-completion but the .pc file did not set \'completionsdir\', fallback to a predefined path') + bash_comp_inst_dir = join_paths(get_option('datadir'), 'bash-completion/completions') + endif + install_data([ 'completion/gapplication', 'completion/gdbus', @@ -787,7 +789,7 @@ if have_bash 'completion/gsettings', 'completion/gresource' ], - install_dir: join_paths(get_option('datadir'), 'bash-completion/completions')) + install_dir: bash_comp_inst_dir) endif if enable_dtrace @@ -810,7 +812,7 @@ libgio = library('gio-2.0', # '$(gio_win32_res_ldflag)', dependencies : [libz_dep, libdl_dep, libmount_dep, libglib_dep, libgobject_dep, libgmodule_dep, selinux_dep, xattr_dep, - platform_deps, network_libs], + platform_deps, network_libs, libsysprof_capture_dep], c_args : gio_c_args, objc_args : gio_c_args, # intl.lib is not compatible with SAFESEH @@ -825,6 +827,10 @@ endif schemas_subdir = join_paths('glib-2.0', 'schemas') +libgio_dep = declare_dependency(link_with : libgio, + dependencies : [libgmodule_dep, libgobject_dep, gioenumtypes_dep], + include_directories : [gioinc]) + pkg.generate(libgio, libraries_private : [osx_ldflags], requires : ['glib-2.0', 'gobject-2.0'], @@ -847,6 +853,11 @@ pkg.generate(libgio, description : 'glib I/O library', ) +if meson.version().version_compare('>=0.54.0') + meson.override_dependency('gio-2.0', libgio_dep) +endif + + if host_system == 'windows' pkg.generate(requires : ['gobject-2.0', 'gmodule-no-export-2.0', 'gio-2.0'], subdirs : ['gio-win32-2.0'], @@ -856,6 +867,9 @@ if host_system == 'windows' name : 'GIO Windows specific APIs', description : 'Windows specific headers for glib I/O library', ) + if meson.version().version_compare('>=0.54.0') + meson.override_dependency('gio-win32-2.0', libgio_dep) + endif else pkg.generate(requires : ['gobject-2.0', 'gio-2.0'], subdirs : ['gio-unix-2.0'], @@ -865,12 +879,11 @@ else name : 'GIO unix specific APIs', description : 'unix specific headers for glib I/O library', ) + if meson.version().version_compare('>=0.54.0') + meson.override_dependency('gio-unix-2.0', libgio_dep) + endif endif -libgio_dep = declare_dependency(link_with : libgio, - dependencies : [libgmodule_dep, libgobject_dep, gioenumtypes_dep], - include_directories : [gioinc]) - if host_system == 'windows' # Hack till https://github.com/mesonbuild/meson/issues/2324 is fixed libgiounix_dep = dependency('', required : false) @@ -882,14 +895,14 @@ endif # Dependencies used by executables below have_libelf = false -libelf = dependency('libelf', version : '>= 0.8.12', required : false) +libelf = dependency('libelf', version : '>= 0.8.12', required : get_option ('libelf')) if libelf.found() have_libelf = true else # This fallback is necessary on *BSD. elfutils isn't the only libelf # implementation, and *BSD usually includes their own libelf as a system # library which doesn't have a corresponding .pc file. - libelf = cc.find_library('elf', required : false) + libelf = cc.find_library('elf', required : get_option ('libelf')) have_libelf = libelf.found() have_libelf = have_libelf and cc.has_function('elf_begin', dependencies : libelf) have_libelf = have_libelf and cc.has_function('elf_getshdrstrndx', dependencies : libelf) @@ -915,6 +928,7 @@ gio_tool_sources = [ 'gio-tool-cat.c', 'gio-tool-copy.c', 'gio-tool-info.c', + 'gio-tool-launch.c', 'gio-tool-list.c', 'gio-tool-mime.c', 'gio-tool-mkdir.c', @@ -951,7 +965,7 @@ gio_querymodules = executable('gio-querymodules', 'gio-querymodules.c', 'giomodu dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) glib_compile_schemas = executable('glib-compile-schemas', - [gconstructor_as_data_h, 'gvdb/gvdb-builder.c', 'glib-compile-schemas.c'], + ['gvdb/gvdb-builder.c', 'glib-compile-schemas.c'], install : true, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, @@ -971,6 +985,7 @@ glib_compile_resources = executable('glib-compile-resources', if not meson.is_cross_build() meson.override_find_program('glib-compile-schemas', glib_compile_schemas) meson.override_find_program('glib-compile-resources', glib_compile_resources) + meson.override_find_program('gio-querymodules', gio_querymodules) endif executable('gsettings', 'gsettings-tool.c', diff --git a/gio/org.freedesktop.portal.Documents.xml b/gio/org.freedesktop.portal.Documents.xml index d1cb7391243144e818218244fb4f035949d8e4ea..786793125a4517d2ca9a64ba8ab129efa239e54e 100644 --- a/gio/org.freedesktop.portal.Documents.xml +++ b/gio/org.freedesktop.portal.Documents.xml @@ -8,7 +8,7 @@ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -45,6 +45,12 @@ The permissions that the application has for a document store entry (see org.freedesktop.portal.Documents.GrantPermissions()) are reflected in the POSIX mode bits in the fuse filesystem. + + The D-Bus interface for the document portal is available under the + bus name org.freedesktop.portal.Documents and the object path + /org/freedesktop/portal/documents. + + This documentation describes version 3 of this interface. --> @@ -72,6 +78,7 @@ access to the file. --> + @@ -89,6 +96,7 @@ Creates an entry in the document store for writing a new file. --> + @@ -99,7 +107,7 @@ + @@ -127,6 +141,43 @@ + + + + + + + + + + + + @@ -211,7 +262,7 @@ @@ -67,18 +83,23 @@ + + + + + + + + + + diff --git a/gio/org.freedesktop.portal.ProxyResolver.xml b/gio/org.freedesktop.portal.ProxyResolver.xml index c6e9ce9a2ee4c39347f2da15587426182e66214b..4b39fc0784308e6b01b2d3056655a2d4ea2e467f 100644 --- a/gio/org.freedesktop.portal.ProxyResolver.xml +++ b/gio/org.freedesktop.portal.ProxyResolver.xml @@ -5,23 +5,45 @@ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, see . + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . Author: Matthias Clasen --> - + + + + diff --git a/gio/tests/actions.c b/gio/tests/actions.c index 3d438fc5db33e747c6ff733d124c259e2feb15f9..c183c7aa1f2cc07f7da0df60e4549e5e4bbe5928 100644 --- a/gio/tests/actions.c +++ b/gio/tests/actions.c @@ -890,7 +890,7 @@ do_export (gpointer data) bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); path = g_strdup_printf("/%p", data); - for (i = 0; i < 100000; i++) + for (i = 0; i < 10000; i++) { id = g_dbus_connection_export_action_group (bus, path, G_ACTION_GROUP (group), &error); g_assert_no_error (error); diff --git a/gio/tests/appinfo-test.c b/gio/tests/appinfo-test.c index 3a91a2f9ba1118ef2ec50fba157003ca09732a54..1b64a8faf3cde76cc6bad04bc9416b8fca4c2324 100644 --- a/gio/tests/appinfo-test.c +++ b/gio/tests/appinfo-test.c @@ -26,4 +26,3 @@ main (int argc, char *argv[]) return 0; } - diff --git a/gio/tests/appinfo.c b/gio/tests/appinfo.c index 4fec6b379306245dbf45b889d4b2b3fac7988b6d..2f0f43074bb3f73e579127709a313754f9f80fe4 100644 --- a/gio/tests/appinfo.c +++ b/gio/tests/appinfo.c @@ -600,4 +600,3 @@ main (int argc, char *argv[]) return g_test_run (); } - diff --git a/gio/tests/appmonitor.c b/gio/tests/appmonitor.c index c4e0721eaa33fd5243865a9690be3cdea3ffb663..725d91e5ce19b2f7df201eecb050beae97d26e74 100644 --- a/gio/tests/appmonitor.c +++ b/gio/tests/appmonitor.c @@ -11,7 +11,7 @@ setup (Fixture *fixture, gconstpointer user_data) { fixture->applications_dir = g_build_filename (g_get_user_data_dir (), "applications", NULL); - g_assert_cmpint (g_mkdir_with_parents (fixture->applications_dir, 0755), ==, 0); + g_assert_no_errno (g_mkdir_with_parents (fixture->applications_dir, 0755)); g_test_message ("Using data directory: %s", g_get_user_data_dir ()); } @@ -20,7 +20,7 @@ static void teardown (Fixture *fixture, gconstpointer user_data) { - g_assert_cmpint (g_rmdir (fixture->applications_dir), ==, 0); + g_assert_no_errno (g_rmdir (fixture->applications_dir)); g_clear_pointer (&fixture->applications_dir, g_free); } diff --git a/gio/tests/async-splice-output-stream.c b/gio/tests/async-splice-output-stream.c index e69c4db5d543ac81734808e0ee14ade12e707a56..fb317b733259f22b96cadedb15405e5a6ab5310b 100644 --- a/gio/tests/async-splice-output-stream.c +++ b/gio/tests/async-splice-output-stream.c @@ -32,6 +32,7 @@ typedef enum TEST_THREADED_NONE = 0, TEST_THREADED_ISTREAM = 1, TEST_THREADED_OSTREAM = 2, + TEST_CANCEL = 4, TEST_THREADED_BOTH = TEST_THREADED_ISTREAM | TEST_THREADED_OSTREAM, } TestThreadedFlags; @@ -58,6 +59,14 @@ test_copy_chunks_splice_cb (GObject *source, bytes_spliced = g_output_stream_splice_finish (G_OUTPUT_STREAM (source), res, &error); + + if (data->flags & TEST_CANCEL) + { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_main_loop_quit (data->main_loop); + return; + } + g_assert_no_error (error); g_assert_cmpint (bytes_spliced, ==, strlen (data->data)); @@ -100,11 +109,18 @@ test_copy_chunks_start (TestThreadedFlags flags) { TestCopyChunksData data; GError *error = NULL; + GCancellable *cancellable = NULL; data.main_loop = g_main_loop_new (NULL, FALSE); data.data = "abcdefghijklmnopqrstuvwxyz"; data.flags = flags; + if (data.flags & TEST_CANCEL) + { + cancellable = g_cancellable_new (); + g_cancellable_cancel (cancellable); + } + if (data.flags & TEST_THREADED_ISTREAM) { GFile *file; @@ -150,7 +166,7 @@ test_copy_chunks_start (TestThreadedFlags flags) g_output_stream_splice_async (data.ostream, data.istream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - G_PRIORITY_DEFAULT, NULL, + G_PRIORITY_DEFAULT, cancellable, test_copy_chunks_splice_cb, &data); /* We do not hold a ref in data struct, this is to make sure the operation @@ -158,6 +174,7 @@ test_copy_chunks_start (TestThreadedFlags flags) */ g_object_unref (data.istream); g_object_unref (data.ostream); + g_clear_object (&cancellable); g_main_loop_run (data.main_loop); g_main_loop_unref (data.main_loop); @@ -187,6 +204,12 @@ test_copy_chunks_threaded (void) test_copy_chunks_start (TEST_THREADED_BOTH); } +static void +test_cancelled (void) +{ + test_copy_chunks_start (TEST_THREADED_NONE | TEST_CANCEL); +} + int main (int argc, char *argv[]) @@ -200,6 +223,8 @@ main (int argc, test_copy_chunks_threaded_output); g_test_add_func ("/async-splice/copy-chunks-threaded", test_copy_chunks_threaded); + g_test_add_func ("/async-splice/cancelled", + test_cancelled); return g_test_run(); } diff --git a/gio/tests/cancellable.c b/gio/tests/cancellable.c index 044628228965b7034b901a64f337af2a7584c864..1eb7529d653c9fc9630a0d0cfdf61e74bfbe4e58 100644 --- a/gio/tests/cancellable.c +++ b/gio/tests/cancellable.c @@ -22,6 +22,8 @@ #include +#include "glib/glib-private.h" + /* How long to wait in ms for each iteration */ #define WAIT_ITERATION (10) @@ -29,8 +31,8 @@ static gint num_async_operations = 0; typedef struct { - guint iterations_requested; - guint iterations_done; + guint iterations_requested; /* construct-only */ + guint iterations_done; /* (atomic) */ } MockOperationData; static void @@ -54,13 +56,13 @@ mock_operation_thread (GTask *task, if (g_cancellable_is_cancelled (cancellable)) break; if (g_test_verbose ()) - g_printerr ("THRD: %u iteration %u\n", data->iterations_requested, i); + g_test_message ("THRD: %u iteration %u", data->iterations_requested, i); g_usleep (WAIT_ITERATION * 1000); } if (g_test_verbose ()) - g_printerr ("THRD: %u stopped at %u\n", data->iterations_requested, i); - data->iterations_done = i; + g_test_message ("THRD: %u stopped at %u", data->iterations_requested, i); + g_atomic_int_add (&data->iterations_done, i); g_task_return_boolean (task, TRUE); } @@ -71,11 +73,13 @@ mock_operation_timeout (gpointer user_data) GTask *task; MockOperationData *data; gboolean done = FALSE; + guint iterations_done; task = G_TASK (user_data); data = g_task_get_task_data (task); + iterations_done = g_atomic_int_get (&data->iterations_done); - if (data->iterations_done >= data->iterations_requested) + if (iterations_done >= data->iterations_requested) done = TRUE; if (g_cancellable_is_cancelled (g_task_get_cancellable (task))) @@ -84,18 +88,18 @@ mock_operation_timeout (gpointer user_data) if (done) { if (g_test_verbose ()) - g_printerr ("LOOP: %u stopped at %u\n", data->iterations_requested,\ - data->iterations_done); + g_test_message ("LOOP: %u stopped at %u", + data->iterations_requested, iterations_done); g_task_return_boolean (task, TRUE); - return FALSE; /* don't call timeout again */ + return G_SOURCE_REMOVE; } else { - data->iterations_done++; + g_atomic_int_inc (&data->iterations_done); if (g_test_verbose ()) - g_printerr ("LOOP: %u iteration %u\n", data->iterations_requested, - data->iterations_done); - return TRUE; /* call timeout */ + g_test_message ("LOOP: %u iteration %u", + data->iterations_requested, iterations_done + 1); + return G_SOURCE_CONTINUE; } } @@ -118,14 +122,14 @@ mock_operation_async (guint wait_iterations, { g_task_run_in_thread (task, mock_operation_thread); if (g_test_verbose ()) - g_printerr ("THRD: %d started\n", wait_iterations); + g_test_message ("THRD: %d started", wait_iterations); } else { g_timeout_add_full (G_PRIORITY_DEFAULT, WAIT_ITERATION, mock_operation_timeout, g_object_ref (task), g_object_unref); if (g_test_verbose ()) - g_printerr ("LOOP: %d started\n", wait_iterations); + g_test_message ("LOOP: %d started", wait_iterations); } g_object_unref (task); @@ -138,7 +142,7 @@ mock_operation_finish (GAsyncResult *result, MockOperationData *data; GTask *task; - g_assert (g_task_is_valid (result, NULL)); + g_assert_true (g_task_is_valid (result, NULL)); /* This test expects the return value to be iterations_done even * when an error is set. @@ -147,11 +151,9 @@ mock_operation_finish (GAsyncResult *result, data = g_task_get_task_data (task); g_task_propagate_boolean (task, error); - return data->iterations_done; + return g_atomic_int_get (&data->iterations_done); } -GMainLoop *loop; - static void on_mock_operation_ready (GObject *source, GAsyncResult *result, @@ -169,17 +171,7 @@ on_mock_operation_ready (GObject *source, g_assert_cmpint (iterations_requested, >, iterations_done); num_async_operations--; - - if (!num_async_operations) - g_main_loop_quit (loop); -} - -static gboolean -on_main_loop_timeout_quit (gpointer user_data) -{ - GMainLoop *loop = user_data; - g_main_loop_quit (loop); - return FALSE; + g_main_context_wakeup (NULL); } static void @@ -188,8 +180,13 @@ test_cancel_multiple_concurrent (void) GCancellable *cancellable; guint i, iterations; + if (!g_test_thorough ()) + { + g_test_skip ("Not running timing heavy test"); + return; + } + cancellable = g_cancellable_new (); - loop = g_main_loop_new (NULL, FALSE); for (i = 0; i < 45; i++) { @@ -199,21 +196,22 @@ test_cancel_multiple_concurrent (void) num_async_operations++; } - /* Wait for two iterations, to give threads a chance to start up */ - g_timeout_add (WAIT_ITERATION * 2, on_main_loop_timeout_quit, loop); - g_main_loop_run (loop); - g_assert_cmpint (num_async_operations, ==, 45); + /* Wait for the threads to start up */ + while (num_async_operations != 45) + g_main_context_iteration (NULL, TRUE); + g_assert_cmpint (num_async_operations, ==, 45);\ + if (g_test_verbose ()) - g_printerr ("CANCEL: %d operations\n", num_async_operations); + g_test_message ("CANCEL: %d operations", num_async_operations); g_cancellable_cancel (cancellable); - g_assert (g_cancellable_is_cancelled (cancellable)); + g_assert_true (g_cancellable_is_cancelled (cancellable)); /* Wait for all operations to be cancelled */ - g_main_loop_run (loop); + while (num_async_operations != 0) + g_main_context_iteration (NULL, TRUE); g_assert_cmpint (num_async_operations, ==, 0); g_object_unref (cancellable); - g_main_loop_unref (loop); } static void @@ -222,6 +220,122 @@ test_cancel_null (void) g_cancellable_cancel (NULL); } +typedef struct +{ + GCond cond; + GMutex mutex; + gboolean thread_ready; + GAsyncQueue *cancellable_source_queue; /* (owned) (element-type GCancellableSource) */ +} ThreadedDisposeData; + +static gboolean +cancelled_cb (GCancellable *cancellable, + gpointer user_data) +{ + /* Nothing needs to be done here. */ + return G_SOURCE_CONTINUE; +} + +static gpointer +threaded_dispose_thread_cb (gpointer user_data) +{ + ThreadedDisposeData *data = user_data; + GSource *cancellable_source; + + g_mutex_lock (&data->mutex); + data->thread_ready = TRUE; + g_cond_broadcast (&data->cond); + g_mutex_unlock (&data->mutex); + + while ((cancellable_source = g_async_queue_pop (data->cancellable_source_queue)) != (gpointer) 1) + { + /* Race with cancellation of the cancellable. */ + g_source_unref (cancellable_source); + } + + return NULL; +} + +static void +test_cancellable_source_threaded_dispose (void) +{ +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks lots of GCancellableSource objects, see glib#2309"); + (void) cancelled_cb; + (void) threaded_dispose_thread_cb; +#else + ThreadedDisposeData data; + GThread *thread = NULL; + guint i; + GPtrArray *cancellables_pending_unref = g_ptr_array_new_with_free_func (g_object_unref); + + g_test_summary ("Test a thread race between disposing of a GCancellableSource " + "(in one thread) and cancelling the GCancellable it refers " + "to (in another thread)"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1841"); + + /* Create a new thread and wait until it’s ready to execute. Each iteration of + * the test will pass it a new #GCancellableSource. */ + g_cond_init (&data.cond); + g_mutex_init (&data.mutex); + data.cancellable_source_queue = g_async_queue_new_full ((GDestroyNotify) g_source_unref); + data.thread_ready = FALSE; + + g_mutex_lock (&data.mutex); + thread = g_thread_new ("/cancellable-source/threaded-dispose", + threaded_dispose_thread_cb, &data); + + while (!data.thread_ready) + g_cond_wait (&data.cond, &data.mutex); + g_mutex_unlock (&data.mutex); + + for (i = 0; i < 100000; i++) + { + GCancellable *cancellable = NULL; + GSource *cancellable_source = NULL; + + /* Create a cancellable and a cancellable source for it. For this test, + * there’s no need to attach the source to a #GMainContext. */ + cancellable = g_cancellable_new (); + cancellable_source = g_cancellable_source_new (cancellable); + g_source_set_callback (cancellable_source, G_SOURCE_FUNC (cancelled_cb), NULL, NULL); + + /* Send it to the thread and wait until it’s ready to execute before + * cancelling our cancellable. */ + g_async_queue_push (data.cancellable_source_queue, g_steal_pointer (&cancellable_source)); + + /* Race with disposal of the cancellable source. */ + g_cancellable_cancel (cancellable); + + /* This thread can’t drop its reference to the #GCancellable here, as it + * might not be the final reference (depending on how the race is + * resolved: #GCancellableSource holds a strong ref on the #GCancellable), + * and at this point we can’t guarantee to support disposing of a + * #GCancellable in a different thread from where it’s created, especially + * when signal handlers are connected to it. + * + * So this is a workaround for a disposal-in-another-thread bug for + * #GCancellable, but there’s no hope of debugging and resolving it with + * this test setup, and the bug is orthogonal to what’s being tested here + * (a race between #GCancellable and #GCancellableSource). */ + g_ptr_array_add (cancellables_pending_unref, g_steal_pointer (&cancellable)); + } + + /* Indicate that the test has finished. Can’t use %NULL as #GAsyncQueue + * doesn’t allow that.*/ + g_async_queue_push (data.cancellable_source_queue, (gpointer) 1); + + g_thread_join (g_steal_pointer (&thread)); + + g_assert (g_async_queue_length (data.cancellable_source_queue) == 0); + g_async_queue_unref (data.cancellable_source_queue); + g_mutex_clear (&data.mutex); + g_cond_clear (&data.cond); + + g_ptr_array_unref (cancellables_pending_unref); +#endif +} + int main (int argc, char *argv[]) { @@ -229,6 +343,7 @@ main (int argc, char *argv[]) g_test_add_func ("/cancellable/multiple-concurrent", test_cancel_multiple_concurrent); g_test_add_func ("/cancellable/null", test_cancel_null); + g_test_add_func ("/cancellable-source/threaded-dispose", test_cancellable_source_threaded_dispose); return g_test_run (); } diff --git a/gio/tests/codegen.py b/gio/tests/codegen.py new file mode 100644 index 0000000000000000000000000000000000000000..d3a09bae71b6471d2293349aaf100cdd78dd414f --- /dev/null +++ b/gio/tests/codegen.py @@ -0,0 +1,590 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# +# Copyright © 2018, 2019 Endless Mobile, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +"""Integration tests for gdbus-codegen utility.""" + +import collections +import os +import shutil +import subprocess +import sys +import tempfile +import unittest + +import taptestrunner + + +# Disable line length warnings as wrapping the C code templates would be hard +# flake8: noqa: E501 + + +Result = collections.namedtuple("Result", ("info", "out", "err", "subs")) + + +class TestCodegen(unittest.TestCase): + """Integration test for running gdbus-codegen. + + This can be run when installed or uninstalled. When uninstalled, it + requires G_TEST_BUILDDIR and G_TEST_SRCDIR to be set. + + The idea with this test harness is to test the gdbus-codegen utility, its + handling of command line arguments, its exit statuses, and its handling of + various C source codes. In future we could split out tests for the core + parsing and generation code of gdbus-codegen into separate unit tests, and + just test command line behaviour in this integration test. + """ + + # Track the cwd, we want to back out to that to clean up our tempdir + cwd = "" + + def setUp(self): + self.timeout_seconds = 10 # seconds per test + self.tmpdir = tempfile.TemporaryDirectory() + self.cwd = os.getcwd() + os.chdir(self.tmpdir.name) + print("tmpdir:", self.tmpdir.name) + if "G_TEST_BUILDDIR" in os.environ: + self.__codegen = os.path.join( + os.environ["G_TEST_BUILDDIR"], + "..", + "gdbus-2.0", + "codegen", + "gdbus-codegen", + ) + else: + self.__codegen = shutil.which("gdbus-codegen") + print("codegen:", self.__codegen) + + def tearDown(self): + os.chdir(self.cwd) + self.tmpdir.cleanup() + + def runCodegen(self, *args): + argv = [self.__codegen] + + # shebang lines are not supported on native + # Windows consoles + if os.name == "nt": + argv.insert(0, sys.executable) + + argv.extend(args) + print("Running:", argv) + + env = os.environ.copy() + env["LC_ALL"] = "C.UTF-8" + print("Environment:", env) + + # We want to ensure consistent line endings... + info = subprocess.run( + argv, + timeout=self.timeout_seconds, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + universal_newlines=True, + ) + info.check_returncode() + out = info.stdout.strip() + err = info.stderr.strip() + + # Known substitutions for standard boilerplate + subs = { + "standard_top_comment": "/*\n" + " * This file is generated by gdbus-codegen, do not modify it.\n" + " *\n" + " * The license of this code is the same as for the D-Bus interface description\n" + " * it was derived from. Note that it links to GLib, so must comply with the\n" + " * LGPL linking clauses.\n" + " */", + "standard_config_h_include": "#ifdef HAVE_CONFIG_H\n" + '# include "config.h"\n' + "#endif", + "standard_header_includes": "#include \n" + "#ifdef G_OS_UNIX\n" + "# include \n" + "#endif", + "standard_typedefs_and_helpers": "typedef struct\n" + "{\n" + " GDBusArgInfo parent_struct;\n" + " gboolean use_gvariant;\n" + "} _ExtendedGDBusArgInfo;\n" + "\n" + "typedef struct\n" + "{\n" + " GDBusMethodInfo parent_struct;\n" + " const gchar *signal_name;\n" + " gboolean pass_fdlist;\n" + "} _ExtendedGDBusMethodInfo;\n" + "\n" + "typedef struct\n" + "{\n" + " GDBusSignalInfo parent_struct;\n" + " const gchar *signal_name;\n" + "} _ExtendedGDBusSignalInfo;\n" + "\n" + "typedef struct\n" + "{\n" + " GDBusPropertyInfo parent_struct;\n" + " const gchar *hyphen_name;\n" + " guint use_gvariant : 1;\n" + " guint emits_changed_signal : 1;\n" + "} _ExtendedGDBusPropertyInfo;\n" + "\n" + "typedef struct\n" + "{\n" + " GDBusInterfaceInfo parent_struct;\n" + " const gchar *hyphen_name;\n" + "} _ExtendedGDBusInterfaceInfo;\n" + "\n" + "typedef struct\n" + "{\n" + " const _ExtendedGDBusPropertyInfo *info;\n" + " guint prop_id;\n" + " GValue orig_value; /* the value before the change */\n" + "} ChangedProperty;\n" + "\n" + "static void\n" + "_changed_property_free (ChangedProperty *data)\n" + "{\n" + " g_value_unset (&data->orig_value);\n" + " g_free (data);\n" + "}\n" + "\n" + "static gboolean\n" + "_g_strv_equal0 (gchar **a, gchar **b)\n" + "{\n" + " gboolean ret = FALSE;\n" + " guint n;\n" + " if (a == NULL && b == NULL)\n" + " {\n" + " ret = TRUE;\n" + " goto out;\n" + " }\n" + " if (a == NULL || b == NULL)\n" + " goto out;\n" + " if (g_strv_length (a) != g_strv_length (b))\n" + " goto out;\n" + " for (n = 0; a[n] != NULL; n++)\n" + " if (g_strcmp0 (a[n], b[n]) != 0)\n" + " goto out;\n" + " ret = TRUE;\n" + "out:\n" + " return ret;\n" + "}\n" + "\n" + "static gboolean\n" + "_g_variant_equal0 (GVariant *a, GVariant *b)\n" + "{\n" + " gboolean ret = FALSE;\n" + " if (a == NULL && b == NULL)\n" + " {\n" + " ret = TRUE;\n" + " goto out;\n" + " }\n" + " if (a == NULL || b == NULL)\n" + " goto out;\n" + " ret = g_variant_equal (a, b);\n" + "out:\n" + " return ret;\n" + "}\n" + "\n" + "G_GNUC_UNUSED static gboolean\n" + "_g_value_equal (const GValue *a, const GValue *b)\n" + "{\n" + " gboolean ret = FALSE;\n" + " g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n" + " switch (G_VALUE_TYPE (a))\n" + " {\n" + " case G_TYPE_BOOLEAN:\n" + " ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n" + " break;\n" + " case G_TYPE_UCHAR:\n" + " ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n" + " break;\n" + " case G_TYPE_INT:\n" + " ret = (g_value_get_int (a) == g_value_get_int (b));\n" + " break;\n" + " case G_TYPE_UINT:\n" + " ret = (g_value_get_uint (a) == g_value_get_uint (b));\n" + " break;\n" + " case G_TYPE_INT64:\n" + " ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n" + " break;\n" + " case G_TYPE_UINT64:\n" + " ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n" + " break;\n" + " case G_TYPE_DOUBLE:\n" + " {\n" + " /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n" + " gdouble da = g_value_get_double (a);\n" + " gdouble db = g_value_get_double (b);\n" + " ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n" + " }\n" + " break;\n" + " case G_TYPE_STRING:\n" + " ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n" + " break;\n" + " case G_TYPE_VARIANT:\n" + " ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n" + " break;\n" + " default:\n" + " if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n" + " ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n" + " else\n" + ' g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));\n' + " break;\n" + " }\n" + " return ret;\n" + "}", + } + + result = Result(info, out, err, subs) + + print("Output:", result.out) + return result + + def runCodegenWithInterface(self, interface_contents, *args): + with tempfile.NamedTemporaryFile( + dir=self.tmpdir.name, suffix=".xml", delete=False + ) as interface_file: + # Write out the interface. + interface_file.write(interface_contents.encode("utf-8")) + print(interface_file.name + ":", interface_contents) + interface_file.flush() + + return self.runCodegen(interface_file.name, *args) + + def test_help(self): + """Test the --help argument.""" + result = self.runCodegen("--help") + self.assertIn("usage: gdbus-codegen", result.out) + + def test_no_args(self): + """Test running with no arguments at all.""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegen() + + def test_empty_interface_header(self): + """Test generating a header with an empty interface file.""" + result = self.runCodegenWithInterface("", "--output", "/dev/stdout", "--header") + self.assertEqual("", result.err) + self.assertEqual( + """{standard_top_comment} + +#ifndef __STDOUT__ +#define __STDOUT__ + +#include + +G_BEGIN_DECLS + + +G_END_DECLS + +#endif /* __STDOUT__ */""".format( + **result.subs + ), + result.out.strip(), + ) + + def test_empty_interface_body(self): + """Test generating a body with an empty interface file.""" + result = self.runCodegenWithInterface("", "--output", "/dev/stdout", "--body") + self.assertEqual("", result.err) + self.assertEqual( + """{standard_top_comment} + +{standard_config_h_include} + +#include "stdout.h" + +{standard_header_includes} + +{standard_typedefs_and_helpers}""".format( + **result.subs + ), + result.out.strip(), + ) + + def test_reproducible(self): + """Test builds are reproducible regardless of file ordering.""" + xml_contents1 = """ + + + + + + + + + + """ + + xml_contents2 = """ + + + + + + """ + + with tempfile.NamedTemporaryFile( + dir=self.tmpdir.name, suffix="1.xml", delete=False + ) as xml_file1, tempfile.NamedTemporaryFile( + dir=self.tmpdir.name, suffix="2.xml", delete=False + ) as xml_file2: + # Write out the interfaces. + xml_file1.write(xml_contents1.encode("utf-8")) + xml_file2.write(xml_contents2.encode("utf-8")) + + xml_file1.flush() + xml_file2.flush() + + # Repeat this for headers and bodies. + for header_or_body in ["--header", "--body"]: + # Run gdbus-codegen with the interfaces in one order, and then + # again in another order. + result1 = self.runCodegen( + xml_file1.name, + xml_file2.name, + "--output", + "/dev/stdout", + header_or_body, + ) + self.assertEqual("", result1.err) + + result2 = self.runCodegen( + xml_file2.name, + xml_file1.name, + "--output", + "/dev/stdout", + header_or_body, + ) + self.assertEqual("", result2.err) + + # The output should be the same. + self.assertEqual(result1.out, result2.out) + + def test_glib_min_required_invalid(self): + """Test running with an invalid --glib-min-required.""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegenWithInterface( + "", + "--output", + "/dev/stdout", + "--body", + "--glib-min-required", + "hello mum", + ) + + def test_glib_min_required_too_low(self): + """Test running with a --glib-min-required which is too low (and hence + probably a typo).""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegenWithInterface( + "", "--output", "/dev/stdout", "--body", "--glib-min-required", "2.6" + ) + + def test_glib_min_required_major_only(self): + """Test running with a --glib-min-required which contains only a major version.""" + result = self.runCodegenWithInterface( + "", + "--output", + "/dev/stdout", + "--header", + "--glib-min-required", + "3", + "--glib-max-allowed", + "3.2", + ) + self.assertEqual("", result.err) + self.assertNotEqual("", result.out.strip()) + + def test_glib_min_required_with_micro(self): + """Test running with a --glib-min-required which contains a micro version.""" + result = self.runCodegenWithInterface( + "", "--output", "/dev/stdout", "--header", "--glib-min-required", "2.46.2" + ) + self.assertEqual("", result.err) + self.assertNotEqual("", result.out.strip()) + + def test_glib_max_allowed_too_low(self): + """Test running with a --glib-max-allowed which is too low (and hence + probably a typo).""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegenWithInterface( + "", "--output", "/dev/stdout", "--body", "--glib-max-allowed", "2.6" + ) + + def test_glib_max_allowed_major_only(self): + """Test running with a --glib-max-allowed which contains only a major version.""" + result = self.runCodegenWithInterface( + "", "--output", "/dev/stdout", "--header", "--glib-max-allowed", "3" + ) + self.assertEqual("", result.err) + self.assertNotEqual("", result.out.strip()) + + def test_glib_max_allowed_with_micro(self): + """Test running with a --glib-max-allowed which contains a micro version.""" + result = self.runCodegenWithInterface( + "", "--output", "/dev/stdout", "--header", "--glib-max-allowed", "2.46.2" + ) + self.assertEqual("", result.err) + self.assertNotEqual("", result.out.strip()) + + def test_glib_max_allowed_unstable(self): + """Test running with a --glib-max-allowed which is unstable. It should + be rounded up to the next stable version number, and hence should not + end up less than --glib-min-required.""" + result = self.runCodegenWithInterface( + "", + "--output", + "/dev/stdout", + "--header", + "--glib-max-allowed", + "2.63", + "--glib-min-required", + "2.64", + ) + self.assertEqual("", result.err) + self.assertNotEqual("", result.out.strip()) + + def test_glib_max_allowed_less_than_min_required(self): + """Test running with a --glib-max-allowed which is less than + --glib-min-required.""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegenWithInterface( + "", + "--output", + "/dev/stdout", + "--body", + "--glib-max-allowed", + "2.62", + "--glib-min-required", + "2.64", + ) + + def test_unix_fd_types_and_annotations(self): + """Test an interface with `h` arguments, no annotation, and GLib < 2.64. + + See issue #1726. + """ + interface_xml = """ + + + + + + + + + + + + + + + + + + """ + + # Try without specifying --glib-min-required. + result = self.runCodegenWithInterface( + interface_xml, "--output", "/dev/stdout", "--header" + ) + self.assertEqual("", result.err) + self.assertEqual(result.out.strip().count("GUnixFDList"), 6) + + # Specify an old --glib-min-required. + result = self.runCodegenWithInterface( + interface_xml, + "--output", + "/dev/stdout", + "--header", + "--glib-min-required", + "2.32", + ) + self.assertEqual("", result.err) + self.assertEqual(result.out.strip().count("GUnixFDList"), 6) + + # Specify a --glib-min-required ≥ 2.64. There should be more + # mentions of `GUnixFDList` now, since the annotation is not needed to + # trigger its use. + result = self.runCodegenWithInterface( + interface_xml, + "--output", + "/dev/stdout", + "--header", + "--glib-min-required", + "2.64", + ) + self.assertEqual("", result.err) + self.assertEqual(result.out.strip().count("GUnixFDList"), 18) + + def test_call_flags_and_timeout_method_args(self): + """Test that generated method call functions have @call_flags and + @timeout_msec args if and only if GLib >= 2.64. + """ + interface_xml = """ + + + + + """ + + # Try without specifying --glib-min-required. + result = self.runCodegenWithInterface( + interface_xml, "--output", "/dev/stdout", "--header" + ) + self.assertEqual("", result.err) + self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 0) + self.assertEqual(result.out.strip().count("gint timeout_msec,"), 0) + + # Specify an old --glib-min-required. + result = self.runCodegenWithInterface( + interface_xml, + "--output", + "/dev/stdout", + "--header", + "--glib-min-required", + "2.32", + ) + self.assertEqual("", result.err) + self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 0) + self.assertEqual(result.out.strip().count("gint timeout_msec,"), 0) + + # Specify a --glib-min-required ≥ 2.64. The two arguments should be + # present for both the async and sync method call functions. + result = self.runCodegenWithInterface( + interface_xml, + "--output", + "/dev/stdout", + "--header", + "--glib-min-required", + "2.64", + ) + self.assertEqual("", result.err) + self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 2) + self.assertEqual(result.out.strip().count("gint timeout_msec,"), 2) + + +if __name__ == "__main__": + unittest.main(testRunner=taptestrunner.TAPTestRunner()) diff --git a/gio/tests/contenttype.c b/gio/tests/contenttype.c index 3696e3662a58c72ec5f61ba501e2321745b42850..71e8b0df665b8b73bf51d0f4a773e8da715bb2b3 100644 --- a/gio/tests/contenttype.c +++ b/gio/tests/contenttype.c @@ -1,6 +1,8 @@ #include #include +#include "glib/glib-private.h" + #define g_assert_content_type_equals(s1, s2) \ do { \ const char *__s1 = (s1), *__s2 = (s2); \ @@ -16,6 +18,9 @@ static void test_guess (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gchar *res; gchar *expected; gchar *existing_directory; @@ -126,11 +131,15 @@ test_guess (void) g_assert_false (uncertain); g_free (res); g_free (expected); +#endif } static void test_unknown (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gchar *unknown; gchar *str; @@ -140,11 +149,15 @@ test_unknown (void) g_assert_cmpstr (str, ==, "application/octet-stream"); g_free (str); g_free (unknown); +#endif } static void test_subtype (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gchar *plain; gchar *xml; @@ -156,6 +169,7 @@ test_subtype (void) g_free (plain); g_free (xml); +#endif } static gint @@ -169,6 +183,10 @@ find_mime (gconstpointer a, gconstpointer b) static void test_list (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); + (void) find_mime; +#else GList *types; gchar *plain; gchar *xml; @@ -193,11 +211,15 @@ test_list (void) g_free (plain); g_free (xml); +#endif } static void test_executable (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gchar *type; type = g_content_type_from_mime_type ("application/x-executable"); @@ -211,11 +233,15 @@ test_executable (void) type = g_content_type_from_mime_type ("image/png"); g_assert_false (g_content_type_can_be_executable (type)); g_free (type); +#endif } static void test_description (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gchar *type; gchar *desc; @@ -225,11 +251,15 @@ test_description (void) g_free (desc); g_free (type); +#endif } static void test_icon (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gchar *type; GIcon *icon; @@ -266,12 +296,15 @@ test_icon (void) } g_object_unref (icon); g_free (type); +#endif } static void test_symbolic_icon (void) { -#ifndef G_OS_WIN32 +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#elif !defined(G_OS_WIN32) gchar *type; GIcon *icon; @@ -319,6 +352,9 @@ test_symbolic_icon (void) static void test_tree (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else const gchar *tests[] = { "x-content/image-dcf", "x-content/unix-software", @@ -343,11 +379,15 @@ test_tree (void) g_strfreev (types); g_object_unref (file); } +#endif } static void test_type_is_a_special_case (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else gboolean res; g_test_bug ("782311"); @@ -359,11 +399,15 @@ test_type_is_a_special_case (void) res = g_content_type_is_a ("anything", "application/octet-stream"); g_assert_true (res); #endif +#endif } static void test_guess_svg_from_data (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310"); +#else const gchar svgfilecontent[] = "\n\ uid, ==, geteuid ()); g_assert_cmpuint (native->pid, ==, getpid ()); } +#elif G_CREDENTIALS_USE_APPLE_XUCRED + { + struct xucred *native = g_credentials_get_native (creds, + G_CREDENTIALS_TYPE_APPLE_XUCRED); + + g_assert_cmpuint (native->cr_version, ==, XUCRED_VERSION); + g_assert_cmpuint (native->cr_uid, ==, geteuid ()); + } #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED { struct cmsgcred *native = g_credentials_get_native (creds, diff --git a/gio/tests/dbus-appinfo.c b/gio/tests/dbus-appinfo.c index 8961a549554388bddbd05fdb236a193ef2d814f0..7e2fc4d795a725ba4f6034dd1204f9ecf50641f0 100644 --- a/gio/tests/dbus-appinfo.c +++ b/gio/tests/dbus-appinfo.c @@ -276,12 +276,95 @@ test_dbus_appinfo (void) g_object_unref (app); } +static void +on_flatpak_launch_uris_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GApplication *app = user_data; + GError *error = NULL; + + g_app_info_launch_uris_finish (G_APP_INFO (object), result, &error); + g_assert_no_error (error); + + g_application_release (app); +} + +static void +on_flatpak_activate (GApplication *app, + gpointer user_data) +{ + GDesktopAppInfo *flatpak_appinfo = user_data; + char *uri; + GList *uris; + + /* The app will be released in on_flatpak_launch_uris_finish */ + g_application_hold (app); + + uri = g_filename_to_uri (g_desktop_app_info_get_filename (flatpak_appinfo), NULL, NULL); + g_assert_nonnull (uri); + uris = g_list_prepend (NULL, uri); + g_app_info_launch_uris_async (G_APP_INFO (flatpak_appinfo), uris, NULL, + NULL, on_flatpak_launch_uris_finish, app); + g_list_free (uris); + g_free (uri); +} + +static void +on_flatpak_open (GApplication *app, + GFile **files, + gint n_files, + const char *hint) +{ + GFile *f; + + g_assert_cmpint (n_files, ==, 1); + g_test_message ("on_flatpak_open received file '%s'", g_file_peek_path (files[0])); + + /* The file has been exported via the document portal */ + f = g_file_new_for_uri ("file:///document-portal/document-id/org.gtk.test.dbusappinfo.flatpak.desktop"); + g_assert_true (g_file_equal (files[0], f)); + g_object_unref (f); +} + +static void +test_flatpak_doc_export (void) +{ + const gchar *argv[] = { "myapp", NULL }; + gchar *desktop_file = NULL; + GDesktopAppInfo *flatpak_appinfo; + GApplication *app; + int status; + + g_test_summary ("Test that files launched via Flatpak apps are made available via the document portal."); + + desktop_file = g_test_build_filename (G_TEST_DIST, + "org.gtk.test.dbusappinfo.flatpak.desktop", + NULL); + flatpak_appinfo = g_desktop_app_info_new_from_filename (desktop_file); + g_assert_nonnull (flatpak_appinfo); + g_free (desktop_file); + + app = g_application_new ("org.gtk.test.dbusappinfo.flatpak", + G_APPLICATION_HANDLES_OPEN); + g_signal_connect (app, "activate", G_CALLBACK (on_flatpak_activate), + flatpak_appinfo); + g_signal_connect (app, "open", G_CALLBACK (on_flatpak_open), NULL); + + status = g_application_run (app, 1, (gchar **) argv); + g_assert_cmpint (status, ==, 0); + + g_object_unref (app); + g_object_unref (flatpak_appinfo); +} + int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/appinfo/dbusappinfo", test_dbus_appinfo); + g_test_add_func ("/appinfo/flatpak-doc-export", test_flatpak_doc_export); return session_bus_run (); } diff --git a/gio/tests/defaultvalue.c b/gio/tests/defaultvalue.c index 84a8635da2fa1dac122302c882d30ce0871d6825..de0e9b104bef29f75b43830e7606ac6ece459579 100644 --- a/gio/tests/defaultvalue.c +++ b/gio/tests/defaultvalue.c @@ -29,7 +29,6 @@ check_property (const char *output, if (g_param_value_defaults (pspec, value)) return; - g_value_init (&default_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_param_value_set_default (pspec, &default_value); v = g_strdup_value_contents (value); diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c index f4e509a59ebe17f0f1adab1742ff5ad069d26388..fcc29c5795228e938f1b3350a0fcb62931270811 100644 --- a/gio/tests/desktop-app-info.c +++ b/gio/tests/desktop-app-info.c @@ -303,7 +303,7 @@ test_extra_getters (void) g_assert_cmpstr (s, ==, "Bratwurst"); g_free (s); - g_setenv ("LANGUAGE", "sv_SV.UTF8", TRUE); + g_setenv ("LANGUAGE", "sv_SE.UTF8", TRUE); setlocale (LC_ALL, ""); s = g_desktop_app_info_get_locale_string (appinfo, "X-JunkFood"); @@ -350,6 +350,7 @@ wait_for_file (const gchar *want_this, static void test_actions (void) { + const char *expected[] = { "frob", "tweak", "twiddle", "broken", NULL }; const gchar * const *actions; GDesktopAppInfo *appinfo; gchar *name; @@ -358,11 +359,7 @@ test_actions (void) g_assert_nonnull (appinfo); actions = g_desktop_app_info_list_actions (appinfo); - g_assert_cmpstr (actions[0], ==, "frob"); - g_assert_cmpstr (actions[1], ==, "tweak"); - g_assert_cmpstr (actions[2], ==, "twiddle"); - g_assert_cmpstr (actions[3], ==, "broken"); - g_assert_cmpstr (actions[4], ==, NULL); + g_assert_cmpstrv (actions, expected); name = g_desktop_app_info_get_action_name (appinfo, "frob"); g_assert_cmpstr (name, ==, "Frobnicate"); @@ -571,7 +568,8 @@ assert_implementations (const gchar *interface, "gnome-terminal.desktop nautilus-autorun-software.desktop gcr-viewer.desktop " \ "nautilus-connect-server.desktop kde4-dolphin.desktop gnome-music.desktop " \ "kde4-konqbrowser.desktop gucharmap.desktop kde4-okular.desktop nautilus.desktop " \ - "gedit.desktop evince.desktop file-roller.desktop dconf-editor.desktop glade.desktop" + "gedit.desktop evince.desktop file-roller.desktop dconf-editor.desktop glade.desktop " \ + "invalid-desktop.desktop" #define HOME_APPS "epiphany-weather-for-toronto-island-9c6a4e022b17686306243dada811d550d25eb1fb.desktop" #define ALL_HOME_APPS HOME_APPS " eog.desktop" @@ -726,6 +724,9 @@ test_show_in (void) assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic"); assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic:KDE"); assert_shown ("gcr-prompter.desktop", TRUE, "KDE:GNOME-Classic"); + assert_shown ("invalid-desktop.desktop", TRUE, "GNOME"); + assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop"); + assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop:../invalid/desktop"); } /* Test g_desktop_app_info_launch_uris_as_manager() and diff --git a/gio/tests/desktop-files/home/applications/epiphany-weather-for-toronto-island-9c6a4e022b17686306243dada811d550d25eb1fb.desktop b/gio/tests/desktop-files/home/applications/epiphany-weather-for-toronto-island-9c6a4e022b similarity index 100% rename from gio/tests/desktop-files/home/applications/epiphany-weather-for-toronto-island-9c6a4e022b17686306243dada811d550d25eb1fb.desktop rename to gio/tests/desktop-files/home/applications/epiphany-weather-for-toronto-island-9c6a4e022b diff --git a/gio/tests/desktop-files/usr/applications/invalid-desktop.desktop b/gio/tests/desktop-files/usr/applications/invalid-desktop.desktop new file mode 100644 index 0000000000000000000000000000000000000000..dffaa2469222c399378336238ce70f0c060b9ac0 --- /dev/null +++ b/gio/tests/desktop-files/usr/applications/invalid-desktop.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Type=Application +Name=appinfo-test +OnlyShowIn=../invalid/desktop;GNOME +NotShowIn=ROX; diff --git a/gio/tests/empty.txt b/gio/tests/empty.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/gio/tests/fake-document-portal.c b/gio/tests/fake-document-portal.c new file mode 100644 index 0000000000000000000000000000000000000000..c9bb7950b2e79df78ffe3b19ac2bd069c9aafd47 --- /dev/null +++ b/gio/tests/fake-document-portal.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2019 Canonical Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Authors: James Henstridge + */ + +/* A stub implementation of xdg-document-portal covering enough to + * support g_document_portal_add_documents */ + +#include +#include +#include + +#include "fake-document-portal-generated.h" + +static gboolean +on_handle_get_mount_point (FakeDocuments *object, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + fake_documents_complete_get_mount_point (object, + invocation, + "/document-portal"); + return TRUE; +} + +static gboolean +on_handle_add_full (FakeDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *o_path_fds, + guint flags, + const gchar *app_id, + const gchar * const *permissions, + gpointer user_data) +{ + const gchar **doc_ids = NULL; + GVariant *extra_out = NULL; + gsize length, i; + + if (o_path_fds != NULL) + length = g_unix_fd_list_get_length (o_path_fds); + else + length = 0; + + doc_ids = g_new0 (const gchar *, length + 1 /* NULL terminator */); + for (i = 0; i < length; i++) + { + doc_ids[i] = "document-id"; + } + extra_out = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); + + fake_documents_complete_add_full (object, + invocation, + NULL, + doc_ids, + extra_out); + + g_free (doc_ids); + + return TRUE; +} + +static void +on_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + FakeDocuments *interface; + GError *error = NULL; + + g_test_message ("Acquired a message bus connection"); + + interface = fake_documents_skeleton_new (); + g_signal_connect (interface, + "handle-get-mount-point", + G_CALLBACK (on_handle_get_mount_point), + NULL); + g_signal_connect (interface, + "handle-add-full", + G_CALLBACK (on_handle_add_full), + NULL); + + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (interface), + connection, + "/org/freedesktop/portal/documents", + &error); + g_assert_no_error (error); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_test_message ("Acquired the name %s", name); +} + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_test_message ("Lost the name %s", name); +} + + +gint +main (gint argc, gchar *argv[]) +{ + GMainLoop *loop; + guint id; + + loop = g_main_loop_new (NULL, FALSE); + + id = g_bus_own_name (G_BUS_TYPE_SESSION, + "org.freedesktop.portal.Documents", + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | + G_BUS_NAME_OWNER_FLAGS_REPLACE, + on_bus_acquired, + on_name_acquired, + on_name_lost, + loop, + NULL); + + g_main_loop_run (loop); + + g_bus_unown_name (id); + g_main_loop_unref (loop); + + return 0; +} diff --git a/gio/tests/fake-service-name.c b/gio/tests/fake-service-name.c new file mode 100644 index 0000000000000000000000000000000000000000..1a601a50cb61e0ed947e800437d9d76b70f24864 --- /dev/null +++ b/gio/tests/fake-service-name.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2021 Frederic Martinsons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Authors: Frederic Martinsons + */ + +/* A dummy service which just own a dbus name and implement a method to quit*/ + +#include +#include + +static GDBusNodeInfo *introspection_data = NULL; +static GMainLoop *loop = NULL; +static const gchar introspection_xml[] = + "" + " " + " " + " " + ""; + +static void +incoming_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + if (g_strcmp0 (method_name, "Quit") == 0) + { + g_dbus_method_invocation_return_value (invocation, NULL); + g_main_loop_quit (loop); + } +} + +static const GDBusInterfaceVTable interface_vtable = { + incoming_method_call, + NULL, + NULL +}; + +static void +on_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + guint registration_id; + GError *error = NULL; + g_test_message ("Acquired a message bus connection"); + + registration_id = g_dbus_connection_register_object (connection, + "/org/gtk/GDBus/FakeService", + introspection_data->interfaces[0], + &interface_vtable, + NULL, /* user_data */ + NULL, /* user_data_free_func */ + &error); + g_assert_no_error (error); + g_assert (registration_id > 0); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_test_message ("Acquired the name %s", name); +} + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_test_message ("Lost the name %s", name); +} + +gint +main (gint argc, gchar *argv[]) +{ + guint id; + + loop = g_main_loop_new (NULL, FALSE); + introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); + g_assert (introspection_data != NULL); + + id = g_bus_own_name (G_BUS_TYPE_SESSION, + "org.gtk.GDBus.FakeService", + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | + G_BUS_NAME_OWNER_FLAGS_REPLACE, + on_bus_acquired, + on_name_acquired, + on_name_lost, + loop, + NULL); + + g_main_loop_run (loop); + + g_bus_unown_name (id); + g_main_loop_unref (loop); + g_dbus_node_info_unref (introspection_data); + + return 0; +} diff --git a/gio/tests/file.c b/gio/tests/file.c index 5b02526f3118b1922ea5d81506ac485693240392..7f5ee8e786a1a6df9181327d2fff6dc49dbc6333 100644 --- a/gio/tests/file.c +++ b/gio/tests/file.c @@ -18,11 +18,11 @@ test_basic_for_file (GFile *file, g_free (s); s = g_file_get_uri (file); - g_assert (g_str_has_prefix (s, "file://")); - g_assert (g_str_has_suffix (s, suffix)); + g_assert_true (g_str_has_prefix (s, "file://")); + g_assert_true (g_str_has_suffix (s, suffix)); g_free (s); - g_assert (g_file_has_uri_scheme (file, "file")); + g_assert_true (g_file_has_uri_scheme (file, "file")); s = g_file_get_uri_scheme (file); g_assert_cmpstr (s, ==, "file"); g_free (s); @@ -64,13 +64,13 @@ test_parent (void) file2 = g_file_new_for_path ("./some/directory"); root = g_file_new_for_path ("/"); - g_assert (g_file_has_parent (file, file2)); + g_assert_true (g_file_has_parent (file, file2)); parent = g_file_get_parent (file); - g_assert (g_file_equal (parent, file2)); + g_assert_true (g_file_equal (parent, file2)); g_object_unref (parent); - g_assert (g_file_get_parent (root) == NULL); + g_assert_null (g_file_get_parent (root)); g_object_unref (file); g_object_unref (file2); @@ -86,16 +86,36 @@ test_child (void) file = g_file_new_for_path ("./some/directory"); child = g_file_get_child (file, "child"); - g_assert (g_file_has_parent (child, file)); + g_assert_true (g_file_has_parent (child, file)); child2 = g_file_get_child_for_display_name (file, "child2", NULL); - g_assert (g_file_has_parent (child2, file)); + g_assert_true (g_file_has_parent (child2, file)); g_object_unref (child); g_object_unref (child2); g_object_unref (file); } +static void +test_empty_path (void) +{ + GFile *file = NULL; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2328"); + g_test_summary ("Check that creating a file with an empty path results in errors"); + + /* Creating the file must always succeed. */ + file = g_file_new_for_path (""); + g_assert_nonnull (file); + + /* But then querying its path should indicate it’s invalid. */ + g_assert_null (g_file_get_path (file)); + g_assert_null (g_file_get_basename (file)); + g_assert_null (g_file_get_parent (file)); + + g_object_unref (file); +} + static void test_type (void) { @@ -137,18 +157,18 @@ test_parse_name (void) file = g_file_parse_name ("~foo"); name = g_file_get_parse_name (file); - g_assert (name != NULL); + g_assert_nonnull (name); g_object_unref (file); g_free (name); } typedef struct { + GMainContext *context; GFile *file; GFileMonitor *monitor; GOutputStream *ostream; GInputStream *istream; - GMainLoop *loop; gint buffersize; gint monitor_created; gint monitor_deleted; @@ -158,6 +178,8 @@ typedef struct const gchar *data; gchar *buffer; guint timeout; + gboolean file_deleted; + gboolean timed_out; } CreateDeleteData; static void @@ -183,18 +205,8 @@ monitor_changed (GFileMonitor *monitor, data->monitor_deleted++; if (event_type == G_FILE_MONITOR_EVENT_CHANGED) data->monitor_changed++; -} - -static gboolean -quit_idle (gpointer user_data) -{ - CreateDeleteData *data = user_data; - - g_source_remove (data->timeout); - g_main_loop_quit (data->loop); - - return FALSE; + g_main_context_wakeup (data->context); } static void @@ -209,19 +221,16 @@ iclosed_cb (GObject *source, error = NULL; ret = g_input_stream_close_finish (data->istream, res, &error); g_assert_no_error (error); - g_assert (ret); + g_assert_true (ret); - g_assert (g_input_stream_is_closed (data->istream)); + g_assert_true (g_input_stream_is_closed (data->istream)); ret = g_file_delete (data->file, NULL, &error); - g_assert (ret); + g_assert_true (ret); g_assert_no_error (error); - /* work around file monitor bug: - * inotify events are only processed every 1000 ms, regardless - * of the rate limit set on the file monitor - */ - g_timeout_add (2000, quit_idle, data); + data->file_deleted = TRUE; + g_main_context_wakeup (data->context); } static void @@ -251,7 +260,7 @@ read_cb (GObject *source, else { g_assert_cmpstr (data->buffer, ==, data->data); - g_assert (!g_input_stream_is_closed (data->istream)); + g_assert_false (g_input_stream_is_closed (data->istream)); g_input_stream_close_async (data->istream, 0, NULL, iclosed_cb, data); } } @@ -346,8 +355,8 @@ oclosed_cb (GObject *source, error = NULL; ret = g_output_stream_close_finish (data->ostream, res, &error); g_assert_no_error (error); - g_assert (ret); - g_assert (g_output_stream_is_closed (data->ostream)); + g_assert_true (ret); + g_assert_true (g_output_stream_is_closed (data->ostream)); g_file_read_async (data->file, 0, NULL, opened_cb, data); } @@ -378,7 +387,7 @@ written_cb (GObject *source, } else { - g_assert (!g_output_stream_is_closed (data->ostream)); + g_assert_false (g_output_stream_is_closed (data->ostream)); g_output_stream_close_async (data->ostream, 0, NULL, oclosed_cb, data); } } @@ -409,7 +418,7 @@ created_cb (GObject *source, error = NULL; base = g_file_create_finish (G_FILE (source), res, &error); g_assert_no_error (error); - g_assert (g_file_query_exists (data->file, NULL)); + g_assert_true (g_file_query_exists (data->file, NULL)); if (data->buffersize == 0) data->ostream = G_OUTPUT_STREAM (g_object_ref (base)); @@ -435,11 +444,14 @@ created_cb (GObject *source, } static gboolean -stop_timeout (gpointer data) +stop_timeout (gpointer user_data) { - g_assert_not_reached (); + CreateDeleteData *data = user_data; - return FALSE; + data->timed_out = TRUE; + g_main_context_wakeup (data->context); + + return G_SOURCE_REMOVE; } /* @@ -461,13 +473,13 @@ test_create_delete (gconstpointer d) data->file = g_file_new_tmp ("g_file_create_delete_XXXXXX", &iostream, NULL); - g_assert (data->file != NULL); + g_assert_nonnull (data->file); g_object_unref (iostream); data->monitor_path = g_file_get_path (data->file); remove (data->monitor_path); - g_assert (!g_file_query_exists (data->file, NULL)); + g_assert_false (g_file_query_exists (data->file, NULL)); error = NULL; data->monitor = g_file_monitor_file (data->file, 0, NULL, &error); @@ -495,23 +507,32 @@ test_create_delete (gconstpointer d) g_signal_connect (data->monitor, "changed", G_CALLBACK (monitor_changed), data); - data->loop = g_main_loop_new (NULL, FALSE); - - data->timeout = g_timeout_add (10000, stop_timeout, NULL); + /* Use the global default main context */ + data->context = NULL; + data->timeout = g_timeout_add_seconds (10, stop_timeout, data); g_file_create_async (data->file, 0, 0, NULL, created_cb, data); - g_main_loop_run (data->loop); + while (!data->timed_out && + (data->monitor_created == 0 || + data->monitor_deleted == 0 || + data->monitor_changed == 0 || + !data->file_deleted)) + g_main_context_iteration (data->context, TRUE); + g_source_remove (data->timeout); + + g_assert_false (data->timed_out); + g_assert_true (data->file_deleted); g_assert_cmpint (data->monitor_created, ==, 1); g_assert_cmpint (data->monitor_deleted, ==, 1); g_assert_cmpint (data->monitor_changed, >, 0); - g_assert (!g_file_monitor_is_cancelled (data->monitor)); + g_assert_false (g_file_monitor_is_cancelled (data->monitor)); g_file_monitor_cancel (data->monitor); - g_assert (g_file_monitor_is_cancelled (data->monitor)); + g_assert_true (g_file_monitor_is_cancelled (data->monitor)); - g_main_loop_unref (data->loop); + g_clear_pointer (&data->context, g_main_context_unref); g_object_unref (data->ostream); g_object_unref (data->istream); @@ -582,7 +603,7 @@ loaded_cb (GObject *source, error = NULL; ret = g_file_load_contents_finish (data->file, res, &contents, &length, NULL, &error); - g_assert (ret); + g_assert_true (ret); g_assert_no_error (error); g_assert_cmpint (length, ==, strlen (data->data)); g_assert_cmpstr (contents, ==, data->data); @@ -609,8 +630,8 @@ loaded_cb (GObject *source, error = NULL; ret = g_file_delete (data->file, NULL, &error); g_assert_no_error (error); - g_assert (ret); - g_assert (!g_file_query_exists (data->file, NULL)); + g_assert_true (ret); + g_assert_false (g_file_query_exists (data->file, NULL)); g_main_loop_quit (data->loop); } @@ -644,13 +665,13 @@ test_replace_load (void) data->file = g_file_new_tmp ("g_file_replace_load_XXXXXX", &iostream, NULL); - g_assert (data->file != NULL); + g_assert_nonnull (data->file); g_object_unref (iostream); path = g_file_peek_path (data->file); remove (path); - g_assert (!g_file_query_exists (data->file, NULL)); + g_assert_false (g_file_query_exists (data->file, NULL)); data->loop = g_main_loop_new (NULL, FALSE); @@ -717,11 +738,11 @@ test_replace_cancel (void) info = g_file_enumerator_next_file (fenum, NULL, &error); g_assert_no_error (error); - g_assert (info != NULL); + g_assert_nonnull (info); g_object_unref (info); info = g_file_enumerator_next_file (fenum, NULL, &error); g_assert_no_error (error); - g_assert (info != NULL); + g_assert_nonnull (info); g_object_unref (info); g_file_enumerator_close (fenum, NULL, &error); @@ -736,7 +757,7 @@ test_replace_cancel (void) while (TRUE) { gboolean ret = g_file_enumerator_iterate (fenum, &info, NULL, NULL, &error); - g_assert (ret); + g_assert_true (ret); g_assert_no_error (error); if (!info) break; @@ -758,13 +779,13 @@ test_replace_cancel (void) GFile *child; gboolean ret = g_file_enumerator_iterate (fenum, NULL, &child, NULL, &error); - g_assert (ret); + g_assert_true (ret); g_assert_no_error (error); if (!child) break; - g_assert (G_IS_FILE (child)); + g_assert_true (G_IS_FILE (child)); count++; } g_assert_cmpint (count, ==, 2); @@ -820,6 +841,7 @@ test_replace_symlink (void) GError *local_error = NULL; g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2325"); + g_test_summary ("Test that G_FILE_CREATE_REPLACE_DESTINATION doesn’t follow symlinks"); /* Create a fresh, empty working directory. */ tmpdir_path = g_dir_make_tmp ("g_file_replace_symlink_XXXXXX", &local_error); @@ -910,6 +932,912 @@ test_replace_symlink (void) #endif } +/* FIXME: These tests have only been checked on Linux. Most of them are probably + * applicable on Windows, too, but that has not been tested yet. + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2325 */ +#ifdef __linux__ + +/* Different kinds of file which create_test_file() can create. */ +typedef enum +{ + FILE_TEST_SETUP_TYPE_NONEXISTENT, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, + FILE_TEST_SETUP_TYPE_DIRECTORY, + FILE_TEST_SETUP_TYPE_SOCKET, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, +} FileTestSetupType; + +/* Create file `tmpdir/basename`, of type @setup_type, and chmod it to + * @setup_mode. Return the #GFile representing it. Abort on any errors. */ +static GFile * +create_test_file (GFile *tmpdir, + const gchar *basename, + FileTestSetupType setup_type, + guint setup_mode) +{ + GFile *test_file = g_file_get_child (tmpdir, basename); + gchar *target_basename = g_strdup_printf ("%s-target", basename); /* for symlinks */ + GFile *target_file = g_file_get_child (tmpdir, target_basename); + GError *local_error = NULL; + + switch (setup_type) + { + case FILE_TEST_SETUP_TYPE_NONEXISTENT: + /* Nothing to do here. */ + g_assert (setup_mode == 0); + break; + case FILE_TEST_SETUP_TYPE_REGULAR_EMPTY: + case FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY: + { + gchar *contents = NULL; + + if (setup_type == FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY) + contents = g_strdup_printf ("this is some test content in %s", basename); + else + contents = g_strdup (""); + + g_file_set_contents (g_file_peek_path (test_file), contents, -1, &local_error); + g_assert_no_error (local_error); + + g_file_set_attribute_uint32 (test_file, G_FILE_ATTRIBUTE_UNIX_MODE, + setup_mode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, &local_error); + g_assert_no_error (local_error); + + g_free (contents); + break; + } + case FILE_TEST_SETUP_TYPE_DIRECTORY: + g_assert (setup_mode == 0); + + g_file_make_directory (test_file, NULL, &local_error); + g_assert_no_error (local_error); + break; + case FILE_TEST_SETUP_TYPE_SOCKET: + g_assert_no_errno (mknod (g_file_peek_path (test_file), S_IFSOCK | setup_mode, 0)); + break; + case FILE_TEST_SETUP_TYPE_SYMLINK_VALID: + g_file_set_contents (g_file_peek_path (target_file), "target file", -1, &local_error); + g_assert_no_error (local_error); + G_GNUC_FALLTHROUGH; + case FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING: + /* Permissions on a symlink are not used by the kernel, so are only + * applicable if the symlink is valid (and are applied to the target) */ + g_assert (setup_type != FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING || setup_mode == 0); + + g_file_make_symbolic_link (test_file, target_basename, NULL, &local_error); + g_assert_no_error (local_error); + + if (setup_type == FILE_TEST_SETUP_TYPE_SYMLINK_VALID) + { + g_file_set_attribute_uint32 (test_file, G_FILE_ATTRIBUTE_UNIX_MODE, + setup_mode, G_FILE_QUERY_INFO_NONE, + NULL, &local_error); + g_assert_no_error (local_error); + } + + if (setup_type == FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING) + { + /* Ensure that the target doesn’t exist */ + g_assert_false (g_file_query_exists (target_file, NULL)); + } + break; + default: + g_assert_not_reached (); + } + + g_clear_object (&target_file); + g_free (target_basename); + + return g_steal_pointer (&test_file); +} + +/* Check that @test_file is of the @expected_type, has the @expected_mode, and + * (if it’s a regular file) has the @expected_contents or (if it’s a symlink) + * has the symlink target given by @expected_contents. + * + * @test_file must point to the file `tmpdir/basename`. + * + * Aborts on any errors or mismatches against the expectations. + */ +static void +check_test_file (GFile *test_file, + GFile *tmpdir, + const gchar *basename, + FileTestSetupType expected_type, + guint expected_mode, + const gchar *expected_contents) +{ + gchar *target_basename = g_strdup_printf ("%s-target", basename); /* for symlinks */ + GFile *target_file = g_file_get_child (tmpdir, target_basename); + GFileType test_file_type = g_file_query_file_type (test_file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL); + GFileInfo *info = NULL; + GError *local_error = NULL; + + switch (expected_type) + { + case FILE_TEST_SETUP_TYPE_NONEXISTENT: + g_assert (expected_mode == 0); + g_assert (expected_contents == NULL); + + g_assert_false (g_file_query_exists (test_file, NULL)); + g_assert_cmpint (test_file_type, ==, G_FILE_TYPE_UNKNOWN); + break; + case FILE_TEST_SETUP_TYPE_REGULAR_EMPTY: + case FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY: + g_assert (expected_type != FILE_TEST_SETUP_TYPE_REGULAR_EMPTY || expected_contents == NULL); + g_assert (expected_type != FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY || expected_contents != NULL); + + g_assert_cmpint (test_file_type, ==, G_FILE_TYPE_REGULAR); + + info = g_file_query_info (test_file, + G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_UNIX_MODE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); + g_assert_no_error (local_error); + + if (expected_type == FILE_TEST_SETUP_TYPE_REGULAR_EMPTY) + g_assert_cmpint (g_file_info_get_size (info), ==, 0); + else + g_assert_cmpint (g_file_info_get_size (info), >, 0); + + if (expected_contents != NULL) + { + gchar *contents = NULL; + gsize length = 0; + + g_file_get_contents (g_file_peek_path (test_file), &contents, &length, &local_error); + g_assert_no_error (local_error); + + g_assert_cmpstr (contents, ==, expected_contents); + g_free (contents); + } + + g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & 0777, ==, expected_mode); + + break; + case FILE_TEST_SETUP_TYPE_DIRECTORY: + g_assert (expected_mode == 0); + g_assert (expected_contents == NULL); + + g_assert_cmpint (test_file_type, ==, G_FILE_TYPE_DIRECTORY); + break; + case FILE_TEST_SETUP_TYPE_SOCKET: + g_assert (expected_contents == NULL); + + g_assert_cmpint (test_file_type, ==, G_FILE_TYPE_SPECIAL); + + info = g_file_query_info (test_file, + G_FILE_ATTRIBUTE_UNIX_MODE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); + g_assert_no_error (local_error); + + g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & 0777, ==, expected_mode); + break; + case FILE_TEST_SETUP_TYPE_SYMLINK_VALID: + case FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING: + { + GFile *symlink_target_file = NULL; + + /* Permissions on a symlink are not used by the kernel, so are only + * applicable if the symlink is valid (and are applied to the target) */ + g_assert (expected_type != FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING || expected_mode == 0); + g_assert (expected_contents != NULL); + + g_assert_cmpint (test_file_type, ==, G_FILE_TYPE_SYMBOLIC_LINK); + + info = g_file_query_info (test_file, + G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); + g_assert_no_error (local_error); + + g_assert_cmpstr (g_file_info_get_symlink_target (info), ==, expected_contents); + + symlink_target_file = g_file_get_child (tmpdir, g_file_info_get_symlink_target (info)); + if (expected_type == FILE_TEST_SETUP_TYPE_SYMLINK_VALID) + g_assert_true (g_file_query_exists (symlink_target_file, NULL)); + else + g_assert_false (g_file_query_exists (symlink_target_file, NULL)); + + if (expected_type == FILE_TEST_SETUP_TYPE_SYMLINK_VALID) + { + GFileInfo *target_info = NULL; + + /* Need to re-query the info so we follow symlinks */ + target_info = g_file_query_info (test_file, + G_FILE_ATTRIBUTE_UNIX_MODE, + G_FILE_QUERY_INFO_NONE, NULL, &local_error); + g_assert_no_error (local_error); + + g_assert_cmpuint (g_file_info_get_attribute_uint32 (target_info, G_FILE_ATTRIBUTE_UNIX_MODE) & 0777, ==, expected_mode); + + g_clear_object (&target_info); + } + + g_clear_object (&symlink_target_file); + break; + } + default: + g_assert_not_reached (); + } + + g_clear_object (&info); + g_clear_object (&target_file); + g_free (target_basename); +} + +#endif /* __linux__ */ + +/* A big test for g_file_replace() and g_file_replace_readwrite(). The + * @test_data is a boolean: %TRUE to test g_file_replace_readwrite(), %FALSE to + * test g_file_replace(). The test setup and checks are identical for both + * functions; in the case of testing g_file_replace_readwrite(), only the output + * stream side of the returned #GIOStream is tested. i.e. We test the write + * behaviour of both functions is identical. + * + * This is intended to test all static behaviour of the function: for each test + * scenario, a temporary directory is set up with a source file (and maybe some + * other files) in a set configuration, g_file_replace{,_readwrite}() is called, + * and the final state of the directory is checked. + * + * This test does not check dynamic behaviour or race conditions. For example, + * it does not test what happens if the source file is deleted from another + * process half-way through a call to g_file_replace(). + */ +static void +test_replace (gconstpointer test_data) +{ +#ifdef __linux__ + gboolean read_write = GPOINTER_TO_UINT (test_data); + const gchar *new_contents = "this is a new test message which should be written to source"; + const gchar *original_source_contents = "this is some test content in source"; + const gchar *original_backup_contents = "this is some test content in source~"; + mode_t current_umask = umask (0); + guint32 default_public_mode = 0666 & ~current_umask; + guint32 default_private_mode = 0600; + + const struct + { + /* Arguments to pass to g_file_replace(). */ + gboolean replace_make_backup; + GFileCreateFlags replace_flags; + const gchar *replace_etag; /* (nullable) */ + + /* File system setup. */ + FileTestSetupType setup_source_type; + guint setup_source_mode; + FileTestSetupType setup_backup_type; + guint setup_backup_mode; + + /* Expected results. */ + gboolean expected_success; + GQuark expected_error_domain; + gint expected_error_code; + + /* Expected final file system state. */ + guint expected_n_files; + FileTestSetupType expected_source_type; + guint expected_source_mode; + const gchar *expected_source_contents; /* content for a regular file, or target for a symlink; NULL otherwise */ + FileTestSetupType expected_backup_type; + guint expected_backup_mode; + const gchar *expected_backup_contents; /* content for a regular file, or target for a symlink; NULL otherwise */ + } + tests[] = + { + /* replace_make_backup == FALSE, replace_flags == NONE, replace_etag == NULL, + * all the different values of setup_source_type, mostly with a backup + * file created to check it’s not modified */ + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + 2, FILE_TEST_SETUP_TYPE_DIRECTORY, 0, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_NOT_REGULAR_FILE, + 2, FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 3, FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, "source-target", + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 3, FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, "source-target", + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + + /* replace_etag set to an invalid value, with setup_source_type as a + * regular non-empty file; replacement should fail */ + { + FALSE, G_FILE_CREATE_NONE, "incorrect etag", + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + + /* replace_make_backup == TRUE, replace_flags == NONE, replace_etag == NULL, + * all the different values of setup_source_type, with a backup + * file created to check it’s either replaced or the operation fails */ + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, NULL, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + 2, FILE_TEST_SETUP_TYPE_DIRECTORY, 0, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_NOT_REGULAR_FILE, + 2, FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + /* The final situation here is a bit odd; the backup file is a bit + * pointless as the original source file was a dangling symlink. + * Theoretically the backup file should be that symlink, pointing to + * `source-target`, and hence no longer dangling, as that file has now + * been created as the new source content, since REPLACE_DESTINATION was + * not specified. However, the code instead creates an empty regular + * file as the backup. FIXME: This seems acceptable for now, but not + * entirely ideal and would be good to fix at some point. */ + 3, FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, "source-target", + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, 0777 & ~current_umask, NULL, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + /* FIXME: The permissions for the backup file are just the default umask, + * but should probably be the same as the permissions for the source + * file (`default_public_mode`). This probably arises from the fact that + * symlinks don’t have permissions. */ + 3, FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, "source-target", + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, 0777 & ~current_umask, "target file", + }, + + /* replace_make_backup == TRUE, replace_flags == NONE, replace_etag == NULL, + * setup_source_type is a regular file, with a backup file of every type + * created to check it’s either replaced or the operation fails */ + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, + FALSE, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, NULL, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, + TRUE, 0, 0, + /* the third file is `source~-target`, the original target of the old + * backup symlink */ + 3, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + + /* replace_make_backup == FALSE, replace_flags == REPLACE_DESTINATION, + * replace_etag == NULL, all the different values of setup_source_type, + * mostly with a backup file created to check it’s not modified */ + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + 2, FILE_TEST_SETUP_TYPE_DIRECTORY, 0, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_NOT_REGULAR_FILE, + 2, FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + /* the third file is `source-target`, the original target of the old + * source file */ + 3, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + + /* replace_flags == REPLACE_DESTINATION, replace_etag set to an invalid + * value, with setup_source_type as a regular non-empty file; replacement + * should fail */ + { + FALSE, G_FILE_CREATE_REPLACE_DESTINATION, "incorrect etag", + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + + /* replace_make_backup == TRUE, replace_flags == REPLACE_DESTINATION, + * replace_etag == NULL, all the different values of setup_source_type, + * with a backup file created to check it’s either replaced or the + * operation fails */ + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, NULL, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + 2, FILE_TEST_SETUP_TYPE_DIRECTORY, 0, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FALSE, G_IO_ERROR, G_IO_ERROR_NOT_REGULAR_FILE, + 2, FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_backup_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, "source-target", + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + /* the third file is `source-target`, the original target of the old + * source file */ + 3, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, "source-target", + }, + + /* replace_make_backup == TRUE, replace_flags == REPLACE_DESTINATION, + * replace_etag == NULL, setup_source_type is a regular file, with a + * backup file of every type created to check it’s either replaced or the + * operation fails */ + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, + FALSE, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + FILE_TEST_SETUP_TYPE_DIRECTORY, 0, NULL, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_SOCKET, default_public_mode, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_SYMLINK_DANGLING, 0, + TRUE, 0, 0, + 2, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + { + TRUE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_SYMLINK_VALID, default_public_mode, + TRUE, 0, 0, + /* the third file is `source~-target`, the original target of the old + * backup symlink */ + 3, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, original_source_contents, + }, + + /* several different setups with replace_flags == PRIVATE */ + { + FALSE, G_FILE_CREATE_PRIVATE, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_private_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + FALSE, G_FILE_CREATE_PRIVATE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + /* the file isn’t being replaced, so it should keep its existing permissions */ + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + FALSE, G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_private_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + { + FALSE, G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_public_mode, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + TRUE, 0, 0, + 1, FILE_TEST_SETUP_TYPE_REGULAR_NONEMPTY, default_private_mode, new_contents, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + + /* make the initial source file unreadable, so the replace operation + * should fail */ + { + FALSE, G_FILE_CREATE_NONE, NULL, + FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, 0 /* most restrictive permissions */, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, + FALSE, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, + 1, FILE_TEST_SETUP_TYPE_REGULAR_EMPTY, 0, NULL, + FILE_TEST_SETUP_TYPE_NONEXISTENT, 0, NULL, + }, + }; + gsize i; + + g_test_summary ("Test various situations for g_file_replace()"); + + /* Reset the umask after querying it above. There’s no way to query it without + * changing it. */ + umask (current_umask); + g_test_message ("Current umask: %u", current_umask); + + for (i = 0; i < G_N_ELEMENTS (tests); i++) + { + gchar *tmpdir_path = NULL; + GFile *tmpdir = NULL, *source_file = NULL, *backup_file = NULL; + GFileOutputStream *output_stream = NULL; + GFileIOStream *io_stream = NULL; + GFileEnumerator *enumerator = NULL; + GFileInfo *info = NULL; + guint n_files; + GError *local_error = NULL; + + /* Create a fresh, empty working directory. */ + tmpdir_path = g_dir_make_tmp ("g_file_replace_XXXXXX", &local_error); + g_assert_no_error (local_error); + tmpdir = g_file_new_for_path (tmpdir_path); + + g_test_message ("Test %" G_GSIZE_FORMAT ", using temporary directory %s", i, tmpdir_path); + g_free (tmpdir_path); + + /* Set up the test directory. */ + source_file = create_test_file (tmpdir, "source", tests[i].setup_source_type, tests[i].setup_source_mode); + backup_file = create_test_file (tmpdir, "source~", tests[i].setup_backup_type, tests[i].setup_backup_mode); + + /* Replace the source file. Check the error state only after finishing + * writing, as the replace operation is split across g_file_replace() and + * g_output_stream_close(). */ + if (read_write) + io_stream = g_file_replace_readwrite (source_file, + tests[i].replace_etag, + tests[i].replace_make_backup, + tests[i].replace_flags, + NULL, + &local_error); + else + output_stream = g_file_replace (source_file, + tests[i].replace_etag, + tests[i].replace_make_backup, + tests[i].replace_flags, + NULL, + &local_error); + + if (tests[i].expected_success) + { + g_assert_no_error (local_error); + if (read_write) + g_assert_nonnull (io_stream); + else + g_assert_nonnull (output_stream); + } + + /* Write new content to it. */ + if (io_stream != NULL) + { + GOutputStream *io_output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream)); + gsize n_written; + + g_output_stream_write_all (G_OUTPUT_STREAM (io_output_stream), new_contents, strlen (new_contents), + &n_written, NULL, &local_error); + + if (tests[i].expected_success) + { + g_assert_no_error (local_error); + g_assert_cmpint (n_written, ==, strlen (new_contents)); + } + + g_io_stream_close (G_IO_STREAM (io_stream), NULL, (local_error == NULL) ? &local_error : NULL); + + if (tests[i].expected_success) + g_assert_no_error (local_error); + } + else if (output_stream != NULL) + { + gsize n_written; + + g_output_stream_write_all (G_OUTPUT_STREAM (output_stream), new_contents, strlen (new_contents), + &n_written, NULL, &local_error); + + if (tests[i].expected_success) + { + g_assert_no_error (local_error); + g_assert_cmpint (n_written, ==, strlen (new_contents)); + } + + g_output_stream_close (G_OUTPUT_STREAM (output_stream), NULL, (local_error == NULL) ? &local_error : NULL); + + if (tests[i].expected_success) + g_assert_no_error (local_error); + } + + if (tests[i].expected_success) + g_assert_no_error (local_error); + else + g_assert_error (local_error, tests[i].expected_error_domain, tests[i].expected_error_code); + + g_clear_error (&local_error); + g_clear_object (&io_stream); + g_clear_object (&output_stream); + + /* Verify the final state of the directory. */ + enumerator = g_file_enumerate_children (tmpdir, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); + g_assert_no_error (local_error); + + n_files = 0; + do + { + g_file_enumerator_iterate (enumerator, &info, NULL, NULL, &local_error); + g_assert_no_error (local_error); + + if (info != NULL) + n_files++; + } + while (info != NULL); + + g_clear_object (&enumerator); + + g_assert_cmpuint (n_files, ==, tests[i].expected_n_files); + + check_test_file (source_file, tmpdir, "source", tests[i].expected_source_type, tests[i].expected_source_mode, tests[i].expected_source_contents); + check_test_file (backup_file, tmpdir, "source~", tests[i].expected_backup_type, tests[i].expected_backup_mode, tests[i].expected_backup_contents); + + /* Tidy up. Ignore failure apart from when deleting the directory, which + * should be empty. */ + g_file_delete (source_file, NULL, NULL); + g_file_delete (backup_file, NULL, NULL); + + /* Other files which are occasionally generated by the tests. */ + { + GFile *backup_target_file = g_file_get_child (tmpdir, "source~-target"); + g_file_delete (backup_target_file, NULL, NULL); + g_clear_object (&backup_target_file); + } + { + GFile *backup_target_file = g_file_get_child (tmpdir, "source-target"); + g_file_delete (backup_target_file, NULL, NULL); + g_clear_object (&backup_target_file); + } + + g_file_delete (tmpdir, NULL, &local_error); + g_assert_no_error (local_error); + + g_clear_object (&backup_file); + g_clear_object (&source_file); + g_clear_object (&tmpdir); + } +#else /* if !__linux__ */ + g_test_skip ("File replacement tests can only be run on Linux"); +#endif +} + static void on_file_deleted (GObject *object, GAsyncResult *result, @@ -938,7 +1866,7 @@ test_async_delete (void) g_assert_no_error (local_error); g_object_unref (iostream); - g_assert (g_file_query_exists (file, NULL)); + g_assert_true (g_file_query_exists (file, NULL)); loop = g_main_loop_new (NULL, TRUE); @@ -946,64 +1874,109 @@ test_async_delete (void) g_main_loop_run (loop); - g_assert (!g_file_query_exists (file, NULL)); + g_assert_false (g_file_query_exists (file, NULL)); g_main_loop_unref (loop); g_object_unref (file); } -#ifdef G_OS_UNIX static void test_copy_preserve_mode (void) { - GFile *tmpfile; - GFile *dest_tmpfile; - GFileInfo *dest_info; - GFileIOStream *iostream; - GError *local_error = NULL; - GError **error = &local_error; - guint32 romode = S_IFREG | 0600; - guint32 dest_mode; - - tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX", - &iostream, error); - g_assert_no_error (local_error); - g_io_stream_close ((GIOStream*)iostream, NULL, error); - g_assert_no_error (local_error); - g_clear_object (&iostream); - - g_file_set_attribute (tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_ATTRIBUTE_TYPE_UINT32, - &romode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, error); - g_assert_no_error (local_error); - - dest_tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX", - &iostream, error); - g_assert_no_error (local_error); - g_io_stream_close ((GIOStream*)iostream, NULL, error); - g_assert_no_error (local_error); - g_clear_object (&iostream); - - g_file_copy (tmpfile, dest_tmpfile, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA, - NULL, NULL, NULL, error); - g_assert_no_error (local_error); - - dest_info = g_file_query_info (dest_tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, error); - g_assert_no_error (local_error); - - dest_mode = g_file_info_get_attribute_uint32 (dest_info, G_FILE_ATTRIBUTE_UNIX_MODE); - - g_assert_cmpint (dest_mode, ==, romode); - - (void) g_file_delete (tmpfile, NULL, NULL); - (void) g_file_delete (dest_tmpfile, NULL, NULL); - - g_clear_object (&tmpfile); - g_clear_object (&dest_tmpfile); - g_clear_object (&dest_info); -} +#ifdef G_OS_UNIX + mode_t current_umask = umask (0); + const struct + { + guint32 source_mode; + guint32 expected_destination_mode; + gboolean create_destination_before_copy; + GFileCopyFlags copy_flags; + } + vectors[] = + { + /* Overwriting the destination file should copy the permissions from the + * source file, even if %G_FILE_COPY_ALL_METADATA is set: */ + { 0600, 0600, TRUE, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, + { 0600, 0600, TRUE, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS }, + /* The same behaviour should hold if the destination file is not being + * overwritten because it doesn’t already exist: */ + { 0600, 0600, FALSE, G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, + { 0600, 0600, FALSE, G_FILE_COPY_NOFOLLOW_SYMLINKS }, + /* Anything with %G_FILE_COPY_TARGET_DEFAULT_PERMS should use the current + * umask for the destination file: */ + { 0600, 0666 & ~current_umask, TRUE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, + { 0600, 0666 & ~current_umask, TRUE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS }, + { 0600, 0666 & ~current_umask, FALSE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, + { 0600, 0666 & ~current_umask, FALSE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS }, + }; + gsize i; + + /* Reset the umask after querying it above. There’s no way to query it without + * changing it. */ + umask (current_umask); + g_test_message ("Current umask: %u", current_umask); + + for (i = 0; i < G_N_ELEMENTS (vectors); i++) + { + GFile *tmpfile; + GFile *dest_tmpfile; + GFileInfo *dest_info; + GFileIOStream *iostream; + GError *local_error = NULL; + guint32 romode = vectors[i].source_mode; + guint32 dest_mode; + + g_test_message ("Vector %" G_GSIZE_FORMAT, i); + + tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX", + &iostream, &local_error); + g_assert_no_error (local_error); + g_io_stream_close ((GIOStream*)iostream, NULL, &local_error); + g_assert_no_error (local_error); + g_clear_object (&iostream); + + g_file_set_attribute (tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_ATTRIBUTE_TYPE_UINT32, + &romode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, &local_error); + g_assert_no_error (local_error); + + dest_tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX", + &iostream, &local_error); + g_assert_no_error (local_error); + g_io_stream_close ((GIOStream*)iostream, NULL, &local_error); + g_assert_no_error (local_error); + g_clear_object (&iostream); + + if (!vectors[i].create_destination_before_copy) + { + g_file_delete (dest_tmpfile, NULL, &local_error); + g_assert_no_error (local_error); + } + + g_file_copy (tmpfile, dest_tmpfile, vectors[i].copy_flags, + NULL, NULL, NULL, &local_error); + g_assert_no_error (local_error); + + dest_info = g_file_query_info (dest_tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, &local_error); + g_assert_no_error (local_error); + + dest_mode = g_file_info_get_attribute_uint32 (dest_info, G_FILE_ATTRIBUTE_UNIX_MODE); + + g_assert_cmpint (dest_mode & ~S_IFMT, ==, vectors[i].expected_destination_mode); + g_assert_cmpint (dest_mode & S_IFMT, ==, S_IFREG); + + (void) g_file_delete (tmpfile, NULL, NULL); + (void) g_file_delete (dest_tmpfile, NULL, NULL); + + g_clear_object (&tmpfile); + g_clear_object (&dest_tmpfile); + g_clear_object (&dest_info); + } +#else /* if !G_OS_UNIX */ + g_test_skip ("File permissions tests can only be run on Unix") #endif +} static gchar * splice_to_string (GInputStream *stream, @@ -1095,13 +2068,13 @@ test_measure (void) &num_dirs, &num_files, &error); - g_assert (ok); + g_assert_true (ok); g_assert_no_error (error); if (size > 0) g_assert_cmpuint (num_bytes, ==, size); g_assert_cmpuint (num_dirs, ==, 6); - g_assert_cmpuint (num_files, ==, 31); + g_assert_cmpuint (num_files, ==, 32); g_object_unref (file); g_free (path); @@ -1148,7 +2121,7 @@ measure_done (GObject *source, gboolean ok; ok = g_file_measure_disk_usage_finish (G_FILE (source), res, &num_bytes, &num_dirs, &num_files, &error); - g_assert (ok); + g_assert_true (ok); g_assert_no_error (error); if (data->expected_bytes > 0) @@ -1191,7 +2164,7 @@ test_measure_async (void) g_free (path); data->expected_dirs = 6; - data->expected_files = 31; + data->expected_files = 32; g_file_measure_disk_usage_async (file, G_FILE_MEASURE_APPARENT_SIZE, @@ -1221,7 +2194,7 @@ test_load_bytes (void) file = g_file_new_for_path (filename); bytes = g_file_load_bytes (file, NULL, NULL, &error); g_assert_no_error (error); - g_assert (bytes != NULL); + g_assert_nonnull (bytes); g_assert_cmpint (len, ==, g_bytes_get_size (bytes)); g_assert_cmpstr ("test_load_bytes", ==, (gchar *)g_bytes_get_data (bytes, NULL)); @@ -1249,7 +2222,7 @@ test_load_bytes_cb (GObject *object, data->bytes = g_file_load_bytes_finish (file, result, NULL, &error); g_assert_no_error (error); - g_assert (data->bytes != NULL); + g_assert_nonnull (data->bytes); g_main_loop_quit (data->main_loop); } @@ -1840,17 +2813,89 @@ test_writev_async_all_too_big_vectors (void) g_object_unref (file); } +static void +test_build_attribute_list_for_copy (void) +{ + GFile *tmpfile; + GFileIOStream *iostream; + GError *error = NULL; + const GFileCopyFlags test_flags[] = + { + G_FILE_COPY_NONE, + G_FILE_COPY_TARGET_DEFAULT_PERMS, + G_FILE_COPY_ALL_METADATA, + G_FILE_COPY_ALL_METADATA | G_FILE_COPY_TARGET_DEFAULT_PERMS, + }; + gsize i; + char *attrs; + gchar *attrs_with_commas; + + tmpfile = g_file_new_tmp ("tmp-build-attribute-list-for-copyXXXXXX", + &iostream, &error); + g_assert_no_error (error); + g_io_stream_close ((GIOStream*)iostream, NULL, &error); + g_assert_no_error (error); + g_clear_object (&iostream); + + for (i = 0; i < G_N_ELEMENTS (test_flags); i++) + { + GFileCopyFlags flags = test_flags[i]; + + attrs = g_file_build_attribute_list_for_copy (tmpfile, flags, NULL, &error); + g_test_message ("Attributes for copy: %s", attrs); + g_assert_no_error (error); + g_assert_nonnull (attrs); + attrs_with_commas = g_strconcat (",", attrs, ",", NULL); + g_free (attrs); + + /* See g_local_file_class_init for reference. */ + if (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_MODE ",")); + else + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_MODE ",")); +#ifdef G_OS_UNIX + if (flags & G_FILE_COPY_ALL_METADATA) + { + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_UID ",")); + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_GID ",")); + } + else + { + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_UID ",")); + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_UNIX_GID ",")); + } +#endif +#ifdef HAVE_UTIMES + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ",")); + if (flags & G_FILE_COPY_ALL_METADATA) + { + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ",")); + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC ",")); + } + else + { + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ",")); + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC ",")); + } +#endif + g_free (attrs_with_commas); + } + + (void) g_file_delete (tmpfile, NULL, NULL); + g_clear_object (&tmpfile); +} + int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base (""); - g_test_add_func ("/file/basic", test_basic); g_test_add_func ("/file/build-filename", test_build_filename); g_test_add_func ("/file/parent", test_parent); g_test_add_func ("/file/child", test_child); + g_test_add_func ("/file/empty-path", test_empty_path); g_test_add_func ("/file/type", test_type); g_test_add_func ("/file/parse-name", test_parse_name); g_test_add_data_func ("/file/async-create-delete/0", GINT_TO_POINTER (0), test_create_delete); @@ -1861,10 +2906,10 @@ main (int argc, char *argv[]) g_test_add_func ("/file/replace-load", test_replace_load); g_test_add_func ("/file/replace-cancel", test_replace_cancel); g_test_add_func ("/file/replace-symlink", test_replace_symlink); + g_test_add_data_func ("/file/replace/write-only", GUINT_TO_POINTER (FALSE), test_replace); + g_test_add_data_func ("/file/replace/read-write", GUINT_TO_POINTER (TRUE), test_replace); g_test_add_func ("/file/async-delete", test_async_delete); -#ifdef G_OS_UNIX g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode); -#endif g_test_add_func ("/file/measure", test_measure); g_test_add_func ("/file/measure-async", test_measure_async); g_test_add_func ("/file/load-bytes", test_load_bytes); @@ -1880,6 +2925,7 @@ main (int argc, char *argv[]) g_test_add_func ("/file/writev/async_all-no-vectors", test_writev_async_all_no_vectors); g_test_add_func ("/file/writev/async_all-to-big-vectors", test_writev_async_all_too_big_vectors); g_test_add_func ("/file/writev/async_all-cancellation", test_writev_async_all_cancellation); + g_test_add_func ("/file/build-attribute-list-for-copy", test_build_attribute_list_for_copy); return g_test_run (); } diff --git a/gio/tests/g-file-info-filesystem-readonly.c b/gio/tests/g-file-info-filesystem-readonly.c index a715ef8d064c15036864678d74f47d8917222fe7..16fa83e332ed4a06d7efb828464e6f013d7979e3 100644 --- a/gio/tests/g-file-info-filesystem-readonly.c +++ b/gio/tests/g-file-info-filesystem-readonly.c @@ -25,7 +25,7 @@ #include #include -static void +static gboolean run (GError **error, const gchar *argv0, ...) @@ -34,6 +34,8 @@ run (GError **error, const gchar *arg; va_list ap; GSubprocess *subprocess; + gchar *command_line = NULL; + gboolean success; args = g_ptr_array_new (); @@ -44,14 +46,20 @@ run (GError **error, g_ptr_array_add (args, NULL); va_end (ap); + command_line = g_strjoinv (" ", (gchar **) args->pdata); + g_test_message ("Running command `%s`", command_line); + g_free (command_line); + subprocess = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error); g_ptr_array_free (args, TRUE); if (subprocess == NULL) - return; + return FALSE; - g_subprocess_wait_check (subprocess, NULL, error); + success = g_subprocess_wait_check (subprocess, NULL, error); g_object_unref (subprocess); + + return success; } static void @@ -61,6 +69,24 @@ assert_remove (const gchar *file) g_error ("failed to remove %s: %s", file, g_strerror (errno)); } +static gboolean +fuse_module_loaded (void) +{ + char *contents = NULL; + gboolean ret; + + if (!g_file_get_contents ("/proc/modules", &contents, NULL, NULL) || + contents == NULL) + { + g_free (contents); + return FALSE; + } + + ret = (strstr (contents, "\nfuse ") != NULL); + g_free (contents); + return ret; +} + static void test_filesystem_readonly (gconstpointer with_mount_monitor) { @@ -87,6 +113,18 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) return; } + /* If the fuse module is loaded but there's no /dev/fuse, then we're + * we're probably in a rootless container and won't be able to + * use bindfs to run our tests */ + if (fuse_module_loaded () && + !g_file_test ("/dev/fuse", G_FILE_TEST_EXISTS)) + { + g_test_skip ("fuse support is needed to run this test (rootless container?)"); + g_free (fusermount); + g_free (bindfs); + return; + } + curdir = g_get_current_dir (); dir_to_mount = g_strdup_printf ("%s/dir_bindfs_to_mount", curdir); file_in_mount = g_strdup_printf ("%s/example.txt", dir_to_mount); @@ -105,8 +143,14 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) /* Use bindfs, which does not need root privileges, to mount the contents of one dir * into another dir (and do the mount as readonly as per passed '-o ro' option) */ - run (&error, bindfs, "-n", "-o", "ro", dir_to_mount, dir_mountpoint, NULL); - g_assert_no_error (error); + if (!run (&error, bindfs, "-n", "-o", "ro", dir_to_mount, dir_mountpoint, NULL)) + { + gchar *skip_message = g_strdup_printf ("Failed to run bindfs to set up test: %s", error->message); + g_test_skip (skip_message); + g_free (skip_message); + g_clear_error (&error); + return; + } /* Let's check now, that the file is in indeed in a readonly filesystem */ file_in_mountpoint = g_strdup_printf ("%s/example.txt", dir_mountpoint); diff --git a/gio/tests/g-file-info.c b/gio/tests/g-file-info.c index 1fbdf71fa3b1e7b827fde15a8ac30a92964bf6ec..1a02b5e0eba2ba7b5bf1a7370a5d418839412fd4 100644 --- a/gio/tests/g-file-info.c +++ b/gio/tests/g-file-info.c @@ -221,7 +221,7 @@ test_internal_enhanced_stdio (void) guint64 size_p0, alsize_p0, size_ps, alsize_ps; const gchar *id_p0; const gchar *id_p1; - volatile guint64 time_p0; + guint64 time_p0; gchar *tmp_dir; wchar_t *programdata_dir_w; wchar_t *users_dir_w; @@ -229,6 +229,13 @@ test_internal_enhanced_stdio (void) { 0x62AB5D82, 0xFDC1, 0x4DC3, { 0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97 } }; static const GUID folder_id_users = { 0x0762D272, 0xC50A, 0x4BB0, { 0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80 } }; + GDateTime *dt = NULL, *dt2 = NULL; + GTimeSpan ts; + /* Just before SYSTEMTIME limit (Jan 1 30827) */ + const gint64 one_sec_before_systemtime_limit = 910670515199; + gboolean retval; + GError *local_error = NULL; + programdata_dir_w = NULL; SHGetKnownFolderPath (&folder_id_programdata, 0, NULL, &programdata_dir_w); @@ -552,7 +559,8 @@ test_internal_enhanced_stdio (void) G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE "," G_FILE_ATTRIBUTE_ID_FILE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_ATTRIBUTE_TIME_MODIFIED "," + G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, G_FILE_QUERY_INFO_NONE, NULL, NULL); @@ -560,7 +568,8 @@ test_internal_enhanced_stdio (void) G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE "," G_FILE_ATTRIBUTE_ID_FILE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_ATTRIBUTE_TIME_MODIFIED "," + G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, G_FILE_QUERY_INFO_NONE, NULL, NULL); @@ -568,11 +577,13 @@ test_internal_enhanced_stdio (void) g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE)); g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_ID_FILE)); g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED)); + g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC)); g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_SIZE)); g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE)); g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_ID_FILE)); g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED)); + g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC)); size_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE); alsize_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE); @@ -604,6 +615,56 @@ test_internal_enhanced_stdio (void) */ g_assert_cmpuint (time_p0, >, G_GUINT64_CONSTANT (0xFFFFFFFF)); + dt = g_file_info_get_modification_date_time (fi_p0); + g_assert_nonnull (dt); + dt2 = g_date_time_add (dt, G_USEC_PER_SEC / 100 * 200); + g_object_unref (fi_p0); + fi_p0 = g_file_info_new (); + g_file_info_set_modification_date_time (fi_p0, dt2); + + g_assert_true (g_file_set_attributes_from_info (gf_p0, + fi_p0, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL)); + g_date_time_unref (dt2); + g_object_unref (fi_p0); + fi_p0 = g_file_query_info (gf_p0, + G_FILE_ATTRIBUTE_TIME_MODIFIED "," + G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, + G_FILE_QUERY_INFO_NONE, + NULL, NULL); + dt2 = g_file_info_get_modification_date_time (fi_p0); + ts = g_date_time_difference (dt2, dt); + g_assert_cmpint (ts, >, 0); + g_assert_cmpint (ts, <, G_USEC_PER_SEC / 100 * 300); + + g_date_time_unref (dt); + g_date_time_unref (dt2); + + g_file_info_set_attribute_uint64 (fi_p0, + G_FILE_ATTRIBUTE_TIME_MODIFIED, + one_sec_before_systemtime_limit); + g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0); + g_assert_true (g_file_set_attributes_from_info (gf_p0, + fi_p0, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL)); + + g_file_info_set_attribute_uint64 (fi_p0, + G_FILE_ATTRIBUTE_TIME_MODIFIED, + one_sec_before_systemtime_limit + G_USEC_PER_SEC * 2); + g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0); + retval = g_file_set_attributes_from_info (gf_p0, + fi_p0, + G_FILE_QUERY_INFO_NONE, + NULL, + &local_error); + g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA); + g_assert_false (retval); + g_clear_error (&local_error); + g_object_unref (fi_p0); g_object_unref (fi_p1); g_object_unref (gf_p0); @@ -616,6 +677,66 @@ test_internal_enhanced_stdio (void) } #endif +static void +test_xattrs (void) +{ + GFile *file = NULL; + GFileIOStream *stream = NULL; + GFileInfo *file_info0 = NULL, *file_info1 = NULL; + GError *local_error = NULL; + + g_test_summary ("Test setting and getting escaped xattrs"); + + /* Create a temporary file; no need to write anything to it. */ + file = g_file_new_tmp ("g-file-info-test-xattrs-XXXXXX", &stream, &local_error); + g_assert_no_error (local_error); + g_assert_nonnull (file); + + g_io_stream_close (G_IO_STREAM (stream), NULL, NULL); + g_object_unref (stream); + + /* Check the existing xattrs. */ + file_info0 = g_file_query_info (file, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, &local_error); + g_assert_no_error (local_error); + g_assert_nonnull (file_info0); + + /* Set some new xattrs, with escaping and some embedded nuls. */ + g_file_info_set_attribute_string (file_info0, "xattr::escaped", "hello\\x82\\x80\\xbd"); + g_file_info_set_attribute_string (file_info0, "xattr::string", "hi there"); + g_file_info_set_attribute_string (file_info0, "xattr::embedded-nul", "hi\\x00there"); + + g_file_set_attributes_from_info (file, file_info0, G_FILE_QUERY_INFO_NONE, NULL, &local_error); + + g_object_unref (file_info0); + + if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) + { + g_test_skip ("xattrs not supported on this file system"); + g_clear_error (&local_error); + } + else + { + g_assert_no_error (local_error); + + /* Check they were set properly. */ + file_info1 = g_file_query_info (file, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, &local_error); + g_assert_no_error (local_error); + g_assert_nonnull (file_info1); + + g_assert_true (g_file_info_has_namespace (file_info1, "xattr")); + + g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::escaped"), ==, "hello\\x82\\x80\\xbd"); + g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::string"), ==, "hi there"); + g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::embedded-nul"), ==, "hi\\x00there"); + + g_object_unref (file_info1); + } + + /* Tidy up. */ + g_file_delete (file, NULL, NULL); + + g_object_unref (file); +} int main (int argc, @@ -628,6 +749,7 @@ main (int argc, #ifdef G_OS_WIN32 g_test_add_func ("/g-file-info/internal-enhanced-stdio", test_internal_enhanced_stdio); #endif + g_test_add_func ("/g-file-info/xattrs", test_xattrs); return g_test_run(); } diff --git a/gio/tests/gdbus-addresses.c b/gio/tests/gdbus-addresses.c index 173383d8358612463d367b4941a13245f2771dba..dbff79c3e0b61d6f1417e5517f0c821b58d6a187 100644 --- a/gio/tests/gdbus-addresses.c +++ b/gio/tests/gdbus-addresses.c @@ -39,7 +39,7 @@ test_empty_address (void) g_error_free (error); } -/* Test that g_dbus_is_supported_address() returns FALSE for an unparseable +/* Test that g_dbus_is_supported_address() returns FALSE for an unparsable * address. */ static void test_unsupported_address (void) @@ -146,6 +146,7 @@ test_nonce_tcp_address (void) assert_not_supported_address ("nonce-tcp:host=localhost,port=420000"); assert_not_supported_address ("nonce-tcp:host=localhost,port=42x"); assert_not_supported_address ("nonce-tcp:host=localhost,port="); + assert_not_supported_address ("nonce-tcp:host=localhost,port=42,noncefile="); } static void @@ -220,4 +221,3 @@ main (int argc, return g_test_run(); } - diff --git a/gio/tests/gdbus-auth.c b/gio/tests/gdbus-auth.c index f44e932e29ff9076e8d765d8f0f058595859e816..18288f36d13381b95ab76584939f8db28879794d 100644 --- a/gio/tests/gdbus-auth.c +++ b/gio/tests/gdbus-auth.c @@ -121,7 +121,7 @@ test_auth_on_timeout (gpointer user_data) { g_error ("Timeout waiting for client"); g_assert_not_reached (); - return FALSE; + return G_SOURCE_REMOVE; } @@ -310,4 +310,3 @@ main (int argc, return ret; } - diff --git a/gio/tests/gdbus-close-pending.c b/gio/tests/gdbus-close-pending.c index d2c5b62f5b3ba6e33b6f8e552dd3c2f0adb859dd..bd8fda5a704105b8c3921cc43952a640f2ba28f3 100644 --- a/gio/tests/gdbus-close-pending.c +++ b/gio/tests/gdbus-close-pending.c @@ -188,7 +188,7 @@ delayed_close_cb (gpointer data) close_async (df->stream, df->io_priority, df->cancellable, df->callback, df->user_data); - return FALSE; + return G_SOURCE_REMOVE; } static void diff --git a/gio/tests/gdbus-connection-flush.c b/gio/tests/gdbus-connection-flush.c index 39f08e8aab97a07c091c27b46339d8889a729d34..8c925825a3fbd87aa3d5afe20eb9dd9766725d7b 100644 --- a/gio/tests/gdbus-connection-flush.c +++ b/gio/tests/gdbus-connection-flush.c @@ -43,9 +43,9 @@ G_LOCK_DEFINE_STATIC (write); typedef struct { GFilterOutputStream parent; - volatile gint started; - volatile gint finished; - volatile gint flushed; + gint started; /* (atomic) */ + gint finished; /* (atomic) */ + gint flushed; /* (atomic) */ GOutputStream *real_output; } MyOutputStream; @@ -368,6 +368,9 @@ main (int argc, { gint ret; + /* FIXME: Add debug for https://gitlab.gnome.org/GNOME/glib/issues/1929 */ + g_setenv ("G_DBUS_DEBUG", "authentication", TRUE); + g_test_init (&argc, &argv, NULL); g_test_add ("/gdbus/connection/flush/busy", Fixture, NULL, diff --git a/gio/tests/gdbus-connection-loss.c b/gio/tests/gdbus-connection-loss.c index 8f7023f3f3cf5e1dbad089b2eac68b26cdfe86cc..cc88cb0ccbc55d8a61fc1e693fb70ab8da0e790c 100644 --- a/gio/tests/gdbus-connection-loss.c +++ b/gio/tests/gdbus-connection-loss.c @@ -53,7 +53,7 @@ on_timeout (gpointer user_data) { /* tear down bus */ session_bus_stop (); - return FALSE; /* remove source */ + return G_SOURCE_REMOVE; } static void @@ -124,14 +124,14 @@ main (int argc, g_assert (g_spawn_command_line_async (path, NULL)); g_free (path); - ensure_gdbus_testserver_up (); - /* Create the connection in the main thread */ error = NULL; c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); g_assert (c != NULL); + ensure_gdbus_testserver_up (c, NULL); + g_test_add_func ("/gdbus/connection-loss", test_connection_loss); ret = g_test_run(); diff --git a/gio/tests/gdbus-connection-slow.c b/gio/tests/gdbus-connection-slow.c index dd1ababd47f5d2f3ca2a0d582edb4b3b4714c512..7819e669a8f5458cb1ea15add1d19b5044bf3fb5 100644 --- a/gio/tests/gdbus-connection-slow.c +++ b/gio/tests/gdbus-connection-slow.c @@ -49,7 +49,7 @@ test_connection_flush_on_timeout (gpointer user_data) guint iteration = GPOINTER_TO_UINT (user_data); g_printerr ("Timeout waiting 1000 msec on iteration %d\n", iteration); g_assert_not_reached (); - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -86,17 +86,25 @@ test_connection_flush (void) gboolean ret; gint exit_status; guint timeout_mainloop_id; + gchar *flush_helper_stdout = NULL; + gchar *flush_helper_stderr = NULL; error = NULL; ret = g_spawn_command_line_sync (flush_helper, - NULL, /* stdout */ - NULL, /* stderr */ + &flush_helper_stdout, + &flush_helper_stderr, &exit_status, - &error); - g_assert_no_error (error); - g_spawn_check_exit_status (exit_status, &error); + &error) && + g_spawn_check_exit_status (exit_status, &error); + if (!ret) + g_test_message ("Child process ‘%s’ failed. stdout:\n%s\nstderr:\n%s", + flush_helper, flush_helper_stdout, flush_helper_stderr); + + g_free (flush_helper_stdout); + g_free (flush_helper_stderr); + g_assert_no_error (error); - g_assert (ret); + g_assert_true (ret); timeout_mainloop_id = g_timeout_add (1000, test_connection_flush_on_timeout, GUINT_TO_POINTER (n)); g_main_loop_run (loop); @@ -125,7 +133,7 @@ large_message_timeout_cb (gpointer data) g_error ("Error: timeout waiting for dbus name to appear"); - return FALSE; + return G_SOURCE_REMOVE; } static void diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c index 6e4c7eb058286515afd1a4d46fd53454bd215a5c..51dd27f7ecceb6fcaa4ad9a05618ee4f405e1226 100644 --- a/gio/tests/gdbus-connection.c +++ b/gio/tests/gdbus-connection.c @@ -61,11 +61,11 @@ _log (const gchar *format, ...) static gboolean test_connection_quit_mainloop (gpointer user_data) { - volatile gboolean *quit_mainloop_fired = user_data; + gboolean *quit_mainloop_fired = user_data; /* (atomic) */ _log ("quit_mainloop_fired"); - *quit_mainloop_fired = TRUE; + g_atomic_int_set (quit_mainloop_fired, TRUE); g_main_loop_quit (loop); - return TRUE; + return G_SOURCE_CONTINUE; } /* ---------------------------------------------------------------------------------------------------- */ @@ -89,6 +89,7 @@ static const GDBusInterfaceVTable boo_vtable = NULL /* _set_property */ }; +/* Runs in a worker thread. */ static GDBusMessage * some_filter_func (GDBusConnection *connection, GDBusMessage *message, @@ -112,8 +113,8 @@ on_name_owner_changed (GDBusConnection *connection, static void a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop (gpointer user_data) { - volatile gboolean *val = user_data; - *val = TRUE; + gboolean *val = user_data; /* (atomic) */ + g_atomic_int_set (val, TRUE); _log ("destroynotify fired for %p", val); g_main_loop_quit (loop); } @@ -129,9 +130,9 @@ test_connection_bus_failure (void) * */ c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - g_assert (error != NULL); - g_assert (!g_dbus_error_is_remote_error (error)); - g_assert (c == NULL); + g_assert_nonnull (error); + g_assert_false (g_dbus_error_is_remote_error (error)); + g_assert_null (c); g_error_free (error); } @@ -142,10 +143,10 @@ test_connection_life_cycle (void) GDBusConnection *c; GDBusConnection *c2; GError *error; - volatile gboolean on_signal_registration_freed_called; - volatile gboolean on_filter_freed_called; - volatile gboolean on_register_object_freed_called; - volatile gboolean quit_mainloop_fired; + gboolean on_signal_registration_freed_called; /* (atomic) */ + gboolean on_filter_freed_called; /* (atomic) */ + gboolean on_register_object_freed_called; /* (atomic) */ + gboolean quit_mainloop_fired; /* (atomic) */ guint quit_mainloop_id; guint registration_id; @@ -159,8 +160,8 @@ test_connection_life_cycle (void) error = NULL; c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c != NULL); - g_assert (!g_dbus_connection_is_closed (c)); + g_assert_nonnull (c); + g_assert_false (g_dbus_connection_is_closed (c)); /* * Check that singleton handling work @@ -168,8 +169,8 @@ test_connection_life_cycle (void) error = NULL; c2 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c2 != NULL); - g_assert (c == c2); + g_assert_nonnull (c2); + g_assert_true (c == c2); g_object_unref (c2); /* @@ -177,23 +178,23 @@ test_connection_life_cycle (void) */ c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c2 != NULL); - g_assert (c != c2); + g_assert_nonnull (c2); + g_assert_true (c != c2); g_object_unref (c2); c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c2 != NULL); - g_assert (!g_dbus_connection_is_closed (c2)); + g_assert_nonnull (c2); + g_assert_false (g_dbus_connection_is_closed (c2)); ret = g_dbus_connection_close_sync (c2, NULL, &error); g_assert_no_error (error); - g_assert (ret); + g_assert_true (ret); _g_assert_signal_received (c2, "closed"); - g_assert (g_dbus_connection_is_closed (c2)); + g_assert_true (g_dbus_connection_is_closed (c2)); ret = g_dbus_connection_close_sync (c2, NULL, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED); g_error_free (error); - g_assert (!ret); + g_assert_false (ret); g_object_unref (c2); /* @@ -205,9 +206,9 @@ test_connection_life_cycle (void) error = NULL; c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c2 != NULL); + g_assert_nonnull (c2); /* signal registration */ - on_signal_registration_freed_called = FALSE; + g_atomic_int_set (&on_signal_registration_freed_called, FALSE); g_dbus_connection_signal_subscribe (c2, "org.freedesktop.DBus", /* bus name */ "org.freedesktop.DBus", /* interface */ @@ -219,13 +220,13 @@ test_connection_life_cycle (void) (gpointer) &on_signal_registration_freed_called, a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop); /* filter func */ - on_filter_freed_called = FALSE; + g_atomic_int_set (&on_filter_freed_called, FALSE); g_dbus_connection_add_filter (c2, some_filter_func, (gpointer) &on_filter_freed_called, a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop); /* object registration */ - on_register_object_freed_called = FALSE; + g_atomic_int_set (&on_register_object_freed_called, FALSE); error = NULL; registration_id = g_dbus_connection_register_object (c2, "/foo", @@ -235,10 +236,10 @@ test_connection_life_cycle (void) a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop, &error); g_assert_no_error (error); - g_assert (registration_id > 0); + g_assert_cmpuint (registration_id, >, 0); /* ok, finalize the connection and check that all the GDestroyNotify functions are invoked as expected */ g_object_unref (c2); - quit_mainloop_fired = FALSE; + g_atomic_int_set (&quit_mainloop_fired, FALSE); quit_mainloop_id = g_timeout_add (30000, test_connection_quit_mainloop, (gpointer) &quit_mainloop_fired); _log ("destroynotifies for\n" " register_object %p\n" @@ -249,31 +250,31 @@ test_connection_life_cycle (void) &on_signal_registration_freed_called); while (TRUE) { - if (on_signal_registration_freed_called && - on_filter_freed_called && - on_register_object_freed_called) + if (g_atomic_int_get (&on_signal_registration_freed_called) && + g_atomic_int_get (&on_filter_freed_called) && + g_atomic_int_get (&on_register_object_freed_called)) break; - if (quit_mainloop_fired) + if (g_atomic_int_get (&quit_mainloop_fired)) break; _log ("entering loop"); g_main_loop_run (loop); _log ("exiting loop"); } g_source_remove (quit_mainloop_id); - g_assert (on_signal_registration_freed_called); - g_assert (on_filter_freed_called); - g_assert (on_register_object_freed_called); - g_assert (!quit_mainloop_fired); + g_assert_true (g_atomic_int_get (&on_signal_registration_freed_called)); + g_assert_true (g_atomic_int_get (&on_filter_freed_called)); + g_assert_true (g_atomic_int_get (&on_register_object_freed_called)); + g_assert_false (g_atomic_int_get (&quit_mainloop_fired)); /* * Check for correct behavior when the bus goes away * */ - g_assert (!g_dbus_connection_is_closed (c)); + g_assert_false (g_dbus_connection_is_closed (c)); g_dbus_connection_set_exit_on_close (c, FALSE); session_bus_stop (); _g_assert_signal_received (c, "closed"); - g_assert (g_dbus_connection_is_closed (c)); + g_assert_true (g_dbus_connection_is_closed (c)); g_object_unref (c); session_bus_down (); @@ -299,9 +300,9 @@ msg_cb_expect_error_disconnected (GDBusConnection *connection, res, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED); - g_assert (!g_dbus_error_is_remote_error (error)); + g_assert_false (g_dbus_error_is_remote_error (error)); g_error_free (error); - g_assert (result == NULL); + g_assert_null (result); g_main_loop_quit (loop); } @@ -322,9 +323,9 @@ msg_cb_expect_error_unknown_method (GDBusConnection *connection, res, &error); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); - g_assert (g_dbus_error_is_remote_error (error)); + g_assert_true (g_dbus_error_is_remote_error (error)); g_error_free (error); - g_assert (result == NULL); + g_assert_null (result); g_main_loop_quit (loop); } @@ -345,7 +346,7 @@ msg_cb_expect_success (GDBusConnection *connection, res, &error); g_assert_no_error (error); - g_assert (result != NULL); + g_assert_nonnull (result); g_variant_unref (result); g_main_loop_quit (loop); @@ -367,9 +368,9 @@ msg_cb_expect_error_cancelled (GDBusConnection *connection, res, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); - g_assert (!g_dbus_error_is_remote_error (error)); + g_assert_false (g_dbus_error_is_remote_error (error)); g_error_free (error); - g_assert (result == NULL); + g_assert_null (result); g_main_loop_quit (loop); } @@ -390,9 +391,9 @@ msg_cb_expect_error_cancelled_2 (GDBusConnection *connection, res, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); - g_assert (!g_dbus_error_is_remote_error (error)); + g_assert_false (g_dbus_error_is_remote_error (error)); g_error_free (error); - g_assert (result == NULL); + g_assert_null (result); g_main_loop_quit (loop); } @@ -409,8 +410,8 @@ test_connection_send (void) /* First, get an unopened connection */ c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); - g_assert (c != NULL); - g_assert (!g_dbus_connection_is_closed (c)); + g_assert_nonnull (c); + g_assert_false (g_dbus_connection_is_closed (c)); /* * Check that we never actually send a message if the GCancellable @@ -490,7 +491,7 @@ test_connection_send (void) g_dbus_connection_set_exit_on_close (c, FALSE); session_bus_stop (); _g_assert_signal_received (c, "closed"); - g_assert (g_dbus_connection_is_closed (c)); + g_assert_true (g_dbus_connection_is_closed (c)); g_dbus_connection_call (c, "org.freedesktop.DBus", /* bus_name */ @@ -567,13 +568,13 @@ test_connection_signals (void) if (g_getenv ("G_DBUS_MONITOR") == NULL) { c1 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL); - g_assert (c1 != NULL); - g_assert (!g_dbus_connection_is_closed (c1)); + g_assert_nonnull (c1); + g_assert_false (g_dbus_connection_is_closed (c1)); g_object_unref (c1); } c1 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); - g_assert (c1 != NULL); - g_assert (!g_dbus_connection_is_closed (c1)); + g_assert_nonnull (c1); + g_assert_false (g_dbus_connection_is_closed (c1)); g_assert_cmpstr (g_dbus_connection_get_unique_name (c1), ==, ":1.1"); /* @@ -628,10 +629,10 @@ test_connection_signals (void) test_connection_signal_handler, &count_s1b, NULL); - g_assert (s1 != 0); - g_assert (s1b != 0); - g_assert (s2 != 0); - g_assert (s3 != 0); + g_assert_cmpuint (s1, !=, 0); + g_assert_cmpuint (s1b, !=, 0); + g_assert_cmpuint (s2, !=, 0); + g_assert_cmpuint (s3, !=, 0); count_s1 = 0; count_s1b = 0; @@ -661,19 +662,19 @@ test_connection_signals (void) NULL, &error); g_assert_no_error (error); - g_assert (result != NULL); + g_assert_nonnull (result); g_variant_unref (result); /* * Bring up two other connections */ c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL); - g_assert (c2 != NULL); - g_assert (!g_dbus_connection_is_closed (c2)); + g_assert_nonnull (c2); + g_assert_false (g_dbus_connection_is_closed (c2)); g_assert_cmpstr (g_dbus_connection_get_unique_name (c2), ==, ":1.2"); c3 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL); - g_assert (c3 != NULL); - g_assert (!g_dbus_connection_is_closed (c3)); + g_assert_nonnull (c3); + g_assert_false (g_dbus_connection_is_closed (c3)); g_assert_cmpstr (g_dbus_connection_get_unique_name (c3), ==, ":1.3"); /* now, emit the signal on c2 */ @@ -685,7 +686,7 @@ test_connection_signals (void) NULL, &error); g_assert_no_error (error); - g_assert (ret); + g_assert_true (ret); while (!(count_s1 >= 1 && count_s2 >= 1)) g_main_loop_run (loop); g_assert_cmpint (count_s1, ==, 1); @@ -702,7 +703,7 @@ test_connection_signals (void) NULL, &error); g_assert_no_error (error); - g_assert (ret); + g_assert_true (ret); while (!(count_s1 == 1 && count_s2 == 2)) g_main_loop_run (loop); g_assert_cmpint (count_s1, ==, 1); @@ -812,13 +813,15 @@ test_connection_signal_match_rules (void) /* ---------------------------------------------------------------------------------------------------- */ +/* Accessed both from the test code and the filter function (in a worker thread) + * so all accesses must be atomic. */ typedef struct { - guint num_handled; - guint num_outgoing; - guint32 serial; + GAsyncQueue *incoming_queue; /* (element-type GDBusMessage) */ + guint num_outgoing; /* (atomic) */ } FilterData; +/* Runs in a worker thread. */ static GDBusMessage * filter_func (GDBusConnection *connection, GDBusMessage *message, @@ -826,22 +829,31 @@ filter_func (GDBusConnection *connection, gpointer user_data) { FilterData *data = user_data; - guint32 reply_serial; if (incoming) - { - reply_serial = g_dbus_message_get_reply_serial (message); - if (reply_serial == data->serial) - data->num_handled += 1; - } + g_async_queue_push (data->incoming_queue, g_object_ref (message)); else - { - data->num_outgoing += 1; - } + g_atomic_int_inc (&data->num_outgoing); return message; } +static void +wait_for_filtered_reply (GAsyncQueue *incoming_queue, + guint32 expected_serial) +{ + GDBusMessage *popped_message = NULL; + + while ((popped_message = g_async_queue_pop (incoming_queue)) != NULL) + { + guint32 reply_serial = g_dbus_message_get_reply_serial (popped_message); + g_object_unref (popped_message); + if (reply_serial == expected_serial) + return; + } + + g_assert_not_reached (); +} typedef struct { @@ -849,13 +861,14 @@ typedef struct gboolean alter_outgoing; } FilterEffects; +/* Runs in a worker thread. */ static GDBusMessage * other_filter_func (GDBusConnection *connection, GDBusMessage *message, gboolean incoming, gpointer user_data) { - FilterEffects *effects = user_data; + const FilterEffects *effects = user_data; GDBusMessage *ret; gboolean alter; @@ -921,14 +934,14 @@ test_connection_filter_on_timeout (gpointer user_data) { g_printerr ("Timeout waiting 30 sec on service\n"); g_assert_not_reached (); - return FALSE; + return G_SOURCE_REMOVE; } static void test_connection_filter (void) { GDBusConnection *c; - FilterData data; + FilterData data = { NULL, 0 }; GDBusMessage *m; GDBusMessage *m2; GDBusMessage *r; @@ -939,16 +952,17 @@ test_connection_filter (void) FilterEffects effects; GVariant *result; const gchar *s; - - memset (&data, '\0', sizeof (FilterData)); + guint32 serial_temp; session_bus_up (); error = NULL; c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c != NULL); + g_assert_nonnull (c); + data.incoming_queue = g_async_queue_new_full (g_object_unref); + data.num_outgoing = 0; filter_id = g_dbus_connection_add_filter (c, filter_func, &data, @@ -960,32 +974,29 @@ test_connection_filter (void) "GetNameOwner"); g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus")); error = NULL; - g_dbus_connection_send_message (c, m, G_DBUS_SEND_MESSAGE_FLAGS_NONE, &data.serial, &error); + g_dbus_connection_send_message (c, m, G_DBUS_SEND_MESSAGE_FLAGS_NONE, &serial_temp, &error); g_assert_no_error (error); - while (data.num_handled == 0) - g_thread_yield (); + wait_for_filtered_reply (data.incoming_queue, serial_temp); m2 = g_dbus_message_copy (m, &error); g_assert_no_error (error); - g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_NONE, &data.serial, &error); + g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_NONE, &serial_temp, &error); g_object_unref (m2); g_assert_no_error (error); - while (data.num_handled == 1) - g_thread_yield (); + wait_for_filtered_reply (data.incoming_queue, serial_temp); m2 = g_dbus_message_copy (m, &error); g_assert_no_error (error); - g_dbus_message_set_serial (m2, data.serial); + g_dbus_message_set_serial (m2, serial_temp); /* lock the message to test PRESERVE_SERIAL flag. */ g_dbus_message_lock (m2); - g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, &data.serial, &error); + g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, &serial_temp, &error); g_object_unref (m2); g_assert_no_error (error); - while (data.num_handled == 2) - g_thread_yield (); + wait_for_filtered_reply (data.incoming_queue, serial_temp); m2 = g_dbus_message_copy (m, &error); g_assert_no_error (error); @@ -993,14 +1004,16 @@ test_connection_filter (void) m2, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, - &data.serial, + &serial_temp, NULL, /* GCancellable */ &error); g_object_unref (m2); g_assert_no_error (error); - g_assert (r != NULL); + g_assert_nonnull (r); g_object_unref (r); - g_assert_cmpint (data.num_handled, ==, 4); + + wait_for_filtered_reply (data.incoming_queue, serial_temp); + g_assert_cmpint (g_async_queue_length (data.incoming_queue), ==, 0); g_dbus_connection_remove_filter (c, filter_id); @@ -1010,15 +1023,15 @@ test_connection_filter (void) m2, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, - &data.serial, + &serial_temp, NULL, /* GCancellable */ &error); g_object_unref (m2); g_assert_no_error (error); - g_assert (r != NULL); + g_assert_nonnull (r); g_object_unref (r); - g_assert_cmpint (data.num_handled, ==, 4); - g_assert_cmpint (data.num_outgoing, ==, 4); + g_assert_cmpint (g_async_queue_length (data.incoming_queue), ==, 0); + g_assert_cmpint (g_atomic_int_get (&data.num_outgoing), ==, 4); /* wait for service to be available */ signal_handler_id = g_dbus_connection_signal_subscribe (c, @@ -1034,7 +1047,7 @@ test_connection_filter (void) g_assert_cmpint (signal_handler_id, !=, 0); /* this is safe; testserver will exit once the bus goes away */ - g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL)); + g_assert_true (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL)); timeout_mainloop_id = g_timeout_add (30000, test_connection_filter_on_timeout, NULL); g_main_loop_run (loop); @@ -1090,6 +1103,7 @@ test_connection_filter (void) g_object_unref (c); g_object_unref (m); + g_async_queue_unref (data.incoming_queue); session_bus_down (); } @@ -1159,7 +1173,7 @@ test_connection_serials (void) error = NULL; c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c != NULL); + g_assert_nonnull (c); /* Status after initialization */ g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 1); @@ -1210,11 +1224,11 @@ test_connection_basic (void) error = NULL; connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (connection != NULL); + g_assert_nonnull (connection); flags = g_dbus_connection_get_capabilities (connection); - g_assert (flags == G_DBUS_CAPABILITY_FLAGS_NONE || - flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); + g_assert_true (flags == G_DBUS_CAPABILITY_FLAGS_NONE || + flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); connection_flags = g_dbus_connection_get_flags (connection); g_assert_cmpint (connection_flags, ==, @@ -1222,7 +1236,7 @@ test_connection_basic (void) G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION); credentials = g_dbus_connection_get_peer_credentials (connection); - g_assert (credentials == NULL); + g_assert_null (credentials); g_object_get (connection, "stream", &stream, @@ -1233,13 +1247,13 @@ test_connection_basic (void) "capabilities", &flags, NULL); - g_assert (G_IS_IO_STREAM (stream)); - g_assert (g_dbus_is_guid (guid)); - g_assert (g_dbus_is_unique_name (name)); - g_assert (!closed); - g_assert (exit_on_close); - g_assert (flags == G_DBUS_CAPABILITY_FLAGS_NONE || - flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); + g_assert_true (G_IS_IO_STREAM (stream)); + g_assert_true (g_dbus_is_guid (guid)); + g_assert_true (g_dbus_is_unique_name (name)); + g_assert_false (closed); + g_assert_true (exit_on_close); + g_assert_true (flags == G_DBUS_CAPABILITY_FLAGS_NONE || + flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); g_object_unref (stream); g_free (name); g_free (guid); @@ -1256,6 +1270,7 @@ main (int argc, char *argv[]) { int ret; + g_test_init (&argc, &argv, NULL); /* all the tests rely on a shared main loop */ diff --git a/gio/tests/gdbus-example-objectmanager-server.c b/gio/tests/gdbus-example-objectmanager-server.c index c460e66e987f59386f867ac299acd320d0082014..dcedba2d1570493f9f5d7cf897503960f6cbc3be 100644 --- a/gio/tests/gdbus-example-objectmanager-server.c +++ b/gio/tests/gdbus-example-objectmanager-server.c @@ -53,7 +53,7 @@ on_animal_poke (ExampleAnimal *animal, g_assert_not_reached (); out: - return TRUE; /* to indicate that the method was handled */ + return G_DBUS_METHOD_INVOCATION_HANDLED; } diff --git a/gio/tests/gdbus-example-server.c b/gio/tests/gdbus-example-server.c index 6f1123d85f5e07dbf96ad5ad234b90a55b34c933..00e482724c7d39d1f5b1553e6e3e83c9a4945dbe 100644 --- a/gio/tests/gdbus-example-server.c +++ b/gio/tests/gdbus-example-server.c @@ -315,7 +315,7 @@ on_timeout_cb (gpointer user_data) g_assert_no_error (error); - return TRUE; + return G_SOURCE_CONTINUE; } /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/tests/gdbus-exit-on-close.c b/gio/tests/gdbus-exit-on-close.c index 3c4e5ecd6f379cdefbcb50deb14fec0bc25dec11..4241fc7a4674d25891d4b7364046a3f3653945a4 100644 --- a/gio/tests/gdbus-exit-on-close.c +++ b/gio/tests/gdbus-exit-on-close.c @@ -57,7 +57,7 @@ quit_later_cb (gpointer data G_GNUC_UNUSED) { g_main_loop_quit (loop); - return FALSE; + return G_SOURCE_REMOVE; } static void diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index 8affbc97e933dfe38b23812e86a136219f20502e..61d47e90a1be6f31e8f8bf3ef376593f1cc7ff29 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -189,7 +189,7 @@ foo_set_property (GDBusConnection *connection, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FILE_INVALID, "Returning some error instead of writing the value '%s' to the property '%s'", - property_name, s); + s, property_name); g_free (s); return FALSE; } @@ -927,7 +927,7 @@ test_dispatch_thread_func (gpointer user_data) { /* _with_closures variant doesn't support customizing error data. */ g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FILE_INVALID); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.Spawn.FileInvalid: Returning some error instead of writing the value 'NotReadable' to the property ''But Writable you are!''"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.Spawn.FileInvalid: Returning some error instead of writing the value ''But Writable you are!'' to the property 'NotReadable'"); } g_assert (error != NULL && error->domain == G_DBUS_ERROR); g_error_free (error); @@ -1279,7 +1279,7 @@ test_object_registration (void) g_strfreev (nodes); g_assert_cmpint (count_interfaces (c, "/foo/dyna/dynamicallycreated"), ==, 4); - /* now check that the object hierarachy is properly generated... yes, it's a bit + /* now check that the object hierarchy is properly generated... yes, it's a bit * perverse that we round-trip to the bus to introspect ourselves ;-) */ nodes = get_nodes_at (c, "/"); diff --git a/gio/tests/gdbus-message.c b/gio/tests/gdbus-message.c index 5cb141d94e73eaa01ddd9c918a07952ee4fc5875..93235749a7f68f27a1b3a4cb9ead2808e72282a0 100644 --- a/gio/tests/gdbus-message.c +++ b/gio/tests/gdbus-message.c @@ -223,4 +223,3 @@ main (int argc, return g_test_run (); } - diff --git a/gio/tests/gdbus-names.c b/gio/tests/gdbus-names.c index 4f95b457a02e16fc8a51251ff9b7a08ba6877b36..05d2015d0444b924ba97c732725dd02e778dddd6 100644 --- a/gio/tests/gdbus-names.c +++ b/gio/tests/gdbus-names.c @@ -32,7 +32,6 @@ static GMainLoop *loop; typedef struct { - GMainLoop *loop; gboolean expect_null_connection; guint num_bus_acquired; guint num_acquired; @@ -189,6 +188,7 @@ test_bus_own_name (void) * Stop owning the name - this should invoke our free func */ g_bus_unown_name (id); + g_main_loop_run (loop); g_assert_cmpint (data.num_free_func, ==, 2); /* @@ -296,6 +296,7 @@ test_bus_own_name (void) g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); g_bus_unown_name (id2); + g_main_loop_run (loop); g_assert_cmpint (data2.num_bus_acquired, ==, 1); g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); @@ -330,6 +331,7 @@ test_bus_own_name (void) g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); g_bus_unown_name (id2); + g_main_loop_run (loop); g_assert_cmpint (data2.num_bus_acquired, ==, 0); g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); @@ -355,6 +357,7 @@ test_bus_own_name (void) g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); g_bus_unown_name (id2); + g_main_loop_run (loop); g_assert_cmpint (data2.num_bus_acquired, ==, 0); g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); @@ -365,6 +368,7 @@ test_bus_own_name (void) */ data.expect_null_connection = FALSE; g_bus_unown_name (id); + g_main_loop_run (loop); g_assert_cmpint (data.num_bus_acquired, ==, 1); g_assert_cmpint (data.num_acquired, ==, 1); g_assert_cmpint (data.num_free_func, ==, 4); @@ -418,6 +422,7 @@ test_bus_own_name (void) g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); g_bus_unown_name (id2); + g_main_loop_run (loop); g_assert_cmpint (data2.num_bus_acquired, ==, 0); g_assert_cmpint (data2.num_acquired, ==, 0); g_assert_cmpint (data2.num_lost, ==, 1); @@ -450,8 +455,9 @@ test_bus_own_name (void) g_assert_cmpint (data2.num_bus_acquired, ==, 0); /* ok, make owner2 release the name - then wait for owner to automagically reacquire it */ g_bus_unown_name (id2); - g_assert_cmpint (data2.num_free_func, ==, 1); g_main_loop_run (loop); + g_main_loop_run (loop); + g_assert_cmpint (data2.num_free_func, ==, 1); g_assert_cmpint (data.num_acquired, ==, 2); g_assert_cmpint (data.num_lost, ==, 1); @@ -466,6 +472,7 @@ test_bus_own_name (void) g_assert_cmpint (data.num_acquired, ==, 2); g_assert_cmpint (data.num_lost, ==, 2); g_bus_unown_name (id); + g_main_loop_run (loop); g_assert_cmpint (data.num_free_func, ==, 5); g_object_unref (c); @@ -529,6 +536,7 @@ name_appeared_handler (GDBusConnection *connection, gpointer user_data) { WatchNameData *data = user_data; + if (data->expect_null_connection) { g_assert (connection == NULL); @@ -548,6 +556,7 @@ name_vanished_handler (GDBusConnection *connection, gpointer user_data) { WatchNameData *data = user_data; + if (data->expect_null_connection) { g_assert (connection == NULL); @@ -561,13 +570,95 @@ name_vanished_handler (GDBusConnection *connection, g_main_loop_quit (loop); } +typedef struct +{ + guint watcher_flags; + gboolean watch_with_closures; + gboolean existing_service; +} WatchNameTest; + +static const WatchNameTest watch_no_closures_no_flags = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_NONE, + .watch_with_closures = FALSE, + .existing_service = FALSE +}; + +static const WatchNameTest watch_no_closures_flags_auto_start = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + .watch_with_closures = FALSE, + .existing_service = FALSE +}; + +static const WatchNameTest watch_no_closures_flags_auto_start_service_exist = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + .watch_with_closures = FALSE, + .existing_service = TRUE +}; + +static const WatchNameTest watch_closures_no_flags = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_NONE, + .watch_with_closures = TRUE, + .existing_service = FALSE +}; + +static const WatchNameTest watch_closures_flags_auto_start = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + .watch_with_closures = TRUE, + .existing_service = FALSE +}; + +static void +stop_service (GDBusConnection *connection, + WatchNameData *data) +{ + GError *error = NULL; + GDBusProxy *proxy = NULL; + + data->num_vanished = 0; + + proxy = g_dbus_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "org.gtk.GDBus.FakeService", + "/org/gtk/GDBus/FakeService", + "org.gtk.GDBus.FakeService", + NULL, + &error); + g_assert_no_error (error); + + g_dbus_proxy_call_sync (proxy, + "Quit", + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 100, + NULL, + &error); + g_assert_no_error (error); + g_object_unref (proxy); + while (data->num_vanished == 0) + g_main_loop_run (loop); +} + static void -test_bus_watch_name (void) +test_bus_watch_name (gconstpointer d) { WatchNameData data; guint id; guint owner_id; GDBusConnection *connection; + const WatchNameTest *watch_name_test; + const gchar *name; + + watch_name_test = (WatchNameTest *) d; + + if (watch_name_test->existing_service) + { + name = "org.gtk.GDBus.FakeService"; + } + else + { + name = "org.gtk.GDBus.Name1"; + } /* * First check that name_vanished_handler() is invoked if there is no bus. @@ -579,8 +670,8 @@ test_bus_watch_name (void) data.num_vanished = 0; data.expect_null_connection = TRUE; id = g_bus_watch_name (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", - G_BUS_NAME_WATCHER_FLAGS_NONE, + name, + watch_name_test->watcher_flags, name_appeared_handler, name_vanished_handler, &data, @@ -605,7 +696,7 @@ test_bus_watch_name (void) data.num_lost = 0; data.expect_null_connection = FALSE; owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", + name, G_BUS_NAME_OWNER_FLAGS_NONE, w_bus_acquired_handler, w_name_acquired_handler, @@ -614,7 +705,7 @@ test_bus_watch_name (void) (GDestroyNotify) watch_name_data_free_func); g_main_loop_run (loop); g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (data.num_lost, ==, 0); connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); g_assert (connection != NULL); @@ -622,13 +713,28 @@ test_bus_watch_name (void) /* now watch the name */ data.num_appeared = 0; data.num_vanished = 0; - id = g_bus_watch_name_on_connection (connection, - "org.gtk.GDBus.Name1", - G_BUS_NAME_WATCHER_FLAGS_NONE, - name_appeared_handler, - name_vanished_handler, - &data, - (GDestroyNotify) watch_name_data_free_func); + if (watch_name_test->watch_with_closures) + { + id = g_bus_watch_name_on_connection_with_closures (connection, + name, + watch_name_test->watcher_flags, + g_cclosure_new (G_CALLBACK (name_appeared_handler), + &data, + NULL), + g_cclosure_new (G_CALLBACK (name_vanished_handler), + &data, + (GClosureNotify) watch_name_data_free_func)); + } + else + { + id = g_bus_watch_name_on_connection (connection, + name, + watch_name_test->watcher_flags, + name_appeared_handler, + name_vanished_handler, + &data, + (GDestroyNotify) watch_name_data_free_func); + } g_assert_cmpint (data.num_appeared, ==, 0); g_assert_cmpint (data.num_vanished, ==, 0); g_main_loop_run (loop); @@ -641,10 +747,9 @@ test_bus_watch_name (void) g_bus_unwatch_name (id); g_assert_cmpint (data.num_free_func, ==, 1); - g_object_unref (connection); - /* unown the name */ g_bus_unown_name (owner_id); + g_main_loop_run (loop); g_assert_cmpint (data.num_acquired, ==, 1); g_assert_cmpint (data.num_free_func, ==, 2); @@ -657,55 +762,96 @@ test_bus_watch_name (void) data.num_appeared = 0; data.num_vanished = 0; data.num_free_func = 0; - id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", - G_BUS_NAME_WATCHER_FLAGS_NONE, - g_cclosure_new (G_CALLBACK (name_appeared_handler), - &data, - NULL), - g_cclosure_new (G_CALLBACK (name_vanished_handler), - &data, - (GClosureNotify) watch_name_data_free_func)); + if (watch_name_test->watch_with_closures) + { + id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION, + name, + watch_name_test->watcher_flags, + g_cclosure_new (G_CALLBACK (name_appeared_handler), + &data, + NULL), + g_cclosure_new (G_CALLBACK (name_vanished_handler), + &data, + (GClosureNotify) watch_name_data_free_func)); + } + else + { + id = g_bus_watch_name (G_BUS_TYPE_SESSION, + name, + watch_name_test->watcher_flags, + name_appeared_handler, + name_vanished_handler, + &data, + (GDestroyNotify) watch_name_data_free_func); + } + g_assert_cmpint (data.num_appeared, ==, 0); g_assert_cmpint (data.num_vanished, ==, 0); g_main_loop_run (loop); - g_assert_cmpint (data.num_appeared, ==, 0); - g_assert_cmpint (data.num_vanished, ==, 1); + if (watch_name_test->existing_service) + { + g_assert_cmpint (data.num_appeared, ==, 1); + g_assert_cmpint (data.num_vanished, ==, 0); + } + else + { + g_assert_cmpint (data.num_appeared, ==, 0); + g_assert_cmpint (data.num_vanished, ==, 1); + } - /* own the name */ - data.num_acquired = 0; - data.num_lost = 0; - data.expect_null_connection = FALSE; - owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", - G_BUS_NAME_OWNER_FLAGS_NONE, - w_bus_acquired_handler, - w_name_acquired_handler, - w_name_lost_handler, - &data, - (GDestroyNotify) watch_name_data_free_func); - while (data.num_acquired == 0 || data.num_appeared == 0) - g_main_loop_run (loop); - g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_lost, ==, 0); - g_assert_cmpint (data.num_appeared, ==, 1); - g_assert_cmpint (data.num_vanished, ==, 1); + if (!watch_name_test->existing_service) + { + /* own the name */ + data.num_acquired = 0; + data.num_lost = 0; + data.expect_null_connection = FALSE; + owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + name, + G_BUS_NAME_OWNER_FLAGS_NONE, + w_bus_acquired_handler, + w_name_acquired_handler, + w_name_lost_handler, + &data, + (GDestroyNotify) watch_name_data_free_func); + while (data.num_acquired == 0 || data.num_appeared == 0) + g_main_loop_run (loop); + g_assert_cmpint (data.num_acquired, ==, 1); + g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (data.num_appeared, ==, 1); + g_assert_cmpint (data.num_vanished, ==, 1); + } + data.expect_null_connection = TRUE; + if (watch_name_test->existing_service) + { + data.expect_null_connection = FALSE; + stop_service (connection, &data); + } + g_object_unref (connection); /* * Nuke the bus and check that the name vanishes and is lost. */ - data.expect_null_connection = TRUE; session_bus_stop (); - g_main_loop_run (loop); - g_assert_cmpint (data.num_lost, ==, 1); - g_assert_cmpint (data.num_vanished, ==, 2); - + if (!watch_name_test->existing_service) + { + g_main_loop_run (loop); + g_assert_cmpint (data.num_lost, ==, 1); + g_assert_cmpint (data.num_vanished, ==, 2); + } + else + { + g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (data.num_vanished, ==, 1); + } g_bus_unwatch_name (id); g_assert_cmpint (data.num_free_func, ==, 1); - g_bus_unown_name (owner_id); - g_assert_cmpint (data.num_free_func, ==, 2); - + if (!watch_name_test->existing_service) + { + g_bus_unown_name (owner_id); + g_main_loop_run (loop); + g_assert_cmpint (data.num_free_func, ==, 2); + } session_bus_down (); } @@ -759,6 +905,49 @@ test_validate_names (void) } } +static void +assert_cmp_escaped_object_path (const gchar *s, + const gchar *correct_escaped) +{ + gchar *escaped; + guint8 *unescaped; + + escaped = g_dbus_escape_object_path (s); + g_assert_cmpstr (escaped, ==, correct_escaped); + + g_free (escaped); + escaped = g_dbus_escape_object_path_bytestring ((const guint8 *) s); + g_assert_cmpstr (escaped, ==, correct_escaped); + + unescaped = g_dbus_unescape_object_path (escaped); + g_assert_cmpstr ((const gchar *) unescaped, ==, s); + + g_free (escaped); + g_free (unescaped); +} + +static void +test_escape_object_path (void) +{ + assert_cmp_escaped_object_path ("Foo42", "Foo42"); + assert_cmp_escaped_object_path ("foo.bar.baz", "foo_2ebar_2ebaz"); + assert_cmp_escaped_object_path ("foo_bar_baz", "foo_5fbar_5fbaz"); + assert_cmp_escaped_object_path ("_", "_5f"); + assert_cmp_escaped_object_path ("__", "_5f_5f"); + assert_cmp_escaped_object_path ("", "_"); + assert_cmp_escaped_object_path (":1.42", "_3a1_2e42"); + assert_cmp_escaped_object_path ("a/b", "a_2fb"); + assert_cmp_escaped_object_path (" ", "_20"); + assert_cmp_escaped_object_path ("\n", "_0a"); + + g_assert_null (g_dbus_unescape_object_path ("_ii")); + g_assert_null (g_dbus_unescape_object_path ("döner")); + g_assert_null (g_dbus_unescape_object_path ("_00")); + g_assert_null (g_dbus_unescape_object_path ("_61")); + g_assert_null (g_dbus_unescape_object_path ("_ga")); + g_assert_null (g_dbus_unescape_object_path ("_ag")); +} + /* ---------------------------------------------------------------------------------------------------- */ int @@ -775,8 +964,22 @@ main (int argc, g_test_add_func ("/gdbus/validate-names", test_validate_names); g_test_add_func ("/gdbus/bus-own-name", test_bus_own_name); - g_test_add_func ("/gdbus/bus-watch-name", test_bus_watch_name); - + g_test_add_data_func ("/gdbus/bus-watch-name", + &watch_no_closures_no_flags, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-auto-start", + &watch_no_closures_flags_auto_start, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-auto-start-service-exist", + &watch_no_closures_flags_auto_start_service_exist, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-closures", + &watch_closures_no_flags, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-closures-auto-start", + &watch_closures_flags_auto_start, + test_bus_watch_name); + g_test_add_func ("/gdbus/escape-object-path", test_escape_object_path); ret = g_test_run(); g_main_loop_unref (loop); diff --git a/gio/tests/gdbus-object-manager-example/meson.build b/gio/tests/gdbus-object-manager-example/meson.build index 404c37788b5abff366b8493e96b33ee3b1aae599..f9c3bce26b11530b22ac161e48cbde1c6e4d4fdf 100644 --- a/gio/tests/gdbus-object-manager-example/meson.build +++ b/gio/tests/gdbus-object-manager-example/meson.build @@ -1,6 +1,7 @@ # FIXME: set UNINSTALLED_GLIB_{SRC|BUILD}DIR=top_{src|build}dir ? +gdbus_example_objectmanager_xml = files('gdbus-example-objectmanager.xml') gdbus_example_objectmanager_generated = custom_target('objectmanager-gen', - input : ['gdbus-example-objectmanager.xml'], + input : gdbus_example_objectmanager_xml, output : ['objectmanager-gen.h', 'objectmanager-gen.c', 'objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml', @@ -12,6 +13,8 @@ gdbus_example_objectmanager_generated = custom_target('objectmanager-gen', '--output-directory', '@OUTDIR@', '--generate-c-code', 'objectmanager-gen', '--generate-docbook', 'objectmanager-gen', + '--symbol-decorator', '_GLIB_EXTERN', + '--symbol-decorator-define', 'HAVE_CONFIG_H', '@INPUT@']) libgdbus_example_objectmanager = library('gdbus-example-objectmanager', @@ -23,4 +26,5 @@ libgdbus_example_objectmanager = library('gdbus-example-objectmanager', libgdbus_example_objectmanager_dep = declare_dependency( sources : gdbus_example_objectmanager_generated[0], - link_with : libgdbus_example_objectmanager) + link_with : libgdbus_example_objectmanager, + dependencies : [libgio_dep]) diff --git a/gio/tests/gdbus-overflow.c b/gio/tests/gdbus-overflow.c index 53ec9c0b66eeddc0134ab2777ab718f2e4c86ce4..d3e1eb2951490309a06c1850f56dfc3aedfd4509 100644 --- a/gio/tests/gdbus-overflow.c +++ b/gio/tests/gdbus-overflow.c @@ -86,8 +86,8 @@ overflow_filter_func (GDBusConnection *connection, gboolean incoming, gpointer user_data) { - volatile gint *counter = user_data; - *counter += 1; + gint *counter = user_data; /* (atomic) */ + g_atomic_int_inc (counter); return message; } @@ -95,7 +95,7 @@ static gboolean overflow_on_500ms_later_func (gpointer user_data) { g_main_loop_quit (loop); - return FALSE; /* don't keep the idle */ + return G_SOURCE_REMOVE; } static void @@ -108,8 +108,8 @@ test_overflow (void) GDBusConnection *producer, *consumer; GError *error; GTimer *timer; - volatile gint n_messages_received; - volatile gint n_messages_sent; + gint n_messages_received; /* (atomic) */ + gint n_messages_sent; /* (atomic) */ g_assert_cmpint (socketpair (AF_UNIX, SOCK_STREAM, 0, sv), ==, 0); @@ -129,7 +129,7 @@ test_overflow (void) g_dbus_connection_set_exit_on_close (producer, TRUE); g_assert_no_error (error); g_object_unref (socket_connection); - n_messages_sent = 0; + g_atomic_int_set (&n_messages_sent, 0); g_dbus_connection_add_filter (producer, overflow_filter_func, (gpointer) &n_messages_sent, NULL); /* send enough data that we get an EAGAIN */ @@ -155,7 +155,7 @@ test_overflow (void) */ g_timeout_add (500, overflow_on_500ms_later_func, NULL); g_main_loop_run (loop); - g_assert_cmpint (n_messages_sent, <, OVERFLOW_NUM_SIGNALS); + g_assert_cmpint (g_atomic_int_get (&n_messages_sent), <, OVERFLOW_NUM_SIGNALS); /* now suck it all out as a client, and add it up */ socket = g_socket_new_from_fd (sv[1], &error); @@ -171,18 +171,18 @@ test_overflow (void) &error); g_assert_no_error (error); g_object_unref (socket_connection); - n_messages_received = 0; + g_atomic_int_set (&n_messages_received, 0); g_dbus_connection_add_filter (consumer, overflow_filter_func, (gpointer) &n_messages_received, NULL); g_dbus_connection_start_message_processing (consumer); timer = g_timer_new (); g_timer_start (timer); - while (n_messages_received < OVERFLOW_NUM_SIGNALS && g_timer_elapsed (timer, NULL) < OVERFLOW_TIMEOUT_SEC) + while (g_atomic_int_get (&n_messages_received) < OVERFLOW_NUM_SIGNALS && g_timer_elapsed (timer, NULL) < OVERFLOW_TIMEOUT_SEC) g_main_context_iteration (NULL, FALSE); - g_assert_cmpint (n_messages_sent, ==, OVERFLOW_NUM_SIGNALS); - g_assert_cmpint (n_messages_received, ==, OVERFLOW_NUM_SIGNALS); + g_assert_cmpint (g_atomic_int_get (&n_messages_sent), ==, OVERFLOW_NUM_SIGNALS); + g_assert_cmpint (g_atomic_int_get (&n_messages_received), ==, OVERFLOW_NUM_SIGNALS); g_timer_destroy (timer); g_object_unref (consumer); diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index d01bc9a7a4ea54d966cf3e29a53e5f344ba8c415..34fab57134780db0474b8cdb4c88bf6547840e2c 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -76,6 +76,12 @@ typedef struct gboolean signal_received; } PeerData; +/* This needs to be enough to usually take more than one write(), + * to reproduce + * . + * 1 MiB ought to be enough. */ +#define BIG_MESSAGE_ARRAY_SIZE (1024 * 1024) + static const gchar *test_interface_introspection_xml = "" " " @@ -88,6 +94,11 @@ static const gchar *test_interface_introspection_xml = " " " " " " + " " + " " + " " + " " + " " " " " " " " @@ -164,7 +175,8 @@ test_interface_method_call (GDBusConnection *connection, g_dbus_method_invocation_return_value (invocation, NULL); } - else if (g_strcmp0 (method_name, "OpenFile") == 0) + else if (g_strcmp0 (method_name, "OpenFile") == 0 || + g_strcmp0 (method_name, "OpenFileWithBigMessage") == 0) { #ifdef G_OS_UNIX const gchar *path; @@ -190,6 +202,21 @@ test_interface_method_call (GDBusConnection *connection, g_object_unref (fd_list); g_object_unref (invocation); + if (g_strcmp0 (method_name, "OpenFileWithBigMessage") == 0) + { + char *junk; + + junk = g_new0 (char, BIG_MESSAGE_ARRAY_SIZE); + g_dbus_message_set_body (reply, + g_variant_new ("(h@ay)", + 0, + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + junk, + BIG_MESSAGE_ARRAY_SIZE, + 1))); + g_free (junk); + } + error = NULL; g_dbus_connection_send_message (connection, reply, @@ -344,7 +371,7 @@ on_new_connection (GDBusServer *server, gpointer user_data) { PeerData *data = user_data; - GError *error; + GError *error = NULL; guint reg_id; //g_printerr ("Client connected.\n" @@ -362,13 +389,19 @@ on_new_connection (GDBusServer *server, g_assert (credentials != NULL); g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==, getuid ()); - g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==, - getpid ()); +#if G_CREDENTIALS_HAS_PID + g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, + getpid ()); + g_assert_no_error (error); +#else + g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, -1); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_clear_error (&error); +#endif } #endif /* export object on the newly established connection */ - error = NULL; reg_id = g_dbus_connection_register_object (connection, "/org/gtk/GDBus/PeerTestObject", test_interface_introspection_data, @@ -638,7 +671,7 @@ check_connection (gpointer user_data) } } - return FALSE; + return G_SOURCE_REMOVE; } static gboolean @@ -648,7 +681,7 @@ on_do_disconnect_in_idle (gpointer data) g_debug ("GDC %p has ref_count %d", c, G_OBJECT (c)->ref_count); g_dbus_connection_disconnect (c); g_object_unref (c); - return FALSE; + return G_SOURCE_REMOVE; } #endif @@ -717,6 +750,7 @@ do_test_peer (void) const gchar *s; GThread *service_thread; gulong signal_handler_id; + gsize i; memset (&data, '\0', sizeof (PeerData)); data.current_connections = g_ptr_array_new_with_free_func (g_object_unref); @@ -837,73 +871,116 @@ do_test_peer (void) g_assert_cmpint (data.num_method_calls, ==, 3); g_signal_handler_disconnect (proxy, signal_handler_id); - /* check for UNIX fd passing */ + /* + * Check for UNIX fd passing. + * + * The first time through, we use a very simple method call. Note that + * because this does not have a G_VARIANT_TYPE_HANDLE in the message body + * to refer to the fd, it is a GDBus-specific idiom that would not + * interoperate with libdbus or sd-bus + * (see ). + * + * The second time, we call a method that returns a fd attached to a + * large message, to reproduce + * . It also happens + * to follow the more usual pattern for D-Bus messages containing a + * G_VARIANT_TYPE_HANDLE to refer to attached fds. + */ + for (i = 0; i < 2; i++) + { #ifdef G_OS_UNIX - { - GDBusMessage *method_call_message; - GDBusMessage *method_reply_message; - GUnixFDList *fd_list; - gint fd; - gchar *buf; - gsize len; - gchar *buf2; - gsize len2; - const char *testfile = g_test_get_filename (G_TEST_DIST, "file.c", NULL); - - method_call_message = g_dbus_message_new_method_call (NULL, /* name */ - "/org/gtk/GDBus/PeerTestObject", - "org.gtk.GDBus.PeerTestInterface", - "OpenFile"); - g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", testfile)); - error = NULL; - method_reply_message = g_dbus_connection_send_message_with_reply_sync (c, - method_call_message, - G_DBUS_SEND_MESSAGE_FLAGS_NONE, - -1, - NULL, /* out_serial */ - NULL, /* cancellable */ - &error); - g_assert_no_error (error); - g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN); - fd_list = g_dbus_message_get_unix_fd_list (method_reply_message); - g_assert (fd_list != NULL); - g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1); - error = NULL; - fd = g_unix_fd_list_get (fd_list, 0, &error); - g_assert_no_error (error); - g_object_unref (method_call_message); - g_object_unref (method_reply_message); + GDBusMessage *method_call_message; + GDBusMessage *method_reply_message; + GUnixFDList *fd_list; + gint fd; + gchar *buf; + gsize len; + gchar *buf2; + gsize len2; + const char *testfile = g_test_get_filename (G_TEST_DIST, "file.c", NULL); + const char *method = "OpenFile"; + GVariant *body; + + if (i == 1) + method = "OpenFileWithBigMessage"; + + method_call_message = g_dbus_message_new_method_call (NULL, /* name */ + "/org/gtk/GDBus/PeerTestObject", + "org.gtk.GDBus.PeerTestInterface", + method); + g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", testfile)); + error = NULL; + method_reply_message = g_dbus_connection_send_message_with_reply_sync (c, + method_call_message, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + -1, + NULL, /* out_serial */ + NULL, /* cancellable */ + &error); + g_assert_no_error (error); + g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN); - error = NULL; - len = 0; - buf = read_all_from_fd (fd, &len, &error); - g_assert_no_error (error); - g_assert (buf != NULL); - close (fd); + body = g_dbus_message_get_body (method_reply_message); - error = NULL; - g_file_get_contents (testfile, - &buf2, - &len2, - &error); - g_assert_no_error (error); - g_assert_cmpmem (buf, len, buf2, len2); - g_free (buf2); - g_free (buf); - } + if (i == 1) + { + gint32 handle = -1; + GVariant *junk = NULL; + + g_assert_cmpstr (g_variant_get_type_string (body), ==, "(hay)"); + g_variant_get (body, "(h@ay)", &handle, &junk); + g_assert_cmpint (handle, ==, 0); + g_assert_cmpuint (g_variant_n_children (junk), ==, BIG_MESSAGE_ARRAY_SIZE); + g_variant_unref (junk); + } + else + { + g_assert_null (body); + } + + fd_list = g_dbus_message_get_unix_fd_list (method_reply_message); + g_assert (fd_list != NULL); + g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1); + error = NULL; + fd = g_unix_fd_list_get (fd_list, 0, &error); + g_assert_no_error (error); + g_object_unref (method_call_message); + g_object_unref (method_reply_message); + + error = NULL; + len = 0; + buf = read_all_from_fd (fd, &len, &error); + g_assert_no_error (error); + g_assert (buf != NULL); + close (fd); + + error = NULL; + g_file_get_contents (testfile, + &buf2, + &len2, + &error); + g_assert_no_error (error); + g_assert_cmpmem (buf, len, buf2, len2); + g_free (buf2); + g_free (buf); #else - error = NULL; - result = g_dbus_proxy_call_sync (proxy, - "OpenFile", - g_variant_new ("(s)", "boo"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable */ - &error); - g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR); - g_assert (result == NULL); - g_error_free (error); + /* We do the same number of iterations on non-Unix, so that + * the method call count will match. In this case we use + * OpenFile both times, because the difference between this + * and OpenFileWithBigMessage is only relevant on Unix. */ + error = NULL; + result = g_dbus_proxy_call_sync (proxy, + "OpenFile", + g_variant_new ("(s)", "boo"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* GCancellable */ + &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR); + g_assert (result == NULL); + g_error_free (error); #endif /* G_OS_UNIX */ + } /* Check that g_socket_get_credentials() work - (though this really * should be in socket.c) @@ -922,8 +999,15 @@ do_test_peer (void) g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==, getuid ()); - g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==, - getpid ()); +#if G_CREDENTIALS_HAS_PID + g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, + getpid ()); + g_assert_no_error (error); +#else + g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, -1); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_clear_error (&error); +#endif g_object_unref (credentials); #else g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); @@ -1004,7 +1088,7 @@ do_test_peer (void) g_variant_get (result, "(&s)", &s); g_assert_cmpstr (s, ==, "You greeted me with 'Hey Again Peer!'."); g_variant_unref (result); - g_assert_cmpint (data.num_method_calls, ==, 5); + g_assert_cmpint (data.num_method_calls, ==, 6); #if 0 /* TODO: THIS TEST DOESN'T WORK YET */ @@ -1055,6 +1139,183 @@ test_peer (void) /* ---------------------------------------------------------------------------------------------------- */ +#define VALID_GUID "0123456789abcdef0123456789abcdef" + +static void +test_peer_invalid_server (void) +{ + GDBusServer *server; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + if (g_test_subprocess ()) + { + /* This assumes we are not going to run out of GDBusServerFlags + * any time soon */ + server = g_dbus_server_new_sync ("tcp:", (GDBusServerFlags) (1 << 30), + VALID_GUID, + NULL, NULL, NULL); + g_assert_null (server); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_SERVER_FLAGS_ALL*"); + } +} + +static void +test_peer_invalid_conn_stream_sync (void) +{ + GSocket *sock; + GSocketConnection *socket_conn; + GIOStream *iostream; + GDBusConnection *conn; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + sock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, + NULL); + + if (sock == NULL) + { + g_test_skip ("TCP not available?"); + return; + } + + socket_conn = g_socket_connection_factory_create_connection (sock); + g_assert_nonnull (socket_conn); + iostream = G_IO_STREAM (socket_conn); + g_assert_nonnull (iostream); + + if (g_test_subprocess ()) + { + /* This assumes we are not going to run out of GDBusConnectionFlags + * any time soon */ + conn = g_dbus_connection_new_sync (iostream, VALID_GUID, + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL); + g_assert_null (conn); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } + + g_clear_object (&sock); + g_clear_object (&socket_conn); +} + +static void +test_peer_invalid_conn_stream_async (void) +{ + GSocket *sock; + GSocketConnection *socket_conn; + GIOStream *iostream; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + sock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, + NULL); + + if (sock == NULL) + { + g_test_skip ("TCP not available?"); + return; + } + + socket_conn = g_socket_connection_factory_create_connection (sock); + g_assert_nonnull (socket_conn); + iostream = G_IO_STREAM (socket_conn); + g_assert_nonnull (iostream); + + if (g_test_subprocess ()) + { + g_dbus_connection_new (iostream, VALID_GUID, + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL, NULL); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } + + g_clear_object (&sock); + g_clear_object (&socket_conn); +} + +static void +test_peer_invalid_conn_addr_sync (void) +{ + GDBusConnection *conn; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + if (g_test_subprocess ()) + { + conn = g_dbus_connection_new_for_address_sync ("tcp:", + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL); + g_assert_null (conn); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } +} + +static void +test_peer_invalid_conn_addr_async (void) +{ + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + if (g_test_subprocess ()) + { + g_dbus_connection_new_for_address ("tcp:", + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL, NULL); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } +} + +/* ---------------------------------------------------------------------------------------------------- */ + static void test_peer_signals (void) { @@ -1706,7 +1967,7 @@ codegen_on_animal_poke (ExampleAnimal *animal, g_assert_not_reached (); out: - return TRUE; /* to indicate that the method was handled */ + return G_DBUS_METHOD_INVOCATION_HANDLED; } /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */ @@ -1781,7 +2042,7 @@ static gboolean codegen_quit_mainloop_timeout (gpointer data) { g_main_loop_quit (loop); - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -1849,7 +2110,7 @@ codegen_test_peer (void) g_assert (value != NULL); g_variant_unref (value); - /* Give the proxies a chance to refresh in the defaul main loop */ + /* Give the proxies a chance to refresh in the default main loop */ g_timeout_add (100, codegen_quit_mainloop_timeout, NULL); g_main_loop_run (loop); @@ -1884,7 +2145,7 @@ codegen_test_peer (void) g_assert (value != NULL); g_variant_unref (value); - /* Give the proxies a chance to refresh in the defaul main loop */ + /* Give the proxies a chance to refresh in the default main loop */ g_timeout_add (1000, codegen_quit_mainloop_timeout, NULL); g_main_loop_run (loop); @@ -1926,6 +2187,16 @@ main (int argc, test_interface_introspection_data = introspection_data->interfaces[0]; g_test_add_func ("/gdbus/peer-to-peer", test_peer); + g_test_add_func ("/gdbus/peer-to-peer/invalid/server", + test_peer_invalid_server); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/async", + test_peer_invalid_conn_stream_async); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/sync", + test_peer_invalid_conn_stream_sync); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/async", + test_peer_invalid_conn_addr_async); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/sync", + test_peer_invalid_conn_addr_sync); g_test_add_func ("/gdbus/peer-to-peer/signals", test_peer_signals); g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing); g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp); diff --git a/gio/tests/gdbus-proxy-threads.c b/gio/tests/gdbus-proxy-threads.c index 75ed21d51e6d062e2928e85765f06fc2b8b3f592..690a9cc0ebeabee067fb259ef85604f5d89d4703 100644 --- a/gio/tests/gdbus-proxy-threads.c +++ b/gio/tests/gdbus-proxy-threads.c @@ -230,7 +230,7 @@ test_proxy (void) g_main_loop_unref (loop); /* TODO: should call session_bus_down() but that requires waiting - * for all the oustanding method calls to complete... + * for all the outstanding method calls to complete... */ if (g_test_verbose ()) g_printerr ("\n"); diff --git a/gio/tests/gdbus-proxy.c b/gio/tests/gdbus-proxy.c index 05b22ea1c3979ba75a4f5adf3a51979c45223981..a2160dcca7426b2a7787ec5175d662f823d85447 100644 --- a/gio/tests/gdbus-proxy.c +++ b/gio/tests/gdbus-proxy.c @@ -388,7 +388,7 @@ test_proxy_signals_on_emit_signal_cb (GDBusProxy *proxy, g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); g_variant_unref (result); - /* check that the signal was recieved before we got the method result */ + /* check that the signal was received before we got the method result */ g_assert_cmpuint (strlen (data->s->str), >, 0); /* break out of the loop */ diff --git a/gio/tests/gdbus-serialization.c b/gio/tests/gdbus-serialization.c index 2ca28d99b48b2007e4d2751f45d184f39255806f..b95244c9a75bf99d1161dd56bca751388f8a6bde 100644 --- a/gio/tests/gdbus-serialization.c +++ b/gio/tests/gdbus-serialization.c @@ -524,6 +524,7 @@ get_and_check_serialization (GVariant *value) GDBusMessage *recovered_message; GError *error; DBusError dbus_error; + gchar *last_serialization = NULL; gchar *s = NULL; guint n; @@ -617,11 +618,19 @@ get_and_check_serialization (GVariant *value) } g_object_unref (recovered_message); g_free (blob); + + if (last_serialization != NULL) + { + g_assert_cmpstr (last_serialization, ==, s); + g_free (last_serialization); + } + + last_serialization = g_steal_pointer (&s); } g_object_unref (message); - return g_steal_pointer (&s); + return g_steal_pointer (&last_serialization); } /* If @value is floating, this assumes ownership. */ @@ -1118,28 +1127,37 @@ test_message_serialize_double_array (void) /* Test that an invalid header in a D-Bus message (specifically, with a type * which doesn’t match what’s expected for the given header) is gracefully - * handled with an error rather than a crash. - * The set of bytes here come directly from fuzzer output. */ + * handled with an error rather than a crash. */ static void test_message_parse_non_signature_header (void) { const guint8 data[] = { 'l', /* little-endian byte order */ - 0x04, /* message type */ - 0x0f, /* message flags */ + 0x02, /* message type (method return) */ + 0x00, /* message flags (none) */ 0x01, /* major protocol version */ - 0x00, 0x00, 0x00, 0x00, /* body length */ + 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */ 0x00, 0x00, 0x00, 0xbc, /* message serial */ /* a{yv} of header fields: * (things start to be invalid below here) */ - 0x02, 0x00, 0x00, 0x00, /* array length (in bytes) */ - G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, /* array key */ + 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */ + 0x08, /* array key (SIGNATURE) */ /* Variant array value: */ 0x04, /* signature length */ 'd', 0x00, 0x00, 'F', /* signature (invalid) */ 0x00, /* nul terminator */ /* (Variant array value payload missing) */ - /* (message body length missing) */ + /* alignment padding before the next header array element, as structs must + * be 8-aligned: */ + 0x00, + 0x05, /* array key (REPLY_SERIAL, required for method return messages) */ + /* Variant array value: */ + 0x01, /* signature length */ + 'u', /* one complete type */ + 0x00, /* nul terminator */ + /* (Variant array value payload) */ + 0x00, 0x01, 0x02, 0x03, + /* (message body is zero-length) */ }; gsize size = sizeof (data); GDBusMessage *message = NULL; @@ -1158,27 +1176,36 @@ test_message_parse_non_signature_header (void) /* Test that an invalid header in a D-Bus message (specifically, containing a * variant with an empty type signature) is gracefully handled with an error - * rather than a crash. The set of bytes here come directly from fuzzer - * output. */ + * rather than a crash. */ static void test_message_parse_empty_signature_header (void) { const guint8 data[] = { 'l', /* little-endian byte order */ - 0x20, /* message type */ - 0x20, /* message flags */ + 0x02, /* message type (method return) */ + 0x00, /* message flags (none) */ 0x01, /* major protocol version */ - 0x20, 0x20, 0x20, 0x00, /* body length (invalid) */ + 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */ 0x20, 0x20, 0x20, 0x20, /* message serial */ /* a{yv} of header fields: - * (things start to be even more invalid below here) */ - 0x20, 0x20, 0x20, 0x00, /* array length (in bytes) */ - 0x20, /* array key */ + * (things start to be invalid below here) */ + 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */ + 0x20, /* array key (this is not currently a valid header field) */ /* Variant array value: */ 0x00, /* signature length */ 0x00, /* nul terminator */ /* (Variant array value payload missing) */ - /* (message body length missing) */ + /* alignment padding before the next header array element, as structs must + * be 8-aligned: */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, /* array key (REPLY_SERIAL, required for method return messages) */ + /* Variant array value: */ + 0x01, /* signature length */ + 'u', /* one complete type */ + 0x00, /* nul terminator */ + /* (Variant array value payload) */ + 0x00, 0x01, 0x02, 0x03, + /* (message body is zero-length) */ }; gsize size = sizeof (data); GDBusMessage *message = NULL; @@ -1197,28 +1224,37 @@ test_message_parse_empty_signature_header (void) /* Test that an invalid header in a D-Bus message (specifically, containing a * variant with a type signature containing multiple complete types) is - * gracefully handled with an error rather than a crash. The set of bytes here - * come directly from fuzzer output. */ + * gracefully handled with an error rather than a crash. */ static void test_message_parse_multiple_signature_header (void) { const guint8 data[] = { 'l', /* little-endian byte order */ - 0x20, /* message type */ - 0x20, /* message flags */ + 0x02, /* message type (method return) */ + 0x00, /* message flags (none) */ 0x01, /* major protocol version */ - 0x20, 0x20, 0x20, 0x00, /* body length (invalid) */ + 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */ 0x20, 0x20, 0x20, 0x20, /* message serial */ /* a{yv} of header fields: - * (things start to be even more invalid below here) */ - 0x20, 0x20, 0x20, 0x00, /* array length (in bytes) */ - 0x20, /* array key */ + * (things start to be invalid below here) */ + 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */ + 0x20, /* array key (this is not currently a valid header field) */ /* Variant array value: */ 0x02, /* signature length */ 'b', 'b', /* two complete types */ 0x00, /* nul terminator */ /* (Variant array value payload missing) */ - /* (message body length missing) */ + /* alignment padding before the next header array element, as structs must + * be 8-aligned: */ + 0x00, 0x00, 0x00, + 0x05, /* array key (REPLY_SERIAL, required for method return messages) */ + /* Variant array value: */ + 0x01, /* signature length */ + 'u', /* one complete type */ + 0x00, /* nul terminator */ + /* (Variant array value payload) */ + 0x00, 0x01, 0x02, 0x03, + /* (message body is zero-length) */ }; gsize size = sizeof (data); GDBusMessage *message = NULL; @@ -1238,22 +1274,21 @@ test_message_parse_multiple_signature_header (void) /* Test that an invalid header in a D-Bus message (specifically, containing a * variant with a valid type signature that is too long to be a valid * #GVariantType due to exceeding the array nesting limits) is gracefully - * handled with an error rather than a crash. The set of bytes here come - * directly from fuzzer output. */ + * handled with an error rather than a crash. */ static void test_message_parse_over_long_signature_header (void) { const guint8 data[] = { 'l', /* little-endian byte order */ - 0x20, /* message type */ - 0x20, /* message flags */ + 0x02, /* message type (method return) */ + 0x00, /* message flags (none) */ 0x01, /* major protocol version */ - 0x20, 0x20, 0x20, 0x01, /* body length (invalid) */ + 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */ 0x20, 0x20, 0x20, 0x20, /* message serial */ /* a{yv} of header fields: - * (things start to be even more invalid below here) */ - 0x20, 0x00, 0x00, 0x00, /* array length (in bytes) */ - 0x08, /* array key */ + * (things start to be invalid below here) */ + 0xa0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */ + 0x08, /* array key (SIGNATURE) */ /* Variant array value: */ 0x04, /* signature length */ 'g', 0x00, 0x20, 0x20, /* one complete type plus some rubbish */ @@ -1275,8 +1310,16 @@ test_message_parse_over_long_signature_header (void) 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'v' - /* (message body length missing) */ + 'v', + /* first header length is a multiple of 8 so no padding is needed */ + 0x05, /* array key (REPLY_SERIAL, required for method return messages) */ + /* Variant array value: */ + 0x01, /* signature length */ + 'u', /* one complete type */ + 0x00, /* nul terminator */ + /* (Variant array value payload) */ + 0x00, 0x01, 0x02, 0x03, + /* (message body is zero-length) */ }; gsize size = sizeof (data); GDBusMessage *message = NULL; @@ -1295,20 +1338,20 @@ test_message_parse_over_long_signature_header (void) /* Test that an invalid header in a D-Bus message (specifically, containing too * many levels of nested variant) is gracefully handled with an error rather - * than a crash. The set of bytes here come almost directly from fuzzer output. */ + * than a crash. */ static void test_message_parse_deep_header_nesting (void) { const guint8 data[] = { 'l', /* little-endian byte order */ - 0x20, /* message type */ - 0x20, /* message flags */ + 0x02, /* message type (method return) */ + 0x00, /* message flags (none) */ 0x01, /* major protocol version */ - 0x20, 0x20, 0x20, 0x00, /* body length (invalid) */ + 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */ 0x20, 0x20, 0x20, 0x20, /* message serial */ /* a{yv} of header fields: - * (things start to be even more invalid below here) */ - 0x20, 0x20, 0x20, 0x00, /* array length (in bytes) */ + * (things start to be invalid below here) */ + 0xd0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */ 0x20, /* array key (this is not currently a valid header field) */ /* Variant array value: */ 0x01, /* signature length */ @@ -1333,10 +1376,18 @@ test_message_parse_deep_header_nesting (void) 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, - 0x01, 'v', 0x00, 0x01, 'v', 0x00, + 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, /* Some arbitrary valid content inside the innermost variant: */ 0x01, 'y', 0x00, 0xcc, - /* (message body length missing) */ + /* no padding needed as this header element length is a multiple of 8 */ + 0x05, /* array key (REPLY_SERIAL, required for method return messages) */ + /* Variant array value: */ + 0x01, /* signature length */ + 'u', /* one complete type */ + 0x00, /* nul terminator */ + /* (Variant array value payload) */ + 0x00, 0x01, 0x02, 0x03, + /* (message body is zero-length) */ }; gsize size = sizeof (data); GDBusMessage *message = NULL; @@ -1362,22 +1413,30 @@ test_message_parse_deep_body_nesting (void) { const guint8 data[] = { 'l', /* little-endian byte order */ - 0x20, /* message type */ - 0x20, /* message flags */ + 0x02, /* message type (method return) */ + 0x00, /* message flags (none) */ 0x01, /* major protocol version */ - 0x20, 0x20, 0x20, 0x00, /* body length (invalid) */ + 0xc4, 0x00, 0x00, 0x00, /* body length (in bytes) */ 0x20, 0x20, 0x20, 0x20, /* message serial */ /* a{yv} of header fields: */ - 0x07, 0x00, 0x00, 0x00, /* array length (in bytes) */ - 0x08, /* array key (signature field) */ + 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */ + 0x08, /* array key (SIGNATURE) */ /* Variant array value: */ 0x01, /* signature length */ 'g', /* one complete type */ 0x00, /* nul terminator */ /* (Variant array value payload) */ 0x01, 'v', 0x00, - /* End-of-header padding to reach an 8-byte boundary: */ - 0x00, + /* alignment padding before the next header array element, as structs must + * be 8-aligned: */ + 0x00, + 0x05, /* array key (REPLY_SERIAL, required for method return messages) */ + /* Variant array value: */ + 0x01, /* signature length */ + 'u', /* one complete type */ + 0x00, /* nul terminator */ + /* (Variant array value payload) */ + 0x00, 0x01, 0x02, 0x03, /* Message body: over 64 levels of nested variant, which is not valid: */ 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, @@ -1451,4 +1510,3 @@ main (int argc, return g_test_run(); } - diff --git a/gio/tests/gdbus-server-auth.c b/gio/tests/gdbus-server-auth.c new file mode 100644 index 0000000000000000000000000000000000000000..bd1443eb1c02a0a317b6e795dbc320fe2ef30c8f --- /dev/null +++ b/gio/tests/gdbus-server-auth.c @@ -0,0 +1,554 @@ +/* + * Copyright 2019 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include "config.h" + +#include + +#include +#include + +/* For G_CREDENTIALS_*_SUPPORTED */ +#include + +#ifdef HAVE_DBUS1 +#include +#endif + +typedef enum +{ + INTEROP_FLAGS_EXTERNAL = (1 << 0), + INTEROP_FLAGS_ANONYMOUS = (1 << 1), + INTEROP_FLAGS_SHA1 = (1 << 2), + INTEROP_FLAGS_TCP = (1 << 3), + INTEROP_FLAGS_LIBDBUS = (1 << 4), + INTEROP_FLAGS_ABSTRACT = (1 << 5), + INTEROP_FLAGS_REQUIRE_SAME_USER = (1 << 6), + INTEROP_FLAGS_NONE = 0 +} InteropFlags; + +static gboolean +allow_external_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "EXTERNAL") == 0) + { + g_debug ("Accepting EXTERNAL authentication"); + return TRUE; + } + else + { + g_debug ("Rejecting \"%s\" authentication: not EXTERNAL", mechanism); + return FALSE; + } +} + +static gboolean +allow_anonymous_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "ANONYMOUS") == 0) + { + g_debug ("Accepting ANONYMOUS authentication"); + return TRUE; + } + else + { + g_debug ("Rejecting \"%s\" authentication: not ANONYMOUS", mechanism); + return FALSE; + } +} + +static gboolean +allow_sha1_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "DBUS_COOKIE_SHA1") == 0) + { + g_debug ("Accepting DBUS_COOKIE_SHA1 authentication"); + return TRUE; + } + else + { + g_debug ("Rejecting \"%s\" authentication: not DBUS_COOKIE_SHA1", + mechanism); + return FALSE; + } +} + +static gboolean +allow_any_mechanism_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + g_debug ("Accepting \"%s\" authentication", mechanism); + return TRUE; +} + +static gboolean +authorize_any_authenticated_peer_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + G_GNUC_UNUSED GIOStream *stream, + GCredentials *credentials, + G_GNUC_UNUSED gpointer user_data) +{ + if (credentials == NULL) + { + g_debug ("Authorizing peer with no credentials"); + } + else + { + gchar *str = g_credentials_to_string (credentials); + + g_debug ("Authorizing peer with credentials: %s", str); + g_free (str); + } + + return TRUE; +} + +static GDBusMessage * +whoami_filter_cb (GDBusConnection *connection, + GDBusMessage *message, + gboolean incoming, + G_GNUC_UNUSED gpointer user_data) +{ + if (!incoming) + return message; + + if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL && + g_strcmp0 (g_dbus_message_get_member (message), "WhoAmI") == 0) + { + GDBusMessage *reply = g_dbus_message_new_method_reply (message); + gint64 uid = -1; + gint64 pid = -1; +#ifdef G_OS_UNIX + GCredentials *credentials = g_dbus_connection_get_peer_credentials (connection); + + if (credentials != NULL) + { + uid = (gint64) g_credentials_get_unix_user (credentials, NULL); + pid = (gint64) g_credentials_get_unix_pid (credentials, NULL); + } +#endif + + g_dbus_message_set_body (reply, + g_variant_new ("(xx)", uid, pid)); + g_dbus_connection_send_message (connection, reply, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + NULL, NULL); + g_object_unref (reply); + + /* handled */ + g_object_unref (message); + return NULL; + } + + return message; +} + +static gboolean +new_connection_cb (G_GNUC_UNUSED GDBusServer *server, + GDBusConnection *connection, + G_GNUC_UNUSED gpointer user_data) +{ + GCredentials *credentials = g_dbus_connection_get_peer_credentials (connection); + + if (credentials == NULL) + { + g_debug ("New connection from peer with no credentials"); + } + else + { + gchar *str = g_credentials_to_string (credentials); + + g_debug ("New connection from peer with credentials: %s", str); + g_free (str); + } + + g_object_ref (connection); + g_dbus_connection_add_filter (connection, whoami_filter_cb, NULL, NULL); + return TRUE; +} + +#ifdef HAVE_DBUS1 +typedef struct +{ + DBusError error; + DBusConnection *conn; + DBusMessage *call; + DBusMessage *reply; +} LibdbusCall; + +static void +libdbus_call_task_cb (GTask *task, + G_GNUC_UNUSED gpointer source_object, + gpointer task_data, + G_GNUC_UNUSED GCancellable *cancellable) +{ + LibdbusCall *libdbus_call = task_data; + + libdbus_call->reply = dbus_connection_send_with_reply_and_block (libdbus_call->conn, + libdbus_call->call, + -1, + &libdbus_call->error); +} +#endif /* HAVE_DBUS1 */ + +static void +store_result_cb (G_GNUC_UNUSED GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GAsyncResult **result = user_data; + + g_assert_nonnull (result); + g_assert_null (*result); + *result = g_object_ref (res); +} + +static void +assert_expected_uid_pid (InteropFlags flags, + gint64 uid, + gint64 pid) +{ +#ifdef G_OS_UNIX + if (flags & (INTEROP_FLAGS_ANONYMOUS | INTEROP_FLAGS_SHA1 | INTEROP_FLAGS_TCP)) + { + /* No assertion. There is no guarantee whether credentials will be + * passed even though we didn't send them. Conversely, if + * credentials were not passed, + * g_dbus_connection_get_peer_credentials() always returns the + * credentials of the socket, and not the uid that a + * client might have proved it has by using DBUS_COOKIE_SHA1. */ + } + else /* We should prefer EXTERNAL whenever it is allowed. */ + { +#ifdef __linux__ + /* We know that both GDBus and libdbus support full credentials-passing + * on Linux. */ + g_assert_cmpint (uid, ==, getuid ()); + g_assert_cmpint (pid, ==, getpid ()); +#elif defined(__APPLE__) + /* We know (or at least suspect) that both GDBus and libdbus support + * passing the uid only on macOS. */ + g_assert_cmpint (uid, ==, getuid ()); + /* No pid here */ +#else + g_test_message ("Please open a merge request to add appropriate " + "assertions for your platform"); +#endif + } +#endif /* G_OS_UNIX */ +} + +static void +do_test_server_auth (InteropFlags flags) +{ + GError *error = NULL; + gchar *tmpdir = NULL; + gchar *listenable_address = NULL; + GDBusServer *server = NULL; + GDBusAuthObserver *observer = NULL; + GDBusServerFlags server_flags = G_DBUS_SERVER_FLAGS_RUN_IN_THREAD; + gchar *guid = NULL; + const char *connectable_address; + GDBusConnection *client = NULL; + GAsyncResult *result = NULL; + GVariant *tuple = NULL; + gint64 uid, pid; +#ifdef HAVE_DBUS1 + /* GNOME/glib#1831 seems to involve a race condition, so try a few times + * to see if we can trigger it. */ + gsize i; + gsize n = 20; +#endif + + if (flags & INTEROP_FLAGS_TCP) + { + listenable_address = g_strdup ("tcp:host=127.0.0.1"); + } + else + { +#ifdef G_OS_UNIX + gchar *escaped; + + tmpdir = g_dir_make_tmp ("gdbus-server-auth-XXXXXX", &error); + g_assert_no_error (error); + escaped = g_dbus_address_escape_value (tmpdir); + listenable_address = g_strdup_printf ("unix:%s=%s", + (flags & INTEROP_FLAGS_ABSTRACT) ? "tmpdir" : "dir", + escaped); + g_free (escaped); +#else + g_test_skip ("unix: addresses only work on Unix"); + goto out; +#endif + } + + g_test_message ("Testing GDBus server at %s / libdbus client, with flags: " + "external:%s " + "anonymous:%s " + "sha1:%s " + "abstract:%s " + "tcp:%s", + listenable_address, + (flags & INTEROP_FLAGS_EXTERNAL) ? "true" : "false", + (flags & INTEROP_FLAGS_ANONYMOUS) ? "true" : "false", + (flags & INTEROP_FLAGS_SHA1) ? "true" : "false", + (flags & INTEROP_FLAGS_ABSTRACT) ? "true" : "false", + (flags & INTEROP_FLAGS_TCP) ? "true" : "false"); + +#if !defined(G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED) \ + && !defined(G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED) + if (flags & INTEROP_FLAGS_EXTERNAL) + { + g_test_skip ("EXTERNAL authentication not implemented on this platform"); + goto out; + } +#endif + + if (flags & INTEROP_FLAGS_ANONYMOUS) + server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; + if (flags & INTEROP_FLAGS_REQUIRE_SAME_USER) + server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER; + + observer = g_dbus_auth_observer_new (); + + if (flags & INTEROP_FLAGS_EXTERNAL) + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_external_cb), NULL); + else if (flags & INTEROP_FLAGS_ANONYMOUS) + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_anonymous_cb), NULL); + else if (flags & INTEROP_FLAGS_SHA1) + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_sha1_cb), NULL); + else + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_any_mechanism_cb), NULL); + + g_signal_connect (observer, "authorize-authenticated-peer", + G_CALLBACK (authorize_any_authenticated_peer_cb), + NULL); + + guid = g_dbus_generate_guid (); + server = g_dbus_server_new_sync (listenable_address, + server_flags, + guid, + observer, + NULL, + &error); + g_assert_no_error (error); + g_assert_nonnull (server); + g_signal_connect (server, "new-connection", G_CALLBACK (new_connection_cb), NULL); + g_dbus_server_start (server); + connectable_address = g_dbus_server_get_client_address (server); + g_test_message ("Connectable address: %s", connectable_address); + + result = NULL; + g_dbus_connection_new_for_address (connectable_address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, NULL, store_result_cb, &result); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + client = g_dbus_connection_new_for_address_finish (result, &error); + g_assert_no_error (error); + g_assert_nonnull (client); + g_clear_object (&result); + + g_dbus_connection_call (client, NULL, "/", "com.example.Test", "WhoAmI", + NULL, G_VARIANT_TYPE ("(xx)"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, store_result_cb, + &result); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + tuple = g_dbus_connection_call_finish (client, result, &error); + g_assert_no_error (error); + g_assert_nonnull (tuple); + g_clear_object (&result); + g_clear_object (&client); + + uid = -2; + pid = -2; + g_variant_get (tuple, "(xx)", &uid, &pid); + + g_debug ("Server says GDBus client is uid %" G_GINT64_FORMAT ", pid %" G_GINT64_FORMAT, + uid, pid); + + assert_expected_uid_pid (flags, uid, pid); + + g_clear_pointer (&tuple, g_variant_unref); + +#ifdef HAVE_DBUS1 + for (i = 0; i < n; i++) + { + LibdbusCall libdbus_call = { DBUS_ERROR_INIT, NULL, NULL, NULL }; + GTask *task; + + /* The test suite uses %G_TEST_OPTION_ISOLATE_DIRS, which sets + * `HOME=/dev/null` and leaves g_get_home_dir() pointing to the per-test + * temp home directory. Unfortunately, libdbus doesn’t allow the home dir + * to be overridden except using the environment, so copy the per-test + * temp home directory back there so that libdbus uses the same + * `$HOME/.dbus-keyrings` path as GLib. This is not thread-safe. */ + g_setenv ("HOME", g_get_home_dir (), TRUE); + + libdbus_call.conn = dbus_connection_open_private (connectable_address, + &libdbus_call.error); + g_assert_cmpstr (libdbus_call.error.name, ==, NULL); + g_assert_nonnull (libdbus_call.conn); + + libdbus_call.call = dbus_message_new_method_call (NULL, "/", + "com.example.Test", + "WhoAmI"); + + if (libdbus_call.call == NULL) + g_error ("Out of memory"); + + result = NULL; + task = g_task_new (NULL, NULL, store_result_cb, &result); + g_task_set_task_data (task, &libdbus_call, NULL); + g_task_run_in_thread (task, libdbus_call_task_cb); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + g_clear_object (&result); + + g_assert_cmpstr (libdbus_call.error.name, ==, NULL); + g_assert_nonnull (libdbus_call.reply); + + uid = -2; + pid = -2; + dbus_message_get_args (libdbus_call.reply, &libdbus_call.error, + DBUS_TYPE_INT64, &uid, + DBUS_TYPE_INT64, &pid, + DBUS_TYPE_INVALID); + g_assert_cmpstr (libdbus_call.error.name, ==, NULL); + + g_debug ("Server says libdbus client %" G_GSIZE_FORMAT " is uid %" G_GINT64_FORMAT ", pid %" G_GINT64_FORMAT, + i, uid, pid); + assert_expected_uid_pid (flags | INTEROP_FLAGS_LIBDBUS, uid, pid); + + dbus_connection_close (libdbus_call.conn); + dbus_connection_unref (libdbus_call.conn); + dbus_message_unref (libdbus_call.call); + dbus_message_unref (libdbus_call.reply); + g_clear_object (&task); + } +#else /* !HAVE_DBUS1 */ + g_test_skip ("Testing interop with libdbus not supported"); +#endif /* !HAVE_DBUS1 */ + + /* No practical effect, just to avoid -Wunused-label under some + * combinations of #ifdefs */ + goto out; + +out: + if (server != NULL) + g_dbus_server_stop (server); + + if (tmpdir != NULL) + g_assert_cmpstr (g_rmdir (tmpdir) == 0 ? "OK" : g_strerror (errno), + ==, "OK"); + + g_clear_object (&server); + g_clear_object (&observer); + g_free (guid); + g_free (listenable_address); + g_free (tmpdir); +} + +static void +test_server_auth (void) +{ + do_test_server_auth (INTEROP_FLAGS_NONE); +} + +static void +test_server_auth_abstract (void) +{ + do_test_server_auth (INTEROP_FLAGS_ABSTRACT); +} + +static void +test_server_auth_tcp (void) +{ + do_test_server_auth (INTEROP_FLAGS_TCP); +} + +static void +test_server_auth_anonymous (void) +{ + do_test_server_auth (INTEROP_FLAGS_ANONYMOUS); +} + +static void +test_server_auth_anonymous_tcp (void) +{ + do_test_server_auth (INTEROP_FLAGS_ANONYMOUS | INTEROP_FLAGS_TCP); +} + +static void +test_server_auth_external (void) +{ + do_test_server_auth (INTEROP_FLAGS_EXTERNAL); +} + +static void +test_server_auth_external_require_same_user (void) +{ + do_test_server_auth (INTEROP_FLAGS_EXTERNAL | INTEROP_FLAGS_REQUIRE_SAME_USER); +} + +static void +test_server_auth_sha1 (void) +{ + do_test_server_auth (INTEROP_FLAGS_SHA1); +} + +static void +test_server_auth_sha1_tcp (void) +{ + do_test_server_auth (INTEROP_FLAGS_SHA1 | INTEROP_FLAGS_TCP); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); + + g_test_add_func ("/gdbus/server-auth", test_server_auth); + g_test_add_func ("/gdbus/server-auth/abstract", test_server_auth_abstract); + g_test_add_func ("/gdbus/server-auth/tcp", test_server_auth_tcp); + g_test_add_func ("/gdbus/server-auth/anonymous", test_server_auth_anonymous); + g_test_add_func ("/gdbus/server-auth/anonymous/tcp", test_server_auth_anonymous_tcp); + g_test_add_func ("/gdbus/server-auth/external", test_server_auth_external); + g_test_add_func ("/gdbus/server-auth/external/require-same-user", test_server_auth_external_require_same_user); + g_test_add_func ("/gdbus/server-auth/sha1", test_server_auth_sha1); + g_test_add_func ("/gdbus/server-auth/sha1/tcp", test_server_auth_sha1_tcp); + + return g_test_run(); +} diff --git a/gio/tests/gdbus-sessionbus.c b/gio/tests/gdbus-sessionbus.c index e900969737962134c8f979117d36fad5e5f81ae8..29f05d41493b3fce2cf16aa8272ec8dd909cef11 100644 --- a/gio/tests/gdbus-sessionbus.c +++ b/gio/tests/gdbus-sessionbus.c @@ -25,8 +25,21 @@ static GTestDBus *singleton = NULL; void session_bus_up (void) { + gchar *relative, *servicesdir; g_assert (singleton == NULL); singleton = g_test_dbus_new (G_TEST_DBUS_NONE); + + /* We ignore deprecations here so that gdbus-test-codegen-old can + * build successfully despite these two functions not being + * available in GLib 2.36 */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + relative = g_test_build_filename (G_TEST_BUILT, "services", NULL); + servicesdir = g_canonicalize_filename (relative, NULL); + G_GNUC_END_IGNORE_DEPRECATIONS + g_free (relative); + + g_test_dbus_add_service_dir (singleton, servicesdir); + g_free (servicesdir); g_test_dbus_up (singleton); } diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c index 985cb10950d78be56bdb7404d84a03d75d7b6480..36be37b725533dd0fe5fe60a980d33d82171086c 100644 --- a/gio/tests/gdbus-test-codegen.c +++ b/gio/tests/gdbus-test-codegen.c @@ -23,11 +23,23 @@ #include #include +#include "glib/glib-private.h" + #include "gdbus-tests.h" +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 +#include "gdbus-test-codegen-generated-min-required-2-64.h" +#else #include "gdbus-test-codegen-generated.h" +#endif + #include "gdbus-test-codegen-generated-interface-info.h" +#if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_68 +# undef G_DBUS_METHOD_INVOCATION_HANDLED +# define G_DBUS_METHOD_INVOCATION_HANDLED TRUE +#endif + /* ---------------------------------------------------------------------------------------------------- */ static guint @@ -95,7 +107,7 @@ on_handle_hello_world (FooiGenBar *object, response = g_strdup_printf ("Word! You said '%s'. I'm Skeleton, btw!", greeting); foo_igen_bar_complete_hello_world (object, invocation, response); g_free (response); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -140,7 +152,7 @@ on_handle_test_primitive_types (FooiGenBar *object, g_free (s1); g_free (s2); g_free (s3); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -180,7 +192,7 @@ on_handle_test_non_primitive_types (FooiGenBar *object, array_of_bytestrings, str->str); g_string_free (str, TRUE); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -197,7 +209,7 @@ on_handle_request_signal_emission (FooiGenBar *object, foo_igen_bar_emit_test_signal (object, 43, a_strv, a_bytestring_array, a_variant); /* consumes a_variant */ foo_igen_bar_complete_request_signal_emission (object, invocation); } - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -213,7 +225,7 @@ on_handle_request_multi_property_mods (FooiGenBar *object, foo_igen_bar_set_y (object, foo_igen_bar_get_y (object) + 1); foo_igen_bar_set_i (object, foo_igen_bar_get_i (object) + 1); foo_igen_bar_complete_request_multi_property_mods (object, invocation); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -233,7 +245,7 @@ on_handle_property_cancellation (FooiGenBar *object, g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (object)); /* this makes us return the reply D-Bus method */ foo_igen_bar_complete_property_cancellation (object, invocation); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } /* ---------------------------------------------------------------------------------------------------- */ @@ -288,7 +300,7 @@ on_handle_force_method (FooiGenBat *object, g_variant_unref (ret_ay); g_variant_unref (ret_struct); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } @@ -377,7 +389,7 @@ on_handle_check_not_authorized (FooiGenAuthorize *object, gpointer user_data) { foo_igen_authorize_complete_check_not_authorized (object, invocation); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -386,7 +398,7 @@ on_handle_check_authorized (FooiGenAuthorize *object, gpointer user_data) { foo_igen_authorize_complete_check_authorized (object, invocation); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -395,7 +407,7 @@ on_handle_check_not_authorized_from_object (FooiGenAuthorize *object, gpointer user_data) { foo_igen_authorize_complete_check_not_authorized_from_object (object, invocation); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } /* ---------------------------------------------------------------------------------------------------- */ @@ -409,7 +421,7 @@ on_handle_get_self (FooiGenMethodThreads *object, s = g_strdup_printf ("%p", (void *)g_thread_self ()); foo_igen_method_threads_complete_get_self (object, invocation, s); g_free (s); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } /* ---------------------------------------------------------------------------------------------------- */ @@ -878,6 +890,10 @@ check_bar_proxy (FooiGenBar *proxy, "/a/path", "asig", "bytestring\xff", +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + G_DBUS_CALL_FLAGS_NONE, + -1, +#endif &ret_val_byte, &ret_val_boolean, &ret_val_int16, @@ -913,6 +929,10 @@ check_bar_proxy (FooiGenBar *proxy, array_of_objpaths, array_of_signatures, array_of_bytestrings, +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + G_DBUS_CALL_FLAGS_NONE, + -1, +#endif &ret_array_of_strings, &ret_array_of_objpaths, &ret_array_of_signatures, @@ -946,7 +966,11 @@ check_bar_proxy (FooiGenBar *proxy, * unimplemented methods. */ error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_bar_call_unimplemented_method_sync (proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL /* GCancellable */, &error); +#else ret = foo_igen_bar_call_unimplemented_method_sync (proxy, NULL /* GCancellable */, &error); +#endif g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); g_error_free (error); error = NULL; @@ -957,7 +981,11 @@ check_bar_proxy (FooiGenBar *proxy, G_CALLBACK (on_test_signal), data); error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_bar_call_request_signal_emission_sync (proxy, 0, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); +#else ret = foo_igen_bar_call_request_signal_emission_sync (proxy, 0, NULL, &error); +#endif g_assert_no_error (error); g_assert (ret); @@ -1011,7 +1039,11 @@ check_bar_proxy (FooiGenBar *proxy, G_CALLBACK (on_g_properties_changed), data); error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_bar_call_request_multi_property_mods_sync (proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); +#else ret = foo_igen_bar_call_request_multi_property_mods_sync (proxy, NULL, &error); +#endif g_assert_no_error (error); g_assert (ret); g_main_loop_run (thread_loop); @@ -1077,6 +1109,10 @@ check_bar_proxy (FooiGenBar *proxy, */ error = NULL; foo_igen_bar_call_property_cancellation (proxy, +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + G_DBUS_CALL_FLAGS_NONE, + -1, +#endif NULL, /* GCancellable */ (GAsyncReadyCallback) on_property_cancellation_cb, data); @@ -1159,6 +1195,10 @@ check_bat_proxy (FooiGenBat *proxy, g_variant_new_string ("a string"), g_variant_new_bytestring ("a bytestring\xff"), g_variant_new ("(i)", 4200), +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + G_DBUS_CALL_FLAGS_NONE, + -1, +#endif &ret_i, &ret_s, &ret_ay, @@ -1191,18 +1231,30 @@ check_authorize_proxy (FooiGenAuthorize *proxy, /* Check that g-authorize-method works as intended */ error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_authorize_call_check_not_authorized_sync (proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); +#else ret = foo_igen_authorize_call_check_not_authorized_sync (proxy, NULL, &error); +#endif g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED); g_error_free (error); g_assert (!ret); error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_authorize_call_check_authorized_sync (proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); +#else ret = foo_igen_authorize_call_check_authorized_sync (proxy, NULL, &error); +#endif g_assert_no_error (error); g_assert (ret); error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_authorize_call_check_not_authorized_from_object_sync (proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); +#else ret = foo_igen_authorize_call_check_not_authorized_from_object_sync (proxy, NULL, &error); +#endif g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); g_error_free (error); g_assert (!ret); @@ -1219,7 +1271,11 @@ get_self_via_proxy (FooiGenMethodThreads *proxy_1) gpointer self; error = NULL; +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 + ret = foo_igen_method_threads_call_get_self_sync (proxy_1, G_DBUS_CALL_FLAGS_NONE, -1, &self_str, NULL, &error); +#else ret = foo_igen_method_threads_call_get_self_sync (proxy_1, &self_str, NULL, &error); +#endif g_assert_no_error (error); g_assert (ret); @@ -1248,6 +1304,18 @@ static gpointer check_proxies_in_thread (gpointer user_data) { GMainLoop *loop = user_data; +#ifdef _GLIB_ADDRESS_SANITIZER + + /* Silence "Not available before 2.38" when using old API */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + g_test_incomplete ("FIXME: Leaks a GWeakRef, see glib#2312"); + G_GNUC_END_IGNORE_DEPRECATIONS + + (void) check_thread_proxies; + (void) check_authorize_proxy; + (void) check_bat_proxy; + (void) check_bar_proxy; +#else GMainContext *thread_context; GMainLoop *thread_loop; GError *error; @@ -1316,6 +1384,7 @@ check_proxies_in_thread (gpointer user_data) g_main_loop_unref (thread_loop); g_main_context_unref (thread_context); +#endif /* this breaks out of the loop in main() (below) */ g_main_loop_quit (loop); @@ -2385,7 +2454,7 @@ test_interface_stability (void) * * - check that a property with name "Type" is mapped into g-name "type" * with C accessors get_type_ (to avoid clashing with the GType accessor) - * and set_type_ (for symmetri) + * and set_type_ (for symmetry) * (see https://bugzilla.gnome.org/show_bug.cgi?id=679473 for details) * * - (could add more tests here) @@ -2588,6 +2657,86 @@ test_standalone_interface_info (void) g_clear_object (&skel); } +/* ---------------------------------------------------------------------------------------------------- */ +static gboolean +handle_hello_fd (FooiGenFDPassing *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_greeting) +{ + foo_igen_fdpassing_complete_hello_fd (object, invocation, fd_list, arg_greeting); + return G_DBUS_METHOD_INVOCATION_HANDLED; +} + +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 +static gboolean +handle_no_annotation (FooiGenFDPassing *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_greeting, + const gchar *arg_greeting_locale) +{ + foo_igen_fdpassing_complete_no_annotation (object, invocation, fd_list, arg_greeting, arg_greeting_locale); + return G_DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +handle_no_annotation_nested (FooiGenFDPassing *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_files) +{ + foo_igen_fdpassing_complete_no_annotation_nested (object, invocation, fd_list); + return G_DBUS_METHOD_INVOCATION_HANDLED; +} +#else +static gboolean +handle_no_annotation (FooiGenFDPassing *object, + GDBusMethodInvocation *invocation, + GVariant *arg_greeting, + const gchar *arg_greeting_locale) +{ + foo_igen_fdpassing_complete_no_annotation (object, invocation, arg_greeting, arg_greeting_locale); + return G_DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +handle_no_annotation_nested (FooiGenFDPassing *object, + GDBusMethodInvocation *invocation, + GVariant *arg_files) +{ + foo_igen_fdpassing_complete_no_annotation_nested (object, invocation); + return G_DBUS_METHOD_INVOCATION_HANDLED; +} +#endif + +/* Test that generated code for methods includes GUnixFDList arguments + * unconditionally if the method is explicitly annotated as C.UnixFD, and only + * emits GUnixFDList arguments when there's merely an 'h' parameter if + * --glib-min-required=2.64 or greater. + */ +static void +test_unix_fd_list (void) +{ + FooiGenFDPassingIface iface; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1726"); + + /* This method is explicitly annotated. */ + iface.handle_hello_fd = handle_hello_fd; + + /* This one is not annotated; even though it's got an in and out 'h' + * parameter, for backwards compatibility we cannot emit GUnixFDList + * arguments unless --glib-min-required >= 2.64 was used. + */ + iface.handle_no_annotation = handle_no_annotation; + + /* This method has an 'h' inside a complex type. */ + iface.handle_no_annotation_nested = handle_no_annotation_nested; + + (void) iface; +} + /* ---------------------------------------------------------------------------------------------------- */ int @@ -2603,6 +2752,7 @@ main (int argc, g_test_add_func ("/gdbus/codegen/autocleanups", test_autocleanups); g_test_add_func ("/gdbus/codegen/deprecations", test_deprecations); g_test_add_func ("/gdbus/codegen/standalone-interface-info", test_standalone_interface_info); + g_test_add_func ("/gdbus/codegen/unix-fd-list", test_unix_fd_list); return session_bus_run (); } diff --git a/gio/tests/gdbus-test-fixture.c b/gio/tests/gdbus-test-fixture.c index f8b9b93b6efd34b1d6e03dc1886f25700e8986b8..2071bbad9d88da07ca5b984e0cd87f87923eff6c 100644 --- a/gio/tests/gdbus-test-fixture.c +++ b/gio/tests/gdbus-test-fixture.c @@ -15,16 +15,20 @@ static void fixture_setup (TestFixture *fixture, gconstpointer unused) { GError *error = NULL; + gchar *relative, *servicesdir; /* Create the global dbus-daemon for this test suite */ fixture->dbus = g_test_dbus_new (G_TEST_DBUS_NONE); - /* Add the private directory with our in-tree service files, - * TEST_SERVICES is defined by the build system to point - * to the right directory. + /* Add the private directory with our in-tree service files. */ - g_test_dbus_add_service_dir (fixture->dbus, TEST_SERVICES); + relative = g_test_build_filename (G_TEST_BUILT, "services", NULL); + servicesdir = g_canonicalize_filename (relative, NULL); + g_free (relative); + + g_test_dbus_add_service_dir (fixture->dbus, servicesdir); + g_free (servicesdir); /* Start the private D-Bus daemon */ diff --git a/gio/tests/gdbus-tests.c b/gio/tests/gdbus-tests.c index 35e379bd2c32295308539659f6844be6cd044c6e..1003d07e0a2073c0c500346a21705e0fab3d4b3c 100644 --- a/gio/tests/gdbus-tests.c +++ b/gio/tests/gdbus-tests.c @@ -48,7 +48,7 @@ on_property_notify_timeout (gpointer user_data) PropertyNotifyData *data = user_data; data->timed_out = TRUE; g_main_loop_quit (data->loop); - return TRUE; + return G_SOURCE_CONTINUE; } gboolean @@ -83,52 +83,75 @@ static gboolean _give_up (gpointer data) { g_error ("%s", (const gchar *) data); - g_return_val_if_reached (TRUE); + g_return_val_if_reached (G_SOURCE_CONTINUE); +} + +typedef struct +{ + GMainContext *context; + gboolean name_appeared; + gboolean unwatch_complete; +} WatchData; + +static void +name_appeared_cb (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + WatchData *data = user_data; + + g_assert (name_owner != NULL); + data->name_appeared = TRUE; + g_main_context_wakeup (data->context); +} + +static void +watch_free_cb (gpointer user_data) +{ + WatchData *data = user_data; + + data->unwatch_complete = TRUE; + g_main_context_wakeup (data->context); } void -ensure_gdbus_testserver_up (void) +ensure_gdbus_testserver_up (GDBusConnection *connection, + GMainContext *context) { - guint id; - gchar *name_owner; - GDBusConnection *connection; - GDBusProxy *proxy; - GError *error = NULL; - - connection = g_bus_get_sync (G_BUS_TYPE_SESSION, - NULL, - &error); - - g_assert_no_error (error); - error = NULL; - - proxy = g_dbus_proxy_new_sync (connection, - G_DBUS_PROXY_FLAGS_NONE, - NULL, /* GDBusInterfaceInfo */ - "com.example.TestService", /* name */ - "/com/example/TestObject", /* object path */ - "com.example.Frob", /* interface */ - NULL, /* GCancellable */ - &error); - g_assert_no_error (error); - - id = g_timeout_add_seconds (60, _give_up, - "waited more than ~ 60s for gdbus-testserver to take its bus name"); - - while (TRUE) - { - name_owner = g_dbus_proxy_get_name_owner (proxy); - - if (name_owner != NULL) - break; - - g_main_context_iteration (NULL, TRUE); - } - - g_source_remove (id); - g_free (name_owner); - g_object_unref (proxy); - g_object_unref (connection); + GSource *timeout_source = NULL; + guint watch_id; + WatchData data = { context, FALSE, FALSE }; + + g_main_context_push_thread_default (context); + + watch_id = g_bus_watch_name_on_connection (connection, + "com.example.TestService", + G_BUS_NAME_WATCHER_FLAGS_NONE, + name_appeared_cb, + NULL, + &data, + watch_free_cb); + + timeout_source = g_timeout_source_new_seconds (60); + g_source_set_callback (timeout_source, _give_up, + "waited more than ~ 60s for gdbus-testserver to take its bus name", + NULL); + g_source_attach (timeout_source, context); + + while (!data.name_appeared) + g_main_context_iteration (context, TRUE); + + g_bus_unwatch_name (watch_id); + watch_id = 0; + + while (!data.unwatch_complete) + g_main_context_iteration (context, TRUE); + + g_source_destroy (timeout_source); + g_source_unref (timeout_source); + + g_main_context_pop_thread_default (context); } /* ---------------------------------------------------------------------------------------------------- */ @@ -152,7 +175,7 @@ on_signal_received_timeout (gpointer user_data) SignalReceivedData *data = user_data; data->timed_out = TRUE; g_main_loop_quit (data->loop); - return TRUE; + return G_SOURCE_CONTINUE; } gboolean diff --git a/gio/tests/gdbus-tests.h b/gio/tests/gdbus-tests.h index 00cda37130ea5740973db21df3d5c1b35d4fee9a..eaef23480d8f66188263920cca3167505d801b08 100644 --- a/gio/tests/gdbus-tests.h +++ b/gio/tests/gdbus-tests.h @@ -114,7 +114,8 @@ GDBusConnection *_g_bus_get_priv (GBusType bus_type, GCancellable *cancellable, GError **error); -void ensure_gdbus_testserver_up (void); +void ensure_gdbus_testserver_up (GDBusConnection *connection, + GMainContext *context); G_END_DECLS diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c index ffca6f317bf97d8578fa7b762e1f10e69b321212..4519fda9134a64795369d4706987a84afa16d52b 100644 --- a/gio/tests/gdbus-threading.c +++ b/gio/tests/gdbus-threading.c @@ -27,59 +27,77 @@ /* all tests rely on a global connection */ static GDBusConnection *c = NULL; -/* ---------------------------------------------------------------------------------------------------- */ -/* Ensure that signal and method replies are delivered in the right thread */ -/* ---------------------------------------------------------------------------------------------------- */ +typedef struct +{ + GMainContext *context; + gboolean timed_out; +} TimeoutData; -typedef struct { - GThread *thread; - GMainLoop *thread_loop; - guint signal_count; -} DeliveryData; +static gboolean +timeout_cb (gpointer user_data) +{ + TimeoutData *data = user_data; + + data->timed_out = TRUE; + g_main_context_wakeup (data->context); + return G_SOURCE_REMOVE; +} + +/* Check that the given @connection has only one ref, waiting to let any pending + * unrefs complete first. This is typically used on the shared connection, to + * ensure it’s in a correct state before beginning the next test. */ static void -msg_cb_expect_success (GDBusConnection *connection, - GAsyncResult *res, - gpointer user_data) +assert_connection_has_one_ref (GDBusConnection *connection, + GMainContext *context) { - DeliveryData *data = user_data; - GError *error; - GVariant *result; + GSource *timeout_source = NULL; + TimeoutData data = { context, FALSE }; - error = NULL; - result = g_dbus_connection_call_finish (connection, - res, - &error); - g_assert_no_error (error); - g_assert (result != NULL); - g_variant_unref (result); + if (g_atomic_int_get (&G_OBJECT (connection)->ref_count) == 1) + return; - g_assert (g_thread_self () == data->thread); + timeout_source = g_timeout_source_new_seconds (3); + g_source_set_callback (timeout_source, timeout_cb, &data, NULL); + g_source_attach (timeout_source, context); - g_main_loop_quit (data->thread_loop); + while (g_atomic_int_get (&G_OBJECT (connection)->ref_count) != 1 && !data.timed_out) + { + g_debug ("refcount of %p is not right, sleeping", connection); + g_main_context_iteration (NULL, TRUE); + } + + g_source_destroy (timeout_source); + g_source_unref (timeout_source); + + if (g_atomic_int_get (&G_OBJECT (connection)->ref_count) != 1) + g_error ("connection %p had too many refs", connection); } +/* ---------------------------------------------------------------------------------------------------- */ +/* Ensure that signal and method replies are delivered in the right thread */ +/* ---------------------------------------------------------------------------------------------------- */ + +typedef struct { + GThread *thread; + GMainContext *context; + guint signal_count; + gboolean unsubscribe_complete; + GAsyncResult *async_result; +} DeliveryData; + static void -msg_cb_expect_error_cancelled (GDBusConnection *connection, - GAsyncResult *res, - gpointer user_data) +async_result_cb (GDBusConnection *connection, + GAsyncResult *res, + gpointer user_data) { DeliveryData *data = user_data; - GError *error; - GVariant *result; - error = NULL; - result = g_dbus_connection_call_finish (connection, - res, - &error); - g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); - g_assert (!g_dbus_error_is_remote_error (error)); - g_error_free (error); - g_assert (result == NULL); + data->async_result = g_object_ref (res); - g_assert (g_thread_self () == data->thread); + g_assert_true (g_thread_self () == data->thread); - g_main_loop_quit (data->thread_loop); + g_main_context_wakeup (data->context); } static void @@ -93,33 +111,43 @@ signal_handler (GDBusConnection *connection, { DeliveryData *data = user_data; - g_assert (g_thread_self () == data->thread); + g_assert_true (g_thread_self () == data->thread); data->signal_count++; - g_main_loop_quit (data->thread_loop); + g_main_context_wakeup (data->context); +} + +static void +signal_data_free_cb (gpointer user_data) +{ + DeliveryData *data = user_data; + + g_assert_true (g_thread_self () == data->thread); + + data->unsubscribe_complete = TRUE; + + g_main_context_wakeup (data->context); } static gpointer test_delivery_in_thread_func (gpointer _data) { - GMainLoop *thread_loop; GMainContext *thread_context; DeliveryData data; GCancellable *ca; guint subscription_id; - GDBusConnection *priv_c; - GError *error; - - error = NULL; + GError *error = NULL; + GVariant *result_variant = NULL; thread_context = g_main_context_new (); - thread_loop = g_main_loop_new (thread_context, FALSE); g_main_context_push_thread_default (thread_context); data.thread = g_thread_self (); - data.thread_loop = thread_loop; + data.context = thread_context; data.signal_count = 0; + data.unsubscribe_complete = FALSE; + data.async_result = NULL; /* ---------------------------------------------------------------------------------------------------- */ @@ -135,9 +163,16 @@ test_delivery_in_thread_func (gpointer _data) G_DBUS_CALL_FLAGS_NONE, -1, NULL, - (GAsyncReadyCallback) msg_cb_expect_success, + (GAsyncReadyCallback) async_result_cb, &data); - g_main_loop_run (thread_loop); + while (data.async_result == NULL) + g_main_context_iteration (thread_context, TRUE); + + result_variant = g_dbus_connection_call_finish (c, data.async_result, &error); + g_assert_no_error (error); + g_assert_nonnull (result_variant); + g_clear_pointer (&result_variant, g_variant_unref); + g_clear_object (&data.async_result); /* * Check that we never actually send a message if the GCancellable @@ -155,9 +190,18 @@ test_delivery_in_thread_func (gpointer _data) G_DBUS_CALL_FLAGS_NONE, -1, ca, - (GAsyncReadyCallback) msg_cb_expect_error_cancelled, + (GAsyncReadyCallback) async_result_cb, &data); - g_main_loop_run (thread_loop); + while (data.async_result == NULL) + g_main_context_iteration (thread_context, TRUE); + + result_variant = g_dbus_connection_call_finish (c, data.async_result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_assert_false (g_dbus_error_is_remote_error (error)); + g_clear_error (&error); + g_assert_null (result_variant); + g_clear_object (&data.async_result); + g_object_unref (ca); /* @@ -173,47 +217,74 @@ test_delivery_in_thread_func (gpointer _data) G_DBUS_CALL_FLAGS_NONE, -1, ca, - (GAsyncReadyCallback) msg_cb_expect_error_cancelled, + (GAsyncReadyCallback) async_result_cb, &data); g_cancellable_cancel (ca); - g_main_loop_run (thread_loop); + + while (data.async_result == NULL) + g_main_context_iteration (thread_context, TRUE); + + result_variant = g_dbus_connection_call_finish (c, data.async_result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_assert_false (g_dbus_error_is_remote_error (error)); + g_clear_error (&error); + g_assert_null (result_variant); + g_clear_object (&data.async_result); + g_object_unref (ca); /* * Check that signals are delivered to the correct thread. * - * First we subscribe to the signal, then we create a a private - * connection. This should cause a NameOwnerChanged message from - * the message bus. + * First we subscribe to the signal, then we call EmitSignal(). This should + * cause a TestSignal emission from the testserver. */ subscription_id = g_dbus_connection_signal_subscribe (c, - "org.freedesktop.DBus", /* sender */ - "org.freedesktop.DBus", /* interface */ - "NameOwnerChanged", /* member */ - "/org/freedesktop/DBus", /* path */ + "com.example.TestService", /* sender */ + "com.example.Frob", /* interface */ + "TestSignal", /* member */ + "/com/example/TestObject", /* path */ NULL, G_DBUS_SIGNAL_FLAGS_NONE, signal_handler, &data, - NULL); - g_assert (subscription_id != 0); - g_assert (data.signal_count == 0); + signal_data_free_cb); + g_assert_cmpuint (subscription_id, !=, 0); + g_assert_cmpuint (data.signal_count, ==, 0); - priv_c = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error); - g_assert_no_error (error); - g_assert (priv_c != NULL); + g_dbus_connection_call (c, + "com.example.TestService", /* bus_name */ + "/com/example/TestObject", /* object path */ + "com.example.Frob", /* interface name */ + "EmitSignal", /* method name */ + g_variant_new_parsed ("('hello', @o '/com/example/TestObject')"), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) async_result_cb, + &data); + while (data.async_result == NULL || data.signal_count < 1) + g_main_context_iteration (thread_context, TRUE); - g_main_loop_run (thread_loop); - g_assert (data.signal_count == 1); + result_variant = g_dbus_connection_call_finish (c, data.async_result, &error); + g_assert_no_error (error); + g_assert_nonnull (result_variant); + g_clear_pointer (&result_variant, g_variant_unref); + g_clear_object (&data.async_result); - g_object_unref (priv_c); + g_assert_cmpuint (data.signal_count, ==, 1); g_dbus_connection_signal_unsubscribe (c, subscription_id); + subscription_id = 0; + + while (!data.unsubscribe_complete) + g_main_context_iteration (thread_context, TRUE); + g_assert_true (data.unsubscribe_complete); /* ---------------------------------------------------------------------------------------------------- */ g_main_context_pop_thread_default (thread_context); - g_main_loop_unref (thread_loop); g_main_context_unref (thread_context); return NULL; @@ -229,6 +300,8 @@ test_delivery_in_thread (void) NULL); g_thread_join (thread); + + assert_connection_has_one_ref (c, NULL); } /* ---------------------------------------------------------------------------------------------------- */ @@ -257,11 +330,11 @@ sleep_cb (GDBusProxy *proxy, res, &error); g_assert_no_error (error); - g_assert (result != NULL); + g_assert_nonnull (result); g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); g_variant_unref (result); - g_assert (data->thread == g_thread_self ()); + g_assert_true (data->thread == g_thread_self ()); g_main_loop_quit (data->thread_loop); @@ -317,7 +390,7 @@ test_sleep_in_thread_func (gpointer _data) g_printerr ("S"); //g_debug ("done invoking sync (%p)", g_thread_self ()); g_assert_no_error (error); - g_assert (result != NULL); + g_assert_nonnull (result); g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); g_variant_unref (result); } @@ -333,10 +406,10 @@ test_sleep_in_thread_func (gpointer _data) static void test_method_calls_on_proxy (GDBusProxy *proxy) { - guint n; + guint n, divisor; /* - * Check that multiple threads can do calls without interferring with + * Check that multiple threads can do calls without interfering with * each other. We do this by creating three threads that call the * Sleep() method on the server (which handles it asynchronously, e.g. * it won't block other requests) with different sleep durations and @@ -352,6 +425,11 @@ test_method_calls_on_proxy (GDBusProxy *proxy) * again with sync calls */ + if (g_test_thorough ()) + divisor = 1; + else + divisor = 10; + for (n = 0; n < 2; n++) { gboolean do_async; @@ -370,7 +448,7 @@ test_method_calls_on_proxy (GDBusProxy *proxy) data1.proxy = proxy; data1.msec = 40; - data1.num = 100; + data1.num = 100 / divisor; data1.async = do_async; thread1 = g_thread_new ("sleep", test_sleep_in_thread_func, @@ -378,7 +456,7 @@ test_method_calls_on_proxy (GDBusProxy *proxy) data2.proxy = proxy; data2.msec = 20; - data2.num = 200; + data2.num = 200 / divisor; data2.async = do_async; thread2 = g_thread_new ("sleep2", test_sleep_in_thread_func, @@ -386,7 +464,7 @@ test_method_calls_on_proxy (GDBusProxy *proxy) data3.proxy = proxy; data3.msec = 100; - data3.num = 40; + data3.num = 40 / divisor; data3.async = do_async; thread3 = g_thread_new ("sleep3", test_sleep_in_thread_func, @@ -403,8 +481,8 @@ test_method_calls_on_proxy (GDBusProxy *proxy) //g_debug ("Elapsed time for %s = %d msec", n == 0 ? "async" : "sync", elapsed_msec); /* elapsed_msec should be 4000 msec +/- change for overhead/inaccuracy */ - g_assert_cmpint (elapsed_msec, >=, 3950); - g_assert_cmpint (elapsed_msec, <, 30000); + g_assert_cmpint (elapsed_msec, >=, 3950 / divisor); + g_assert_cmpint (elapsed_msec, <, 30000 / divisor); if (g_test_verbose ()) g_printerr (" "); @@ -441,6 +519,8 @@ test_method_calls_in_thread (void) if (g_test_verbose ()) g_printerr ("\n"); + + assert_connection_has_one_ref (c, NULL); } #define SLEEP_MIN_USEC 1 @@ -457,8 +537,8 @@ ensure_connection_works (GDBusConnection *conn) "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetId", NULL, NULL, 0, -1, NULL, &error); g_assert_no_error (error); - g_assert (v != NULL); - g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE ("(s)"))); + g_assert_nonnull (v); + g_assert_true (g_variant_is_of_type (v, G_VARIANT_TYPE ("(s)"))); g_variant_unref (v); } @@ -500,29 +580,16 @@ test_threaded_singleton (void) if (g_test_thorough ()) n = 100000; else - n = 5000; + n = 1000; for (i = 0; i < n; i++) { GThread *thread; - guint j; guint unref_delay, get_delay; GDBusConnection *new_conn; /* We want to be the last ref, so let it finish setting up */ - for (j = 0; j < 100; j++) - { - guint r = g_atomic_int_get (&G_OBJECT (c)->ref_count); - - if (r == 1) - break; - - g_debug ("run %u: refcount is %u, sleeping", i, r); - g_usleep (1000); - } - - if (j == 100) - g_error ("connection had too many refs"); + assert_connection_has_one_ref (c, NULL); if (g_test_verbose () && (i % (n/50)) == 0) g_printerr ("%u%%\n", ((i * 100) / n)); @@ -586,16 +653,16 @@ main (int argc, /* this is safe; testserver will exit once the bus goes away */ path = g_test_build_filename (G_TEST_BUILT, "gdbus-testserver", NULL); - g_assert (g_spawn_command_line_async (path, NULL)); + g_assert_true (g_spawn_command_line_async (path, NULL)); g_free (path); - ensure_gdbus_testserver_up (); - /* Create the connection in the main thread */ error = NULL; c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); - g_assert (c != NULL); + g_assert_nonnull (c); + + ensure_gdbus_testserver_up (c, NULL); g_test_add_func ("/gdbus/delivery-in-thread", test_delivery_in_thread); g_test_add_func ("/gdbus/method-calls-in-thread", test_method_calls_in_thread); diff --git a/gio/tests/gen-big-test-resource.py b/gio/tests/gen-big-test-resource.py index e031a0a08b87e46232b1834a7e9d78a3532644a5..b2e478dd585c4f26fe5b56dd0e3e93861231a0ba 100644 --- a/gio/tests/gen-big-test-resource.py +++ b/gio/tests/gen-big-test-resource.py @@ -8,14 +8,13 @@ # # See issue #1580 -import io import string import sys if len(sys.argv) != 2: - raise SystemExit('Usage: %s ' % sys.argv[0]) + raise SystemExit("Usage: %s " % sys.argv[0]) -with open(sys.argv[1], 'w', newline='\n') as f: +with open(sys.argv[1], "w", newline="\n") as f: for count in range(12): for c in string.ascii_lowercase: f.write("%s\n" % (c * 100)) diff --git a/gio/tests/gengiotypefuncs.py b/gio/tests/gengiotypefuncs.py index 47219f3574d386d4523c98efa3c7c08eb9504b3b..dbd8195e74ef6a8333c14c8be3d967680bc198ff 100644 --- a/gio/tests/gengiotypefuncs.py +++ b/gio/tests/gengiotypefuncs.py @@ -5,7 +5,7 @@ import sys import re import os -debug = os.getenv('GIO_GENTYPEFUNCS_DEBUG') is not None +debug = os.getenv("GIO_GENTYPEFUNCS_DEBUG") is not None out_file = sys.argv[1] in_files = sys.argv[2:] @@ -13,32 +13,37 @@ in_files = sys.argv[2:] funcs = [] -if debug: print ('Output file: ', out_file) +if debug: + print("Output file: ", out_file) -if debug: print (len(in_files), 'input files') +if debug: + print(len(in_files), "input files") for filename in in_files: - if debug: print ('Input file: ', filename) - with open(filename, 'rb') as f: - for line in f: - line = line.rstrip(b'\n').rstrip(b'\r') - # print line - match = re.search(b'\bg_[a-zA-Z0-9_]*_get_type\b', line) - if match: - func = match.group(0) - if not func in funcs: - funcs.append(func) - if debug: print ('Found ', func) - -file_output = 'G_GNUC_BEGIN_IGNORE_DEPRECATIONS\n' + if debug: + print("Input file: ", filename) + with open(filename, "rb") as f: + for line in f: + line = line.rstrip(b"\n").rstrip(b"\r") + # print line + match = re.search(b"\bg_[a-zA-Z0-9_]*_get_type\b", line) + if match: + func = match.group(0) + if func not in funcs: + funcs.append(func) + if debug: + print("Found ", func) + +file_output = "G_GNUC_BEGIN_IGNORE_DEPRECATIONS\n" funcs = sorted(funcs) for f in funcs: - if f not in ['g_io_extension_get_type', 'g_settings_backend_get_type']: - file_output += '*tp++ = {0} ();\n'.format(f) + if f not in ["g_io_extension_get_type", "g_settings_backend_get_type"]: + file_output += "*tp++ = {0} ();\n".format(f) -if debug: print (len(funcs), 'functions') +if debug: + print(len(funcs), "functions") ofile = open(out_file, "w") ofile.write(file_output) diff --git a/gio/tests/glistmodel.c b/gio/tests/glistmodel.c index 562037f62c879eefdf89b3ef95790ddf6d4d6c91..5ecf45f79db22339f66d251c57f99b0c858dbb4b 100644 --- a/gio/tests/glistmodel.c +++ b/gio/tests/glistmodel.c @@ -805,6 +805,72 @@ test_store_past_end (void) g_object_unref (store); } +static gboolean +list_model_casecmp_action_by_name (gconstpointer a, + gconstpointer b) +{ + return g_ascii_strcasecmp (g_action_get_name (G_ACTION (a)), + g_action_get_name (G_ACTION (b))) == 0; +} + +/* Test if find() and find_with_equal_func() works */ +static void +test_store_find (void) +{ + GListStore *store; + guint position = 100; + const gchar *item_strs[4] = { "aaa", "bbb", "xxx", "ccc" }; + GSimpleAction *items[4] = { NULL, }; + GSimpleAction *other_item; + guint i; + + store = g_list_store_new (G_TYPE_SIMPLE_ACTION); + + for (i = 0; i < G_N_ELEMENTS (item_strs); i++) + items[i] = g_simple_action_new (item_strs[i], NULL); + + /* Shouldn't crash on an empty list, or change the position pointer */ + g_assert_false (g_list_store_find (store, items[0], NULL)); + g_assert_false (g_list_store_find (store, items[0], &position)); + g_assert_cmpint (position, ==, 100); + + for (i = 0; i < G_N_ELEMENTS (item_strs); i++) + g_list_store_append (store, items[i]); + + /* Check whether it could still find the the elements */ + for (i = 0; i < G_N_ELEMENTS (item_strs); i++) + { + g_assert_true (g_list_store_find (store, items[i], &position)); + g_assert_cmpint (position, ==, i); + /* Shouldn't try to write to position pointer if NULL given */ + g_assert_true (g_list_store_find (store, items[i], NULL)); + } + + /* try to find element not part of the list */ + other_item = g_simple_action_new ("111", NULL); + g_assert_false (g_list_store_find (store, other_item, NULL)); + g_clear_object (&other_item); + + /* Re-add item; find() should only return the first position */ + g_list_store_append (store, items[0]); + g_assert_true (g_list_store_find (store, items[0], &position)); + g_assert_cmpint (position, ==, 0); + + /* try to find element which should only work with custom equality check */ + other_item = g_simple_action_new ("XXX", NULL); + g_assert_false (g_list_store_find (store, other_item, NULL)); + g_assert_true (g_list_store_find_with_equal_func (store, + other_item, + list_model_casecmp_action_by_name, + &position)); + g_assert_cmpint (position, ==, 2); + g_clear_object (&other_item); + + for (i = 0; i < G_N_ELEMENTS (item_strs); i++) + g_clear_object(&items[i]); + g_clear_object (&store); +} + int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); @@ -837,6 +903,7 @@ int main (int argc, char *argv[]) g_test_add_func ("/glistmodel/store/items-changed", test_store_signal_items_changed); g_test_add_func ("/glistmodel/store/past-end", test_store_past_end); + g_test_add_func ("/glistmodel/store/find", test_store_find); return g_test_run (); } diff --git a/gio/tests/gmenumodel.c b/gio/tests/gmenumodel.c index fc0fcea4828eebfb6120da89d08f932cc0c56c25..492daf8c472d3be4de585ecc6e07e98146d854c3 100644 --- a/gio/tests/gmenumodel.c +++ b/gio/tests/gmenumodel.c @@ -5,6 +5,8 @@ #include "gdbus-sessionbus.h" +#include "glib/glib-private.h" + static gboolean time_out (gpointer unused G_GNUC_UNUSED) { @@ -1012,11 +1014,17 @@ test_dbus_roundtrip (void) static void test_dbus_peer_roundtrip (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks a GCancellableSource, see glib#2313"); + (void) peer_connection_up; + (void) peer_connection_down; +#else PeerConnection peer; peer_connection_up (&peer); do_roundtrip (peer.server_connection, peer.client_connection); peer_connection_down (&peer); +#endif } static gint items_changed_count; @@ -1145,11 +1153,17 @@ test_dbus_subscriptions (void) static void test_dbus_peer_subscriptions (void) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks a GCancellableSource, see glib#2313"); + (void) peer_connection_up; + (void) peer_connection_down; +#else PeerConnection peer; peer_connection_up (&peer); do_subscriptions (peer.server_connection, peer.client_connection); peer_connection_down (&peer); +#endif } static gpointer diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c index baadca8f536e9b77fc49a27fb8c2019f7d7af66f..9e570a1b22aee630b96ea6bf3674fb972f14e2de 100644 --- a/gio/tests/gsettings.c +++ b/gio/tests/gsettings.c @@ -39,7 +39,7 @@ static void teardown (Fixture *fixture, gconstpointer user_data) { - g_assert_cmpint (g_rmdir (fixture->tmp_dir), ==, 0); + g_assert_no_errno (g_rmdir (fixture->tmp_dir)); g_clear_pointer (&fixture->tmp_dir, g_free); } @@ -1060,7 +1060,7 @@ test_object_set_property (GObject *object, static GType test_enum_get_type (void) { - static volatile gsize define_type_id = 0; + static gsize define_type_id = 0; if (g_once_init_enter (&define_type_id)) { @@ -1082,7 +1082,7 @@ test_enum_get_type (void) static GType test_flags_get_type (void) { - static volatile gsize define_type_id = 0; + static gsize define_type_id = 0; if (g_once_init_enter (&define_type_id)) { @@ -1740,6 +1740,14 @@ key_changed_cb (GSettings *settings, const gchar *key, gpointer data) (*b) = TRUE; } +typedef struct +{ + const gchar *path; + const gchar *root_group; + const gchar *keyfile_group; + const gchar *root_path; +} KeyfileTestData; + /* * Test that using a keyfile works */ @@ -1834,7 +1842,11 @@ test_keyfile (Fixture *fixture, g_free (str); g_settings_set (settings, "farewell", "s", "cheerio"); - + + /* Check that empty keys/groups are not allowed. */ + g_assert_false (g_settings_is_writable (settings, "")); + g_assert_false (g_settings_is_writable (settings, "/")); + /* When executing as root, changing the mode of the keyfile will have * no effect on the writability of the settings. */ @@ -1844,7 +1856,7 @@ test_keyfile (Fixture *fixture, g_signal_connect (settings, "writable-changed::greeting", G_CALLBACK (key_changed_cb), &called); - g_chmod (keyfile_path, 0500); + g_assert_no_errno (g_chmod (keyfile_path, 0500)); while (!called) g_main_context_iteration (NULL, FALSE); g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called); @@ -1859,9 +1871,152 @@ test_keyfile (Fixture *fixture, g_object_unref (settings); /* Clean up the temporary directory. */ - g_chmod (keyfile_path, 0777); - g_assert_cmpint (g_remove (store_path), ==, 0); - g_rmdir (keyfile_path); + g_assert_no_errno (g_chmod (keyfile_path, 0777)); + g_assert_no_errno (g_remove (store_path)); + g_assert_no_errno (g_rmdir (keyfile_path)); + g_free (store_path); + g_free (keyfile_path); +} + +/* + * Test that using a keyfile works with a schema with no path set. + */ +static void +test_keyfile_no_path (Fixture *fixture, + gconstpointer user_data) +{ + const KeyfileTestData *test_data = user_data; + GSettingsBackend *kf_backend; + GSettings *settings; + GKeyFile *keyfile; + gboolean writable; + gchar *key = NULL; + GError *error = NULL; + gchar *keyfile_path = NULL, *store_path = NULL; + + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); + kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group); + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path); + g_object_unref (kf_backend); + + g_settings_reset (settings, "test-boolean"); + g_assert_true (g_settings_get_boolean (settings, "test-boolean")); + + writable = g_settings_is_writable (settings, "test-boolean"); + g_assert_true (writable); + g_settings_set (settings, "test-boolean", "b", FALSE); + + g_assert_false (g_settings_get_boolean (settings, "test-boolean")); + + g_settings_delay (settings); + g_settings_set (settings, "test-boolean", "b", TRUE); + g_settings_apply (settings); + + keyfile = g_key_file_new (); + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); + + g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL)); + + g_key_file_free (keyfile); + + g_settings_reset (settings, "test-boolean"); + g_settings_apply (settings); + keyfile = g_key_file_new (); + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); + + g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error)); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); + g_clear_error (&error); + + /* Check that empty keys/groups are not allowed. */ + g_assert_false (g_settings_is_writable (settings, "")); + g_assert_false (g_settings_is_writable (settings, "/")); + + /* Keys which ghost the root group name are not allowed. This can only be + * tested when the path is `/` as otherwise it acts as a prefix and prevents + * any ghosting. */ + if (g_str_equal (test_data->path, "/")) + { + key = g_strdup_printf ("%s/%s", test_data->root_group, ""); + g_assert_false (g_settings_is_writable (settings, key)); + g_free (key); + + key = g_strdup_printf ("%s/%s", test_data->root_group, "/"); + g_assert_false (g_settings_is_writable (settings, key)); + g_free (key); + + key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean"); + g_assert_false (g_settings_is_writable (settings, key)); + g_free (key); + } + + g_key_file_free (keyfile); + g_object_unref (settings); + + /* Clean up the temporary directory. */ + g_assert_no_errno (g_chmod (keyfile_path, 0777)); + g_assert_no_errno (g_remove (store_path)); + g_assert_no_errno (g_rmdir (keyfile_path)); + g_free (store_path); + g_free (keyfile_path); +} + +/* + * Test that a keyfile rejects writes to keys outside its root path. + */ +static void +test_keyfile_outside_root_path (Fixture *fixture, + gconstpointer user_data) +{ + GSettingsBackend *kf_backend; + GSettings *settings; + gchar *keyfile_path = NULL, *store_path = NULL; + + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); + kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root"); + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/"); + g_object_unref (kf_backend); + + g_assert_false (g_settings_is_writable (settings, "test-boolean")); + + g_object_unref (settings); + + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so + * don’t error on failure. */ + g_remove (store_path); + g_assert_no_errno (g_rmdir (keyfile_path)); + g_free (store_path); + g_free (keyfile_path); +} + +/* + * Test that a keyfile rejects writes to keys in the root if no root group is set. + */ +static void +test_keyfile_no_root_group (Fixture *fixture, + gconstpointer user_data) +{ + GSettingsBackend *kf_backend; + GSettings *settings; + gchar *keyfile_path = NULL, *store_path = NULL; + + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); + kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL); + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/"); + g_object_unref (kf_backend); + + g_assert_false (g_settings_is_writable (settings, "test-boolean")); + g_assert_true (g_settings_is_writable (settings, "child/test-boolean")); + + g_object_unref (settings); + + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so + * don’t error on failure. */ + g_remove (store_path); + g_assert_no_errno (g_rmdir (keyfile_path)); g_free (store_path); g_free (keyfile_path); } @@ -2844,6 +2999,14 @@ main (int argc, char *argv[]) gchar *override_text; gchar *enums; gint result; + const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" }; + const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" }; + const KeyfileTestData keyfile_test_data_long_path = { + "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/", + "root", + "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch", + "/" + }; /* Meson build sets this */ #ifdef TEST_LOCALE_PATH @@ -2967,6 +3130,11 @@ main (int argc, char *argv[]) } g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown); + g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown); + g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown); + g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown); + g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown); + g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown); g_test_add_func ("/gsettings/child-schema", test_child_schema); g_test_add_func ("/gsettings/strinfo", test_strinfo); g_test_add_func ("/gsettings/enums", test_enums); @@ -3001,5 +3169,19 @@ main (int argc, char *argv[]) g_settings_sync (); + /* FIXME: Due to the way #GSettings objects can be used without specifying a + * backend, the default backend is leaked. In order to be able to run this + * test under valgrind and get meaningful checking for real leaks, use this + * hack to drop the final reference to the default #GSettingsBackend. + * + * This should not be used in production code. */ + { + GSettingsBackend *backend; + + backend = g_settings_backend_get_default (); + g_object_unref (backend); /* reference from the *_get_default() call */ + g_assert_finalize_object (backend); /* singleton reference owned by GLib */ + } + return result; } diff --git a/gio/tests/gsocketclient-slow.c b/gio/tests/gsocketclient-slow.c index 4143bc3d8a10eda18ad0b55e13c68f4a13e4d258..803ed908257a49a56fcddb93d515712c3cdabc08 100644 --- a/gio/tests/gsocketclient-slow.c +++ b/gio/tests/gsocketclient-slow.c @@ -79,23 +79,26 @@ on_connected_cancelled (GObject *source_object, g_main_loop_quit (user_data); } -static int -on_timer (GCancellable *cancel) +typedef struct { - g_cancellable_cancel (cancel); - return G_SOURCE_REMOVE; -} + GCancellable *cancellable; + gboolean completed; +} EventCallbackData; static void on_event (GSocketClient *client, GSocketClientEvent event, GSocketConnectable *connectable, GIOStream *connection, - gboolean *got_completed_event) + EventCallbackData *data) { - if (event == G_SOCKET_CLIENT_COMPLETE) + if (data->cancellable && event == G_SOCKET_CLIENT_CONNECTED) { - *got_completed_event = TRUE; + g_cancellable_cancel (data->cancellable); + } + else if (event == G_SOCKET_CLIENT_COMPLETE) + { + data->completed = TRUE; g_assert_null (connection); } } @@ -108,8 +111,7 @@ test_happy_eyeballs_cancel_delayed (void) GError *error = NULL; guint16 port; GMainLoop *loop; - GCancellable *cancel; - gboolean got_completed_event = FALSE; + EventCallbackData data = { NULL, FALSE }; /* This just tests that cancellation works as expected, still emits the completed signal, * and never returns a connection */ @@ -122,17 +124,16 @@ test_happy_eyeballs_cancel_delayed (void) g_socket_service_start (service); client = g_socket_client_new (); - cancel = g_cancellable_new (); - g_socket_client_connect_to_host_async (client, "localhost", port, cancel, on_connected_cancelled, loop); - g_timeout_add (1, (GSourceFunc) on_timer, cancel); - g_signal_connect (client, "event", G_CALLBACK (on_event), &got_completed_event); + data.cancellable = g_cancellable_new (); + g_socket_client_connect_to_host_async (client, "localhost", port, data.cancellable, on_connected_cancelled, loop); + g_signal_connect (client, "event", G_CALLBACK (on_event), &data); g_main_loop_run (loop); - g_assert_true (got_completed_event); + g_assert_true (data.completed); g_main_loop_unref (loop); g_object_unref (service); g_object_unref (client); - g_object_unref (cancel); + g_object_unref (data.cancellable); } static void @@ -144,7 +145,7 @@ test_happy_eyeballs_cancel_instant (void) guint16 port; GMainLoop *loop; GCancellable *cancel; - gboolean got_completed_event = FALSE; + EventCallbackData data = { NULL, FALSE }; /* This tests the same things as above, test_happy_eyeballs_cancel_delayed(), but * with different timing since it sends an already cancelled cancellable */ @@ -160,10 +161,10 @@ test_happy_eyeballs_cancel_instant (void) cancel = g_cancellable_new (); g_cancellable_cancel (cancel); g_socket_client_connect_to_host_async (client, "localhost", port, cancel, on_connected_cancelled, loop); - g_signal_connect (client, "event", G_CALLBACK (on_event), &got_completed_event); + g_signal_connect (client, "event", G_CALLBACK (on_event), &data); g_main_loop_run (loop); - g_assert_true (got_completed_event); + g_assert_true (data.completed); g_main_loop_unref (loop); g_object_unref (service); g_object_unref (client); @@ -181,4 +182,4 @@ main (int argc, char *argv[]) return g_test_run (); -} \ No newline at end of file +} diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c index 400fa00a199fd4eac469cb6e4e0cc3eab299c73b..7e22678ec3be59f16814a07faf00e793cfd990a5 100644 --- a/gio/tests/gsubprocess.c +++ b/gio/tests/gsubprocess.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #endif /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n" @@ -1046,7 +1048,7 @@ test_communicate_utf8_async (gconstpointer test_data) g_object_unref (proc); } -/* Test g_subprocess_communicate_utf8_async() can be cancelled correclty. */ +/* Test g_subprocess_communicate_utf8_async() can be cancelled correctly. */ static void test_communicate_utf8_cancelled_async (gconstpointer test_data) { @@ -1483,6 +1485,56 @@ test_cwd (void) g_object_unref (launcher); } #ifdef G_OS_UNIX + +static void +test_subprocess_launcher_close (void) +{ + GError *local_error = NULL; + GError **error = &local_error; + GSubprocessLauncher *launcher; + GSubprocess *proc; + GPtrArray *args; + int fd, fd2; + gboolean is_open; + + /* Open two arbitrary FDs. One of them, @fd, will be transferred to the + * launcher, and the other’s FD integer will be used as its target FD, giving + * the mapping `fd → fd2` if a child process were to be spawned. + * + * The launcher will then be closed, which should close @fd but *not* @fd2, + * as the value of @fd2 is only valid as an FD in a child process. (A child + * process is not actually spawned in this test.) + */ + fd = dup (0); + fd2 = dup (0); + launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); + g_subprocess_launcher_take_fd (launcher, fd, fd2); + + is_open = fcntl (fd, F_GETFD) != -1; + g_assert_true (is_open); + is_open = fcntl (fd2, F_GETFD) != -1; + g_assert_true (is_open); + + g_subprocess_launcher_close (launcher); + + is_open = fcntl (fd, F_GETFD) != -1; + g_assert_false (is_open); + is_open = fcntl (fd2, F_GETFD) != -1; + g_assert_true (is_open); + + /* Now test that actually trying to spawn the child gives %G_IO_ERROR_CLOSED, + * as g_subprocess_launcher_close() has been called. */ + args = get_test_subprocess_args ("cat", NULL); + proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error); + g_ptr_array_free (args, TRUE); + g_assert_null (proc); + g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_CLOSED); + g_clear_error (error); + + close (fd2); + g_object_unref (launcher); +} + static void test_stdout_file (void) { @@ -1721,7 +1773,7 @@ test_launcher_environment (void) /* unset a variable */ g_subprocess_launcher_unsetenv (launcher, "A"); - /* and set a diffferent one */ + /* and set a different one */ g_subprocess_launcher_setenv (launcher, "E", "F", TRUE); args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL); @@ -1835,6 +1887,7 @@ main (int argc, char **argv) g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit); g_test_add_func ("/gsubprocess/cwd", test_cwd); #ifdef G_OS_UNIX + g_test_add_func ("/gsubprocess/launcher-close", test_subprocess_launcher_close); g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file); g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd); g_test_add_func ("/gsubprocess/child-setup", test_child_setup); diff --git a/gio/tests/gtesttlsbackend.c b/gio/tests/gtesttlsbackend.c index 157a4a3f34b6af2e1f9db0563287d506a7b5aad9..56d155031097d9c959cb3390472fb382eb450933 100644 --- a/gio/tests/gtesttlsbackend.c +++ b/gio/tests/gtesttlsbackend.c @@ -59,6 +59,8 @@ g_test_tls_backend_iface_init (GTlsBackendInterface *iface) iface->get_certificate_type = _g_test_tls_certificate_get_type; iface->get_client_connection_type = _g_test_tls_connection_get_type; iface->get_server_connection_type = _g_test_tls_connection_get_type; + iface->get_dtls_client_connection_type = _g_test_tls_connection_get_type; + iface->get_dtls_server_connection_type = _g_test_tls_connection_get_type; iface->get_default_database = _g_test_tls_backend_get_default_database; iface->get_file_database_type = _g_test_tls_database_get_type; } @@ -91,6 +93,8 @@ struct _GTestTlsCertificate { gchar *key_pem; gchar *cert_pem; GTlsCertificate *issuer; + gchar *pkcs11_uri; + gchar *private_key_pkcs11_uri; }; struct _GTestTlsCertificateClass { @@ -103,7 +107,9 @@ enum PROP_CERT_CERTIFICATE_PEM, PROP_CERT_PRIVATE_KEY, PROP_CERT_PRIVATE_KEY_PEM, - PROP_CERT_ISSUER + PROP_CERT_ISSUER, + PROP_CERT_PKCS11_URI, + PROP_CERT_PRIVATE_KEY_PKCS11_URI, }; static void g_test_tls_certificate_initable_iface_init (GInitableIface *iface); @@ -141,6 +147,15 @@ g_test_tls_certificate_get_property (GObject *object, case PROP_CERT_ISSUER: g_value_set_object (value, cert->issuer); break; + case PROP_CERT_PKCS11_URI: + /* This test value simulates a backend that ignores the value + because it is unsupported */ + if (g_strcmp0 (cert->pkcs11_uri, "unsupported") != 0) + g_value_set_string (value, cert->pkcs11_uri); + break; + case PROP_CERT_PRIVATE_KEY_PKCS11_URI: + g_value_set_string (value, cert->private_key_pkcs11_uri); + break; default: g_assert_not_reached (); break; @@ -166,6 +181,12 @@ g_test_tls_certificate_set_property (GObject *object, case PROP_CERT_ISSUER: cert->issuer = g_value_dup_object (value); break; + case PROP_CERT_PKCS11_URI: + cert->pkcs11_uri = g_value_dup_string (value); + break; + case PROP_CERT_PRIVATE_KEY_PKCS11_URI: + cert->private_key_pkcs11_uri = g_value_dup_string (value); + break; case PROP_CERT_CERTIFICATE: case PROP_CERT_PRIVATE_KEY: /* ignore */ @@ -183,6 +204,8 @@ g_test_tls_certificate_finalize (GObject *object) g_free (cert->cert_pem); g_free (cert->key_pem); + g_free (cert->pkcs11_uri); + g_free (cert->private_key_pkcs11_uri); g_clear_object (&cert->issuer); G_OBJECT_CLASS (g_test_tls_certificate_parent_class)->finalize (object); @@ -205,6 +228,8 @@ g_test_tls_certificate_class_init (GTestTlsCertificateClass *test_class) g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY, "private-key"); g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PEM, "private-key-pem"); g_object_class_override_property (gobject_class, PROP_CERT_ISSUER, "issuer"); + g_object_class_override_property (gobject_class, PROP_CERT_PKCS11_URI, "pkcs11-uri"); + g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PKCS11_URI, "private-key-pkcs11-uri"); } static void @@ -245,6 +270,7 @@ struct _GTestTlsConnectionClass { enum { PROP_CONN_BASE_IO_STREAM = 1, + PROP_CONN_BASE_SOCKET, PROP_CONN_USE_SYSTEM_CERTDB, PROP_CONN_REQUIRE_CLOSE_NOTIFY, PROP_CONN_REHANDSHAKE_MODE, @@ -264,6 +290,8 @@ static void g_test_tls_connection_initable_iface_init (GInitableIface *iface); G_DEFINE_TYPE_WITH_CODE (GTestTlsConnection, g_test_tls_connection, G_TYPE_TLS_CONNECTION, G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION, NULL) G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION, NULL) + G_IMPLEMENT_INTERFACE (G_TYPE_DATAGRAM_BASED, NULL) + G_IMPLEMENT_INTERFACE (G_TYPE_DTLS_CONNECTION, NULL) G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, g_test_tls_connection_initable_iface_init)) @@ -308,6 +336,7 @@ g_test_tls_connection_class_init (GTestTlsConnectionClass *connection_class) io_stream_class->close_fn = g_test_tls_connection_close; g_object_class_override_property (gobject_class, PROP_CONN_BASE_IO_STREAM, "base-io-stream"); + g_object_class_override_property (gobject_class, PROP_CONN_BASE_SOCKET, "base-socket"); g_object_class_override_property (gobject_class, PROP_CONN_USE_SYSTEM_CERTDB, "use-system-certdb"); g_object_class_override_property (gobject_class, PROP_CONN_REQUIRE_CLOSE_NOTIFY, "require-close-notify"); g_object_class_override_property (gobject_class, PROP_CONN_REHANDSHAKE_MODE, "rehandshake-mode"); diff --git a/gio/tests/gtlsconsoleinteraction.c b/gio/tests/gtlsconsoleinteraction.c index ae734ba60fa9d04bf2bc3130838cf89bdc230663..4a12ea86079daf62565686e4af67e528303b3023 100644 --- a/gio/tests/gtlsconsoleinteraction.c +++ b/gio/tests/gtlsconsoleinteraction.c @@ -32,7 +32,7 @@ /* * WARNING: This is not the example you're looking for [slow hand wave]. This - * is not industrial strength, it's just for testing. It uses embarassing + * is not industrial strength, it's just for testing. It uses embarrassing * functions like getpass() and does lazy things with threads. */ diff --git a/gio/tests/live-g-file.c b/gio/tests/live-g-file.c index 0156c8aac5ca1de514c3dad2fe3b098ca595227d..316e23c9e76b6ab4b98a1c1a5ea7128deabc97f5 100644 --- a/gio/tests/live-g-file.c +++ b/gio/tests/live-g-file.c @@ -149,13 +149,13 @@ check_cap_dac_override (const char *tmpdir) dac_denies_write = g_build_filename (tmpdir, "dac-denies-write", NULL); inside = g_build_filename (dac_denies_write, "inside", NULL); - g_assert_cmpint (mkdir (dac_denies_write, S_IRWXU) == 0 ? 0 : errno, ==, 0); - g_assert_cmpint (chmod (dac_denies_write, 0) == 0 ? 0 : errno, ==, 0); + g_assert_no_errno (mkdir (dac_denies_write, S_IRWXU)); + g_assert_no_errno (chmod (dac_denies_write, 0)); if (mkdir (inside, S_IRWXU) == 0) { g_test_message ("Looks like we have CAP_DAC_OVERRIDE or equivalent"); - g_assert_cmpint (rmdir (inside) == 0 ? 0 : errno, ==, 0); + g_assert_no_errno (rmdir (inside)); have_cap = TRUE; } else @@ -167,8 +167,8 @@ check_cap_dac_override (const char *tmpdir) have_cap = FALSE; } - g_assert_cmpint (chmod (dac_denies_write, S_IRWXU) == 0 ? 0 : errno, ==, 0); - g_assert_cmpint (rmdir (dac_denies_write) == 0 ? 0 : errno, ==, 0); + g_assert_no_errno (chmod (dac_denies_write, S_IRWXU)); + g_assert_no_errno (rmdir (dac_denies_write)); g_free (dac_denies_write); g_free (inside); return have_cap; @@ -198,12 +198,12 @@ create_empty_file (GFile * parent, const char *filename, GFileOutputStream *outs; child = g_file_get_child (parent, filename); - g_assert (child != NULL); + g_assert_nonnull (child); error = NULL; outs = g_file_replace (child, NULL, FALSE, create_flags, NULL, &error); g_assert_no_error (error); - g_assert (outs != NULL); + g_assert_nonnull (outs); error = NULL; g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error); g_object_unref (outs); @@ -218,10 +218,10 @@ create_empty_dir (GFile * parent, const char *filename) GError *error; child = g_file_get_child (parent, filename); - g_assert (child != NULL); + g_assert_nonnull (child); error = NULL; res = g_file_make_directory (child, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); return child; } @@ -234,10 +234,10 @@ create_symlink (GFile * parent, const char *filename, const char *points_to) GError *error; child = g_file_get_child (parent, filename); - g_assert (child != NULL); + g_assert_nonnull (child); error = NULL; res = g_file_make_symbolic_link (child, points_to, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); return child; } @@ -248,22 +248,22 @@ test_create_structure (gconstpointer test_data) GFile *root; GFile *child; gboolean res; - GError *error; + GError *error = NULL; GFileOutputStream *outs; GDataOutputStream *outds; guint i; struct StructureItem item; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n Going to create testing structure in '%s'...\n", (char *) test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); /* create root directory */ - res = g_file_make_directory (root, NULL, NULL); - /* don't care about errors here */ + g_file_make_directory (root, NULL, &error); + g_assert_no_error (error); /* create any other items */ for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) @@ -297,17 +297,16 @@ test_create_structure (gconstpointer test_data) default: break; } - g_assert (child != NULL); + g_assert_nonnull (child); if ((item.mode > 0) && (posix_compat)) { - error = NULL; res = g_file_set_attribute_uint32 (child, G_FILE_ATTRIBUTE_UNIX_MODE, item.mode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); } @@ -335,24 +334,22 @@ test_create_structure (gconstpointer test_data) /* create a pattern file */ log (" Creating pattern file..."); child = g_file_get_child (root, "pattern_file"); - g_assert (child != NULL); + g_assert_nonnull (child); - error = NULL; outs = g_file_replace (child, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error); g_assert_no_error (error); - g_assert (outs != NULL); + g_assert_nonnull (outs); outds = g_data_output_stream_new (G_OUTPUT_STREAM (outs)); - g_assert (outds != NULL); + g_assert_nonnull (outds); for (i = 0; i < PATTERN_FILE_SIZE; i++) { - error = NULL; - res = g_data_output_stream_put_byte (outds, i % 256, NULL, &error); + g_data_output_stream_put_byte (outds, i % 256, NULL, &error); g_assert_no_error (error); } - error = NULL; - res = g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error); + + g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error); g_assert_no_error (error); g_object_unref (outds); g_object_unref (outs); @@ -372,7 +369,7 @@ file_exists (GFile * parent, const char *filename, gboolean * result) *result = FALSE; child = g_file_get_child (parent, filename); - g_assert (child != NULL); + g_assert_nonnull (child); res = g_file_query_exists (child, NULL); if (result) *result = res; @@ -394,7 +391,7 @@ test_attributes (struct StructureItem item, GFileInfo * info) /* standard::type */ has_attr = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE); - g_assert_cmpint (has_attr, ==, TRUE); + g_assert_true (has_attr); ftype = g_file_info_get_file_type (info); g_assert_cmpint (ftype, !=, G_FILE_TYPE_UNKNOWN); g_assert_cmpint (ftype, ==, item.file_type); @@ -414,7 +411,7 @@ test_attributes (struct StructureItem item, GFileInfo * info) can_read = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ); - g_assert_cmpint (can_read, ==, TRUE); + g_assert_true (can_read); } /* access::can-write */ @@ -423,25 +420,25 @@ test_attributes (struct StructureItem item, GFileInfo * info) can_write = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); - g_assert_cmpint (can_write, ==, TRUE); + g_assert_true (can_write); } /* standard::name */ name = g_file_info_get_name (info); - g_assert (name != NULL); + g_assert_nonnull (name); /* standard::display-name */ display_name = g_file_info_get_display_name (info); - g_assert (display_name != NULL); + g_assert_nonnull (display_name); utf8_valid = g_utf8_validate (display_name, -1, NULL); - g_assert_cmpint (utf8_valid, ==, TRUE); + g_assert_true (utf8_valid); /* standard::edit-name */ edit_name = g_file_info_get_edit_name (info); if (edit_name) { utf8_valid = g_utf8_validate (edit_name, -1, NULL); - g_assert_cmpint (utf8_valid, ==, TRUE); + g_assert_true (utf8_valid); } /* standard::copy-name */ @@ -451,7 +448,7 @@ test_attributes (struct StructureItem item, GFileInfo * info) if (copy_name) { utf8_valid = g_utf8_validate (copy_name, -1, NULL); - g_assert_cmpint (utf8_valid, ==, TRUE); + g_assert_true (utf8_valid); } /* standard::is-symlink */ @@ -475,7 +472,7 @@ test_attributes (struct StructureItem item, GFileInfo * info) is_hidden = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN); - g_assert_cmpint (is_hidden, ==, TRUE); + g_assert_true (is_hidden); } /* unix::is-mountpoint */ @@ -503,14 +500,13 @@ test_initial_structure (gconstpointer test_data) gssize read, total_read; struct StructureItem item; - - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n Testing sample structure in '%s'...\n", (char *) test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); /* test the structure */ for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) @@ -523,15 +519,15 @@ test_initial_structure (gconstpointer test_data) log (" Testing file '%s'...\n", item.filename); child = file_exists (root, item.filename, &res); - g_assert (child != NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_nonnull (child); + g_assert_true (res); error = NULL; info = g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); g_assert_no_error (error); - g_assert (info != NULL); + g_assert_nonnull (info); test_attributes (item, info); @@ -542,22 +538,22 @@ test_initial_structure (gconstpointer test_data) /* read and test the pattern file */ log (" Testing pattern file...\n"); child = file_exists (root, "pattern_file", &res); - g_assert (child != NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_nonnull (child); + g_assert_true (res); error = NULL; info = g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); g_assert_no_error (error); - g_assert (info != NULL); + g_assert_nonnull (info); size = g_file_info_get_size (info); g_assert_cmpint (size, ==, PATTERN_FILE_SIZE); g_object_unref (info); error = NULL; ins = g_file_read (child, NULL, &error); - g_assert (ins != NULL); + g_assert_nonnull (ins); g_assert_no_error (error); buffer = g_malloc (PATTERN_FILE_SIZE); @@ -579,7 +575,7 @@ test_initial_structure (gconstpointer test_data) error = NULL; res = g_input_stream_close (G_INPUT_STREAM (ins), NULL, &error); g_assert_no_error (error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); for (i = 0; i < PATTERN_FILE_SIZE; i++) g_assert_cmpint (*(buffer + i), ==, i % 256); @@ -602,26 +598,26 @@ traverse_recurse_dirs (GFile * parent, GFile * root) guint i; gboolean found; - g_assert (root != NULL); + g_assert_nonnull (root); error = NULL; enumerator = g_file_enumerate_children (parent, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); - g_assert (enumerator != NULL); + g_assert_nonnull (enumerator); g_assert_no_error (error); - g_assert (g_file_enumerator_get_container (enumerator) == parent); + g_assert_true (g_file_enumerator_get_container (enumerator) == parent); error = NULL; info = g_file_enumerator_next_file (enumerator, NULL, &error); while ((info) && (!error)) { descend = g_file_enumerator_get_child (enumerator, info); - g_assert (descend != NULL); + g_assert_nonnull (descend); relative_path = g_file_get_relative_path (root, descend); - g_assert (relative_path != NULL); + g_assert_nonnull (relative_path); found = FALSE; for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) @@ -635,7 +631,7 @@ traverse_recurse_dirs (GFile * parent, GFile * root) break; } } - g_assert_cmpint (found, ==, TRUE); + g_assert_true (found); log (" Found file %s, relative to root: %s\n", g_file_info_get_display_name (info), relative_path); @@ -654,9 +650,9 @@ traverse_recurse_dirs (GFile * parent, GFile * root) error = NULL; res = g_file_enumerator_close (enumerator, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); - g_assert (g_file_enumerator_is_closed (enumerator)); + g_assert_true (g_file_enumerator_is_closed (enumerator)); g_object_unref (enumerator); } @@ -667,14 +663,14 @@ test_traverse_structure (gconstpointer test_data) GFile *root; gboolean res; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n Traversing through the sample structure in '%s'...\n", (char *) test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); traverse_recurse_dirs (root, root); @@ -696,13 +692,13 @@ test_enumerate (gconstpointer test_data) struct StructureItem item; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n Test enumerate '%s'...\n", (char *) test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) @@ -719,7 +715,7 @@ test_enumerate (gconstpointer test_data) { log (" Testing file '%s'\n", item.filename); child = g_file_get_child (root, item.filename); - g_assert (child != NULL); + g_assert_nonnull (child); error = NULL; enumerator = g_file_enumerate_children (child, "*", @@ -728,21 +724,21 @@ test_enumerate (gconstpointer test_data) if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) { - g_assert (enumerator == NULL); + g_assert_null (enumerator); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); } if ((item.extra_flags & TEST_ENUMERATE_FILE) == TEST_ENUMERATE_FILE) { - g_assert (enumerator == NULL); + g_assert_null (enumerator); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY); } if ((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) { - g_assert (enumerator != NULL); + g_assert_nonnull (enumerator); error = NULL; info = g_file_enumerator_next_file (enumerator, NULL, &error); - g_assert (info == NULL); + g_assert_null (info); g_assert_no_error (error); /* no items should be found, no error should be logged */ } @@ -754,7 +750,7 @@ test_enumerate (gconstpointer test_data) { error = NULL; res = g_file_enumerator_close (enumerator, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); g_object_unref (enumerator); @@ -779,11 +775,11 @@ do_copy_move (GFile * root, struct StructureItem item, const char *target_dir, log (" do_copy_move: '%s' --> '%s'\n", item.filename, target_dir); dst_dir = g_file_get_child (root, target_dir); - g_assert (dst_dir != NULL); + g_assert_nonnull (dst_dir); src_file = g_file_get_child (root, item.filename); - g_assert (src_file != NULL); + g_assert_nonnull (src_file); dst_file = g_file_get_child (dst_dir, item.filename); - g_assert (dst_file != NULL); + g_assert_nonnull (dst_file); error = NULL; if ((item.extra_flags & TEST_COPY) == TEST_COPY) @@ -806,28 +802,28 @@ do_copy_move (GFile * root, struct StructureItem item, const char *target_dir, if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) && (extra_flags == TEST_ALREADY_EXISTS)) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); } /* target file is a file, overwrite is not set */ else if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) && (extra_flags == TEST_TARGET_IS_FILE)) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY); } /* source file is directory */ else if ((item.extra_flags & TEST_COPY_ERROR_RECURSE) == TEST_COPY_ERROR_RECURSE) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE); } /* source or target path doesn't exist */ else if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) || (extra_flags == TEST_NOT_EXISTS)) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); } /* source or target path permission denied */ @@ -847,14 +843,14 @@ do_copy_move (GFile * root, struct StructureItem item, const char *target_dir, else #endif { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED); } } /* no error should be found, all exceptions defined above */ else { - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); } @@ -877,11 +873,11 @@ test_copy_move (gconstpointer test_data) log ("\n"); - g_assert (test_data != NULL); + g_assert_nonnull (test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) @@ -967,13 +963,13 @@ test_create (gconstpointer test_data) struct StructureItem item; GFileOutputStream *os; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n"); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) { @@ -986,7 +982,7 @@ test_create (gconstpointer test_data) log (" test_create: '%s'\n", item.filename); child = g_file_get_child (root, item.filename); - g_assert (child != NULL); + g_assert_nonnull (child); error = NULL; os = NULL; @@ -1006,12 +1002,12 @@ test_create (gconstpointer test_data) if (((item.extra_flags & TEST_NOT_EXISTS) == 0) && ((item.extra_flags & TEST_CREATE) == TEST_CREATE)) { - g_assert (os == NULL); + g_assert_null (os); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); } else if (item.file_type == G_FILE_TYPE_DIRECTORY) { - g_assert (os == NULL); + g_assert_null (os); if ((item.extra_flags & TEST_CREATE) == TEST_CREATE) g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); else @@ -1019,7 +1015,7 @@ test_create (gconstpointer test_data) } else { - g_assert (os != NULL); + g_assert_nonnull (os); g_assert_no_error (error); } @@ -1034,7 +1030,7 @@ test_create (gconstpointer test_data) if (error) log (" g_output_stream_close: error %d = %s\n", error->code, error->message); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); g_object_unref (os); } @@ -1054,13 +1050,13 @@ test_open (gconstpointer test_data) struct StructureItem item; GFileInputStream *input_stream; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n"); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) { @@ -1074,7 +1070,7 @@ test_open (gconstpointer test_data) log (" test_open: '%s'\n", item.filename); child = g_file_get_child (root, item.filename); - g_assert (child != NULL); + g_assert_nonnull (child); error = NULL; input_stream = g_file_read (child, NULL, &error); @@ -1082,17 +1078,17 @@ test_open (gconstpointer test_data) ((item.extra_flags & TEST_INVALID_SYMLINK) == TEST_INVALID_SYMLINK)) { - g_assert (input_stream == NULL); + g_assert_null (input_stream); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); } else if (item.file_type == G_FILE_TYPE_DIRECTORY) { - g_assert (input_stream == NULL); + g_assert_null (input_stream); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY); } else { - g_assert (input_stream != NULL); + g_assert_nonnull (input_stream); g_assert_no_error (error); } @@ -1105,7 +1101,7 @@ test_open (gconstpointer test_data) res = g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); g_object_unref (input_stream); } @@ -1126,13 +1122,13 @@ test_delete (gconstpointer test_data) struct StructureItem item; gchar *path; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n"); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) { @@ -1145,7 +1141,7 @@ test_delete (gconstpointer test_data) ((item.extra_flags & TEST_DELETE_TRASH) == TEST_DELETE_TRASH)) { child = file_exists (root, item.filename, &res); - g_assert (child != NULL); + g_assert_nonnull (child); /* we don't care about result here */ path = g_file_get_path (child); @@ -1161,17 +1157,17 @@ test_delete (gconstpointer test_data) if ((item.extra_flags & TEST_DELETE_NON_EMPTY) == TEST_DELETE_NON_EMPTY) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY); } if ((item.extra_flags & TEST_DELETE_FAILURE) == TEST_DELETE_FAILURE) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); } if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) { - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); } @@ -1197,12 +1193,12 @@ test_make_directory_with_parents (gconstpointer test_data) gboolean have_cap_dac_override = check_cap_dac_override (test_data); #endif - g_assert (test_data != NULL); + g_assert_nonnull (test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); res = g_file_query_exists (root, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); child = g_file_get_child (root, "a"); grandchild = g_file_get_child (child, "b"); @@ -1212,27 +1208,27 @@ test_make_directory_with_parents (gconstpointer test_data) * depth 1, 2, or 3 */ res = g_file_make_directory_with_parents (child, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); res = g_file_query_exists (child, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_file_delete (child, NULL, NULL); res = g_file_make_directory_with_parents (grandchild, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); res = g_file_query_exists (grandchild, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_file_delete (grandchild, NULL, NULL); g_file_delete (child, NULL, NULL); res = g_file_make_directory_with_parents (greatgrandchild, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); res = g_file_query_exists (greatgrandchild, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_file_delete (greatgrandchild, NULL, NULL); g_file_delete (grandchild, NULL, NULL); @@ -1259,22 +1255,22 @@ test_make_directory_with_parents (gconstpointer test_data) #endif g_file_make_directory (child, NULL, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); res = g_file_set_attribute_uint32 (child, G_FILE_ATTRIBUTE_UNIX_MODE, S_IRUSR + S_IXUSR, /* -r-x------ */ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); res = g_file_make_directory_with_parents (grandchild, NULL, &error); - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED); g_clear_error (&error); res = g_file_make_directory_with_parents (greatgrandchild, NULL, &error); - g_assert_cmpint (res, ==, FALSE); + g_assert_false (res); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED); g_clear_error (&error); @@ -1296,7 +1292,7 @@ cleanup_dir_recurse (GFile *parent, GFile *root) GFile *descend; char *relative_path; - g_assert (root != NULL); + g_assert_nonnull (root); enumerator = g_file_enumerate_children (parent, "*", @@ -1310,9 +1306,9 @@ cleanup_dir_recurse (GFile *parent, GFile *root) while ((info) && (!error)) { descend = g_file_enumerator_get_child (enumerator, info); - g_assert (descend != NULL); + g_assert_nonnull (descend); relative_path = g_file_get_relative_path (root, descend); - g_assert (relative_path != NULL); + g_assert_nonnull (relative_path); g_free (relative_path); log (" deleting '%s'\n", g_file_info_get_display_name (info)); @@ -1322,7 +1318,7 @@ cleanup_dir_recurse (GFile *parent, GFile *root) error = NULL; res = g_file_delete (descend, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_object_unref (descend); error = NULL; @@ -1334,7 +1330,7 @@ cleanup_dir_recurse (GFile *parent, GFile *root) error = NULL; res = g_file_enumerator_close (enumerator, NULL, &error); - g_assert_cmpint (res, ==, TRUE); + g_assert_true (res); g_assert_no_error (error); g_object_unref (enumerator); @@ -1345,12 +1341,12 @@ prep_clean_structure (gconstpointer test_data) { GFile *root; - g_assert (test_data != NULL); + g_assert_nonnull (test_data); log ("\n Cleaning target testing structure in '%s'...\n", (char *) test_data); root = g_file_new_for_commandline_arg ((char *) test_data); - g_assert (root != NULL); + g_assert_nonnull (root); cleanup_dir_recurse (root, root); diff --git a/gio/tests/live-g-file.txt b/gio/tests/live-g-file.txt index 95da0e0adc5f36265f26f38c523c87681b8ea02a..1873a0531467dd889e5564f7745364118b8efd25 100644 --- a/gio/tests/live-g-file.txt +++ b/gio/tests/live-g-file.txt @@ -3,7 +3,7 @@ Before you start testing it would be good to explain how it works. The script works in three modes: 1. read-only (no special arguments) - suitable for read-only backends. Just create the sample structure using the second mode, pack it (tar -p is - preffered to preserve unix modes) and put it on a reachable place. + preferred to preserve unix modes) and put it on a reachable place. 2. create-structure - only creates reference structure for later testing in read-only mode 3. write mode - full test suite, creates testing structure and performs all diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in new file mode 100644 index 0000000000000000000000000000000000000000..cd16cf4e3fffe14c30f0274e3908fb5eb8bed21c --- /dev/null +++ b/gio/tests/memory-monitor-dbus.py.in @@ -0,0 +1,111 @@ +#!/usr/bin/python3 + +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text +# of the license. + +__author__ = 'Bastien Nocera' +__email__ = 'hadess@hadess.net' +__copyright__ = '(c) 2019 Red Hat Inc.' +__license__ = 'LGPL 3+' + +import unittest +import sys +import subprocess +import fcntl +import os +import time + +import taptestrunner + +try: + # Do all non-standard imports here so we can skip the tests if any + # needed packages are not available. + import dbus + import dbus.mainloop.glib + import dbusmock + from gi.repository import GLib + from gi.repository import Gio + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + # XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") + XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" + + class TestLowMemoryMonitor(dbusmock.DBusTestCase): + '''Test GMemoryMonitorDBus''' + + @classmethod + def setUpClass(klass): + klass.start_system_bus() + klass.dbus_con = klass.get_dbus(True) + + def setUp(self): + try: + Gio.MemoryMonitor + except AttributeError: + raise unittest.SkipTest('Low memory monitor not in ' + 'introspection data. Requires ' + 'GObject-Introspection ≥ 1.63.2') + try: + (self.p_mock, self.obj_lmm) = self.spawn_server_template( + 'low_memory_monitor', {}, stdout=subprocess.PIPE) + except ModuleNotFoundError: + raise unittest.SkipTest("Low memory monitor dbusmock template not " + "found. Requires dbusmock ≥ 0.18.4.") + # set log to nonblocking + flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) + fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) + self.last_warning = -1 + self.dbusmock = dbus.Interface(self.obj_lmm, dbusmock.MOCK_IFACE) + self.memory_monitor = Gio.MemoryMonitor.dup_default() + self.memory_monitor.connect("low-memory-warning", self.memory_warning_cb) + self.mainloop = GLib.MainLoop() + self.main_context = self.mainloop.get_context() + + def tearDown(self): + self.p_mock.terminate() + self.p_mock.wait() + + def memory_warning_cb(self, monitor, level): + self.last_warning = level + self.main_context.wakeup() + + def test_low_memory_warning_signal(self): + '''LowMemoryWarning signal''' + + # Wait 2 seconds + timeout = 2 + while timeout > 0: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + + self.dbusmock.EmitWarning(100) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 and self.last_warning != 100: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 100) + + self.dbusmock.EmitWarning(255) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 and self.last_warning != 255: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 255) + +except ImportError as e: + @unittest.skip("Cannot import %s" % e.name) + class TestLowMemoryMonitor(unittest.TestCase): + def test_low_memory_warning_signal(self): + pass + +if __name__ == '__main__': + unittest.main(testRunner=taptestrunner.TAPTestRunner()) diff --git a/gio/tests/memory-monitor-portal.py.in b/gio/tests/memory-monitor-portal.py.in new file mode 100644 index 0000000000000000000000000000000000000000..cb4a960eb320f2ba8d2636bf48c422f942602b09 --- /dev/null +++ b/gio/tests/memory-monitor-portal.py.in @@ -0,0 +1,127 @@ +#!/usr/bin/python3 + +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text +# of the license. + +__author__ = 'Bastien Nocera' +__email__ = 'hadess@hadess.net' +__copyright__ = '(c) 2019 Red Hat Inc.' +__license__ = 'LGPL 3+' + +import unittest +import sys +import subprocess +import fcntl +import os +import time + +import taptestrunner + +try: + # Do all non-standard imports here so we can skip the tests if any + # needed packages are not available. + import dbus + import dbus.mainloop.glib + import dbusmock + from gi.repository import GLib + from gi.repository import Gio + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + # XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") + XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" + + class TestLowMemoryMonitorPortal(dbusmock.DBusTestCase): + '''Test GMemoryMonitorPortal''' + + @classmethod + def setUpClass(klass): + klass.start_system_bus() + klass.dbus_con = klass.get_dbus(True) + # Start session bus so that xdg-desktop-portal can run on it + klass.start_session_bus() + + def setUp(self): + try: + Gio.MemoryMonitor + except AttributeError: + raise unittest.SkipTest('Low memory monitor not in ' + 'introspection data. Requires ' + 'GObject-Introspection ≥ 1.63.2') + try: + (self.p_mock, self.obj_lmm) = self.spawn_server_template( + 'low_memory_monitor', {}, stdout=subprocess.PIPE) + except ModuleNotFoundError: + raise unittest.SkipTest("Low memory monitor dbusmock template not " + "found. Requires dbusmock ≥ 0.18.4.") + # set log to nonblocking + flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) + fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) + self.last_warning = -1 + self.dbusmock = dbus.Interface(self.obj_lmm, dbusmock.MOCK_IFACE) + try: + self.xdp = subprocess.Popen([XDG_DESKTOP_PORTAL_PATH]) + except FileNotFoundError: + raise unittest.SkipTest("xdg-desktop-portal not available") + + try: + self.wait_for_bus_object('org.freedesktop.portal.Desktop', + '/org/freedesktop/portal/desktop') + except: + raise + # subprocess.Popen(['gdbus', 'monitor', '--session', '--dest', 'org.freedesktop.portal.Desktop']) + + os.environ['GTK_USE_PORTAL'] = "1" + self.memory_monitor = Gio.MemoryMonitor.dup_default() + assert("GMemoryMonitorPortal" in str(self.memory_monitor)) + self.memory_monitor.connect("low-memory-warning", self.portal_memory_warning_cb) + self.mainloop = GLib.MainLoop() + self.main_context = self.mainloop.get_context() + + def tearDown(self): + self.p_mock.terminate() + self.p_mock.wait() + + def portal_memory_warning_cb(self, monitor, level): + self.last_warning = level + self.main_context.wakeup() + + def test_low_memory_warning_portal_signal(self): + '''LowMemoryWarning signal''' + + # Wait 2 seconds + timeout = 2 + while timeout > 0: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + + self.dbusmock.EmitWarning(100) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 and self.last_warning != 100: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 100) + + self.dbusmock.EmitWarning(255) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 and self.last_warning != 255: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 255) + +except ImportError as e: + @unittest.skip("Cannot import %s" % e.name) + class TestLowMemoryMonitorPortal(unittest.TestCase): + def test_low_memory_warning_portal_signal(self): + pass + +if __name__ == '__main__': + unittest.main(testRunner=taptestrunner.TAPTestRunner()) diff --git a/gio/tests/memory-monitor.c b/gio/tests/memory-monitor.c new file mode 100644 index 0000000000000000000000000000000000000000..06eabefa24782d47be64e4126bd7ee9eb62db9e9 --- /dev/null +++ b/gio/tests/memory-monitor.c @@ -0,0 +1,88 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include + +static const char * +get_level_string (GMemoryMonitorWarningLevel level) +{ + GEnumClass *eclass; + GEnumValue *value; + + eclass = G_ENUM_CLASS (g_type_class_peek (G_TYPE_MEMORY_MONITOR_WARNING_LEVEL)); + value = g_enum_get_value (eclass, level); + + if (value == NULL) + return "unknown"; + + return value->value_nick; +} + +static void +test_dup_default (void) +{ + GMemoryMonitor *monitor; + + monitor = g_memory_monitor_dup_default (); + g_assert_nonnull (monitor); + g_object_unref (monitor); +} + +static void +warning_cb (GMemoryMonitor *m, + GMemoryMonitorWarningLevel level) +{ + const char *str; + + str = get_level_string (level); + g_debug ("Warning level: %s (%d)", str , level); +} + +static void +do_watch_memory (void) +{ + GMemoryMonitor *m; + GMainLoop *loop; + + m = g_memory_monitor_dup_default (); + g_signal_connect (G_OBJECT (m), "low-memory-warning", + G_CALLBACK (warning_cb), NULL); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); +} + +int +main (int argc, char **argv) +{ + int ret; + + if (argc == 2 && !strcmp (argv[1], "--watch")) + { + do_watch_memory (); + return 0; + } + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/memory-monitor/default", test_dup_default); + + ret = g_test_run (); + + return ret; +} diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 382dfccadbb931a51d6da093ece0a17b530b6e42..a926ae01af12d4a9274fe6f8d7b6e2ec54903998 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -7,12 +7,26 @@ common_gio_tests_deps = [ test_c_args = [ '-DG_LOG_DOMAIN="GLib-GIO"', - '-DTEST_SERVICES="@0@/gio/tests/services"'.format(meson.build_root()), '-DGLIB_MKENUMS="@0@"'.format(glib_mkenums), '-DGLIB_COMPILE_SCHEMAS="@0@"'.format(glib_compile_schemas.full_path()), '-UG_DISABLE_ASSERT', ] +# workaround for https://github.com/mesonbuild/meson/issues/6880 +if build_machine.system() == 'linux' + libutil_name = 'libutil' + libutil = run_command('sh', '-c', + '''ldconfig -p | grep -o "[[:space:]]@0@\.so\(\.[0-9]\+\)\?\b"''' + .format(libutil_name)).stdout().strip().split('\n') + + if libutil.length() > 0 + message('Found libutil as @0@'.format(libutil[0])) + test_c_args += '-DLIBUTIL_SONAME="@0@"'.format(libutil[0]) + else + warning('libutil not found') + endif # libutil.length() > 0 +endif # build_machine.system() == 'linux' + if host_machine.system() == 'windows' common_gio_tests_deps += [iphlpapi_dep, winsock2, cc.find_library ('secur32')] endif @@ -53,13 +67,14 @@ gio_tests = { 'inet-address' : {}, 'io-stream' : {}, 'memory-input-stream' : {}, + 'memory-monitor' : {}, 'memory-output-stream' : {}, 'mount-operation' : {}, 'network-address' : {'extra_sources': ['mock-resolver.c']}, 'network-monitor' : {}, 'network-monitor-race' : {}, 'permission' : {}, - 'pollable' : {}, + 'pollable' : {'dependencies' : [libdl_dep]}, 'proxy-test' : {}, 'readwrite' : {}, 'simple-async-result' : {}, @@ -78,7 +93,9 @@ gio_tests = { 'tls-certificate' : {'extra_sources' : ['gtesttlsbackend.c']}, 'tls-interaction' : {'extra_sources' : ['gtesttlsbackend.c']}, 'tls-database' : {'extra_sources' : ['gtesttlsbackend.c']}, + 'tls-bindings' : {'extra_sources' : ['gtesttlsbackend.c']}, 'gdbus-address-get-session' : {}, + 'win32-appinfo' : {}, } test_extra_programs = { @@ -87,11 +104,14 @@ test_extra_programs = { 'gsubprocess-testprog' : {}, } +python_tests = [ + 'codegen.py', +] + test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) test_env.set('GIO_MODULE_DIR', '') -test_env.set('GIO_LAUNCH_DESKTOP', meson.build_root() + '/gio/gio-launch-desktop') # Check for libdbus1 - Optional - is only used in the GDBus test cases # 1.2.14 required for dbus_message_set_serial @@ -101,7 +121,7 @@ if not dbus1_dep.found() # MSVC: Search for the DBus library by the configuration, which corresponds # to the output of CMake builds of DBus. Note that debugoptimized # is really a Release build with .PDB files. - if buildtype == 'debug' + if vs_crt == 'debug' dbus1_dep = cc.find_library('dbus-1d', required : false) else dbus1_dep = cc.find_library('dbus-1', required : false) @@ -115,7 +135,15 @@ if dbus1_dep.found() 'gdbus-serialization' : { 'extra_sources' : ['gdbus-tests.c'], 'dependencies' : [dbus1_dep], - } + }, + 'gdbus-server-auth' : { + 'dependencies' : [dbus1_dep], + }, + } +else + # We can build a cut-down version of this test without libdbus + gio_tests += { + 'gdbus-server-auth' : {}, } endif @@ -139,7 +167,8 @@ if host_machine.system() != 'windows' 'trash' : {}, } - if have_rtld_next + # LD_PRELOAD modules don't work so well with AddressSanitizer + if have_rtld_next and get_option('b_sanitize') == 'none' gio_tests += { 'gsocketclient-slow' : { 'depends' : [ @@ -218,7 +247,23 @@ if host_machine.system() != 'windows' '--generate-docbook', 'gdbus-test-codegen-generated-doc', annotate_args, '@INPUT@']) - + # Generate gdbus-test-codegen-generated-min-required-2-64.{c,h} + gdbus_test_codegen_generated_min_required_2_64 = custom_target('gdbus-test-codegen-generated-min-required-2-64', + input : ['test-codegen.xml'], + output : ['gdbus-test-codegen-generated-min-required-2-64.h', + 'gdbus-test-codegen-generated-min-required-2-64.c'], + depend_files : gdbus_codegen_built_files, + command : [python, gdbus_codegen, + '--glib-min-required', '2.64', + '--interface-prefix', 'org.project.', + '--output-directory', '@OUTDIR@', + '--generate-c-code', 'gdbus-test-codegen-generated-min-required-2-64', + '--c-generate-object-manager', + '--c-generate-autocleanup', 'all', + '--c-namespace', 'Foo_iGen', + '--generate-docbook', 'gdbus-test-codegen-generated-doc', + annotate_args, + '@INPUT@']) gdbus_test_codegen_generated_interface_info = [ custom_target('gdbus-test-codegen-generated-interface-info-h', input : ['test-codegen.xml'], @@ -270,10 +315,11 @@ if host_machine.system() != 'windows' 'gdbus-proxy-well-known-name' : {'extra_sources' : extra_sources}, 'gdbus-test-codegen' : { 'extra_sources' : [extra_sources, gdbus_test_codegen_generated, gdbus_test_codegen_generated_interface_info], + 'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_32'], }, 'gdbus-threading' : { 'extra_sources' : extra_sources, - 'suite' : ['slow', 'flaky'], + 'suite' : ['slow'], }, 'gmenumodel' : { 'extra_sources' : extra_sources, @@ -288,6 +334,11 @@ if host_machine.system() != 'windows' 'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36', '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_36'], }, + 'gdbus-test-codegen-min-required-2-64' : { + 'source' : 'gdbus-test-codegen.c', + 'extra_sources' : [extra_sources, gdbus_test_codegen_generated_min_required_2_64, gdbus_test_codegen_generated_interface_info], + 'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_64'], + }, 'gapplication' : {'extra_sources' : extra_sources}, } @@ -298,6 +349,25 @@ if host_machine.system() != 'windows' }, } endif + + fake_document_portal_generated = custom_target('fake-document-portal-generated', + input : ['../org.freedesktop.portal.Documents.xml'], + output : ['fake-document-portal-generated.h', + 'fake-document-portal-generated.c'], + depend_files : gdbus_codegen_built_files, + command : [python, gdbus_codegen, + '--interface-prefix', 'org.freedesktop.portal.', + '--output-directory', '@OUTDIR@', + '--generate-c-code', 'fake-document-portal-generated', + '--c-namespace', 'Fake', + '@INPUT@']) + + test_extra_programs += { + 'fake-document-portal' : { + 'extra_sources': fake_document_portal_generated, + }, + 'fake-service-name' : {} + } endif # have_dbus_daemon # This test is currently unreliable @@ -378,6 +448,11 @@ test_extra_programs += { }, } +gdbus_example_objectmanager_sources = files( + 'gdbus-example-objectmanager-client.c', + 'gdbus-example-objectmanager-server.c', +) + if cc.get_id() != 'msvc' and cc.get_id() != 'clang-cl' test_extra_programs += { # These three are manual-run tests because they need a session bus but don't bring one up themselves @@ -444,6 +519,7 @@ if installed_tests_enabled 'appinfo-test-static.desktop', 'file.c', 'org.gtk.test.dbusappinfo.desktop', + 'org.gtk.test.dbusappinfo.flatpak.desktop', 'test1.overlay', install_dir : installed_tests_execdir, ) @@ -463,6 +539,32 @@ if installed_tests_enabled ) install_subdir('static-link', install_dir : installed_tests_execdir) install_data('static-link.py', install_dir : installed_tests_execdir) + + memory_monitor_tests = [ + 'memory-monitor-dbus', + 'memory-monitor-portal', + ] + + foreach memory_monitor_test : memory_monitor_tests + cdata = configuration_data() + cdata.set('installed_tests_dir', installed_tests_execdir) + cdata.set('program', memory_monitor_test + '.py') + cdata.set('env', '') + configure_file( + input: installed_tests_template_tap, + output: memory_monitor_test + '.test', + install_dir: installed_tests_metadir, + configuration: cdata + ) + cdata = configuration_data() + cdata.set('libexecdir', join_paths(glib_prefix, get_option('libexecdir'))) + configure_file( + input: memory_monitor_test + '.py.in', + output: memory_monitor_test + '.py', + install_dir : installed_tests_execdir, + configuration: cdata, + ) + endforeach endif if not meson.is_cross_build() or meson.has_exe_wrapper() @@ -577,9 +679,15 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() # Support for --add-symbol was added to LLVM objcopy in 2019 # (https://reviews.llvm.org/D58234). FIXME: This test could be enabled for # LLVM once that support is in a stable release. + objcopy_supports_add_symbol = false objcopy = find_program('objcopy', required : false) + if objcopy.found() + objcopy_supports_add_symbol = run_command(objcopy, '--help').stdout().contains('--add-symbol') + endif - if build_machine.system() == 'linux' and cc.get_id() == 'gcc' and objcopy.found() + ld = find_program('ld', required : false) + + if build_machine.system() == 'linux' and cc.get_id() == 'gcc' and objcopy.found() and objcopy_supports_add_symbol and ld.found() test_gresource_binary = custom_target('test5.gresource', input : 'test5.gresource.xml', output : 'test5.gresource', @@ -608,7 +716,7 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() test_resources_binary = custom_target('test_resources.o', input : test_gresource_binary, output : 'test_resources.o', - command : ['ld', + command : [ld, '-r', '-b','binary', '@INPUT@', @@ -700,5 +808,42 @@ foreach program_name, extra_args : test_extra_programs ) endforeach -# FIXME: subdir('services') +foreach test_name : python_tests + test( + test_name, + python, + args: ['-B', files(test_name)], + env: test_env, + suite: ['gio', 'no-valgrind'], + ) + + if installed_tests_enabled + install_data( + files(test_name), + install_dir: installed_tests_execdir, + install_mode: 'rwxr-xr-x', + ) + + test_conf = configuration_data() + test_conf.set('installed_tests_dir', installed_tests_execdir) + test_conf.set('program', test_name) + test_conf.set('env', '') + configure_file( + input: installed_tests_template_tap, + output: test_name + '.test', + install_dir: installed_tests_metadir, + configuration: test_conf, + ) + endif +endforeach + +# TAP test runner for Python tests +if installed_tests_enabled + install_data( + files('taptestrunner.py'), + install_dir: installed_tests_execdir, + ) +endif + +subdir('services') subdir('modules') diff --git a/gio/tests/mock-resolver.c b/gio/tests/mock-resolver.c index 271aa2cb1cd0e2b822ebe977f30303b53867c0b7..3a7532134464a33d66377ec66ab291f99c9de37f 100644 --- a/gio/tests/mock-resolver.c +++ b/gio/tests/mock-resolver.c @@ -112,6 +112,12 @@ do_lookup_by_name (GTask *task, else g_task_return_pointer (task, g_list_copy_deep (self->ipv6_results, copy_object, NULL), NULL); } + else if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT) + { + /* This is only the minimal implementation needed for some tests */ + g_assert (self->ipv4_error == NULL && self->ipv6_error == NULL && self->ipv6_results == NULL); + g_task_return_pointer (task, g_list_copy_deep (self->ipv4_results, copy_object, NULL), NULL); + } else g_assert_not_reached (); } @@ -130,6 +136,22 @@ lookup_by_name_with_flags_async (GResolver *resolver, g_object_unref (task); } +static GList * +lookup_by_name (GResolver *resolver, + const gchar *hostname, + GCancellable *cancellable, + GError **error) +{ + GList *result = NULL; + GTask *task = g_task_new (resolver, cancellable, NULL, NULL); + g_task_set_task_data (task, GUINT_TO_POINTER (G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT), NULL); + g_task_run_in_thread_sync (task, do_lookup_by_name); + result = g_task_propagate_pointer (task, error); + g_object_unref (task); + return result; +} + + static GList * lookup_by_name_with_flags_finish (GResolver *resolver, GAsyncResult *result, @@ -160,6 +182,7 @@ mock_resolver_class_init (MockResolverClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); resolver_class->lookup_by_name_with_flags_async = lookup_by_name_with_flags_async; resolver_class->lookup_by_name_with_flags_finish = lookup_by_name_with_flags_finish; + resolver_class->lookup_by_name = lookup_by_name; object_class->finalize = mock_resolver_finalize; } diff --git a/gio/tests/network-address.c b/gio/tests/network-address.c index bda76050a4dc693559ad7a15ad5f2fda0577dff5..cbebb6c9f8e092970f9cfe295063d791bef1b23b 100644 --- a/gio/tests/network-address.c +++ b/gio/tests/network-address.c @@ -40,10 +40,10 @@ static ParseTest uri_tests[] = { { "ftp://[fec0::abcd]/start", "ftp", "fec0::abcd", 8080, -1 }, { "ftp://[fec0::abcd]:999/start", "ftp", "fec0::abcd", 999, -1 }, { "ftp://joe%x-@ftp.gnome.org:2020/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, - { "http://[fec0::abcd%em1]/start", "http", "fec0::abcd%em1", 8080, -1 }, + { "http://[fec0::abcd%em1]/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, { "http://[fec0::abcd%25em1]/start", "http", "fec0::abcd%em1", 8080, -1 }, - { "http://[fec0::abcd%10]/start", "http", "fec0::abcd%10", 8080, -1 }, - { "http://[fec0::abcd%25em%31]/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, + { "http://[fec0::abcd%10]/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, + { "http://[fec0::abcd%25em%31]/start", "http", "fec0::abcd%em1", 8080, -1 }, { "ftp://ftp.gnome.org/start?foo=bar@baz", "ftp", "ftp.gnome.org", 8080, -1 } }; @@ -80,6 +80,7 @@ static ParseTest host_tests[] = { "[2001:db8::1]", NULL, "2001:db8::1", 1234, -1 }, { "[2001:db8::1]:888", NULL, "2001:db8::1", 888, -1 }, { "[2001:db8::1%em1]", NULL, "2001:db8::1%em1", 1234, -1 }, + { "[2001:db8::1%25em1]", NULL, "2001:db8::1%25em1", 1234, -1 }, { "[hostname", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, { "[hostnam]e", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, { "hostname:", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }, @@ -337,10 +338,9 @@ test_uri_scope_id (void) SCOPE_ID_TEST_PORT); addr = g_network_address_parse_uri (uri, 0, &error); g_free (uri); - g_assert_no_error (error); - - test_scope_id (addr); - g_object_unref (addr); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT); + g_assert_null (addr); + g_clear_error (&error); uri = g_strdup_printf ("http://[%s%%25%s]:%d/foo", SCOPE_ID_TEST_ADDR, @@ -418,13 +418,150 @@ test_loopback_sync (void) g_object_unref (addr); } +static void +test_localhost_sync (void) +{ + GSocketConnectable *addr; /* owned */ + GSocketAddressEnumerator *enumerator; /* owned */ + GSocketAddress *a; /* owned */ + GError *error = NULL; + GResolver *original_resolver; /* owned */ + MockResolver *mock_resolver; /* owned */ + GList *ipv4_results = NULL; /* owned */ + + /* This test ensures that variations of the "localhost" hostname always resolve to a loopback address */ + + /* Set up a DNS resolver that returns nonsense for "localhost" */ + original_resolver = g_resolver_get_default (); + mock_resolver = mock_resolver_new (); + g_resolver_set_default (G_RESOLVER (mock_resolver)); + ipv4_results = g_list_append (ipv4_results, g_inet_address_new_from_string ("123.123.123.123")); + mock_resolver_set_ipv4_results (mock_resolver, ipv4_results); + + addr = g_network_address_new ("localhost.", 616); + enumerator = g_socket_connectable_enumerate (addr); + + /* IPv6 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "::1", 616); + g_object_unref (a); + + /* IPv4 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "127.0.0.1", 616); + g_object_unref (a); + + /* End of results. */ + g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error)); + g_assert_no_error (error); + g_object_unref (enumerator); + g_object_unref (addr); + + addr = g_network_address_new (".localhost", 616); + enumerator = g_socket_connectable_enumerate (addr); + + /* IPv6 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "::1", 616); + g_object_unref (a); + + /* IPv4 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "127.0.0.1", 616); + g_object_unref (a); + + /* End of results. */ + g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error)); + g_assert_no_error (error); + g_object_unref (enumerator); + g_object_unref (addr); + + addr = g_network_address_new ("foo.localhost", 616); + enumerator = g_socket_connectable_enumerate (addr); + + /* IPv6 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "::1", 616); + g_object_unref (a); + + /* IPv4 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "127.0.0.1", 616); + g_object_unref (a); + + /* End of results. */ + g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error)); + g_assert_no_error (error); + g_object_unref (enumerator); + g_object_unref (addr); + + addr = g_network_address_new (".localhost.", 616); + enumerator = g_socket_connectable_enumerate (addr); + + /* IPv6 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "::1", 616); + g_object_unref (a); + + /* IPv4 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "127.0.0.1", 616); + g_object_unref (a); + + /* End of results. */ + g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error)); + g_assert_no_error (error); + g_object_unref (enumerator); + g_object_unref (addr); + + addr = g_network_address_new ("invalid", 616); + enumerator = g_socket_connectable_enumerate (addr); + + /* IPv4 address. */ + a = g_socket_address_enumerator_next (enumerator, NULL, &error); + g_assert_no_error (error); + assert_socket_address_matches (a, "123.123.123.123", 616); + g_object_unref (a); + + /* End of results. */ + g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error)); + g_assert_no_error (error); + g_object_unref (enumerator); + g_object_unref (addr); + + g_resolver_set_default (original_resolver); + g_list_free_full (ipv4_results, (GDestroyNotify) g_object_unref); + g_object_unref (original_resolver); + g_object_unref (mock_resolver); +} + typedef struct { GList/* */ *addrs; /* owned */ GMainLoop *loop; /* owned */ + GSocketAddressEnumerator *enumerator; /* unowned */ guint delay_ms; gint expected_error_code; } AsyncData; +static void got_addr (GObject *source_object, GAsyncResult *result, gpointer user_data); + +static int +on_delayed_get_addr (gpointer user_data) +{ + AsyncData *data = user_data; + g_socket_address_enumerator_next_async (data->enumerator, NULL, + got_addr, user_data); + return G_SOURCE_REMOVE; +} + static void got_addr (GObject *source_object, GAsyncResult *result, @@ -459,11 +596,14 @@ got_addr (GObject *source_object, g_assert (G_IS_INET_SOCKET_ADDRESS (a)); data->addrs = g_list_prepend (data->addrs, a); - if (data->delay_ms) - g_usleep (data->delay_ms * 1000); - - g_socket_address_enumerator_next_async (enumerator, NULL, - got_addr, user_data); + if (!data->delay_ms) + g_socket_address_enumerator_next_async (enumerator, NULL, + got_addr, user_data); + else + { + data->enumerator = enumerator; + g_timeout_add (data->delay_ms, on_delayed_get_addr, data); + } } } @@ -521,6 +661,51 @@ test_loopback_async (void) g_object_unref (addr); } +static void +test_localhost_async (void) +{ + GSocketConnectable *addr; /* owned */ + GSocketAddressEnumerator *enumerator; /* owned */ + AsyncData data = { 0, }; + GResolver *original_resolver; /* owned */ + MockResolver *mock_resolver; /* owned */ + GList *ipv4_results = NULL; /* owned */ + + /* This test ensures that variations of the "localhost" hostname always resolve to a loopback address */ + + /* Set up a DNS resolver that returns nonsense for "localhost" */ + original_resolver = g_resolver_get_default (); + mock_resolver = mock_resolver_new (); + g_resolver_set_default (G_RESOLVER (mock_resolver)); + ipv4_results = g_list_append (ipv4_results, g_inet_address_new_from_string ("123.123.123.123")); + mock_resolver_set_ipv4_results (mock_resolver, ipv4_results); + + addr = g_network_address_new ("localhost", 610); + enumerator = g_socket_connectable_enumerate (addr); + + /* Get all the addresses. */ + data.addrs = NULL; + data.delay_ms = 1; + data.loop = g_main_loop_new (NULL, FALSE); + + g_socket_address_enumerator_next_async (enumerator, NULL, got_addr, &data); + g_main_loop_run (data.loop); + + /* Check results. */ + g_assert_cmpuint (g_list_length (data.addrs), ==, 2); + assert_socket_address_matches (data.addrs->data, "::1", 610); + assert_socket_address_matches (data.addrs->next->data, "127.0.0.1", 610); + + g_resolver_set_default (original_resolver); + g_list_free_full (data.addrs, (GDestroyNotify) g_object_unref); + g_list_free_full (ipv4_results, (GDestroyNotify) g_object_unref); + g_object_unref (original_resolver); + g_object_unref (mock_resolver); + g_object_unref (enumerator); + g_object_unref (addr); + g_main_loop_unref (data.loop); +} + static void test_to_string (void) { @@ -1039,6 +1224,8 @@ main (int argc, char *argv[]) g_test_add_func ("/network-address/loopback/basic", test_loopback_basic); g_test_add_func ("/network-address/loopback/sync", test_loopback_sync); g_test_add_func ("/network-address/loopback/async", test_loopback_async); + g_test_add_func ("/network-address/localhost/async", test_localhost_async); + g_test_add_func ("/network-address/localhost/sync", test_localhost_sync); g_test_add_func ("/network-address/to-string", test_to_string); g_test_add ("/network-address/happy-eyeballs/basic", HappyEyeballsFixture, NULL, diff --git a/gio/tests/org.gtk.test.dbusappinfo.flatpak.desktop b/gio/tests/org.gtk.test.dbusappinfo.flatpak.desktop new file mode 100644 index 0000000000000000000000000000000000000000..9ef248a5fe6a00c6e6b39d26b60853a04e713603 --- /dev/null +++ b/gio/tests/org.gtk.test.dbusappinfo.flatpak.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Type=Application +Name=Test +DBusActivatable=true +X-Flatpak=org.gtk.test.dbusappinfo.flatpak diff --git a/gio/tests/pollable.c b/gio/tests/pollable.c index b8c8710bb874347e78e5afc6ae62412221419235..516d7f4e479f6aadb8394880839ddc6bd63413d3 100644 --- a/gio/tests/pollable.c +++ b/gio/tests/pollable.c @@ -16,10 +16,13 @@ * Public License along with this library; if not, see . */ +#include "config.h" + #include #include #ifdef G_OS_UNIX +#include #include #include #include @@ -146,10 +149,26 @@ test_streams (void) } #ifdef G_OS_UNIX + +#define g_assert_not_pollable(fd) \ + G_STMT_START { \ + in = G_POLLABLE_INPUT_STREAM (g_unix_input_stream_new (fd, FALSE)); \ + out = g_unix_output_stream_new (fd, FALSE); \ + \ + g_assert (!g_pollable_input_stream_can_poll (in)); \ + g_assert (!g_pollable_output_stream_can_poll ( \ + G_POLLABLE_OUTPUT_STREAM (out))); \ + \ + g_clear_object (&in); \ + g_clear_object (&out); \ + } G_STMT_END + static void -test_pollable_unix (void) +test_pollable_unix_pipe (void) { - int pipefds[2], status, fd; + int pipefds[2], status; + + g_test_summary ("Test that pipes are considered pollable, just like sockets"); status = pipe (pipefds); g_assert_cmpint (status, ==, 0); @@ -161,21 +180,97 @@ test_pollable_unix (void) g_object_unref (in); g_object_unref (out); +} - /* Non-pipe/socket unix streams are not pollable */ - fd = g_open ("/dev/null", O_RDWR, 0); - g_assert_cmpint (fd, !=, -1); - in = G_POLLABLE_INPUT_STREAM (g_unix_input_stream_new (fd, FALSE)); - out = g_unix_output_stream_new (fd, FALSE); +static void +test_pollable_unix_pty (void) +{ + int (*openpty_impl) (int *, int *, char *, void *, void *); + int a, b, status; +#ifdef LIBUTIL_SONAME + void *handle; +#endif - g_assert (!g_pollable_input_stream_can_poll (in)); - g_assert (!g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (out))); + g_test_summary ("Test that PTYs are considered pollable"); + +#ifdef LIBUTIL_SONAME + handle = dlopen (LIBUTIL_SONAME, RTLD_GLOBAL | RTLD_LAZY); + g_assert_nonnull (handle); +#endif + + openpty_impl = dlsym (RTLD_DEFAULT, "openpty"); + if (openpty_impl == NULL) + { + g_test_skip ("System does not support openpty()"); + goto close_libutil; + } + + status = openpty_impl (&a, &b, NULL, NULL, NULL); + if (status == -1) + { + g_test_skip ("Unable to open PTY"); + goto close_libutil; + } + + in = G_POLLABLE_INPUT_STREAM (g_unix_input_stream_new (a, TRUE)); + out = g_unix_output_stream_new (b, TRUE); + + test_streams (); g_object_unref (in); g_object_unref (out); + + close (a); + close (b); + +close_libutil: +#ifdef LIBUTIL_SONAME + dlclose (handle); +#else + return; +#endif +} + +static void +test_pollable_unix_file (void) +{ + int fd; + + g_test_summary ("Test that regular files are not considered pollable"); + + fd = g_open ("/etc/hosts", O_RDONLY, 0); + if (fd == -1) + { + g_test_skip ("Unable to open /etc/hosts"); + return; + } + + g_assert_not_pollable (fd); + close (fd); } +static void +test_pollable_unix_nulldev (void) +{ + int fd; + + g_test_summary ("Test that /dev/null is not considered pollable, but only if " + "on a system where we are able to tell it apart from devices " + "that actually implement poll"); + +#if defined (HAVE_EPOLL_CREATE) || defined (HAVE_KQUEUE) + fd = g_open ("/dev/null", O_RDWR, 0); + g_assert_cmpint (fd, !=, -1); + + g_assert_not_pollable (fd); + + close (fd); +#else + g_test_skip ("Cannot detect /dev/null as non-pollable on this system"); +#endif +} + static void test_pollable_converter (void) { @@ -285,11 +380,13 @@ main (int argc, g_test_init (&argc, &argv, NULL); #ifdef G_OS_UNIX - g_test_add_func ("/pollable/unix", test_pollable_unix); + g_test_add_func ("/pollable/unix/pipe", test_pollable_unix_pipe); + g_test_add_func ("/pollable/unix/pty", test_pollable_unix_pty); + g_test_add_func ("/pollable/unix/file", test_pollable_unix_file); + g_test_add_func ("/pollable/unix/nulldev", test_pollable_unix_nulldev); g_test_add_func ("/pollable/converter", test_pollable_converter); #endif g_test_add_func ("/pollable/socket", test_pollable_socket); return g_test_run(); } - diff --git a/gio/tests/proxy-test.c b/gio/tests/proxy-test.c index 8f6dccf5982efdc59d1d7a1b662d8252c1b5b5bb..e3c0d09c7948bb24dee9903aaeae39ac195034c1 100644 --- a/gio/tests/proxy-test.c +++ b/gio/tests/proxy-test.c @@ -1387,4 +1387,3 @@ main (int argc, return result; } - diff --git a/gio/tests/proxy.c b/gio/tests/proxy.c index 50a20622ef02e1e041abee78aa222179a8baf91b..e64355ae0049c75cdaf1a4576e1dd0b32ce2fdde 100644 --- a/gio/tests/proxy.c +++ b/gio/tests/proxy.c @@ -37,7 +37,7 @@ static const gchar *info = NULL; static GCancellable *cancellable = NULL; static gint return_value = 0; -static void G_GNUC_NORETURN +static G_NORETURN void usage (void) { fprintf (stderr, "Usage: proxy [-s] (uri|host:port|ip:port|path|srv/protocol/domain)\n"); diff --git a/gio/tests/resolver.c b/gio/tests/resolver.c index c57b8186754aab3afef2f36529cf7040f44d66bb..3e6d896704f394f3cabe51b8f36a28e636a93095 100644 --- a/gio/tests/resolver.c +++ b/gio/tests/resolver.c @@ -40,7 +40,7 @@ static gboolean synchronous = FALSE; static guint connectable_count = 0; static GResolverRecordType record_type = 0; -static void G_GNUC_NORETURN +static G_NORETURN void usage (void) { fprintf (stderr, "Usage: resolver [-s] [hostname | IP | service/protocol/domain ] ...\n"); diff --git a/gio/tests/resourceplugin.c b/gio/tests/resourceplugin.c index fc8d8d2f1144ebeff5326a01b99ddf95ddfc4001..1f218f26f7ae75aea4c20bea78e939c83dec7864 100644 --- a/gio/tests/resourceplugin.c +++ b/gio/tests/resourceplugin.c @@ -4,7 +4,7 @@ * This must be done before including any GLib headers, * since GLIB_AVAILABLE_IN_ALL, which is used to mark the * g_io_module*() symbols, is defined to be _GLIB_EXTERN, - * which must be overriden to export the symbols. + * which must be overridden to export the symbols. */ #include "modules/symbol-visibility.h" #define _GLIB_EXTERN GLIB_TEST_EXPORT_SYMBOL @@ -26,4 +26,3 @@ g_io_module_query (void) { return NULL; } - diff --git a/gio/tests/resources.c b/gio/tests/resources.c index c44d214855eeb2673814a62586dcb3e7113c274e..325775fd668381c4ee2e061c48b87974136349a9 100644 --- a/gio/tests/resources.c +++ b/gio/tests/resources.c @@ -68,6 +68,15 @@ test_resource (GResource *resource) g_assert_cmpint (size, ==, 6); g_assert_cmpuint (flags, ==, G_RESOURCE_FLAGS_COMPRESSED); + found = g_resource_get_info (resource, + "/empty.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &size, &flags, &error); + g_assert_true (found); + g_assert_no_error (error); + g_assert_cmpint (size, ==, 0); + g_assert_cmpuint (flags, ==, G_RESOURCE_FLAGS_COMPRESSED); + found = g_resource_get_info (resource, "/a_prefix/test2.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, @@ -105,6 +114,14 @@ test_resource (GResource *resource) g_assert_no_error (error); g_bytes_unref (data); + data = g_resource_lookup_data (resource, + "/empty.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_cmpuint (g_bytes_get_size (data), ==, 0); + g_assert_no_error (error); + g_bytes_unref (data); + for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++) { in = g_resource_open_stream (resource, @@ -136,6 +153,24 @@ test_resource (GResource *resource) g_assert_no_error (error); g_clear_object (&in); + in = g_resource_open_stream (resource, + "/empty.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_no_error (error); + g_assert_nonnull (in); + + success = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1, + &size, + NULL, &error); + g_assert_no_error (error); + g_assert_true (success); + g_assert_cmpint (size, ==, 0); + + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_object (&in); + data = g_resource_lookup_data (resource, "/a_prefix/test2.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, @@ -398,6 +433,14 @@ test_resource_registered (void) g_assert_cmpint (size, ==, 6); g_assert (flags == (G_RESOURCE_FLAGS_COMPRESSED)); + found = g_resources_get_info ("/empty.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &size, &flags, &error); + g_assert_no_error (error); + g_assert_true (found); + g_assert_cmpint (size, ==, 0); + g_assert (flags == (G_RESOURCE_FLAGS_COMPRESSED)); + found = g_resources_get_info ("/a_prefix/test2.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, &size, &flags, &error); @@ -440,6 +483,30 @@ test_resource_registered (void) g_assert_no_error (error); g_clear_object (&in); + data = g_resources_lookup_data ("/empty.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_no_error (error); + g_assert_cmpuint (g_bytes_get_size (data), ==, 0); + g_bytes_unref (data); + + in = g_resources_open_stream ("/empty.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_no_error (error); + g_assert_nonnull (in); + + success = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1, + &size, + NULL, &error); + g_assert_no_error (error); + g_assert_true (success); + g_assert_cmpint (size, ==, 0); + + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_object (&in); + data = g_resources_lookup_data ("/a_prefix/test2.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, &error); @@ -605,7 +672,7 @@ test_resource_binary_linked (void) /* Test resource whose xml file starts with more than one digit * and where no explicit c-name is given - * Checks if resources are sucessfully registered and + * Checks if resources are successfully registered and * data can be found and read. */ static void test_resource_digits (void) diff --git a/gio/tests/services/meson.build b/gio/tests/services/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..fd5117e2322fbb589e09af5ec2b3a186399f3927 --- /dev/null +++ b/gio/tests/services/meson.build @@ -0,0 +1,31 @@ +dbus_service_files = [ + 'org.freedesktop.portal.Documents.service', + 'org.gtk.GDBus.FakeService.service' +] + +srcdir_cdata = configuration_data() +srcdir_cdata.set('installed_tests_dir', meson.current_build_dir() / '..') + +installed_cdata = configuration_data() +installed_cdata.set('installed_tests_dir', installed_tests_execdir) + +foreach service_file : dbus_service_files + configure_file( + input: service_file + '.in', + output: service_file, + configuration: srcdir_cdata, + ) + if installed_tests_enabled + # Build a second copy of the service file for the installed + # version of the tests. + configure_file( + input: service_file + '.in', + output: service_file + '.to-install', + configuration: installed_cdata, + ) + install_data(meson.current_build_dir() / service_file + '.to-install', + install_dir: installed_tests_execdir / 'services', + rename: [service_file], + ) + endif +endforeach diff --git a/gio/tests/services/org.freedesktop.portal.Documents.service.in b/gio/tests/services/org.freedesktop.portal.Documents.service.in new file mode 100644 index 0000000000000000000000000000000000000000..2769ff7b6209b05be066d5ceb6ae6cd6376e6de0 --- /dev/null +++ b/gio/tests/services/org.freedesktop.portal.Documents.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.freedesktop.portal.Documents +Exec=@installed_tests_dir@/fake-document-portal diff --git a/gio/tests/services/org.gtk.GDBus.FakeService.service.in b/gio/tests/services/org.gtk.GDBus.FakeService.service.in new file mode 100644 index 0000000000000000000000000000000000000000..bbfcd73eb07d254c37b6490a9d68a24fee93411a --- /dev/null +++ b/gio/tests/services/org.gtk.GDBus.FakeService.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.gtk.GDBus.FakeService +Exec=@installed_tests_dir@/fake-service-name diff --git a/gio/tests/socket-listener.c b/gio/tests/socket-listener.c index 31f94460e3e81eaf930d14f9136cb4247a031c55..71e70b28fa25e248302316bce35c5078063e7270 100644 --- a/gio/tests/socket-listener.c +++ b/gio/tests/socket-listener.c @@ -92,4 +92,3 @@ main (int argc, return g_test_run(); } - diff --git a/gio/tests/socket-service.c b/gio/tests/socket-service.c index dc8bdec238bc2082b3f704b007260deeb190b569..c763fa6e6512b272c564bba96a78cacd9ca80406 100644 --- a/gio/tests/socket-service.c +++ b/gio/tests/socket-service.c @@ -63,7 +63,7 @@ test_start_stop (void) saddr = g_inet_socket_address_new (iaddr, 0); g_object_unref (iaddr); - /* instanciate with g_object_new so we can pass active = false */ + /* instantiate with g_object_new so we can pass active = false */ service = g_object_new (G_TYPE_SOCKET_SERVICE, "active", FALSE, NULL); g_assert_false (g_socket_service_is_active (service)); @@ -99,7 +99,7 @@ test_start_stop (void) GMutex mutex_712570; GCond cond_712570; -volatile gboolean finalized; +gboolean finalized; /* (atomic) */ GType test_threaded_socket_service_get_type (void); typedef GThreadedSocketService TestThreadedSocketService; @@ -120,7 +120,7 @@ test_threaded_socket_service_finalize (GObject *object) /* Signal the main thread that finalization completed successfully * rather than hanging. */ - finalized = TRUE; + g_atomic_int_set (&finalized, TRUE); g_cond_signal (&cond_712570); g_mutex_unlock (&mutex_712570); } @@ -235,7 +235,7 @@ test_threaded_712570 (void) */ g_object_unref (service); - while (!finalized) + while (!g_atomic_int_get (&finalized)) g_cond_wait (&cond_712570, &mutex_712570); g_mutex_unlock (&mutex_712570); } @@ -342,6 +342,7 @@ writtenv_read_write_async_cb (GOutputStream *ostream, conn = data->conn; g_free (data->data); + g_free (data->vectors); g_free (data); res = g_output_stream_writev_all_finish (ostream, result, &bytes_written, &error); diff --git a/gio/tests/socket.c b/gio/tests/socket.c index eeebddd628b4ab12eaaff042d109f9731c336323..ee098c55fb2c4a49b4301221f55d9fc509917def 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -18,6 +18,7 @@ #include +#include #ifdef G_OS_UNIX #include #include @@ -140,7 +141,11 @@ create_server_full (GSocketFamily family, { g_socket_set_option (data->server, IPPROTO_IPV6, IPV6_V6ONLY, FALSE, NULL); if (!g_socket_speaks_ipv4 (data->server)) - goto error; + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "IPv6-only server cannot speak IPv4"); + goto error; + } } #endif @@ -342,6 +347,7 @@ test_ip_async (GSocketFamily family) g_clear_error (&error); return; } + g_assert_nonnull (data); addr = g_socket_get_local_address (data->server, &error); g_assert_no_error (error); @@ -1130,6 +1136,12 @@ test_timed_wait (void) gint64 start_time; gint poll_duration; + if (!g_test_thorough ()) + { + g_test_skip ("Not running timing heavy test"); + return; + } + data = create_server (G_SOCKET_FAMILY_IPV4, echo_server_thread, FALSE, &error); if (error != NULL) { @@ -1887,6 +1899,238 @@ test_read_write (gconstpointer user_data) g_object_unref (client); } +#ifdef SO_NOSIGPIPE +static void +test_nosigpipe (void) +{ + GSocket *sock; + GError *error = NULL; + gint value; + + sock = g_socket_new (AF_INET, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + g_socket_get_option (sock, SOL_SOCKET, SO_NOSIGPIPE, &value, &error); + g_assert_no_error (error); + g_assert_true (value); + + g_object_unref (sock); +} +#endif + +#if G_CREDENTIALS_SUPPORTED +static gpointer client_setup_thread (gpointer user_data); + +static void +test_credentials_tcp_client (void) +{ + const GSocketFamily family = G_SOCKET_FAMILY_IPV4; + IPTestData *data; + GError *error = NULL; + GSocket *client; + GSocketAddress *addr; + GCredentials *creds; + + data = create_server (family, echo_server_thread, FALSE, &error); + if (error != NULL) + { + gchar *message = g_strdup_printf ("Failed to create server: %s", error->message); + g_test_skip (message); + g_free (message); + g_clear_error (&error); + return; + } + + addr = g_socket_get_local_address (data->server, &error); + g_assert_no_error (error); + + client = g_socket_new (family, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + g_socket_set_blocking (client, TRUE); + g_socket_set_timeout (client, 1); + + g_socket_connect (client, addr, NULL, &error); + g_assert_no_error (error); + g_object_unref (addr); + + creds = g_socket_get_credentials (client, &error); + if (creds != NULL) + { + gchar *str = g_credentials_to_string (creds); + g_print ("Supported on this OS: %s\n", str); + g_free (str); + g_clear_object (&creds); + } + else + { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_print ("Unsupported on this OS: %s\n", error->message); + g_clear_error (&error); + } + + g_socket_close (client, &error); + g_assert_no_error (error); + + g_thread_join (data->thread); + + g_socket_close (data->server, &error); + g_assert_no_error (error); + + g_object_unref (data->server); + g_object_unref (client); + + g_slice_free (IPTestData, data); +} + +static void +test_credentials_tcp_server (void) +{ + const GSocketFamily family = G_SOCKET_FAMILY_IPV4; + IPTestData *data; + GSocket *server; + GError *error = NULL; + GSocketAddress *addr = NULL; + GInetAddress *iaddr = NULL; + GSocket *sock = NULL; + GCredentials *creds; + + data = g_slice_new0 (IPTestData); + data->family = family; + data->server = server = g_socket_new (family, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + if (error != NULL) + goto skip; + + g_socket_set_blocking (server, TRUE); + + iaddr = g_inet_address_new_loopback (family); + addr = g_inet_socket_address_new (iaddr, 0); + + if (!g_socket_bind (server, addr, TRUE, &error)) + goto skip; + + if (!g_socket_listen (server, &error)) + goto skip; + + data->thread = g_thread_new ("client", client_setup_thread, data); + + sock = g_socket_accept (server, NULL, &error); + g_assert_no_error (error); + + creds = g_socket_get_credentials (sock, &error); + if (creds != NULL) + { + gchar *str = g_credentials_to_string (creds); + g_print ("Supported on this OS: %s\n", str); + g_free (str); + g_clear_object (&creds); + } + else + { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_print ("Unsupported on this OS: %s\n", error->message); + g_clear_error (&error); + } + + goto beach; + +skip: + { + gchar *message = g_strdup_printf ("Failed to create server: %s", error->message); + g_test_skip (message); + g_free (message); + + goto beach; + } +beach: + { + g_clear_error (&error); + + g_clear_object (&sock); + g_clear_object (&addr); + g_clear_object (&iaddr); + + g_clear_pointer (&data->thread, g_thread_join); + g_clear_object (&data->server); + g_clear_object (&data->client); + + g_slice_free (IPTestData, data); + } +} + +static gpointer +client_setup_thread (gpointer user_data) +{ + IPTestData *data = user_data; + GSocketAddress *addr; + GSocket *client; + GError *error = NULL; + + addr = g_socket_get_local_address (data->server, &error); + g_assert_no_error (error); + + data->client = client = g_socket_new (data->family, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + &error); + g_assert_no_error (error); + + g_socket_set_blocking (client, TRUE); + g_socket_set_timeout (client, 1); + + g_socket_connect (client, addr, NULL, &error); + g_assert_no_error (error); + + g_object_unref (addr); + + return NULL; +} + +#ifdef G_OS_UNIX +static void +test_credentials_unix_socketpair (void) +{ + gint fds[2]; + gint status; + GSocket *sock; + GError *error = NULL; + GCredentials *creds; + + status = socketpair (PF_UNIX, SOCK_STREAM, 0, fds); + g_assert_cmpint (status, ==, 0); + + sock = g_socket_new_from_fd (fds[0], &error); + + creds = g_socket_get_credentials (sock, &error); + if (creds != NULL) + { + gchar *str = g_credentials_to_string (creds); + g_print ("Supported on this OS: %s\n", str); + g_free (str); + g_clear_object (&creds); + } + else + { + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_print ("Unsupported on this OS: %s\n", error->message); + g_clear_error (&error); + } + + g_object_unref (sock); + close (fds[1]); +} +#endif +#endif + int main (int argc, char *argv[]) @@ -1943,7 +2187,16 @@ main (int argc, test_read_write); g_test_add_data_func ("/socket/read_writev", GUINT_TO_POINTER (TRUE), test_read_write); +#ifdef SO_NOSIGPIPE + g_test_add_func ("/socket/nosigpipe", test_nosigpipe); +#endif +#if G_CREDENTIALS_SUPPORTED + g_test_add_func ("/socket/credentials/tcp_client", test_credentials_tcp_client); + g_test_add_func ("/socket/credentials/tcp_server", test_credentials_tcp_server); +#ifdef G_OS_UNIX + g_test_add_func ("/socket/credentials/unix_socketpair", test_credentials_unix_socketpair); +#endif +#endif return g_test_run(); } - diff --git a/gio/tests/static-link.py b/gio/tests/static-link.py old mode 100755 new mode 100644 index 0af9b1af9605645ed886c5d21aa17bcc55b1d5a0..a8bda5bd38fa7c074813e8ed631f0d16d6ae92e1 --- a/gio/tests/static-link.py +++ b/gio/tests/static-link.py @@ -23,29 +23,33 @@ import sys import tempfile import subprocess -if not 'GLIB_TEST_COMPILATION' in os.environ: - print('''Test disabled because GLIB_TEST_COMPILATION is not set in the env. +if "GLIB_TEST_COMPILATION" not in os.environ: + print( + """Test disabled because GLIB_TEST_COMPILATION is not set in the env. If you wish to run this test, set GLIB_TEST_COMPILATION=1 in the env, and make sure you have glib build dependencies installed, including -meson.''') - sys.exit(0) +meson.""" + ) + sys.exit(77) if len(sys.argv) != 2: - print('Usage: {} '.format(os.path.basename(sys.argv[0]))) - sys.exit(1) + print("Usage: {} ".format(os.path.basename(sys.argv[0]))) + sys.exit(1) test_dir = os.path.dirname(sys.argv[0]) with tempfile.TemporaryDirectory() as builddir: - env = os.environ.copy() - env['PKG_CONFIG_PATH'] = sys.argv[1] - sourcedir = os.path.join(test_dir, 'static-link') + env = os.environ.copy() + env["PKG_CONFIG_PATH"] = sys.argv[1] + sourcedir = os.path.join(test_dir, "static-link") - # Ensure we can static link and run a test app - subprocess.check_call(['meson', sourcedir, builddir], env=env) - subprocess.check_call(['ninja', '-C', builddir, 'test'], env=env) - # FIXME: This probably only works on Linux - out = subprocess.check_output(['ldd', os.path.join(builddir, 'test-static-link')], env=env).decode() - if 'libgio' in out: - print('test-static-link is dynamically linked on libgio') - exit(1) + # Ensure we can static link and run a test app + subprocess.check_call(["meson", sourcedir, builddir], env=env) + subprocess.check_call(["ninja", "-C", builddir, "test"], env=env) + # FIXME: This probably only works on Linux + out = subprocess.check_output( + ["ldd", os.path.join(builddir, "test-static-link")], env=env + ).decode() + if "libgio" in out: + print("test-static-link is dynamically linked on libgio") + exit(1) diff --git a/gio/tests/taptestrunner.py b/gio/tests/taptestrunner.py new file mode 100644 index 0000000000000000000000000000000000000000..9ce3b43a4adb8e285e732b4e911340c5193e02b4 --- /dev/null +++ b/gio/tests/taptestrunner.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright (c) 2015 Remko Tronçon (https://el-tramo.be) +# Copied from https://github.com/remko/pycotap/ +# +# Released under the MIT license +# +# 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. + + +import unittest +import sys +import base64 +from io import StringIO + + +# Log modes +class LogMode(object): + LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4) + + +class TAPTestResult(unittest.TestResult): + def __init__(self, output_stream, error_stream, message_log, test_output_log): + super(TAPTestResult, self).__init__(self, output_stream) + self.output_stream = output_stream + self.error_stream = error_stream + self.orig_stdout = None + self.orig_stderr = None + self.message = None + self.test_output = None + self.message_log = message_log + self.test_output_log = test_output_log + self.output_stream.write("TAP version 13\n") + self._set_streams() + + def printErrors(self): + self.print_raw("1..%d\n" % self.testsRun) + self._reset_streams() + + def _set_streams(self): + self.orig_stdout = sys.stdout + self.orig_stderr = sys.stderr + if self.message_log == LogMode.LogToError: + self.message = self.error_stream + else: + self.message = StringIO() + if self.test_output_log == LogMode.LogToError: + self.test_output = self.error_stream + else: + self.test_output = StringIO() + + if self.message_log == self.test_output_log: + self.test_output = self.message + sys.stdout = sys.stderr = self.test_output + + def _reset_streams(self): + sys.stdout = self.orig_stdout + sys.stderr = self.orig_stderr + + def print_raw(self, text): + self.output_stream.write(text) + self.output_stream.flush() + + def print_result(self, result, test, directive=None): + self.output_stream.write("%s %d %s" % (result, self.testsRun, test.id())) + if directive: + self.output_stream.write(" # " + directive) + self.output_stream.write("\n") + self.output_stream.flush() + + def ok(self, test, directive=None): + self.print_result("ok", test, directive) + + def not_ok(self, test): + self.print_result("not ok", test) + + def startTest(self, test): + super(TAPTestResult, self).startTest(test) + + def stopTest(self, test): + super(TAPTestResult, self).stopTest(test) + if self.message_log == self.test_output_log: + logs = [(self.message_log, self.message, "output")] + else: + logs = [ + (self.test_output_log, self.test_output, "test_output"), + (self.message_log, self.message, "message"), + ] + for log_mode, log, log_name in logs: + if log_mode != LogMode.LogToError: + output = log.getvalue() + if len(output): + if log_mode == LogMode.LogToYAML: + self.print_raw(" ---\n") + self.print_raw(" " + log_name + ": |\n") + self.print_raw( + " " + output.rstrip().replace("\n", "\n ") + "\n" + ) + self.print_raw(" ...\n") + elif log_mode == LogMode.LogToAttachment: + self.print_raw(" ---\n") + self.print_raw(" " + log_name + ":\n") + self.print_raw(" File-Name: " + log_name + ".txt\n") + self.print_raw(" File-Type: text/plain\n") + self.print_raw( + " File-Content: " + base64.b64encode(output) + "\n" + ) + self.print_raw(" ...\n") + else: + self.print_raw( + "# " + output.rstrip().replace("\n", "\n# ") + "\n" + ) + # Truncate doesn't change the current stream position. + # Seek to the beginning to avoid extensions on subsequent writes. + log.seek(0) + log.truncate(0) + + def addSuccess(self, test): + super(TAPTestResult, self).addSuccess(test) + self.ok(test) + + def addError(self, test, err): + super(TAPTestResult, self).addError(test, err) + self.message.write(self.errors[-1][1] + "\n") + self.not_ok(test) + + def addFailure(self, test, err): + super(TAPTestResult, self).addFailure(test, err) + self.message.write(self.failures[-1][1] + "\n") + self.not_ok(test) + + def addSkip(self, test, reason): + super(TAPTestResult, self).addSkip(test, reason) + self.ok(test, "SKIP " + reason) + + def addExpectedFailure(self, test, err): + super(TAPTestResult, self).addExpectedFailure(test, err) + self.ok(test) + + def addUnexpectedSuccess(self, test): + super(TAPTestResult, self).addUnexpectedSuccess(test) + self.message.write("Unexpected success" + "\n") + self.not_ok(test) + + +class TAPTestRunner(object): + def __init__( + self, + message_log=LogMode.LogToYAML, + test_output_log=LogMode.LogToDiagnostics, + output_stream=sys.stdout, + error_stream=sys.stderr, + ): + self.output_stream = output_stream + self.error_stream = error_stream + self.message_log = message_log + self.test_output_log = test_output_log + + def run(self, test): + result = TAPTestResult( + self.output_stream, + self.error_stream, + self.message_log, + self.test_output_log, + ) + test(result) + result.printErrors() + + return result diff --git a/gio/tests/task.c b/gio/tests/task.c index 0caed4403458df0070d52689b7ba597e37edf165..7ce8438ff1abb2bf94e42862911c6b7678909831 100644 --- a/gio/tests/task.c +++ b/gio/tests/task.c @@ -957,7 +957,7 @@ task_weak_notify (gpointer user_data, gboolean *weak_notify_ran = user_data; g_mutex_lock (&run_in_thread_mutex); - *weak_notify_ran = TRUE; + g_atomic_int_set (weak_notify_ran, TRUE); g_cond_signal (&run_in_thread_cond); g_mutex_unlock (&run_in_thread_mutex); } @@ -1007,7 +1007,7 @@ run_in_thread_thread (GTask *task, g_assert (g_thread_self () != main_thread); g_mutex_lock (&run_in_thread_mutex); - *thread_ran = TRUE; + g_atomic_int_set (thread_ran, TRUE); g_cond_signal (&run_in_thread_cond); g_mutex_unlock (&run_in_thread_mutex); @@ -1018,8 +1018,8 @@ static void test_run_in_thread (void) { GTask *task; - volatile gboolean thread_ran = FALSE; - volatile gboolean weak_notify_ran = FALSE; + gboolean thread_ran = FALSE; /* (atomic) */ + gboolean weak_notify_ran = FALSE; /* (atomic) */ gboolean notification_emitted = FALSE; gboolean done = FALSE; @@ -1033,12 +1033,12 @@ test_run_in_thread (void) g_task_run_in_thread (task, run_in_thread_thread); g_mutex_lock (&run_in_thread_mutex); - while (!thread_ran) + while (!g_atomic_int_get (&thread_ran)) g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex); g_mutex_unlock (&run_in_thread_mutex); g_assert (done == FALSE); - g_assert (weak_notify_ran == FALSE); + g_assert_false (g_atomic_int_get (&weak_notify_ran)); g_main_loop_run (loop); @@ -1050,7 +1050,7 @@ test_run_in_thread (void) g_object_unref (task); g_mutex_lock (&run_in_thread_mutex); - while (!weak_notify_ran) + while (!g_atomic_int_get (&weak_notify_ran)) g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex); g_mutex_unlock (&run_in_thread_mutex); } @@ -1081,7 +1081,7 @@ run_in_thread_sync_thread (GTask *task, g_assert (g_thread_self () != main_thread); - *thread_ran = TRUE; + g_atomic_int_set (thread_ran, TRUE); g_task_return_int (task, magic); } @@ -1102,7 +1102,7 @@ test_run_in_thread_sync (void) g_task_set_task_data (task, &thread_ran, NULL); g_task_run_in_thread_sync (task, run_in_thread_sync_thread); - g_assert (thread_ran == TRUE); + g_assert_true (g_atomic_int_get (&thread_ran)); g_assert (task != NULL); g_assert (!g_task_had_error (task)); g_assert_true (g_task_get_completed (task)); @@ -1487,8 +1487,8 @@ test_return_on_cancel (void) { GTask *task; GCancellable *cancellable; - volatile ThreadState thread_state; - volatile gboolean weak_notify_ran = FALSE; + ThreadState thread_state; /* (atomic) */ + gboolean weak_notify_ran = FALSE; /* (atomic) */ gboolean callback_ran; gboolean notification_emitted = FALSE; @@ -1498,7 +1498,7 @@ test_return_on_cancel (void) * early. */ callback_ran = FALSE; - thread_state = THREAD_STARTING; + g_atomic_int_set (&thread_state, THREAD_STARTING); task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran); g_signal_connect (task, "notify::completed", (GCallback) completed_cb, ¬ification_emitted); @@ -1509,18 +1509,18 @@ test_return_on_cancel (void) g_task_run_in_thread (task, return_on_cancel_thread); g_object_unref (task); - while (thread_state == THREAD_STARTING) + while (g_atomic_int_get (&thread_state) == THREAD_STARTING) g_cond_wait (&roc_init_cond, &roc_init_mutex); g_mutex_unlock (&roc_init_mutex); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); g_assert (callback_ran == FALSE); g_cancellable_cancel (cancellable); g_mutex_unlock (&roc_finish_mutex); g_main_loop_run (loop); - g_assert (thread_state == THREAD_COMPLETED); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_COMPLETED); g_assert (callback_ran == TRUE); g_assert_true (notification_emitted); @@ -1529,7 +1529,7 @@ test_return_on_cancel (void) /* If return-on-cancel is TRUE, it does return early */ callback_ran = FALSE; notification_emitted = FALSE; - thread_state = THREAD_STARTING; + g_atomic_int_set (&thread_state, THREAD_STARTING); task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran); g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran); g_signal_connect (task, "notify::completed", @@ -1542,27 +1542,27 @@ test_return_on_cancel (void) g_task_run_in_thread (task, return_on_cancel_thread); g_object_unref (task); - while (thread_state == THREAD_STARTING) + while (g_atomic_int_get (&thread_state) == THREAD_STARTING) g_cond_wait (&roc_init_cond, &roc_init_mutex); g_mutex_unlock (&roc_init_mutex); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); g_assert (callback_ran == FALSE); g_cancellable_cancel (cancellable); g_main_loop_run (loop); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); g_assert (callback_ran == TRUE); - g_assert (weak_notify_ran == FALSE); + g_assert_false (g_atomic_int_get (&weak_notify_ran)); - while (thread_state == THREAD_RUNNING) + while (g_atomic_int_get (&thread_state) == THREAD_RUNNING) g_cond_wait (&roc_finish_cond, &roc_finish_mutex); g_mutex_unlock (&roc_finish_mutex); - g_assert (thread_state == THREAD_CANCELLED); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED); g_mutex_lock (&run_in_thread_mutex); - while (!weak_notify_ran) + while (!g_atomic_int_get (&weak_notify_ran)) g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex); g_mutex_unlock (&run_in_thread_mutex); @@ -1574,7 +1574,7 @@ test_return_on_cancel (void) */ callback_ran = FALSE; notification_emitted = FALSE; - thread_state = THREAD_STARTING; + g_atomic_int_set (&thread_state, THREAD_STARTING); task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran); g_signal_connect (task, "notify::completed", (GCallback) completed_cb, ¬ification_emitted); @@ -1591,17 +1591,17 @@ test_return_on_cancel (void) g_main_loop_run (loop); g_assert (callback_ran == TRUE); - while (thread_state == THREAD_STARTING) + while (g_atomic_int_get (&thread_state) == THREAD_STARTING) g_cond_wait (&roc_init_cond, &roc_init_mutex); g_mutex_unlock (&roc_init_mutex); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); - while (thread_state == THREAD_RUNNING) + while (g_atomic_int_get (&thread_state) == THREAD_RUNNING) g_cond_wait (&roc_finish_cond, &roc_finish_mutex); g_mutex_unlock (&roc_finish_mutex); - g_assert (thread_state == THREAD_CANCELLED); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED); g_assert_true (notification_emitted); g_object_unref (cancellable); @@ -1621,7 +1621,7 @@ test_return_on_cancel_sync (void) { GTask *task; GCancellable *cancellable; - volatile ThreadState thread_state; + ThreadState thread_state; /* (atomic) */ GThread *runner_thread; gssize ret; GError *error = NULL; @@ -1630,7 +1630,7 @@ test_return_on_cancel_sync (void) /* If return-on-cancel is FALSE, the task does not return early. */ - thread_state = THREAD_STARTING; + g_atomic_int_set (&thread_state, THREAD_STARTING); task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL); g_task_set_task_data (task, (gpointer)&thread_state, NULL); @@ -1639,16 +1639,16 @@ test_return_on_cancel_sync (void) runner_thread = g_thread_new ("return-on-cancel-sync runner thread", cancel_sync_runner_thread, task); - while (thread_state == THREAD_STARTING) + while (g_atomic_int_get (&thread_state) == THREAD_STARTING) g_cond_wait (&roc_init_cond, &roc_init_mutex); g_mutex_unlock (&roc_init_mutex); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); g_cancellable_cancel (cancellable); g_mutex_unlock (&roc_finish_mutex); g_thread_join (runner_thread); - g_assert (thread_state == THREAD_COMPLETED); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_COMPLETED); ret = g_task_propagate_int (task, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); @@ -1660,7 +1660,7 @@ test_return_on_cancel_sync (void) g_cancellable_reset (cancellable); /* If return-on-cancel is TRUE, it does return early */ - thread_state = THREAD_STARTING; + g_atomic_int_set (&thread_state, THREAD_STARTING); task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL); g_task_set_return_on_cancel (task, TRUE); @@ -1670,15 +1670,15 @@ test_return_on_cancel_sync (void) runner_thread = g_thread_new ("return-on-cancel-sync runner thread", cancel_sync_runner_thread, task); - while (thread_state == THREAD_STARTING) + while (g_atomic_int_get (&thread_state) == THREAD_STARTING) g_cond_wait (&roc_init_cond, &roc_init_mutex); g_mutex_unlock (&roc_init_mutex); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); g_cancellable_cancel (cancellable); g_thread_join (runner_thread); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); ret = g_task_propagate_int (task, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); @@ -1687,18 +1687,18 @@ test_return_on_cancel_sync (void) g_object_unref (task); - while (thread_state == THREAD_RUNNING) + while (g_atomic_int_get (&thread_state) == THREAD_RUNNING) g_cond_wait (&roc_finish_cond, &roc_finish_mutex); g_mutex_unlock (&roc_finish_mutex); - g_assert (thread_state == THREAD_CANCELLED); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED); g_cancellable_reset (cancellable); /* If the task is already cancelled before it starts, it returns * immediately, but the thread func still runs. */ - thread_state = THREAD_STARTING; + g_atomic_int_set (&thread_state, THREAD_STARTING); task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL); g_task_set_return_on_cancel (task, TRUE); @@ -1711,7 +1711,7 @@ test_return_on_cancel_sync (void) cancel_sync_runner_thread, task); g_thread_join (runner_thread); - g_assert (thread_state == THREAD_STARTING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_STARTING); ret = g_task_propagate_int (task, &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); @@ -1720,17 +1720,17 @@ test_return_on_cancel_sync (void) g_object_unref (task); - while (thread_state == THREAD_STARTING) + while (g_atomic_int_get (&thread_state) == THREAD_STARTING) g_cond_wait (&roc_init_cond, &roc_init_mutex); g_mutex_unlock (&roc_init_mutex); - g_assert (thread_state == THREAD_RUNNING); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING); - while (thread_state == THREAD_RUNNING) + while (g_atomic_int_get (&thread_state) == THREAD_RUNNING) g_cond_wait (&roc_finish_cond, &roc_finish_mutex); g_mutex_unlock (&roc_finish_mutex); - g_assert (thread_state == THREAD_CANCELLED); + g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED); g_object_unref (cancellable); } @@ -1776,7 +1776,7 @@ return_on_cancel_atomic_thread (GTask *task, gpointer task_data, GCancellable *cancellable) { - gint *state = task_data; + gint *state = task_data; /* (atomic) */ g_assert (source_object == g_task_get_source_object (task)); g_assert (task_data == g_task_get_task_data (task)); @@ -1784,34 +1784,34 @@ return_on_cancel_atomic_thread (GTask *task, g_assert_false (g_task_get_completed (task)); g_assert (g_thread_self () != main_thread); - g_assert_cmpint (*state, ==, 0); + g_assert_cmpint (g_atomic_int_get (state), ==, 0); g_mutex_lock (&roca_mutex_1); - *state = 1; + g_atomic_int_set (state, 1); g_cond_signal (&roca_cond_1); g_mutex_unlock (&roca_mutex_1); g_mutex_lock (&roca_mutex_2); if (g_task_set_return_on_cancel (task, FALSE)) - *state = 2; + g_atomic_int_set (state, 2); else - *state = 3; + g_atomic_int_set (state, 3); g_cond_signal (&roca_cond_2); g_mutex_unlock (&roca_mutex_2); g_mutex_lock (&roca_mutex_1); if (g_task_set_return_on_cancel (task, TRUE)) - *state = 4; + g_atomic_int_set (state, 4); else - *state = 5; + g_atomic_int_set (state, 5); g_cond_signal (&roca_cond_1); g_mutex_unlock (&roca_mutex_1); g_mutex_lock (&roca_mutex_2); if (g_task_set_return_on_cancel (task, TRUE)) - *state = 6; + g_atomic_int_set (state, 6); else - *state = 7; + g_atomic_int_set (state, 7); g_cond_signal (&roca_cond_2); g_mutex_unlock (&roca_mutex_2); @@ -1823,7 +1823,7 @@ test_return_on_cancel_atomic (void) { GTask *task; GCancellable *cancellable; - volatile gint state; + gint state; /* (atomic) */ gboolean notification_emitted = FALSE; gboolean callback_ran; @@ -1832,7 +1832,7 @@ test_return_on_cancel_atomic (void) g_mutex_lock (&roca_mutex_2); /* If we don't cancel it, each set_return_on_cancel() call will succeed */ - state = 0; + g_atomic_int_set (&state, 0); callback_ran = FALSE; task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran); g_task_set_return_on_cancel (task, TRUE); @@ -1843,23 +1843,23 @@ test_return_on_cancel_atomic (void) g_task_run_in_thread (task, return_on_cancel_atomic_thread); g_object_unref (task); - g_assert_cmpint (state, ==, 0); + g_assert_cmpint (g_atomic_int_get (&state), ==, 0); - while (state == 0) + while (g_atomic_int_get (&state) == 0) g_cond_wait (&roca_cond_1, &roca_mutex_1); - g_assert (state == 1); + g_assert_cmpint (g_atomic_int_get (&state), ==, 1); - while (state == 1) + while (g_atomic_int_get (&state) == 1) g_cond_wait (&roca_cond_2, &roca_mutex_2); - g_assert (state == 2); + g_assert_cmpint (g_atomic_int_get (&state), ==, 2); - while (state == 2) + while (g_atomic_int_get (&state) == 2) g_cond_wait (&roca_cond_1, &roca_mutex_1); - g_assert (state == 4); + g_assert_cmpint (g_atomic_int_get (&state), ==, 4); - while (state == 4) + while (g_atomic_int_get (&state) == 4) g_cond_wait (&roca_cond_2, &roca_mutex_2); - g_assert (state == 6); + g_assert_cmpint (g_atomic_int_get (&state), ==, 6); /* callback assumes there'll be a cancelled error */ g_cancellable_cancel (cancellable); @@ -1876,7 +1876,7 @@ test_return_on_cancel_atomic (void) * task won't complete right away, and further * g_task_set_return_on_cancel() calls will return FALSE. */ - state = 0; + g_atomic_int_set (&state, 0); callback_ran = FALSE; notification_emitted = FALSE; task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran); @@ -1887,16 +1887,16 @@ test_return_on_cancel_atomic (void) g_task_set_task_data (task, (gpointer)&state, NULL); g_task_run_in_thread (task, return_on_cancel_atomic_thread); - g_assert_cmpint (state, ==, 0); + g_assert_cmpint (g_atomic_int_get (&state), ==, 0); - while (state == 0) + while (g_atomic_int_get (&state) == 0) g_cond_wait (&roca_cond_1, &roca_mutex_1); - g_assert (state == 1); + g_assert_cmpint (g_atomic_int_get (&state), ==, 1); g_assert (g_task_get_return_on_cancel (task)); - while (state == 1) + while (g_atomic_int_get (&state) == 1) g_cond_wait (&roca_cond_2, &roca_mutex_2); - g_assert (state == 2); + g_assert_cmpint (g_atomic_int_get (&state), ==, 2); g_assert (!g_task_get_return_on_cancel (task)); g_cancellable_cancel (cancellable); @@ -1904,18 +1904,18 @@ test_return_on_cancel_atomic (void) g_main_loop_run (loop); g_assert (callback_ran == FALSE); - while (state == 2) + while (g_atomic_int_get (&state) == 2) g_cond_wait (&roca_cond_1, &roca_mutex_1); - g_assert (state == 5); + g_assert_cmpint (g_atomic_int_get (&state), ==, 5); g_assert (!g_task_get_return_on_cancel (task)); g_main_loop_run (loop); g_assert (callback_ran == TRUE); g_assert_true (notification_emitted); - while (state == 5) + while (g_atomic_int_get (&state) == 5) g_cond_wait (&roca_cond_2, &roca_mutex_2); - g_assert (state == 7); + g_assert_cmpint (g_atomic_int_get (&state), ==, 7); g_object_unref (cancellable); g_mutex_unlock (&roca_mutex_1); @@ -2009,6 +2009,47 @@ test_return_pointer (void) g_assert_null (task); } +static void +test_return_value (void) +{ + GObject *object; + GValue value = G_VALUE_INIT; + GValue ret = G_VALUE_INIT; + GTask *task; + GError *error = NULL; + + object = (GObject *)g_dummy_object_new (); + g_assert_cmpint (object->ref_count, ==, 1); + g_object_add_weak_pointer (object, (gpointer *)&object); + + g_value_init (&value, G_TYPE_OBJECT); + g_value_set_object (&value, object); + g_assert_cmpint (object->ref_count, ==, 2); + + task = g_task_new (NULL, NULL, NULL, NULL); + g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task); + g_task_return_value (task, &value); + g_assert_cmpint (object->ref_count, ==, 3); + + g_assert_true (g_task_propagate_value (task, &ret, &error)); + g_assert_no_error (error); + g_assert_true (g_value_get_object (&ret) == object); + g_assert_cmpint (object->ref_count, ==, 3); + + g_object_unref (task); + g_assert_nonnull (task); + wait_for_completed_notification (task); + g_assert_null (task); + + g_assert_cmpint (object->ref_count, ==, 3); + g_value_unset (&ret); + g_assert_cmpint (object->ref_count, ==, 2); + g_value_unset (&value); + g_assert_cmpint (object->ref_count, ==, 1); + g_object_unref (object); + g_assert_null (object); +} + /* test_object_keepalive: GTask takes a ref on its source object */ static GObject *keepalive_object; @@ -2348,6 +2389,7 @@ main (int argc, char **argv) g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync); g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic); g_test_add_func ("/gtask/return-pointer", test_return_pointer); + g_test_add_func ("/gtask/return-value", test_return_value); g_test_add_func ("/gtask/object-keepalive", test_object_keepalive); g_test_add_func ("/gtask/legacy-error", test_legacy_error); g_test_add_func ("/gtask/return/in-idle/error-first", test_return_in_idle_error_first); diff --git a/gio/tests/test-codegen.xml b/gio/tests/test-codegen.xml index 39d8769c77967c4029a7ad14b8101894416afbd1..3090cad4a872dd804d81791d33e3f38e08101379 100644 --- a/gio/tests/test-codegen.xml +++ b/gio/tests/test-codegen.xml @@ -481,6 +481,15 @@ + + + + + + + + + diff --git a/gio/tests/test.gresource.xml b/gio/tests/test.gresource.xml index dd08aa0064029fba8b731630106ab697b8e1c234..62a31f4968797c6f2f2b66a617b8d0b3cd941f24 100644 --- a/gio/tests/test.gresource.xml +++ b/gio/tests/test.gresource.xml @@ -4,6 +4,7 @@ test-generated.txt test1.txt test.gresource.xml + empty.txt test2.txt diff --git a/gio/tests/test2.gresource.xml b/gio/tests/test2.gresource.xml index 0323b47ecb6c4c5e7ac5a0bdc768eccb8584bd95..b6dca2b81320099a208b63f2365b53e76caaecb9 100644 --- a/gio/tests/test2.gresource.xml +++ b/gio/tests/test2.gresource.xml @@ -4,7 +4,7 @@ test1.txt + that has a resource entry size over 65536 bytes --> gresource-big-test.txt diff --git a/gio/tests/testfilemonitor.c b/gio/tests/testfilemonitor.c index 6057958905767d705328a17450a7b6d3a387c7ba..44c70805b0467342d78d68b3a5e9c14321be7ecb 100644 --- a/gio/tests/testfilemonitor.c +++ b/gio/tests/testfilemonitor.c @@ -4,6 +4,8 @@ #include #include +#include "glib/glib-private.h" + /* These tests were written for the inotify implementation. * Other implementations may require slight adjustments in * the tests, e.g. the length of timeouts @@ -27,6 +29,8 @@ setup (Fixture *fixture, fixture->tmp_dir = g_file_new_for_path (path); g_test_message ("Using temporary directory: %s", path); + + g_free (path); } static void @@ -952,6 +956,11 @@ static void test_file_hard_links (Fixture *fixture, gconstpointer user_data) { +#ifdef _GLIB_ADDRESS_SANITIZER + g_test_incomplete ("FIXME: Leaks an inotify data structure, see glib#2311"); + (void) file_hard_links_output; + (void) file_hard_links_step; +#else GError *error = NULL; TestData data; @@ -1002,6 +1011,7 @@ test_file_hard_links (Fixture *fixture, g_object_unref (data.monitor); g_object_unref (data.file); g_object_unref (data.output_stream); +#endif } int diff --git a/gio/tests/thumbnail-verification.c b/gio/tests/thumbnail-verification.c index ef2ca70d7d162d8cc9f0354c7dffe7a3b8f7a0df..f439c8b069203ffb1f4fc25461c60dd75a4a0643 100644 --- a/gio/tests/thumbnail-verification.c +++ b/gio/tests/thumbnail-verification.c @@ -99,8 +99,17 @@ test_validity (void) thumbnail_path = g_test_get_filename (G_TEST_DIST, "thumbnails", tests[i].filename, NULL); file_uri = g_strconcat ("file:///tmp/", tests[i].filename, NULL); +#ifdef HAVE_STATX + stat_buf.stx_mtime.tv_sec = tests[i].mtime; + stat_buf.stx_size = tests[i].size; +#else +#ifdef G_OS_WIN32 + stat_buf.st_mtim.tv_sec = tests[i].mtime; +#else stat_buf.st_mtime = tests[i].mtime; +#endif stat_buf.st_size = tests[i].size; +#endif result = thumbnail_verify (thumbnail_path, file_uri, &stat_buf); diff --git a/gio/tests/tls-bindings.c b/gio/tests/tls-bindings.c new file mode 100644 index 0000000000000000000000000000000000000000..681b658c7cae74b50491d79782c87736ed728f9b --- /dev/null +++ b/gio/tests/tls-bindings.c @@ -0,0 +1,95 @@ +/* + * Copyright 2020 (C) Ruslan N. Marchenko + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "config.h" + +#include + +#include "gtesttlsbackend.h" + +static void +get_tls_channel_binding (void) +{ + GTlsBackend *backend; + gchar *not_null = "NOT_NULL"; + GTlsConnection *tls = NULL; + GError *error = NULL; + + backend = g_tls_backend_get_default (); + g_assert_nonnull (backend); + + /* check unimplemented GTlsConnection API sanity */ + tls = G_TLS_CONNECTION (g_object_new ( + g_tls_backend_get_client_connection_type (backend), NULL)); + g_assert_nonnull (tls); + + g_assert_false (g_tls_connection_get_channel_binding_data (tls, + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, NULL)); + + g_assert_false (g_tls_connection_get_channel_binding_data (tls, + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, &error)); + g_assert_error (error, G_TLS_CHANNEL_BINDING_ERROR, + G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED); + g_clear_error (&error); + + if (g_test_subprocess ()) + g_assert_false (g_tls_connection_get_channel_binding_data (tls, + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, (GError **)¬_null)); + + g_object_unref (tls); + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*GLib-GIO-CRITICAL*"); +} + +static void +get_dtls_channel_binding (void) +{ + GTlsBackend *backend; + gchar *not_null = "NOT_NULL"; + GDtlsConnection *dtls = NULL; + GError *error = NULL; + + backend = g_tls_backend_get_default (); + g_assert_nonnull (backend); + + /* repeat for the dtls now */ + dtls = G_DTLS_CONNECTION (g_object_new ( + g_tls_backend_get_dtls_client_connection_type (backend), NULL)); + g_assert_nonnull (dtls); + + g_assert_false (g_dtls_connection_get_channel_binding_data (dtls, + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, NULL)); + + g_assert_false (g_dtls_connection_get_channel_binding_data (dtls, + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, &error)); + g_assert_error (error, G_TLS_CHANNEL_BINDING_ERROR, + G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED); + g_clear_error (&error); + + if (g_test_subprocess ()) + g_assert_false (g_dtls_connection_get_channel_binding_data (dtls, + G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, (GError **)¬_null)); + + g_object_unref (dtls); + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*GLib-GIO-CRITICAL*"); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + _g_test_tls_backend_get_type (); + + g_test_add_func ("/tls-connection/get-tls-channel-binding", get_tls_channel_binding); + g_test_add_func ("/tls-connection/get-dtls-channel-binding", get_dtls_channel_binding); + + return g_test_run (); +} diff --git a/gio/tests/tls-certificate.c b/gio/tests/tls-certificate.c index e1ba23737b487e7e92702874b1ae53ca26662bf3..c0fc80c4ba0622b3ab082cdfc16a9d32ea2d2838 100644 --- a/gio/tests/tls-certificate.c +++ b/gio/tests/tls-certificate.c @@ -285,7 +285,7 @@ from_files (const Reference *ref) g_assert_null (cert); /* Using this method twice with a file containing both private key and - * certificate as a way to inforce private key presence is a fair use + * certificate as a way to enforce private key presence is a fair use */ cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL), g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL), @@ -398,6 +398,38 @@ list_from_file (const Reference *ref) g_assert_cmpint (g_list_length (list), ==, 0); } +static void +from_pkcs11_uri (void) +{ + GError *error = NULL; + GTlsCertificate *cert; + gchar *pkcs11_uri = NULL; + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + g_object_get (cert, "pkcs11-uri", &pkcs11_uri, NULL); + g_assert_cmpstr ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", ==, pkcs11_uri); + g_free (pkcs11_uri); + + g_object_unref (cert); +} + +static void +from_unsupported_pkcs11_uri (void) +{ + GError *error = NULL; + GTlsCertificate *cert; + + /* This is a magic value in gtesttlsbackend.c simulating an unsupported backend */ + cert = g_tls_certificate_new_from_pkcs11_uris ("unsupported", NULL, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_assert_null (cert); + + g_clear_error (&error); +} + int main (int argc, char *argv[]) @@ -464,6 +496,10 @@ main (int argc, &ref, (GTestDataFunc)from_files_pkcs8enc); g_test_add_data_func ("/tls-certificate/list_from_file", &ref, (GTestDataFunc)list_from_file); + g_test_add_func ("/tls-certificate/pkcs11-uri", + from_pkcs11_uri); + g_test_add_func ("/tls-certificate/pkcs11-uri-unsupported", + from_unsupported_pkcs11_uri); rtv = g_test_run(); diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c index 4f0737d7ef0610a979613764e92cab2e8384096e..5661e8e0d20ec92aa35bc13c700608da2804a282 100644 --- a/gio/tests/tls-interaction.c +++ b/gio/tests/tls-interaction.c @@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction, } +/* Return a copy of @str that is allocated in a silly way, to exercise + * custom free-functions. The returned pointer points to a copy of @str + * in a buffer of the form "BEFORE \0 str \0 AFTER". */ +static guchar * +special_dup (const char *str) +{ + GString *buf = g_string_new ("BEFORE"); + guchar *ret; + + g_string_append_c (buf, '\0'); + g_string_append (buf, str); + g_string_append_c (buf, '\0'); + g_string_append (buf, "AFTER"); + ret = (guchar *) g_string_free (buf, FALSE); + return ret + strlen ("BEFORE") + 1; +} + + +/* Free a copy of @str that was made with special_dup(), after asserting + * that it has not been corrupted. */ +static void +special_free (gpointer p) +{ + gchar *s = p; + gchar *buf = s - strlen ("BEFORE") - 1; + + g_assert_cmpstr (buf, ==, "BEFORE"); + g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER"); + g_free (buf); +} + + static GTlsInteractionResult test_interaction_ask_password_sync_success (GTlsInteraction *interaction, GTlsPassword *password, @@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, GError **error) { TestInteraction *self; + const guchar *value; + gsize len; g_assert (TEST_IS_INTERACTION (interaction)); self = TEST_INTERACTION (interaction); @@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, g_assert (error != NULL); g_assert (*error == NULL); + /* Exercise different ways to set the value */ + g_tls_password_set_value (password, (const guchar *) "foo", 4); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "foo", 4); + + g_tls_password_set_value (password, (const guchar *) "bar", -1); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "bar", 3); + + g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "baa", 4); + + g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "baz", 3); + /* Don't do this in real life. Include a null terminator for testing */ g_tls_password_set_value (password, (const guchar *)"the password", 13); return G_TLS_INTERACTION_HANDLED; diff --git a/gio/tests/trash.c b/gio/tests/trash.c index 4bf8fd0efe1a47f7963aff8c42845b2b25609365..adf729be219a77f992fc5610cb2b596aa7541740 100644 --- a/gio/tests/trash.c +++ b/gio/tests/trash.c @@ -211,4 +211,3 @@ main (int argc, char *argv[]) return g_test_run (); } - diff --git a/gio/tests/unix-streams.c b/gio/tests/unix-streams.c index 65eedb36812a749b41e04e901f762ab86d5db1f6..5ec829919a4139b393bd66dfea6a57dd50d6335f 100644 --- a/gio/tests/unix-streams.c +++ b/gio/tests/unix-streams.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,8 @@ #include #include -#define DATA "abcdefghijklmnopqrstuvwxyz" +/* sizeof(DATA) will give the number of bytes in the array, plus the terminating nul */ +static const gchar DATA[] = "abcdefghijklmnopqrstuvwxyz"; int writer_pipe[2], reader_pipe[2]; GCancellable *writer_cancel, *reader_cancel, *main_cancel; @@ -118,8 +120,8 @@ reader_thread (gpointer user_data) g_assert_not_reached (); } -char main_buf[sizeof (DATA)]; -gssize main_len, main_offset; +static char main_buf[sizeof (DATA)]; +static gssize main_len, main_offset; static void main_thread_read (GObject *source, GAsyncResult *res, gpointer user_data); static void main_thread_skipped (GObject *source, GAsyncResult *res, gpointer user_data); diff --git a/gio/tests/volumemonitor.c b/gio/tests/volumemonitor.c index 6b61c307033b1dada2929dd22e0c955d1cfc2a7f..e902eabf6c91321316d6069df1bf871e14d3fd34 100644 --- a/gio/tests/volumemonitor.c +++ b/gio/tests/volumemonitor.c @@ -178,4 +178,3 @@ main (int argc, char *argv[]) return ret; } - diff --git a/gio/tests/win32-appinfo.c b/gio/tests/win32-appinfo.c new file mode 100644 index 0000000000000000000000000000000000000000..fa8aa2aafbc1169ba64cfb09fdf366aa75213443 --- /dev/null +++ b/gio/tests/win32-appinfo.c @@ -0,0 +1,469 @@ +/* GLib testing framework examples and tests + * Copyright (C) 2019 Руслан Ижбулатов + * + * This work is provided "as is"; redistribution and modification + * in whole or in part, in any medium, physical or electronic is + * permitted without restriction. + * + * This work 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. + * + * In no event shall the authors or contributors be liable for any + * direct, indirect, incidental, special, exemplary, or consequential + * damages (including, but not limited to, procurement of substitute + * goods or services; loss of use, data, or profits; or business + * interruption) however caused and on any theory of liability, whether + * in contract, strict liability, or tort (including negligence or + * otherwise) arising in any way out of the use of this software, even + * if advised of the possibility of such damage. + */ + +#include +#include +#include + +#include "../giowin32-private.c" + +static int +g_utf16_cmp0 (const gunichar2 *str1, + const gunichar2 *str2) +{ + if (!str1) + return -(str1 != str2); + if (!str2) + return str1 != str2; + + while (TRUE) + { + if (str1[0] > str2[0]) + return 1; + else if (str1[0] < str2[0]) + return -1; + else if (str1[0] == 0 && str2[0] == 0) + return 0; + + str1++; + str2++; + } +} + +#define g_assert_cmputf16(s1, cmp, s2, s1u8, s2u8) \ +G_STMT_START { \ + const gunichar2 *__s1 = (s1), *__s2 = (s2); \ + if (g_utf16_cmp0 (__s1, __s2) cmp 0) ; else \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #s1u8 " " #cmp " " #s2u8, s1u8, #cmp, s2u8); \ +} G_STMT_END + +static void +test_utf16_strfuncs (void) +{ + gsize i; + + struct { + gsize len; + const gunichar2 utf16[10]; + const gchar *utf8; + const gchar *utf8_folded; + } string_cases[] = { + { + 0, + { 0x0000 }, + "", + "", + }, + { + 1, + { 0x0020, 0x0000 }, + " ", + " ", + }, + { + 2, + { 0x0020, 0xd800, 0x0000 }, + NULL, + NULL, + }, + }; + + for (i = 0; i < G_N_ELEMENTS (string_cases); i++) + { + gsize len; + gunichar2 *str; + gboolean success; + gchar *utf8; + gchar *utf8_folded; + + len = g_utf16_len (string_cases[i].utf16); + g_assert_cmpuint (len, ==, string_cases[i].len); + + str = (gunichar2 *) g_utf16_find_basename (string_cases[i].utf16, -1); + /* This only works because all testcases lack separators */ + g_assert_true (string_cases[i].utf16 == str); + + str = g_wcsdup (string_cases[i].utf16, string_cases[i].len); + g_assert_cmpmem (string_cases[i].utf16, len, str, len); + g_free (str); + + str = g_wcsdup (string_cases[i].utf16, -1); + g_assert_cmpmem (string_cases[i].utf16, len, str, len); + g_free (str); + + success = g_utf16_to_utf8_and_fold (string_cases[i].utf16, -1, NULL, NULL); + + if (string_cases[i].utf8 == NULL) + g_assert_false (success); + else + g_assert_true (success); + + utf8 = NULL; + success = g_utf16_to_utf8_and_fold (string_cases[i].utf16, -1, &utf8, NULL); + + if (string_cases[i].utf8 != NULL) + { + g_assert_true (success); + g_assert_cmpstr (string_cases[i].utf8, ==, utf8); + /* This only works because all testcases lack separators */ + g_assert_true (utf8 == g_utf8_find_basename (utf8, len)); + } + + g_free (utf8); + + utf8 = NULL; + utf8_folded = NULL; + success = g_utf16_to_utf8_and_fold (string_cases[i].utf16, -1, &utf8, &utf8_folded); + + if (string_cases[i].utf8 != NULL) + { + g_assert_true (success); + g_assert_cmpstr (string_cases[i].utf8_folded, ==, utf8_folded); + } + + g_free (utf8); + g_free (utf8_folded); + } +} + +struct { + const char *orig; + const char *executable; + const char *executable_basename; + gboolean is_rundll32; + const char *fixed; +} rundll32_commandlines[] = { + { + "%SystemRoot%\\System32\\rundll32.exe \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\", ImageView_Fullscreen %1", + "%SystemRoot%\\System32\\rundll32.exe", + "rundll32.exe", + TRUE, + "%SystemRoot%\\System32\\rundll32.exe \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\" ImageView_Fullscreen %1", + }, + { + "%SystemRoot%/System32/rundll32.exe \"%ProgramFiles%/Windows Photo Viewer/PhotoViewer.dll\", ImageView_Fullscreen %1", + "%SystemRoot%/System32/rundll32.exe", + "rundll32.exe", + TRUE, + "%SystemRoot%/System32/rundll32.exe \"%ProgramFiles%/Windows Photo Viewer/PhotoViewer.dll\" ImageView_Fullscreen %1", + }, + { + "%SystemRoot%\\System32/rundll32.exe \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\", ImageView_Fullscreen %1", + "%SystemRoot%\\System32/rundll32.exe", + "rundll32.exe", + TRUE, + "%SystemRoot%\\System32/rundll32.exe \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\" ImageView_Fullscreen %1", + }, + { + "\"some path with spaces\\rundll32.exe\" \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\", ImageView_Fullscreen %1", + "some path with spaces\\rundll32.exe", + "rundll32.exe", + TRUE, + "\"some path with spaces\\rundll32.exe\" \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\" ImageView_Fullscreen %1", + }, + { + " \"some path with spaces\\rundll32.exe\"\"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\",ImageView_Fullscreen %1", + "some path with spaces\\rundll32.exe", + "rundll32.exe", + TRUE, + " \"some path with spaces\\rundll32.exe\"\"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\" ImageView_Fullscreen %1", + }, + { + "rundll32.exe foo.bar,baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "rundll32.exe foo.bar baz", + }, + { + " rundll32.exe foo.bar,baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + " rundll32.exe foo.bar baz", + }, + { + "rundll32.exe", + "rundll32.exe", + "rundll32.exe", + FALSE, + NULL, + }, + { + "rundll32.exe ,foobar", + "rundll32.exe", + "rundll32.exe", + FALSE, + NULL, + }, + { + "rundll32.exe ,foobar", + "rundll32.exe", + "rundll32.exe", + FALSE, + NULL, + }, + { + "rundll32.exe foo.dll", + "rundll32.exe", + "rundll32.exe", + FALSE, + NULL, + }, + { + "rundll32.exe \"foo bar\",baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "rundll32.exe \"foo bar\" baz", + }, + { + "\"rundll32.exe\" \"foo bar\",baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" \"foo bar\" baz", + }, + { + "\"rundll32.exe\" \"foo bar\",, , ,,, , ,,baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" \"foo bar\" , , ,,, , ,,baz", + }, + { + "\"rundll32.exe\" foo.bar,,,,,,,,,baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" foo.bar ,,,,,,,,baz", + }, + { + "\"rundll32.exe\" foo.bar baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" foo.bar baz", + }, + { + "\"RuNdlL32.exe\" foo.bar baz", + "RuNdlL32.exe", + "RuNdlL32.exe", + TRUE, + "\"RuNdlL32.exe\" foo.bar baz", + }, + { + "%SystemRoot%\\System32\\rundll32.exe \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll,\" ImageView_Fullscreen %1", + "%SystemRoot%\\System32\\rundll32.exe", + "rundll32.exe", + TRUE, + "%SystemRoot%\\System32\\rundll32.exe \"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll,\" ImageView_Fullscreen %1", + }, + { + "\"rundll32.exe\" \"foo bar,\"baz", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" \"foo bar,\"baz", + }, + { + "\"rundll32.exe\" some,thing", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" some thing", + }, + { + "\"rundll32.exe\" some,", + "rundll32.exe", + "rundll32.exe", + FALSE, + "\"rundll32.exe\" some,", + }, + /* These filenames are not allowed on Windows, but our function doesn't care about that */ + { + "run\"dll32.exe foo\".bar,baz", + "run\"dll32.exe", + "run\"dll32.exe", + FALSE, + NULL, + }, + { + "run,dll32.exe foo.bar,baz", + "run,dll32.exe", + "run,dll32.exe", + FALSE, + NULL, + }, + { + "\"rundll32.exe\" some, thing", + "rundll32.exe", + "rundll32.exe", + TRUE, + "\"rundll32.exe\" some thing", + }, + /* Commands with "rundll32" (without the .exe suffix) do exist, + * but GLib currently does not recognize them, so there's no point + * in testing these. + */ +}; + +static void +test_win32_rundll32_fixup (void) +{ + gsize i; + + for (i = 0; i < G_N_ELEMENTS (rundll32_commandlines); i++) + { + gunichar2 *argument; + gunichar2 *expected; + + if (!rundll32_commandlines[i].is_rundll32) + continue; + + argument = g_utf8_to_utf16 (rundll32_commandlines[i].orig, -1, NULL, NULL, NULL); + expected = g_utf8_to_utf16 (rundll32_commandlines[i].fixed, -1, NULL, NULL, NULL); + + g_assert_nonnull (argument); + g_assert_nonnull (expected); + _g_win32_fixup_broken_microsoft_rundll_commandline (argument); + + g_assert_cmputf16 (argument, ==, expected, rundll32_commandlines[i].orig, rundll32_commandlines[i].fixed); + + g_free (argument); + g_free (expected); + } +} + +static void +test_win32_extract_executable (void) +{ + gsize i; + + for (i = 0; i < G_N_ELEMENTS (rundll32_commandlines); i++) + { + gunichar2 *argument; + gchar *dll_function; + gchar *executable; + gchar *executable_basename; + gchar *executable_folded; + gchar *executable_folded_basename; + + argument = g_utf8_to_utf16 (rundll32_commandlines[i].orig, -1, NULL, NULL, NULL); + + _g_win32_extract_executable (argument, NULL, NULL, NULL, NULL, &dll_function); + + if (rundll32_commandlines[i].is_rundll32) + g_assert_nonnull (dll_function); + else + g_assert_null (dll_function); + + g_free (dll_function); + + executable = NULL; + executable_basename = NULL; + executable_folded = NULL; + executable_folded_basename = NULL; + _g_win32_extract_executable (argument, &executable, &executable_basename, &executable_folded, &executable_folded_basename, NULL); + + g_assert_cmpstr (rundll32_commandlines[i].executable, ==, executable); + g_assert_cmpstr (rundll32_commandlines[i].executable_basename, ==, executable_basename); + g_assert_nonnull (executable_folded); + + g_free (executable); + g_free (executable_folded); + + /* Check the corner-case where we don't want to know where basename is */ + executable = NULL; + executable_folded = NULL; + _g_win32_extract_executable (argument, &executable, NULL, &executable_folded, NULL, NULL); + + g_assert_cmpstr (rundll32_commandlines[i].executable, ==, executable); + g_assert_nonnull (executable_folded); + + g_free (executable); + g_free (executable_folded); + + g_free (argument); + } +} + +static void +test_win32_parse_filename (void) +{ + gsize i; + + for (i = 0; i < G_N_ELEMENTS (rundll32_commandlines); i++) + { + gunichar2 *argument; + argument = g_utf8_to_utf16 (rundll32_commandlines[i].orig, -1, NULL, NULL, NULL); + /* Just checking that it doesn't blow up on various (sometimes incorrect) strings */ + _g_win32_parse_filename (argument, FALSE, NULL, NULL, NULL, NULL); + g_free (argument); + } +} + +static void +do_fail_on_broken_utf16_1 (void) +{ + const gunichar2 utf16[] = { 0xd800, 0x0000 }; + _g_win32_extract_executable (utf16, NULL, NULL, NULL, NULL, NULL); +} + +static void +do_fail_on_broken_utf16_2 (void) +{ + /* "rundll32.exe r" */ + gchar *dll_function; + const gunichar2 utf16[] = { 0x0072, 0x0075, 0x006E, 0x0064, 0x006C, 0x006C, 0x0033, 0x0032, + 0x002E, 0x0065, 0x0078, 0x0065, 0x0020, 0xd800, 0x0020, 0x0072, 0x0000 }; + _g_win32_extract_executable (utf16, NULL, NULL, NULL, NULL, &dll_function); +} + +static void +test_fail_on_broken_utf16 (void) +{ + g_test_trap_subprocess ("/appinfo/subprocess/win32-assert-broken-utf16_1", 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*GLib-GIO:ERROR:*giowin32-private.c:*:_g_win32_extract_executable: assertion failed: (folded)*"); + g_test_trap_subprocess ("/appinfo/subprocess/win32-assert-broken-utf16_2", 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*GLib-GIO:ERROR:*giowin32-private.c:*:_g_win32_extract_executable: assertion failed: (folded)*"); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/appinfo/utf16-strfuncs", test_utf16_strfuncs); + g_test_add_func ("/appinfo/win32-extract-executable", test_win32_extract_executable); + g_test_add_func ("/appinfo/win32-rundll32-fixup", test_win32_rundll32_fixup); + g_test_add_func ("/appinfo/win32-parse-filename", test_win32_parse_filename); + g_test_add_func ("/appinfo/win32-utf16-conversion-fail", test_fail_on_broken_utf16); + + g_test_add_func ("/appinfo/subprocess/win32-assert-broken-utf16_1", do_fail_on_broken_utf16_1); + g_test_add_func ("/appinfo/subprocess/win32-assert-broken-utf16_2", do_fail_on_broken_utf16_2); + + return g_test_run (); +} diff --git a/gio/tests/x-content/unix-software/autorun.sh b/gio/tests/x-content/unix-software/autorun.sh index 6dfc559449597d70fa3cd1a3ff566d550d984a27..ef09a62a6d882285017c06a5b423db195f8992e6 100644 --- a/gio/tests/x-content/unix-software/autorun.sh +++ b/gio/tests/x-content/unix-software/autorun.sh @@ -1,3 +1,3 @@ #! /bin/sh -do something here +# do something here diff --git a/gio/tests/x-content/win32-software/autorun.exe b/gio/tests/x-content/win32-software/autorun.exe new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/gio/thumbnail-verify.c b/gio/thumbnail-verify.c index 1a722e40c8cf79269854f799eeb9be24cf1c0096..316e8a61fbf7bfc1836ba885617aea288245cf77 100644 --- a/gio/thumbnail-verify.c +++ b/gio/thumbnail-verify.c @@ -232,8 +232,12 @@ thumbnail_verify (const char *thumbnail_path, return FALSE; expected_info.uri = file_uri; - expected_info.mtime = (guint64) file_stat_buf->st_mtime; - expected_info.size = file_stat_buf->st_size; +#ifdef G_OS_WIN32 + expected_info.mtime = (guint64) file_stat_buf->st_mtim.tv_sec; +#else + expected_info.mtime = _g_stat_mtime (file_stat_buf); +#endif + expected_info.size = _g_stat_size (file_stat_buf); file = g_mapped_file_new (thumbnail_path, FALSE, NULL); if (file) diff --git a/gio/win32/gwin32fsmonitorutils.c b/gio/win32/gwin32fsmonitorutils.c index ff8d1710cc63e30feed194b4903ffbc2bd9cda18..b47124634fa5395bd2dc8ef6b8b2fe0f68cf342f 100644 --- a/gio/win32/gwin32fsmonitorutils.c +++ b/gio/win32/gwin32fsmonitorutils.c @@ -345,7 +345,7 @@ g_win32_fs_monitor_init (GWin32FSMonitorPrivate *monitor, monitor->file_attribs = INVALID_FILE_ATTRIBUTES; monitor->pfni_prev = NULL; monitor->hDirectory = CreateFileW (wdirname_with_long_prefix != NULL ? wdirname_with_long_prefix : monitor->wfullpath_with_long_prefix, - FILE_GENERIC_READ | FILE_GENERIC_WRITE, + FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, @@ -416,7 +416,7 @@ g_win32_fs_monitor_close_handle (GWin32FSMonitorPrivate *monitor) /* This triggers a last callback() with nBytes==0. */ /* Actually I am not so sure about that, it seems to trigger a last - * callback allright, but the way to recognize that it is the final + * callback correctly, but the way to recognize that it is the final * one is not to check for nBytes==0, I think that was a * misunderstanding. */ diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c index 1601ec88dc995b1ea174d03fabeacefc054c5844..5b8dcfe0b2d615a266d0a825ce1de8143f387346 100644 --- a/gio/win32/gwinhttpfile.c +++ b/gio/win32/gwinhttpfile.c @@ -29,6 +29,7 @@ #include "gio/gfile.h" #include "gio/gfileattribute.h" #include "gio/gfileinfo.h" +#include "gio/gfileinfo-priv.h" #include "gwinhttpfile.h" #include "gwinhttpfileinputstream.h" #include "gwinhttpfileoutputstream.h" @@ -177,6 +178,21 @@ g_winhttp_file_get_basename (GFile *file) return retval; } +static char * +g_winhttp_file_get_display_name (GFile *file) +{ + char *basename; + + /* FIXME: This could be improved by using a new g_utf16_make_valid() function + * to recover what we can from the URI, and then suffixing it with + * “ (invalid encoding)” as per g_filename_display_basename(). */ + basename = g_winhttp_file_get_basename (file); + if (!basename) + return g_strdup (_(" (invalid encoding)")); + + return g_steal_pointer (&basename); +} + static char * g_winhttp_file_get_path (GFile *file) { @@ -393,10 +409,10 @@ g_winhttp_file_resolve_relative_path (GFile *file, child = g_object_new (G_TYPE_WINHTTP_FILE, NULL); child->vfs = winhttp_file->vfs; child->url = winhttp_file->url; - child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); - child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); - child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); - child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); + child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2); + child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2); + child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2); + child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2); child->url.lpszUrlPath = wnew_path; child->url.dwUrlPathLength = wcslen (wnew_path); child->url.lpszExtraInfo = NULL; @@ -513,6 +529,14 @@ g_winhttp_file_query_info (GFile *file, g_file_info_set_name (info, basename); g_free (basename); + if (_g_file_attribute_matcher_matches_id (matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_DISPLAY_NAME)) + { + char *display_name = g_winhttp_file_get_display_name (file); + g_file_info_set_display_name (info, display_name); + g_free (display_name); + } + content_length = NULL; if (_g_winhttp_query_header (winhttp_file->vfs, request, diff --git a/gio/win32/gwinhttpvfs.c b/gio/win32/gwinhttpvfs.c index 3dfac259efdf8ef8909f774f99ebfb8e4dc39d0f..03feaf983d40f0b6c5b4278ee1e09e2131abd00e 100644 --- a/gio/win32/gwinhttpvfs.c +++ b/gio/win32/gwinhttpvfs.c @@ -39,20 +39,20 @@ static void lookup_funcs (void) { HMODULE winhttp = NULL; - char winhttp_dll[MAX_PATH + 100]; + WCHAR winhttp_dll[MAX_PATH + 100]; int n; if (lookup_done) return; - n = GetSystemDirectory (winhttp_dll, MAX_PATH); + n = GetSystemDirectoryW (winhttp_dll, MAX_PATH); if (n > 0 && n < MAX_PATH) { - if (winhttp_dll[n-1] != '\\' && - winhttp_dll[n-1] != '/') - strcat (winhttp_dll, "\\"); - strcat (winhttp_dll, "winhttp.dll"); - winhttp = LoadLibrary (winhttp_dll); + if (winhttp_dll[n-1] != L'\\' && + winhttp_dll[n-1] != L'/') + wcscat (winhttp_dll, L"\\"); + wcscat (winhttp_dll, L"winhttp.dll"); + winhttp = LoadLibraryW (winhttp_dll); } if (winhttp != NULL) diff --git a/gio/xdgmime/xdgmimeicon.c b/gio/xdgmime/xdgmimeicon.c index 272b062687cf12087f98e20c385b62092cbbca56..a2f4dd2a7d8e14222d594826c4f5497cc974c7e2 100644 --- a/gio/xdgmime/xdgmimeicon.c +++ b/gio/xdgmime/xdgmimeicon.c @@ -178,4 +178,3 @@ _xdg_mime_icon_list_dump (XdgIconList *list) } #endif - diff --git a/gio/xdgmime/xdgmimeparent.c b/gio/xdgmime/xdgmimeparent.c index e87bf55133e9dab3b2f2646f7df8a41219dff0ef..b06b749d432742ce28153fca21837809492d013b 100644 --- a/gio/xdgmime/xdgmimeparent.c +++ b/gio/xdgmime/xdgmimeparent.c @@ -215,4 +215,3 @@ _xdg_mime_parent_list_dump (XdgParentList *list) } #endif - diff --git a/gio/xdp-dbus.c b/gio/xdp-dbus.c index 21e14a3458bebfe2843c10d3b7e7e9bed1116ca9..1372db77bf1024ddf1ecdeddd8eb07c004a5184a 100644 --- a/gio/xdp-dbus.c +++ b/gio/xdp-dbus.c @@ -1,7035 +1,7909 @@ -/* - * Generated by gdbus-codegen 2.62.5 from org.freedesktop.portal.Documents.xml, org.freedesktop.portal.OpenURI.xml, org.freedesktop.portal.ProxyResolver.xml, org.freedesktop.portal.Trash.xml. DO NOT EDIT. - * - * The license of this code is the same as for the D-Bus interface description - * it was derived from. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "xdp-dbus.h" - -#include -#ifdef G_OS_UNIX -# include -#endif - -typedef struct -{ - GDBusArgInfo parent_struct; - gboolean use_gvariant; -} _ExtendedGDBusArgInfo; - -typedef struct -{ - GDBusMethodInfo parent_struct; - const gchar *signal_name; - gboolean pass_fdlist; -} _ExtendedGDBusMethodInfo; - -typedef struct -{ - GDBusSignalInfo parent_struct; - const gchar *signal_name; -} _ExtendedGDBusSignalInfo; - -typedef struct -{ - GDBusPropertyInfo parent_struct; - const gchar *hyphen_name; - guint use_gvariant : 1; - guint emits_changed_signal : 1; -} _ExtendedGDBusPropertyInfo; - -typedef struct -{ - GDBusInterfaceInfo parent_struct; - const gchar *hyphen_name; -} _ExtendedGDBusInterfaceInfo; - -typedef struct -{ - const _ExtendedGDBusPropertyInfo *info; - guint prop_id; - GValue orig_value; /* the value before the change */ -} ChangedProperty; - -static void -_changed_property_free (ChangedProperty *data) -{ - g_value_unset (&data->orig_value); - g_free (data); -} - -static gboolean -_g_strv_equal0 (gchar **a, gchar **b) -{ - gboolean ret = FALSE; - guint n; - if (a == NULL && b == NULL) - { - ret = TRUE; - goto out; - } - if (a == NULL || b == NULL) - goto out; - if (g_strv_length (a) != g_strv_length (b)) - goto out; - for (n = 0; a[n] != NULL; n++) - if (g_strcmp0 (a[n], b[n]) != 0) - goto out; - ret = TRUE; -out: - return ret; -} - -static gboolean -_g_variant_equal0 (GVariant *a, GVariant *b) -{ - gboolean ret = FALSE; - if (a == NULL && b == NULL) - { - ret = TRUE; - goto out; - } - if (a == NULL || b == NULL) - goto out; - ret = g_variant_equal (a, b); -out: - return ret; -} - -G_GNUC_UNUSED static gboolean -_g_value_equal (const GValue *a, const GValue *b) -{ - gboolean ret = FALSE; - g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b)); - switch (G_VALUE_TYPE (a)) - { - case G_TYPE_BOOLEAN: - ret = (g_value_get_boolean (a) == g_value_get_boolean (b)); - break; - case G_TYPE_UCHAR: - ret = (g_value_get_uchar (a) == g_value_get_uchar (b)); - break; - case G_TYPE_INT: - ret = (g_value_get_int (a) == g_value_get_int (b)); - break; - case G_TYPE_UINT: - ret = (g_value_get_uint (a) == g_value_get_uint (b)); - break; - case G_TYPE_INT64: - ret = (g_value_get_int64 (a) == g_value_get_int64 (b)); - break; - case G_TYPE_UINT64: - ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b)); - break; - case G_TYPE_DOUBLE: - { - /* Avoid -Wfloat-equal warnings by doing a direct bit compare */ - gdouble da = g_value_get_double (a); - gdouble db = g_value_get_double (b); - ret = memcmp (&da, &db, sizeof (gdouble)) == 0; - } - break; - case G_TYPE_STRING: - ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0); - break; - case G_TYPE_VARIANT: - ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b)); - break; - default: - if (G_VALUE_TYPE (a) == G_TYPE_STRV) - ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b)); - else - g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a))); - break; - } - return ret; -} - -/* ------------------------------------------------------------------------ - * Code for interface org.freedesktop.portal.Documents - * ------------------------------------------------------------------------ - */ - -/** - * SECTION:GXdpDocuments - * @title: GXdpDocuments - * @short_description: Generated C code for the org.freedesktop.portal.Documents D-Bus interface - * - * This section contains code for working with the org.freedesktop.portal.Documents D-Bus interface in C. - */ - -/* ---- Introspection data for org.freedesktop.portal.Documents ---- */ - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_get_mount_point_OUT_ARG_path = -{ - { - -1, - (gchar *) "path", - (gchar *) "ay", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_get_mount_point_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_get_mount_point_OUT_ARG_path.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_get_mount_point = -{ - { - -1, - (gchar *) "GetMountPoint", - NULL, - (GDBusArgInfo **) &_gxdp_documents_method_info_get_mount_point_OUT_ARG_pointers, - NULL - }, - "handle-get-mount-point", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_IN_ARG_o_path_fd = -{ - { - -1, - (gchar *) "o_path_fd", - (gchar *) "h", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_IN_ARG_reuse_existing = -{ - { - -1, - (gchar *) "reuse_existing", - (gchar *) "b", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_IN_ARG_persistent = -{ - { - -1, - (gchar *) "persistent", - (gchar *) "b", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_add_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_add_IN_ARG_o_path_fd.parent_struct, - &_gxdp_documents_method_info_add_IN_ARG_reuse_existing.parent_struct, - &_gxdp_documents_method_info_add_IN_ARG_persistent.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_OUT_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_add_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_add_OUT_ARG_doc_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add = -{ - { - -1, - (gchar *) "Add", - (GDBusArgInfo **) &_gxdp_documents_method_info_add_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_documents_method_info_add_OUT_ARG_pointers, - NULL - }, - "handle-add", - TRUE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_o_path_parent_fd = -{ - { - -1, - (gchar *) "o_path_parent_fd", - (gchar *) "h", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_filename = -{ - { - -1, - (gchar *) "filename", - (gchar *) "ay", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_reuse_existing = -{ - { - -1, - (gchar *) "reuse_existing", - (gchar *) "b", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_persistent = -{ - { - -1, - (gchar *) "persistent", - (gchar *) "b", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_add_named_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_add_named_IN_ARG_o_path_parent_fd.parent_struct, - &_gxdp_documents_method_info_add_named_IN_ARG_filename.parent_struct, - &_gxdp_documents_method_info_add_named_IN_ARG_reuse_existing.parent_struct, - &_gxdp_documents_method_info_add_named_IN_ARG_persistent.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_OUT_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_add_named_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_add_named_OUT_ARG_doc_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add_named = -{ - { - -1, - (gchar *) "AddNamed", - (GDBusArgInfo **) &_gxdp_documents_method_info_add_named_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_documents_method_info_add_named_OUT_ARG_pointers, - NULL - }, - "handle-add-named", - TRUE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_o_path_fds = -{ - { - -1, - (gchar *) "o_path_fds", - (gchar *) "ah", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_flags = -{ - { - -1, - (gchar *) "flags", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_app_id = -{ - { - -1, - (gchar *) "app_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_permissions = -{ - { - -1, - (gchar *) "permissions", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_add_full_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_add_full_IN_ARG_o_path_fds.parent_struct, - &_gxdp_documents_method_info_add_full_IN_ARG_flags.parent_struct, - &_gxdp_documents_method_info_add_full_IN_ARG_app_id.parent_struct, - &_gxdp_documents_method_info_add_full_IN_ARG_permissions.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_OUT_ARG_doc_ids = -{ - { - -1, - (gchar *) "doc_ids", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_OUT_ARG_extra_out = -{ - { - -1, - (gchar *) "extra_out", - (gchar *) "a{sv}", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_add_full_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_add_full_OUT_ARG_doc_ids.parent_struct, - &_gxdp_documents_method_info_add_full_OUT_ARG_extra_out.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add_full = -{ - { - -1, - (gchar *) "AddFull", - (GDBusArgInfo **) &_gxdp_documents_method_info_add_full_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_documents_method_info_add_full_OUT_ARG_pointers, - NULL - }, - "handle-add-full", - TRUE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_grant_permissions_IN_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_grant_permissions_IN_ARG_app_id = -{ - { - -1, - (gchar *) "app_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_grant_permissions_IN_ARG_permissions = -{ - { - -1, - (gchar *) "permissions", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_grant_permissions_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_grant_permissions_IN_ARG_doc_id.parent_struct, - &_gxdp_documents_method_info_grant_permissions_IN_ARG_app_id.parent_struct, - &_gxdp_documents_method_info_grant_permissions_IN_ARG_permissions.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_grant_permissions = -{ - { - -1, - (gchar *) "GrantPermissions", - (GDBusArgInfo **) &_gxdp_documents_method_info_grant_permissions_IN_ARG_pointers, - NULL, - NULL - }, - "handle-grant-permissions", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_revoke_permissions_IN_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_revoke_permissions_IN_ARG_app_id = -{ - { - -1, - (gchar *) "app_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_revoke_permissions_IN_ARG_permissions = -{ - { - -1, - (gchar *) "permissions", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_revoke_permissions_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_revoke_permissions_IN_ARG_doc_id.parent_struct, - &_gxdp_documents_method_info_revoke_permissions_IN_ARG_app_id.parent_struct, - &_gxdp_documents_method_info_revoke_permissions_IN_ARG_permissions.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_revoke_permissions = -{ - { - -1, - (gchar *) "RevokePermissions", - (GDBusArgInfo **) &_gxdp_documents_method_info_revoke_permissions_IN_ARG_pointers, - NULL, - NULL - }, - "handle-revoke-permissions", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_delete_IN_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_delete_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_delete_IN_ARG_doc_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_delete = -{ - { - -1, - (gchar *) "Delete", - (GDBusArgInfo **) &_gxdp_documents_method_info_delete_IN_ARG_pointers, - NULL, - NULL - }, - "handle-delete", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_lookup_IN_ARG_filename = -{ - { - -1, - (gchar *) "filename", - (gchar *) "ay", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_lookup_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_lookup_IN_ARG_filename.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_lookup_OUT_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_lookup_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_lookup_OUT_ARG_doc_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_lookup = -{ - { - -1, - (gchar *) "Lookup", - (GDBusArgInfo **) &_gxdp_documents_method_info_lookup_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_documents_method_info_lookup_OUT_ARG_pointers, - NULL - }, - "handle-lookup", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_info_IN_ARG_doc_id = -{ - { - -1, - (gchar *) "doc_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_info_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_info_IN_ARG_doc_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_info_OUT_ARG_path = -{ - { - -1, - (gchar *) "path", - (gchar *) "ay", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_info_OUT_ARG_apps = -{ - { - -1, - (gchar *) "apps", - (gchar *) "a{sas}", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_info_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_info_OUT_ARG_path.parent_struct, - &_gxdp_documents_method_info_info_OUT_ARG_apps.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_info = -{ - { - -1, - (gchar *) "Info", - (GDBusArgInfo **) &_gxdp_documents_method_info_info_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_documents_method_info_info_OUT_ARG_pointers, - NULL - }, - "handle-info", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_list_IN_ARG_app_id = -{ - { - -1, - (gchar *) "app_id", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_list_IN_ARG_pointers[] = -{ - &_gxdp_documents_method_info_list_IN_ARG_app_id.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_list_OUT_ARG_docs = -{ - { - -1, - (gchar *) "docs", - (gchar *) "a{say}", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_documents_method_info_list_OUT_ARG_pointers[] = -{ - &_gxdp_documents_method_info_list_OUT_ARG_docs.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_list = -{ - { - -1, - (gchar *) "List", - (GDBusArgInfo **) &_gxdp_documents_method_info_list_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_documents_method_info_list_OUT_ARG_pointers, - NULL - }, - "handle-list", - FALSE -}; - -static const GDBusMethodInfo * const _gxdp_documents_method_info_pointers[] = -{ - &_gxdp_documents_method_info_get_mount_point.parent_struct, - &_gxdp_documents_method_info_add.parent_struct, - &_gxdp_documents_method_info_add_named.parent_struct, - &_gxdp_documents_method_info_add_full.parent_struct, - &_gxdp_documents_method_info_grant_permissions.parent_struct, - &_gxdp_documents_method_info_revoke_permissions.parent_struct, - &_gxdp_documents_method_info_delete.parent_struct, - &_gxdp_documents_method_info_lookup.parent_struct, - &_gxdp_documents_method_info_info.parent_struct, - &_gxdp_documents_method_info_list.parent_struct, - NULL -}; - -static const _ExtendedGDBusPropertyInfo _gxdp_documents_property_info_version = -{ - { - -1, - (gchar *) "version", - (gchar *) "u", - G_DBUS_PROPERTY_INFO_FLAGS_READABLE, - NULL - }, - "version", - FALSE, - TRUE -}; - -static const GDBusPropertyInfo * const _gxdp_documents_property_info_pointers[] = -{ - &_gxdp_documents_property_info_version.parent_struct, - NULL -}; - -static const _ExtendedGDBusInterfaceInfo _gxdp_documents_interface_info = -{ - { - -1, - (gchar *) "org.freedesktop.portal.Documents", - (GDBusMethodInfo **) &_gxdp_documents_method_info_pointers, - NULL, - (GDBusPropertyInfo **) &_gxdp_documents_property_info_pointers, - NULL - }, - "documents", -}; - - -/** - * gxdp_documents_interface_info: - * - * Gets a machine-readable description of the org.freedesktop.portal.Documents D-Bus interface. - * - * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. - */ -GDBusInterfaceInfo * -gxdp_documents_interface_info (void) -{ - return (GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct; -} - -/** - * gxdp_documents_override_properties: - * @klass: The class structure for a #GObject derived class. - * @property_id_begin: The property id to assign to the first overridden property. - * - * Overrides all #GObject properties in the #GXdpDocuments interface for a concrete class. - * The properties are overridden in the order they are defined. - * - * Returns: The last property id. - */ -guint -gxdp_documents_override_properties (GObjectClass *klass, guint property_id_begin) -{ - g_object_class_override_property (klass, property_id_begin++, "version"); - return property_id_begin - 1; -} - - - -/** - * GXdpDocuments: - * - * Abstract interface type for the D-Bus interface org.freedesktop.portal.Documents. - */ - -/** - * GXdpDocumentsIface: - * @parent_iface: The parent interface. - * @handle_add: Handler for the #GXdpDocuments::handle-add signal. - * @handle_add_full: Handler for the #GXdpDocuments::handle-add-full signal. - * @handle_add_named: Handler for the #GXdpDocuments::handle-add-named signal. - * @handle_delete: Handler for the #GXdpDocuments::handle-delete signal. - * @handle_get_mount_point: Handler for the #GXdpDocuments::handle-get-mount-point signal. - * @handle_grant_permissions: Handler for the #GXdpDocuments::handle-grant-permissions signal. - * @handle_info: Handler for the #GXdpDocuments::handle-info signal. - * @handle_list: Handler for the #GXdpDocuments::handle-list signal. - * @handle_lookup: Handler for the #GXdpDocuments::handle-lookup signal. - * @handle_revoke_permissions: Handler for the #GXdpDocuments::handle-revoke-permissions signal. - * @get_version: Getter for the #GXdpDocuments:version property. - * - * Virtual table for the D-Bus interface org.freedesktop.portal.Documents. - */ - -typedef GXdpDocumentsIface GXdpDocumentsInterface; -G_DEFINE_INTERFACE (GXdpDocuments, gxdp_documents, G_TYPE_OBJECT) - -static void -gxdp_documents_default_init (GXdpDocumentsIface *iface) -{ - /* GObject signals for incoming D-Bus method calls: */ - /** - * GXdpDocuments::handle-get-mount-point: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * - * Signal emitted when a remote caller is invoking the GetMountPoint() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_get_mount_point() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-get-mount-point", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_get_mount_point), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 1, - G_TYPE_DBUS_METHOD_INVOCATION); - - /** - * GXdpDocuments::handle-add: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @arg_o_path_fd: Argument passed by remote caller. - * @arg_reuse_existing: Argument passed by remote caller. - * @arg_persistent: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the Add() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-add", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 5, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); - - /** - * GXdpDocuments::handle-add-named: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @arg_o_path_parent_fd: Argument passed by remote caller. - * @arg_filename: Argument passed by remote caller. - * @arg_reuse_existing: Argument passed by remote caller. - * @arg_persistent: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the AddNamed() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add_named() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-add-named", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add_named), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 6, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); - - /** - * GXdpDocuments::handle-add-full: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @arg_o_path_fds: Argument passed by remote caller. - * @arg_flags: Argument passed by remote caller. - * @arg_app_id: Argument passed by remote caller. - * @arg_permissions: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the AddFull() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add_full() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-add-full", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add_full), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 6, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRV); - - /** - * GXdpDocuments::handle-grant-permissions: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @arg_doc_id: Argument passed by remote caller. - * @arg_app_id: Argument passed by remote caller. - * @arg_permissions: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the GrantPermissions() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_grant_permissions() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-grant-permissions", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_grant_permissions), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 4, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRV); - - /** - * GXdpDocuments::handle-revoke-permissions: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @arg_doc_id: Argument passed by remote caller. - * @arg_app_id: Argument passed by remote caller. - * @arg_permissions: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the RevokePermissions() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_revoke_permissions() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-revoke-permissions", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_revoke_permissions), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 4, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRV); - - /** - * GXdpDocuments::handle-delete: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @arg_doc_id: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the Delete() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_delete() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-delete", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_delete), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * GXdpDocuments::handle-lookup: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @arg_filename: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the Lookup() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_lookup() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-lookup", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_lookup), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * GXdpDocuments::handle-info: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @arg_doc_id: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the Info() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_info() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-info", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_info), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /** - * GXdpDocuments::handle-list: - * @object: A #GXdpDocuments. - * @invocation: A #GDBusMethodInvocation. - * @arg_app_id: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the List() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_list() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-list", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpDocumentsIface, handle_list), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - - /* GObject properties for D-Bus properties: */ - /** - * GXdpDocuments:version: - * - * Represents the D-Bus property "version". - * - * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. - */ - g_object_interface_install_property (iface, - g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -/** - * gxdp_documents_get_version: (skip) - * @object: A #GXdpDocuments. - * - * Gets the value of the "version" D-Bus property. - * - * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. - * - * Returns: The property value. - */ -guint -gxdp_documents_get_version (GXdpDocuments *object) -{ - return GXDP_DOCUMENTS_GET_IFACE (object)->get_version (object); -} - -/** - * gxdp_documents_set_version: (skip) - * @object: A #GXdpDocuments. - * @value: The value to set. - * - * Sets the "version" D-Bus property to @value. - * - * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. - */ -void -gxdp_documents_set_version (GXdpDocuments *object, guint value) -{ - g_object_set (G_OBJECT (object), "version", value, NULL); -} - -/** - * gxdp_documents_call_get_mount_point: - * @proxy: A #GXdpDocumentsProxy. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GetMountPoint() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_get_mount_point_finish() to get the result of the operation. - * - * See gxdp_documents_call_get_mount_point_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_get_mount_point ( - GXdpDocuments *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GetMountPoint", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_get_mount_point_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_get_mount_point(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_get_mount_point(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_get_mount_point_finish ( - GXdpDocuments *proxy, - gchar **out_path, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^ay)", - out_path); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_get_mount_point_sync: - * @proxy: A #GXdpDocumentsProxy. - * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GetMountPoint() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_get_mount_point() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_get_mount_point_sync ( - GXdpDocuments *proxy, - gchar **out_path, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetMountPoint", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^ay)", - out_path); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_add: - * @proxy: A #GXdpDocumentsProxy. - * @arg_o_path_fd: Argument to pass with the method invocation. - * @arg_reuse_existing: Argument to pass with the method invocation. - * @arg_persistent: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the Add() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_add_finish() to get the result of the operation. - * - * See gxdp_documents_call_add_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_add ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fd, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), - "Add", - g_variant_new ("(@hbb)", - arg_o_path_fd, - arg_reuse_existing, - arg_persistent), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_add_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_add(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_add_finish ( - GXdpDocuments *proxy, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_doc_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_add_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_o_path_fd: Argument to pass with the method invocation. - * @arg_reuse_existing: Argument to pass with the method invocation. - * @arg_persistent: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the Add() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_add() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_add_sync ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fd, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), - "Add", - g_variant_new ("(@hbb)", - arg_o_path_fd, - arg_reuse_existing, - arg_persistent), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - out_fd_list, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_doc_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_add_named: - * @proxy: A #GXdpDocumentsProxy. - * @arg_o_path_parent_fd: Argument to pass with the method invocation. - * @arg_filename: Argument to pass with the method invocation. - * @arg_reuse_existing: Argument to pass with the method invocation. - * @arg_persistent: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the AddNamed() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_add_named_finish() to get the result of the operation. - * - * See gxdp_documents_call_add_named_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_add_named ( - GXdpDocuments *proxy, - GVariant *arg_o_path_parent_fd, - const gchar *arg_filename, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), - "AddNamed", - g_variant_new ("(@h^aybb)", - arg_o_path_parent_fd, - arg_filename, - arg_reuse_existing, - arg_persistent), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_add_named_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add_named(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_add_named(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_add_named_finish ( - GXdpDocuments *proxy, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_doc_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_add_named_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_o_path_parent_fd: Argument to pass with the method invocation. - * @arg_filename: Argument to pass with the method invocation. - * @arg_reuse_existing: Argument to pass with the method invocation. - * @arg_persistent: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the AddNamed() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_add_named() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_add_named_sync ( - GXdpDocuments *proxy, - GVariant *arg_o_path_parent_fd, - const gchar *arg_filename, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), - "AddNamed", - g_variant_new ("(@h^aybb)", - arg_o_path_parent_fd, - arg_filename, - arg_reuse_existing, - arg_persistent), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - out_fd_list, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_doc_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_add_full: - * @proxy: A #GXdpDocumentsProxy. - * @arg_o_path_fds: Argument to pass with the method invocation. - * @arg_flags: Argument to pass with the method invocation. - * @arg_app_id: Argument to pass with the method invocation. - * @arg_permissions: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the AddFull() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_add_full_finish() to get the result of the operation. - * - * See gxdp_documents_call_add_full_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_add_full ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fds, - guint arg_flags, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), - "AddFull", - g_variant_new ("(@ahus^as)", - arg_o_path_fds, - arg_flags, - arg_app_id, - arg_permissions), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_add_full_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_doc_ids: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @out_extra_out: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add_full(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_add_full(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_add_full_finish ( - GXdpDocuments *proxy, - gchar ***out_doc_ids, - GVariant **out_extra_out, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as@a{sv})", - out_doc_ids, - out_extra_out); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_add_full_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_o_path_fds: Argument to pass with the method invocation. - * @arg_flags: Argument to pass with the method invocation. - * @arg_app_id: Argument to pass with the method invocation. - * @arg_permissions: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @out_doc_ids: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @out_extra_out: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the AddFull() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_add_full() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_add_full_sync ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fds, - guint arg_flags, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GUnixFDList *fd_list, - gchar ***out_doc_ids, - GVariant **out_extra_out, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), - "AddFull", - g_variant_new ("(@ahus^as)", - arg_o_path_fds, - arg_flags, - arg_app_id, - arg_permissions), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - out_fd_list, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as@a{sv})", - out_doc_ids, - out_extra_out); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_grant_permissions: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @arg_app_id: Argument to pass with the method invocation. - * @arg_permissions: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the GrantPermissions() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_grant_permissions_finish() to get the result of the operation. - * - * See gxdp_documents_call_grant_permissions_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_grant_permissions ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "GrantPermissions", - g_variant_new ("(ss^as)", - arg_doc_id, - arg_app_id, - arg_permissions), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_grant_permissions_finish: - * @proxy: A #GXdpDocumentsProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_grant_permissions(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_grant_permissions(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_grant_permissions_finish ( - GXdpDocuments *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_grant_permissions_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @arg_app_id: Argument to pass with the method invocation. - * @arg_permissions: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the GrantPermissions() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_grant_permissions() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_grant_permissions_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GrantPermissions", - g_variant_new ("(ss^as)", - arg_doc_id, - arg_app_id, - arg_permissions), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_revoke_permissions: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @arg_app_id: Argument to pass with the method invocation. - * @arg_permissions: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the RevokePermissions() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_revoke_permissions_finish() to get the result of the operation. - * - * See gxdp_documents_call_revoke_permissions_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_revoke_permissions ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "RevokePermissions", - g_variant_new ("(ss^as)", - arg_doc_id, - arg_app_id, - arg_permissions), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_revoke_permissions_finish: - * @proxy: A #GXdpDocumentsProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_revoke_permissions(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_revoke_permissions(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_revoke_permissions_finish ( - GXdpDocuments *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_revoke_permissions_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @arg_app_id: Argument to pass with the method invocation. - * @arg_permissions: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the RevokePermissions() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_revoke_permissions() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_revoke_permissions_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "RevokePermissions", - g_variant_new ("(ss^as)", - arg_doc_id, - arg_app_id, - arg_permissions), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_delete: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the Delete() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_delete_finish() to get the result of the operation. - * - * See gxdp_documents_call_delete_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_delete ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "Delete", - g_variant_new ("(s)", - arg_doc_id), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_delete_finish: - * @proxy: A #GXdpDocumentsProxy. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_delete(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_delete(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_delete_finish ( - GXdpDocuments *proxy, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_delete_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the Delete() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_delete() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_delete_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "Delete", - g_variant_new ("(s)", - arg_doc_id), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "()"); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_lookup: - * @proxy: A #GXdpDocumentsProxy. - * @arg_filename: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the Lookup() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_lookup_finish() to get the result of the operation. - * - * See gxdp_documents_call_lookup_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_lookup ( - GXdpDocuments *proxy, - const gchar *arg_filename, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "Lookup", - g_variant_new ("(^ay)", - arg_filename), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_lookup_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_lookup(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_lookup(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_lookup_finish ( - GXdpDocuments *proxy, - gchar **out_doc_id, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_doc_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_lookup_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_filename: Argument to pass with the method invocation. - * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the Lookup() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_lookup() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_lookup_sync ( - GXdpDocuments *proxy, - const gchar *arg_filename, - gchar **out_doc_id, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "Lookup", - g_variant_new ("(^ay)", - arg_filename), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(s)", - out_doc_id); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_info: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the Info() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_info_finish() to get the result of the operation. - * - * See gxdp_documents_call_info_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_info ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "Info", - g_variant_new ("(s)", - arg_doc_id), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_info_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_apps: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_info(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_info(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_info_finish ( - GXdpDocuments *proxy, - gchar **out_path, - GVariant **out_apps, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^ay@a{sas})", - out_path, - out_apps); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_info_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_doc_id: Argument to pass with the method invocation. - * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_apps: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the Info() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_info() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_info_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - gchar **out_path, - GVariant **out_apps, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "Info", - g_variant_new ("(s)", - arg_doc_id), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^ay@a{sas})", - out_path, - out_apps); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_list: - * @proxy: A #GXdpDocumentsProxy. - * @arg_app_id: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the List() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_call_list_finish() to get the result of the operation. - * - * See gxdp_documents_call_list_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_documents_call_list ( - GXdpDocuments *proxy, - const gchar *arg_app_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "List", - g_variant_new ("(s)", - arg_app_id), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_documents_call_list_finish: - * @proxy: A #GXdpDocumentsProxy. - * @out_docs: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_list(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_documents_call_list(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_list_finish ( - GXdpDocuments *proxy, - GVariant **out_docs, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(@a{say})", - out_docs); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_call_list_sync: - * @proxy: A #GXdpDocumentsProxy. - * @arg_app_id: Argument to pass with the method invocation. - * @out_docs: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the List() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_documents_call_list() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_documents_call_list_sync ( - GXdpDocuments *proxy, - const gchar *arg_app_id, - GVariant **out_docs, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "List", - g_variant_new ("(s)", - arg_app_id), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(@a{say})", - out_docs); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_documents_complete_get_mount_point: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @path: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the GetMountPoint() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_get_mount_point ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *path) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^ay)", - path)); -} - -/** - * gxdp_documents_complete_add: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @doc_id: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the Add() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_add ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *doc_id) -{ - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(s)", - doc_id), - fd_list); -} - -/** - * gxdp_documents_complete_add_named: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @doc_id: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the AddNamed() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_add_named ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *doc_id) -{ - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(s)", - doc_id), - fd_list); -} - -/** - * gxdp_documents_complete_add_full: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @doc_ids: Parameter to return. - * @extra_out: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the AddFull() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_add_full ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *const *doc_ids, - GVariant *extra_out) -{ - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(^as@a{sv})", - doc_ids, - extra_out), - fd_list); -} - -/** - * gxdp_documents_complete_grant_permissions: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the GrantPermissions() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_grant_permissions ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * gxdp_documents_complete_revoke_permissions: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the RevokePermissions() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_revoke_permissions ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * gxdp_documents_complete_delete: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * - * Helper function used in service implementations to finish handling invocations of the Delete() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_delete ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("()")); -} - -/** - * gxdp_documents_complete_lookup: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @doc_id: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the Lookup() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_lookup ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *doc_id) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", - doc_id)); -} - -/** - * gxdp_documents_complete_info: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @path: Parameter to return. - * @apps: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the Info() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_info ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *path, - GVariant *apps) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^ay@a{sas})", - path, - apps)); -} - -/** - * gxdp_documents_complete_list: - * @object: A #GXdpDocuments. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @docs: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the List() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_documents_complete_list ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GVariant *docs) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(@a{say})", - docs)); -} - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpDocumentsProxy: - * - * The #GXdpDocumentsProxy structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpDocumentsProxyClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpDocumentsProxy. - */ - -struct _GXdpDocumentsProxyPrivate -{ - GData *qdata; -}; - -static void gxdp_documents_proxy_iface_init (GXdpDocumentsIface *iface); - -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsProxy, gxdp_documents_proxy, G_TYPE_DBUS_PROXY, - G_ADD_PRIVATE (GXdpDocumentsProxy) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_proxy_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsProxy, gxdp_documents_proxy, G_TYPE_DBUS_PROXY, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_proxy_iface_init)) - -#endif -static void -gxdp_documents_proxy_finalize (GObject *object) -{ - GXdpDocumentsProxy *proxy = GXDP_DOCUMENTS_PROXY (object); - g_datalist_clear (&proxy->priv->qdata); - G_OBJECT_CLASS (gxdp_documents_proxy_parent_class)->finalize (object); -} - -static void -gxdp_documents_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - const _ExtendedGDBusPropertyInfo *info; - GVariant *variant; - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_documents_property_info_pointers[prop_id - 1]; - variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); - if (info->use_gvariant) - { - g_value_set_variant (value, variant); - } - else - { - if (variant != NULL) - g_dbus_gvariant_to_gvalue (variant, value); - } - if (variant != NULL) - g_variant_unref (variant); -} - -static void -gxdp_documents_proxy_set_property_cb (GDBusProxy *proxy, - GAsyncResult *res, - gpointer user_data) -{ - const _ExtendedGDBusPropertyInfo *info = user_data; - GError *error; - GVariant *_ret; - error = NULL; - _ret = g_dbus_proxy_call_finish (proxy, res, &error); - if (!_ret) - { - g_warning ("Error setting property '%s' on interface org.freedesktop.portal.Documents: %s (%s, %d)", - info->parent_struct.name, - error->message, g_quark_to_string (error->domain), error->code); - g_error_free (error); - } - else - { - g_variant_unref (_ret); - } -} - -static void -gxdp_documents_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - const _ExtendedGDBusPropertyInfo *info; - GVariant *variant; - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_documents_property_info_pointers[prop_id - 1]; - variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_dbus_proxy_call (G_DBUS_PROXY (object), - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", "org.freedesktop.portal.Documents", info->parent_struct.name, variant), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, (GAsyncReadyCallback) gxdp_documents_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); - g_variant_unref (variant); -} - -static void -gxdp_documents_proxy_g_signal (GDBusProxy *proxy, - const gchar *sender_name G_GNUC_UNUSED, - const gchar *signal_name, - GVariant *parameters) -{ - _ExtendedGDBusSignalInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - gsize n; - guint signal_id; - info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, signal_name); - if (info == NULL) - return; - num_params = g_variant_n_children (parameters); - paramv = g_new0 (GValue, num_params + 1); - g_value_init (¶mv[0], GXDP_TYPE_DOCUMENTS); - g_value_set_object (¶mv[0], proxy); - g_variant_iter_init (&iter, parameters); - n = 1; - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_DOCUMENTS); - g_signal_emitv (paramv, signal_id, 0, NULL); - for (n = 0; n < num_params + 1; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static void -gxdp_documents_proxy_g_properties_changed (GDBusProxy *_proxy, - GVariant *changed_properties, - const gchar *const *invalidated_properties) -{ - GXdpDocumentsProxy *proxy = GXDP_DOCUMENTS_PROXY (_proxy); - guint n; - const gchar *key; - GVariantIter *iter; - _ExtendedGDBusPropertyInfo *info; - g_variant_get (changed_properties, "a{sv}", &iter); - while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, key); - g_datalist_remove_data (&proxy->priv->qdata, key); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } - g_variant_iter_free (iter); - for (n = 0; invalidated_properties[n] != NULL; n++) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, invalidated_properties[n]); - g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } -} - -static guint -gxdp_documents_proxy_get_version (GXdpDocuments *object) -{ - GXdpDocumentsProxy *proxy = GXDP_DOCUMENTS_PROXY (object); - GVariant *variant; - guint value = 0; - variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); - if (variant != NULL) - { - value = g_variant_get_uint32 (variant); - g_variant_unref (variant); - } - return value; -} - -static void -gxdp_documents_proxy_init (GXdpDocumentsProxy *proxy) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - proxy->priv = gxdp_documents_proxy_get_instance_private (proxy); -#else - proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxyPrivate); -#endif - - g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_documents_interface_info ()); -} - -static void -gxdp_documents_proxy_class_init (GXdpDocumentsProxyClass *klass) -{ - GObjectClass *gobject_class; - GDBusProxyClass *proxy_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_documents_proxy_finalize; - gobject_class->get_property = gxdp_documents_proxy_get_property; - gobject_class->set_property = gxdp_documents_proxy_set_property; - - proxy_class = G_DBUS_PROXY_CLASS (klass); - proxy_class->g_signal = gxdp_documents_proxy_g_signal; - proxy_class->g_properties_changed = gxdp_documents_proxy_g_properties_changed; - - gxdp_documents_override_properties (gobject_class, 1); - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpDocumentsProxyPrivate)); -#endif -} - -static void -gxdp_documents_proxy_iface_init (GXdpDocumentsIface *iface) -{ - iface->get_version = gxdp_documents_proxy_get_version; -} - -/** - * gxdp_documents_proxy_new: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Documents. See g_dbus_proxy_new() for more details. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_proxy_new_finish() to get the result of the operation. - * - * See gxdp_documents_proxy_new_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_documents_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_DOCUMENTS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); -} - -/** - * gxdp_documents_proxy_new_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_proxy_new(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_documents_proxy_new(). - * - * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpDocuments * -gxdp_documents_proxy_new_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_DOCUMENTS (ret); - else - return NULL; -} - -/** - * gxdp_documents_proxy_new_sync: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Documents. See g_dbus_proxy_new_sync() for more details. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_documents_proxy_new() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpDocuments * -gxdp_documents_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_DOCUMENTS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); - if (ret != NULL) - return GXDP_DOCUMENTS (ret); - else - return NULL; -} - - -/** - * gxdp_documents_proxy_new_for_bus: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Like gxdp_documents_proxy_new() but takes a #GBusType instead of a #GDBusConnection. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_documents_proxy_new_for_bus_finish() to get the result of the operation. - * - * See gxdp_documents_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_documents_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_DOCUMENTS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); -} - -/** - * gxdp_documents_proxy_new_for_bus_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_proxy_new_for_bus(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_documents_proxy_new_for_bus(). - * - * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpDocuments * -gxdp_documents_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_DOCUMENTS (ret); - else - return NULL; -} - -/** - * gxdp_documents_proxy_new_for_bus_sync: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Like gxdp_documents_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_documents_proxy_new_for_bus() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpDocuments * -gxdp_documents_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_DOCUMENTS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); - if (ret != NULL) - return GXDP_DOCUMENTS (ret); - else - return NULL; -} - - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpDocumentsSkeleton: - * - * The #GXdpDocumentsSkeleton structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpDocumentsSkeletonClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpDocumentsSkeleton. - */ - -struct _GXdpDocumentsSkeletonPrivate -{ - GValue *properties; - GList *changed_properties; - GSource *changed_properties_idle_source; - GMainContext *context; - GMutex lock; -}; - -static void -_gxdp_documents_skeleton_handle_method_call ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); - _ExtendedGDBusMethodInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - guint num_extra; - gsize n; - guint signal_id; - GValue return_value = G_VALUE_INIT; - info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); - g_assert (info != NULL); - num_params = g_variant_n_children (parameters); - num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); - n = 0; - g_value_init (¶mv[n], GXDP_TYPE_DOCUMENTS); - g_value_set_object (¶mv[n++], skeleton); - g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); - g_value_set_object (¶mv[n++], invocation); - if (info->pass_fdlist) - { -#ifdef G_OS_UNIX - g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); - g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); -#else - g_assert_not_reached (); -#endif - } - g_variant_iter_init (&iter, parameters); - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_DOCUMENTS); - g_value_init (&return_value, G_TYPE_BOOLEAN); - g_signal_emitv (paramv, signal_id, 0, &return_value); - if (!g_value_get_boolean (&return_value)) - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); - g_value_unset (&return_value); - for (n = 0; n < num_params + num_extra; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static GVariant * -_gxdp_documents_skeleton_handle_get_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - GVariant *ret; - ret = NULL; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); - ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_value_unset (&value); - } - return ret; -} - -static gboolean -_gxdp_documents_skeleton_handle_set_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GVariant *variant, - GError **error, - gpointer user_data) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - gboolean ret; - ret = FALSE; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - if (info->use_gvariant) - g_value_set_variant (&value, variant); - else - g_dbus_gvariant_to_gvalue (variant, &value); - g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); - g_value_unset (&value); - ret = TRUE; - } - return ret; -} - -static const GDBusInterfaceVTable _gxdp_documents_skeleton_vtable = -{ - _gxdp_documents_skeleton_handle_method_call, - _gxdp_documents_skeleton_handle_get_property, - _gxdp_documents_skeleton_handle_set_property, - {NULL} -}; - -static GDBusInterfaceInfo * -gxdp_documents_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return gxdp_documents_interface_info (); -} - -static GDBusInterfaceVTable * -gxdp_documents_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return (GDBusInterfaceVTable *) &_gxdp_documents_skeleton_vtable; -} - -static GVariant * -gxdp_documents_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (_skeleton); - - GVariantBuilder builder; - guint n; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - if (_gxdp_documents_interface_info.parent_struct.properties == NULL) - goto out; - for (n = 0; _gxdp_documents_interface_info.parent_struct.properties[n] != NULL; n++) - { - GDBusPropertyInfo *info = _gxdp_documents_interface_info.parent_struct.properties[n]; - if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) - { - GVariant *value; - value = _gxdp_documents_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.Documents", info->name, NULL, skeleton); - if (value != NULL) - { - g_variant_take_ref (value); - g_variant_builder_add (&builder, "{sv}", info->name, value); - g_variant_unref (value); - } - } - } -out: - return g_variant_builder_end (&builder); -} - -static gboolean _gxdp_documents_emit_changed (gpointer user_data); - -static void -gxdp_documents_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (_skeleton); - gboolean emit_changed = FALSE; - - g_mutex_lock (&skeleton->priv->lock); - if (skeleton->priv->changed_properties_idle_source != NULL) - { - g_source_destroy (skeleton->priv->changed_properties_idle_source); - skeleton->priv->changed_properties_idle_source = NULL; - emit_changed = TRUE; - } - g_mutex_unlock (&skeleton->priv->lock); - - if (emit_changed) - _gxdp_documents_emit_changed (skeleton); -} - -static void gxdp_documents_skeleton_iface_init (GXdpDocumentsIface *iface); -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsSkeleton, gxdp_documents_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_ADD_PRIVATE (GXdpDocumentsSkeleton) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_skeleton_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsSkeleton, gxdp_documents_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_skeleton_iface_init)) - -#endif -static void -gxdp_documents_skeleton_finalize (GObject *object) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); - guint n; - for (n = 0; n < 1; n++) - g_value_unset (&skeleton->priv->properties[n]); - g_free (skeleton->priv->properties); - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - if (skeleton->priv->changed_properties_idle_source != NULL) - g_source_destroy (skeleton->priv->changed_properties_idle_source); - g_main_context_unref (skeleton->priv->context); - g_mutex_clear (&skeleton->priv->lock); - G_OBJECT_CLASS (gxdp_documents_skeleton_parent_class)->finalize (object); -} - -static void -gxdp_documents_skeleton_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); - g_assert (prop_id != 0 && prop_id - 1 < 1); - g_mutex_lock (&skeleton->priv->lock); - g_value_copy (&skeleton->priv->properties[prop_id - 1], value); - g_mutex_unlock (&skeleton->priv->lock); -} - -static gboolean -_gxdp_documents_emit_changed (gpointer user_data) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); - GList *l; - GVariantBuilder builder; - GVariantBuilder invalidated_builder; - guint num_changes; - - g_mutex_lock (&skeleton->priv->lock); - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); - for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) - { - ChangedProperty *cp = l->data; - GVariant *variant; - const GValue *cur_value; - - cur_value = &skeleton->priv->properties[cp->prop_id - 1]; - if (!_g_value_equal (cur_value, &cp->orig_value)) - { - variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); - g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); - g_variant_unref (variant); - num_changes++; - } - } - if (num_changes > 0) - { - GList *connections, *ll; - GVariant *signal_variant; - signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.Documents", - &builder, &invalidated_builder)); - connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); - for (ll = connections; ll != NULL; ll = ll->next) - { - GDBusConnection *connection = ll->data; - - g_dbus_connection_emit_signal (connection, - NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - signal_variant, - NULL); - } - g_variant_unref (signal_variant); - g_list_free_full (connections, g_object_unref); - } - else - { - g_variant_builder_clear (&builder); - g_variant_builder_clear (&invalidated_builder); - } - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - skeleton->priv->changed_properties = NULL; - skeleton->priv->changed_properties_idle_source = NULL; - g_mutex_unlock (&skeleton->priv->lock); - return FALSE; -} - -static void -_gxdp_documents_schedule_emit_changed (GXdpDocumentsSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) -{ - ChangedProperty *cp; - GList *l; - cp = NULL; - for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) - { - ChangedProperty *i_cp = l->data; - if (i_cp->info == info) - { - cp = i_cp; - break; - } - } - if (cp == NULL) - { - cp = g_new0 (ChangedProperty, 1); - cp->prop_id = prop_id; - cp->info = info; - skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); - g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); - g_value_copy (orig_value, &cp->orig_value); - } -} - -static void -gxdp_documents_skeleton_notify (GObject *object, - GParamSpec *pspec G_GNUC_UNUSED) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); - g_mutex_lock (&skeleton->priv->lock); - if (skeleton->priv->changed_properties != NULL && - skeleton->priv->changed_properties_idle_source == NULL) - { - skeleton->priv->changed_properties_idle_source = g_idle_source_new (); - g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); - g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_documents_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); - g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_documents_emit_changed"); - g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); - g_source_unref (skeleton->priv->changed_properties_idle_source); - } - g_mutex_unlock (&skeleton->priv->lock); -} - -static void -gxdp_documents_skeleton_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - const _ExtendedGDBusPropertyInfo *info; - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_documents_property_info_pointers[prop_id - 1]; - g_mutex_lock (&skeleton->priv->lock); - g_object_freeze_notify (object); - if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) - { - if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && - info->emits_changed_signal) - _gxdp_documents_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); - g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); - g_object_notify_by_pspec (object, pspec); - } - g_mutex_unlock (&skeleton->priv->lock); - g_object_thaw_notify (object); -} - -static void -gxdp_documents_skeleton_init (GXdpDocumentsSkeleton *skeleton) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - skeleton->priv = gxdp_documents_skeleton_get_instance_private (skeleton); -#else - skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeletonPrivate); -#endif - - g_mutex_init (&skeleton->priv->lock); - skeleton->priv->context = g_main_context_ref_thread_default (); - skeleton->priv->properties = g_new0 (GValue, 1); - g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); -} - -static guint -gxdp_documents_skeleton_get_version (GXdpDocuments *object) -{ - GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); - guint value; - g_mutex_lock (&skeleton->priv->lock); - value = g_value_get_uint (&(skeleton->priv->properties[0])); - g_mutex_unlock (&skeleton->priv->lock); - return value; -} - -static void -gxdp_documents_skeleton_class_init (GXdpDocumentsSkeletonClass *klass) -{ - GObjectClass *gobject_class; - GDBusInterfaceSkeletonClass *skeleton_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_documents_skeleton_finalize; - gobject_class->get_property = gxdp_documents_skeleton_get_property; - gobject_class->set_property = gxdp_documents_skeleton_set_property; - gobject_class->notify = gxdp_documents_skeleton_notify; - - - gxdp_documents_override_properties (gobject_class, 1); - - skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); - skeleton_class->get_info = gxdp_documents_skeleton_dbus_interface_get_info; - skeleton_class->get_properties = gxdp_documents_skeleton_dbus_interface_get_properties; - skeleton_class->flush = gxdp_documents_skeleton_dbus_interface_flush; - skeleton_class->get_vtable = gxdp_documents_skeleton_dbus_interface_get_vtable; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpDocumentsSkeletonPrivate)); -#endif -} - -static void -gxdp_documents_skeleton_iface_init (GXdpDocumentsIface *iface) -{ - iface->get_version = gxdp_documents_skeleton_get_version; -} - -/** - * gxdp_documents_skeleton_new: - * - * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.Documents. - * - * Returns: (transfer full) (type GXdpDocumentsSkeleton): The skeleton object. - */ -GXdpDocuments * -gxdp_documents_skeleton_new (void) -{ - return GXDP_DOCUMENTS (g_object_new (GXDP_TYPE_DOCUMENTS_SKELETON, NULL)); -} - -/* ------------------------------------------------------------------------ - * Code for interface org.freedesktop.portal.OpenURI - * ------------------------------------------------------------------------ - */ - -/** - * SECTION:GXdpOpenURI - * @title: GXdpOpenURI - * @short_description: Generated C code for the org.freedesktop.portal.OpenURI D-Bus interface - * - * This section contains code for working with the org.freedesktop.portal.OpenURI D-Bus interface in C. - */ - -/* ---- Introspection data for org.freedesktop.portal.OpenURI ---- */ - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_IN_ARG_parent_window = -{ - { - -1, - (gchar *) "parent_window", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_IN_ARG_uri = -{ - { - -1, - (gchar *) "uri", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_IN_ARG_options = -{ - { - -1, - (gchar *) "options", - (gchar *) "a{sv}", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_uri_IN_ARG_pointers[] = -{ - &_gxdp_open_uri_method_info_open_uri_IN_ARG_parent_window.parent_struct, - &_gxdp_open_uri_method_info_open_uri_IN_ARG_uri.parent_struct, - &_gxdp_open_uri_method_info_open_uri_IN_ARG_options.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_OUT_ARG_handle = -{ - { - -1, - (gchar *) "handle", - (gchar *) "o", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_uri_OUT_ARG_pointers[] = -{ - &_gxdp_open_uri_method_info_open_uri_OUT_ARG_handle.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_open_uri_method_info_open_uri = -{ - { - -1, - (gchar *) "OpenURI", - (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_uri_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_uri_OUT_ARG_pointers, - NULL - }, - "handle-open-uri", - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_IN_ARG_parent_window = -{ - { - -1, - (gchar *) "parent_window", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_IN_ARG_fd = -{ - { - -1, - (gchar *) "fd", - (gchar *) "h", - NULL - }, - FALSE -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_IN_ARG_options = -{ - { - -1, - (gchar *) "options", - (gchar *) "a{sv}", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_file_IN_ARG_pointers[] = -{ - &_gxdp_open_uri_method_info_open_file_IN_ARG_parent_window.parent_struct, - &_gxdp_open_uri_method_info_open_file_IN_ARG_fd.parent_struct, - &_gxdp_open_uri_method_info_open_file_IN_ARG_options.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_OUT_ARG_handle = -{ - { - -1, - (gchar *) "handle", - (gchar *) "o", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_file_OUT_ARG_pointers[] = -{ - &_gxdp_open_uri_method_info_open_file_OUT_ARG_handle.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_open_uri_method_info_open_file = -{ - { - -1, - (gchar *) "OpenFile", - (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_file_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_file_OUT_ARG_pointers, - NULL - }, - "handle-open-file", - TRUE -}; - -static const GDBusMethodInfo * const _gxdp_open_uri_method_info_pointers[] = -{ - &_gxdp_open_uri_method_info_open_uri.parent_struct, - &_gxdp_open_uri_method_info_open_file.parent_struct, - NULL -}; - -static const _ExtendedGDBusPropertyInfo _gxdp_open_uri_property_info_version = -{ - { - -1, - (gchar *) "version", - (gchar *) "u", - G_DBUS_PROPERTY_INFO_FLAGS_READABLE, - NULL - }, - "version", - FALSE, - TRUE -}; - -static const GDBusPropertyInfo * const _gxdp_open_uri_property_info_pointers[] = -{ - &_gxdp_open_uri_property_info_version.parent_struct, - NULL -}; - -static const _ExtendedGDBusInterfaceInfo _gxdp_open_uri_interface_info = -{ - { - -1, - (gchar *) "org.freedesktop.portal.OpenURI", - (GDBusMethodInfo **) &_gxdp_open_uri_method_info_pointers, - NULL, - (GDBusPropertyInfo **) &_gxdp_open_uri_property_info_pointers, - NULL - }, - "open-uri", -}; - - -/** - * gxdp_open_uri_interface_info: - * - * Gets a machine-readable description of the org.freedesktop.portal.OpenURI D-Bus interface. - * - * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. - */ -GDBusInterfaceInfo * -gxdp_open_uri_interface_info (void) -{ - return (GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct; -} - -/** - * gxdp_open_uri_override_properties: - * @klass: The class structure for a #GObject derived class. - * @property_id_begin: The property id to assign to the first overridden property. - * - * Overrides all #GObject properties in the #GXdpOpenURI interface for a concrete class. - * The properties are overridden in the order they are defined. - * - * Returns: The last property id. - */ -guint -gxdp_open_uri_override_properties (GObjectClass *klass, guint property_id_begin) -{ - g_object_class_override_property (klass, property_id_begin++, "version"); - return property_id_begin - 1; -} - - - -/** - * GXdpOpenURI: - * - * Abstract interface type for the D-Bus interface org.freedesktop.portal.OpenURI. - */ - -/** - * GXdpOpenURIIface: - * @parent_iface: The parent interface. - * @handle_open_file: Handler for the #GXdpOpenURI::handle-open-file signal. - * @handle_open_uri: Handler for the #GXdpOpenURI::handle-open-uri signal. - * @get_version: Getter for the #GXdpOpenURI:version property. - * - * Virtual table for the D-Bus interface org.freedesktop.portal.OpenURI. - */ - -typedef GXdpOpenURIIface GXdpOpenURIInterface; -G_DEFINE_INTERFACE (GXdpOpenURI, gxdp_open_uri, G_TYPE_OBJECT) - -static void -gxdp_open_uri_default_init (GXdpOpenURIIface *iface) -{ - /* GObject signals for incoming D-Bus method calls: */ - /** - * GXdpOpenURI::handle-open-uri: - * @object: A #GXdpOpenURI. - * @invocation: A #GDBusMethodInvocation. - * @arg_parent_window: Argument passed by remote caller. - * @arg_uri: Argument passed by remote caller. - * @arg_options: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the OpenURI() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_open_uri_complete_open_uri() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-open-uri", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpOpenURIIface, handle_open_uri), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 4, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_VARIANT); - - /** - * GXdpOpenURI::handle-open-file: - * @object: A #GXdpOpenURI. - * @invocation: A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @arg_parent_window: Argument passed by remote caller. - * @arg_fd: Argument passed by remote caller. - * @arg_options: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the OpenFile() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_open_uri_complete_open_file() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-open-file", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpOpenURIIface, handle_open_file), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 5, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_STRING, G_TYPE_VARIANT, G_TYPE_VARIANT); - - /* GObject properties for D-Bus properties: */ - /** - * GXdpOpenURI:version: - * - * Represents the D-Bus property "version". - * - * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. - */ - g_object_interface_install_property (iface, - g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -/** - * gxdp_open_uri_get_version: (skip) - * @object: A #GXdpOpenURI. - * - * Gets the value of the "version" D-Bus property. - * - * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. - * - * Returns: The property value. - */ -guint -gxdp_open_uri_get_version (GXdpOpenURI *object) -{ - return GXDP_OPEN_URI_GET_IFACE (object)->get_version (object); -} - -/** - * gxdp_open_uri_set_version: (skip) - * @object: A #GXdpOpenURI. - * @value: The value to set. - * - * Sets the "version" D-Bus property to @value. - * - * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. - */ -void -gxdp_open_uri_set_version (GXdpOpenURI *object, guint value) -{ - g_object_set (G_OBJECT (object), "version", value, NULL); -} - -/** - * gxdp_open_uri_call_open_uri: - * @proxy: A #GXdpOpenURIProxy. - * @arg_parent_window: Argument to pass with the method invocation. - * @arg_uri: Argument to pass with the method invocation. - * @arg_options: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the OpenURI() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_open_uri_call_open_uri_finish() to get the result of the operation. - * - * See gxdp_open_uri_call_open_uri_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_open_uri_call_open_uri ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - const gchar *arg_uri, - GVariant *arg_options, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "OpenURI", - g_variant_new ("(ss@a{sv})", - arg_parent_window, - arg_uri, - arg_options), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_open_uri_call_open_uri_finish: - * @proxy: A #GXdpOpenURIProxy. - * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_call_open_uri(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_open_uri_call_open_uri(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_open_uri_call_open_uri_finish ( - GXdpOpenURI *proxy, - gchar **out_handle, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(o)", - out_handle); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_open_uri_call_open_uri_sync: - * @proxy: A #GXdpOpenURIProxy. - * @arg_parent_window: Argument to pass with the method invocation. - * @arg_uri: Argument to pass with the method invocation. - * @arg_options: Argument to pass with the method invocation. - * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the OpenURI() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_open_uri_call_open_uri() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_open_uri_call_open_uri_sync ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - const gchar *arg_uri, - GVariant *arg_options, - gchar **out_handle, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "OpenURI", - g_variant_new ("(ss@a{sv})", - arg_parent_window, - arg_uri, - arg_options), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(o)", - out_handle); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_open_uri_call_open_file: - * @proxy: A #GXdpOpenURIProxy. - * @arg_parent_window: Argument to pass with the method invocation. - * @arg_fd: Argument to pass with the method invocation. - * @arg_options: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the OpenFile() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_open_uri_call_open_file_finish() to get the result of the operation. - * - * See gxdp_open_uri_call_open_file_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_open_uri_call_open_file ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - GVariant *arg_fd, - GVariant *arg_options, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), - "OpenFile", - g_variant_new ("(s@h@a{sv})", - arg_parent_window, - arg_fd, - arg_options), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - cancellable, - callback, - user_data); -} - -/** - * gxdp_open_uri_call_open_file_finish: - * @proxy: A #GXdpOpenURIProxy. - * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_call_open_file(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_open_uri_call_open_file(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_open_uri_call_open_file_finish ( - GXdpOpenURI *proxy, - gchar **out_handle, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(o)", - out_handle); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_open_uri_call_open_file_sync: - * @proxy: A #GXdpOpenURIProxy. - * @arg_parent_window: Argument to pass with the method invocation. - * @arg_fd: Argument to pass with the method invocation. - * @arg_options: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the OpenFile() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_open_uri_call_open_file() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_open_uri_call_open_file_sync ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - GVariant *arg_fd, - GVariant *arg_options, - GUnixFDList *fd_list, - gchar **out_handle, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), - "OpenFile", - g_variant_new ("(s@h@a{sv})", - arg_parent_window, - arg_fd, - arg_options), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - out_fd_list, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(o)", - out_handle); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_open_uri_complete_open_uri: - * @object: A #GXdpOpenURI. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @handle: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the OpenURI() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_open_uri_complete_open_uri ( - GXdpOpenURI *object, - GDBusMethodInvocation *invocation, - const gchar *handle) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(o)", - handle)); -} - -/** - * gxdp_open_uri_complete_open_file: - * @object: A #GXdpOpenURI. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @handle: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the OpenFile() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_open_uri_complete_open_file ( - GXdpOpenURI *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *handle) -{ - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(o)", - handle), - fd_list); -} - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpOpenURIProxy: - * - * The #GXdpOpenURIProxy structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpOpenURIProxyClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpOpenURIProxy. - */ - -struct _GXdpOpenURIProxyPrivate -{ - GData *qdata; -}; - -static void gxdp_open_uri_proxy_iface_init (GXdpOpenURIIface *iface); - -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpOpenURIProxy, gxdp_open_uri_proxy, G_TYPE_DBUS_PROXY, - G_ADD_PRIVATE (GXdpOpenURIProxy) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_proxy_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpOpenURIProxy, gxdp_open_uri_proxy, G_TYPE_DBUS_PROXY, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_proxy_iface_init)) - -#endif -static void -gxdp_open_uri_proxy_finalize (GObject *object) -{ - GXdpOpenURIProxy *proxy = GXDP_OPEN_URI_PROXY (object); - g_datalist_clear (&proxy->priv->qdata); - G_OBJECT_CLASS (gxdp_open_uri_proxy_parent_class)->finalize (object); -} - -static void -gxdp_open_uri_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - const _ExtendedGDBusPropertyInfo *info; - GVariant *variant; - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_open_uri_property_info_pointers[prop_id - 1]; - variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); - if (info->use_gvariant) - { - g_value_set_variant (value, variant); - } - else - { - if (variant != NULL) - g_dbus_gvariant_to_gvalue (variant, value); - } - if (variant != NULL) - g_variant_unref (variant); -} - -static void -gxdp_open_uri_proxy_set_property_cb (GDBusProxy *proxy, - GAsyncResult *res, - gpointer user_data) -{ - const _ExtendedGDBusPropertyInfo *info = user_data; - GError *error; - GVariant *_ret; - error = NULL; - _ret = g_dbus_proxy_call_finish (proxy, res, &error); - if (!_ret) - { - g_warning ("Error setting property '%s' on interface org.freedesktop.portal.OpenURI: %s (%s, %d)", - info->parent_struct.name, - error->message, g_quark_to_string (error->domain), error->code); - g_error_free (error); - } - else - { - g_variant_unref (_ret); - } -} - -static void -gxdp_open_uri_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - const _ExtendedGDBusPropertyInfo *info; - GVariant *variant; - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_open_uri_property_info_pointers[prop_id - 1]; - variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_dbus_proxy_call (G_DBUS_PROXY (object), - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", "org.freedesktop.portal.OpenURI", info->parent_struct.name, variant), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, (GAsyncReadyCallback) gxdp_open_uri_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); - g_variant_unref (variant); -} - -static void -gxdp_open_uri_proxy_g_signal (GDBusProxy *proxy, - const gchar *sender_name G_GNUC_UNUSED, - const gchar *signal_name, - GVariant *parameters) -{ - _ExtendedGDBusSignalInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - gsize n; - guint signal_id; - info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, signal_name); - if (info == NULL) - return; - num_params = g_variant_n_children (parameters); - paramv = g_new0 (GValue, num_params + 1); - g_value_init (¶mv[0], GXDP_TYPE_OPEN_URI); - g_value_set_object (¶mv[0], proxy); - g_variant_iter_init (&iter, parameters); - n = 1; - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_OPEN_URI); - g_signal_emitv (paramv, signal_id, 0, NULL); - for (n = 0; n < num_params + 1; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static void -gxdp_open_uri_proxy_g_properties_changed (GDBusProxy *_proxy, - GVariant *changed_properties, - const gchar *const *invalidated_properties) -{ - GXdpOpenURIProxy *proxy = GXDP_OPEN_URI_PROXY (_proxy); - guint n; - const gchar *key; - GVariantIter *iter; - _ExtendedGDBusPropertyInfo *info; - g_variant_get (changed_properties, "a{sv}", &iter); - while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, key); - g_datalist_remove_data (&proxy->priv->qdata, key); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } - g_variant_iter_free (iter); - for (n = 0; invalidated_properties[n] != NULL; n++) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, invalidated_properties[n]); - g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } -} - -static guint -gxdp_open_uri_proxy_get_version (GXdpOpenURI *object) -{ - GXdpOpenURIProxy *proxy = GXDP_OPEN_URI_PROXY (object); - GVariant *variant; - guint value = 0; - variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); - if (variant != NULL) - { - value = g_variant_get_uint32 (variant); - g_variant_unref (variant); - } - return value; -} - -static void -gxdp_open_uri_proxy_init (GXdpOpenURIProxy *proxy) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - proxy->priv = gxdp_open_uri_proxy_get_instance_private (proxy); -#else - proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxyPrivate); -#endif - - g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_open_uri_interface_info ()); -} - -static void -gxdp_open_uri_proxy_class_init (GXdpOpenURIProxyClass *klass) -{ - GObjectClass *gobject_class; - GDBusProxyClass *proxy_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_open_uri_proxy_finalize; - gobject_class->get_property = gxdp_open_uri_proxy_get_property; - gobject_class->set_property = gxdp_open_uri_proxy_set_property; - - proxy_class = G_DBUS_PROXY_CLASS (klass); - proxy_class->g_signal = gxdp_open_uri_proxy_g_signal; - proxy_class->g_properties_changed = gxdp_open_uri_proxy_g_properties_changed; - - gxdp_open_uri_override_properties (gobject_class, 1); - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpOpenURIProxyPrivate)); -#endif -} - -static void -gxdp_open_uri_proxy_iface_init (GXdpOpenURIIface *iface) -{ - iface->get_version = gxdp_open_uri_proxy_get_version; -} - -/** - * gxdp_open_uri_proxy_new: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.OpenURI. See g_dbus_proxy_new() for more details. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_open_uri_proxy_new_finish() to get the result of the operation. - * - * See gxdp_open_uri_proxy_new_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_open_uri_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_OPEN_URI_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); -} - -/** - * gxdp_open_uri_proxy_new_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_proxy_new(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_open_uri_proxy_new(). - * - * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpOpenURI * -gxdp_open_uri_proxy_new_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_OPEN_URI (ret); - else - return NULL; -} - -/** - * gxdp_open_uri_proxy_new_sync: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.OpenURI. See g_dbus_proxy_new_sync() for more details. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_open_uri_proxy_new() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpOpenURI * -gxdp_open_uri_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_OPEN_URI_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); - if (ret != NULL) - return GXDP_OPEN_URI (ret); - else - return NULL; -} - - -/** - * gxdp_open_uri_proxy_new_for_bus: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Like gxdp_open_uri_proxy_new() but takes a #GBusType instead of a #GDBusConnection. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_open_uri_proxy_new_for_bus_finish() to get the result of the operation. - * - * See gxdp_open_uri_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_open_uri_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_OPEN_URI_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); -} - -/** - * gxdp_open_uri_proxy_new_for_bus_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_proxy_new_for_bus(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_open_uri_proxy_new_for_bus(). - * - * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpOpenURI * -gxdp_open_uri_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_OPEN_URI (ret); - else - return NULL; -} - -/** - * gxdp_open_uri_proxy_new_for_bus_sync: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Like gxdp_open_uri_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_open_uri_proxy_new_for_bus() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpOpenURI * -gxdp_open_uri_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_OPEN_URI_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); - if (ret != NULL) - return GXDP_OPEN_URI (ret); - else - return NULL; -} - - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpOpenURISkeleton: - * - * The #GXdpOpenURISkeleton structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpOpenURISkeletonClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpOpenURISkeleton. - */ - -struct _GXdpOpenURISkeletonPrivate -{ - GValue *properties; - GList *changed_properties; - GSource *changed_properties_idle_source; - GMainContext *context; - GMutex lock; -}; - -static void -_gxdp_open_uri_skeleton_handle_method_call ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); - _ExtendedGDBusMethodInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - guint num_extra; - gsize n; - guint signal_id; - GValue return_value = G_VALUE_INIT; - info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); - g_assert (info != NULL); - num_params = g_variant_n_children (parameters); - num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); - n = 0; - g_value_init (¶mv[n], GXDP_TYPE_OPEN_URI); - g_value_set_object (¶mv[n++], skeleton); - g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); - g_value_set_object (¶mv[n++], invocation); - if (info->pass_fdlist) - { -#ifdef G_OS_UNIX - g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); - g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); -#else - g_assert_not_reached (); -#endif - } - g_variant_iter_init (&iter, parameters); - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_OPEN_URI); - g_value_init (&return_value, G_TYPE_BOOLEAN); - g_signal_emitv (paramv, signal_id, 0, &return_value); - if (!g_value_get_boolean (&return_value)) - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); - g_value_unset (&return_value); - for (n = 0; n < num_params + num_extra; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static GVariant * -_gxdp_open_uri_skeleton_handle_get_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - GVariant *ret; - ret = NULL; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); - ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_value_unset (&value); - } - return ret; -} - -static gboolean -_gxdp_open_uri_skeleton_handle_set_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GVariant *variant, - GError **error, - gpointer user_data) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - gboolean ret; - ret = FALSE; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - if (info->use_gvariant) - g_value_set_variant (&value, variant); - else - g_dbus_gvariant_to_gvalue (variant, &value); - g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); - g_value_unset (&value); - ret = TRUE; - } - return ret; -} - -static const GDBusInterfaceVTable _gxdp_open_uri_skeleton_vtable = -{ - _gxdp_open_uri_skeleton_handle_method_call, - _gxdp_open_uri_skeleton_handle_get_property, - _gxdp_open_uri_skeleton_handle_set_property, - {NULL} -}; - -static GDBusInterfaceInfo * -gxdp_open_uri_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return gxdp_open_uri_interface_info (); -} - -static GDBusInterfaceVTable * -gxdp_open_uri_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return (GDBusInterfaceVTable *) &_gxdp_open_uri_skeleton_vtable; -} - -static GVariant * -gxdp_open_uri_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (_skeleton); - - GVariantBuilder builder; - guint n; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - if (_gxdp_open_uri_interface_info.parent_struct.properties == NULL) - goto out; - for (n = 0; _gxdp_open_uri_interface_info.parent_struct.properties[n] != NULL; n++) - { - GDBusPropertyInfo *info = _gxdp_open_uri_interface_info.parent_struct.properties[n]; - if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) - { - GVariant *value; - value = _gxdp_open_uri_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.OpenURI", info->name, NULL, skeleton); - if (value != NULL) - { - g_variant_take_ref (value); - g_variant_builder_add (&builder, "{sv}", info->name, value); - g_variant_unref (value); - } - } - } -out: - return g_variant_builder_end (&builder); -} - -static gboolean _gxdp_open_uri_emit_changed (gpointer user_data); - -static void -gxdp_open_uri_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (_skeleton); - gboolean emit_changed = FALSE; - - g_mutex_lock (&skeleton->priv->lock); - if (skeleton->priv->changed_properties_idle_source != NULL) - { - g_source_destroy (skeleton->priv->changed_properties_idle_source); - skeleton->priv->changed_properties_idle_source = NULL; - emit_changed = TRUE; - } - g_mutex_unlock (&skeleton->priv->lock); - - if (emit_changed) - _gxdp_open_uri_emit_changed (skeleton); -} - -static void gxdp_open_uri_skeleton_iface_init (GXdpOpenURIIface *iface); -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpOpenURISkeleton, gxdp_open_uri_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_ADD_PRIVATE (GXdpOpenURISkeleton) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_skeleton_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpOpenURISkeleton, gxdp_open_uri_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_skeleton_iface_init)) - -#endif -static void -gxdp_open_uri_skeleton_finalize (GObject *object) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); - guint n; - for (n = 0; n < 1; n++) - g_value_unset (&skeleton->priv->properties[n]); - g_free (skeleton->priv->properties); - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - if (skeleton->priv->changed_properties_idle_source != NULL) - g_source_destroy (skeleton->priv->changed_properties_idle_source); - g_main_context_unref (skeleton->priv->context); - g_mutex_clear (&skeleton->priv->lock); - G_OBJECT_CLASS (gxdp_open_uri_skeleton_parent_class)->finalize (object); -} - -static void -gxdp_open_uri_skeleton_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); - g_assert (prop_id != 0 && prop_id - 1 < 1); - g_mutex_lock (&skeleton->priv->lock); - g_value_copy (&skeleton->priv->properties[prop_id - 1], value); - g_mutex_unlock (&skeleton->priv->lock); -} - -static gboolean -_gxdp_open_uri_emit_changed (gpointer user_data) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); - GList *l; - GVariantBuilder builder; - GVariantBuilder invalidated_builder; - guint num_changes; - - g_mutex_lock (&skeleton->priv->lock); - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); - for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) - { - ChangedProperty *cp = l->data; - GVariant *variant; - const GValue *cur_value; - - cur_value = &skeleton->priv->properties[cp->prop_id - 1]; - if (!_g_value_equal (cur_value, &cp->orig_value)) - { - variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); - g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); - g_variant_unref (variant); - num_changes++; - } - } - if (num_changes > 0) - { - GList *connections, *ll; - GVariant *signal_variant; - signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.OpenURI", - &builder, &invalidated_builder)); - connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); - for (ll = connections; ll != NULL; ll = ll->next) - { - GDBusConnection *connection = ll->data; - - g_dbus_connection_emit_signal (connection, - NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - signal_variant, - NULL); - } - g_variant_unref (signal_variant); - g_list_free_full (connections, g_object_unref); - } - else - { - g_variant_builder_clear (&builder); - g_variant_builder_clear (&invalidated_builder); - } - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - skeleton->priv->changed_properties = NULL; - skeleton->priv->changed_properties_idle_source = NULL; - g_mutex_unlock (&skeleton->priv->lock); - return FALSE; -} - -static void -_gxdp_open_uri_schedule_emit_changed (GXdpOpenURISkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) -{ - ChangedProperty *cp; - GList *l; - cp = NULL; - for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) - { - ChangedProperty *i_cp = l->data; - if (i_cp->info == info) - { - cp = i_cp; - break; - } - } - if (cp == NULL) - { - cp = g_new0 (ChangedProperty, 1); - cp->prop_id = prop_id; - cp->info = info; - skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); - g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); - g_value_copy (orig_value, &cp->orig_value); - } -} - -static void -gxdp_open_uri_skeleton_notify (GObject *object, - GParamSpec *pspec G_GNUC_UNUSED) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); - g_mutex_lock (&skeleton->priv->lock); - if (skeleton->priv->changed_properties != NULL && - skeleton->priv->changed_properties_idle_source == NULL) - { - skeleton->priv->changed_properties_idle_source = g_idle_source_new (); - g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); - g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_open_uri_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); - g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_open_uri_emit_changed"); - g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); - g_source_unref (skeleton->priv->changed_properties_idle_source); - } - g_mutex_unlock (&skeleton->priv->lock); -} - -static void -gxdp_open_uri_skeleton_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - const _ExtendedGDBusPropertyInfo *info; - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_open_uri_property_info_pointers[prop_id - 1]; - g_mutex_lock (&skeleton->priv->lock); - g_object_freeze_notify (object); - if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) - { - if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && - info->emits_changed_signal) - _gxdp_open_uri_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); - g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); - g_object_notify_by_pspec (object, pspec); - } - g_mutex_unlock (&skeleton->priv->lock); - g_object_thaw_notify (object); -} - -static void -gxdp_open_uri_skeleton_init (GXdpOpenURISkeleton *skeleton) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - skeleton->priv = gxdp_open_uri_skeleton_get_instance_private (skeleton); -#else - skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeletonPrivate); -#endif - - g_mutex_init (&skeleton->priv->lock); - skeleton->priv->context = g_main_context_ref_thread_default (); - skeleton->priv->properties = g_new0 (GValue, 1); - g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); -} - -static guint -gxdp_open_uri_skeleton_get_version (GXdpOpenURI *object) -{ - GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); - guint value; - g_mutex_lock (&skeleton->priv->lock); - value = g_value_get_uint (&(skeleton->priv->properties[0])); - g_mutex_unlock (&skeleton->priv->lock); - return value; -} - -static void -gxdp_open_uri_skeleton_class_init (GXdpOpenURISkeletonClass *klass) -{ - GObjectClass *gobject_class; - GDBusInterfaceSkeletonClass *skeleton_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_open_uri_skeleton_finalize; - gobject_class->get_property = gxdp_open_uri_skeleton_get_property; - gobject_class->set_property = gxdp_open_uri_skeleton_set_property; - gobject_class->notify = gxdp_open_uri_skeleton_notify; - - - gxdp_open_uri_override_properties (gobject_class, 1); - - skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); - skeleton_class->get_info = gxdp_open_uri_skeleton_dbus_interface_get_info; - skeleton_class->get_properties = gxdp_open_uri_skeleton_dbus_interface_get_properties; - skeleton_class->flush = gxdp_open_uri_skeleton_dbus_interface_flush; - skeleton_class->get_vtable = gxdp_open_uri_skeleton_dbus_interface_get_vtable; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpOpenURISkeletonPrivate)); -#endif -} - -static void -gxdp_open_uri_skeleton_iface_init (GXdpOpenURIIface *iface) -{ - iface->get_version = gxdp_open_uri_skeleton_get_version; -} - -/** - * gxdp_open_uri_skeleton_new: - * - * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.OpenURI. - * - * Returns: (transfer full) (type GXdpOpenURISkeleton): The skeleton object. - */ -GXdpOpenURI * -gxdp_open_uri_skeleton_new (void) -{ - return GXDP_OPEN_URI (g_object_new (GXDP_TYPE_OPEN_URI_SKELETON, NULL)); -} - -/* ------------------------------------------------------------------------ - * Code for interface org.freedesktop.portal.ProxyResolver - * ------------------------------------------------------------------------ - */ - -/** - * SECTION:GXdpProxyResolver - * @title: GXdpProxyResolver - * @short_description: Generated C code for the org.freedesktop.portal.ProxyResolver D-Bus interface - * - * This section contains code for working with the org.freedesktop.portal.ProxyResolver D-Bus interface in C. - */ - -/* ---- Introspection data for org.freedesktop.portal.ProxyResolver ---- */ - -static const _ExtendedGDBusArgInfo _gxdp_proxy_resolver_method_info_lookup_IN_ARG_uri = -{ - { - -1, - (gchar *) "uri", - (gchar *) "s", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_proxy_resolver_method_info_lookup_IN_ARG_pointers[] = -{ - &_gxdp_proxy_resolver_method_info_lookup_IN_ARG_uri.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_proxy_resolver_method_info_lookup_OUT_ARG_proxies = -{ - { - -1, - (gchar *) "proxies", - (gchar *) "as", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_proxy_resolver_method_info_lookup_OUT_ARG_pointers[] = -{ - &_gxdp_proxy_resolver_method_info_lookup_OUT_ARG_proxies.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_proxy_resolver_method_info_lookup = -{ - { - -1, - (gchar *) "Lookup", - (GDBusArgInfo **) &_gxdp_proxy_resolver_method_info_lookup_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_proxy_resolver_method_info_lookup_OUT_ARG_pointers, - NULL - }, - "handle-lookup", - FALSE -}; - -static const GDBusMethodInfo * const _gxdp_proxy_resolver_method_info_pointers[] = -{ - &_gxdp_proxy_resolver_method_info_lookup.parent_struct, - NULL -}; - -static const _ExtendedGDBusInterfaceInfo _gxdp_proxy_resolver_interface_info = -{ - { - -1, - (gchar *) "org.freedesktop.portal.ProxyResolver", - (GDBusMethodInfo **) &_gxdp_proxy_resolver_method_info_pointers, - NULL, - NULL, - NULL - }, - "proxy-resolver", -}; - - -/** - * gxdp_proxy_resolver_interface_info: - * - * Gets a machine-readable description of the org.freedesktop.portal.ProxyResolver D-Bus interface. - * - * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. - */ -GDBusInterfaceInfo * -gxdp_proxy_resolver_interface_info (void) -{ - return (GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct; -} - -/** - * gxdp_proxy_resolver_override_properties: - * @klass: The class structure for a #GObject derived class. - * @property_id_begin: The property id to assign to the first overridden property. - * - * Overrides all #GObject properties in the #GXdpProxyResolver interface for a concrete class. - * The properties are overridden in the order they are defined. - * - * Returns: The last property id. - */ -guint -gxdp_proxy_resolver_override_properties (GObjectClass *klass, guint property_id_begin) -{ - return property_id_begin - 1; -} - - - -/** - * GXdpProxyResolver: - * - * Abstract interface type for the D-Bus interface org.freedesktop.portal.ProxyResolver. - */ - -/** - * GXdpProxyResolverIface: - * @parent_iface: The parent interface. - * @handle_lookup: Handler for the #GXdpProxyResolver::handle-lookup signal. - * - * Virtual table for the D-Bus interface org.freedesktop.portal.ProxyResolver. - */ - -typedef GXdpProxyResolverIface GXdpProxyResolverInterface; -G_DEFINE_INTERFACE (GXdpProxyResolver, gxdp_proxy_resolver, G_TYPE_OBJECT) - -static void -gxdp_proxy_resolver_default_init (GXdpProxyResolverIface *iface) -{ - /* GObject signals for incoming D-Bus method calls: */ - /** - * GXdpProxyResolver::handle-lookup: - * @object: A #GXdpProxyResolver. - * @invocation: A #GDBusMethodInvocation. - * @arg_uri: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the Lookup() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_proxy_resolver_complete_lookup() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-lookup", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpProxyResolverIface, handle_lookup), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 2, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); - -} - -/** - * gxdp_proxy_resolver_call_lookup: - * @proxy: A #GXdpProxyResolverProxy. - * @arg_uri: Argument to pass with the method invocation. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the Lookup() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_proxy_resolver_call_lookup_finish() to get the result of the operation. - * - * See gxdp_proxy_resolver_call_lookup_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_proxy_resolver_call_lookup ( - GXdpProxyResolver *proxy, - const gchar *arg_uri, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call (G_DBUS_PROXY (proxy), - "Lookup", - g_variant_new ("(s)", - arg_uri), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - callback, - user_data); -} - -/** - * gxdp_proxy_resolver_call_lookup_finish: - * @proxy: A #GXdpProxyResolverProxy. - * @out_proxies: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_proxy_resolver_call_lookup(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_proxy_resolver_call_lookup(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_proxy_resolver_call_lookup_finish ( - GXdpProxyResolver *proxy, - gchar ***out_proxies, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_proxies); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_proxy_resolver_call_lookup_sync: - * @proxy: A #GXdpProxyResolverProxy. - * @arg_uri: Argument to pass with the method invocation. - * @out_proxies: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the Lookup() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_proxy_resolver_call_lookup() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_proxy_resolver_call_lookup_sync ( - GXdpProxyResolver *proxy, - const gchar *arg_uri, - gchar ***out_proxies, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "Lookup", - g_variant_new ("(s)", - arg_uri), - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(^as)", - out_proxies); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_proxy_resolver_complete_lookup: - * @object: A #GXdpProxyResolver. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @proxies: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the Lookup() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_proxy_resolver_complete_lookup ( - GXdpProxyResolver *object, - GDBusMethodInvocation *invocation, - const gchar *const *proxies) -{ - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^as)", - proxies)); -} - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpProxyResolverProxy: - * - * The #GXdpProxyResolverProxy structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpProxyResolverProxyClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpProxyResolverProxy. - */ - -struct _GXdpProxyResolverProxyPrivate -{ - GData *qdata; -}; - -static void gxdp_proxy_resolver_proxy_iface_init (GXdpProxyResolverIface *iface); - -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverProxy, gxdp_proxy_resolver_proxy, G_TYPE_DBUS_PROXY, - G_ADD_PRIVATE (GXdpProxyResolverProxy) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_proxy_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverProxy, gxdp_proxy_resolver_proxy, G_TYPE_DBUS_PROXY, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_proxy_iface_init)) - -#endif -static void -gxdp_proxy_resolver_proxy_finalize (GObject *object) -{ - GXdpProxyResolverProxy *proxy = GXDP_PROXY_RESOLVER_PROXY (object); - g_datalist_clear (&proxy->priv->qdata); - G_OBJECT_CLASS (gxdp_proxy_resolver_proxy_parent_class)->finalize (object); -} - -static void -gxdp_proxy_resolver_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ -} - -static void -gxdp_proxy_resolver_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ -} - -static void -gxdp_proxy_resolver_proxy_g_signal (GDBusProxy *proxy, - const gchar *sender_name G_GNUC_UNUSED, - const gchar *signal_name, - GVariant *parameters) -{ - _ExtendedGDBusSignalInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - gsize n; - guint signal_id; - info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, signal_name); - if (info == NULL) - return; - num_params = g_variant_n_children (parameters); - paramv = g_new0 (GValue, num_params + 1); - g_value_init (¶mv[0], GXDP_TYPE_PROXY_RESOLVER); - g_value_set_object (¶mv[0], proxy); - g_variant_iter_init (&iter, parameters); - n = 1; - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_PROXY_RESOLVER); - g_signal_emitv (paramv, signal_id, 0, NULL); - for (n = 0; n < num_params + 1; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static void -gxdp_proxy_resolver_proxy_g_properties_changed (GDBusProxy *_proxy, - GVariant *changed_properties, - const gchar *const *invalidated_properties) -{ - GXdpProxyResolverProxy *proxy = GXDP_PROXY_RESOLVER_PROXY (_proxy); - guint n; - const gchar *key; - GVariantIter *iter; - _ExtendedGDBusPropertyInfo *info; - g_variant_get (changed_properties, "a{sv}", &iter); - while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, key); - g_datalist_remove_data (&proxy->priv->qdata, key); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } - g_variant_iter_free (iter); - for (n = 0; invalidated_properties[n] != NULL; n++) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, invalidated_properties[n]); - g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } -} - -static void -gxdp_proxy_resolver_proxy_init (GXdpProxyResolverProxy *proxy) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - proxy->priv = gxdp_proxy_resolver_proxy_get_instance_private (proxy); -#else - proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxyPrivate); -#endif - - g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_proxy_resolver_interface_info ()); -} - -static void -gxdp_proxy_resolver_proxy_class_init (GXdpProxyResolverProxyClass *klass) -{ - GObjectClass *gobject_class; - GDBusProxyClass *proxy_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_proxy_resolver_proxy_finalize; - gobject_class->get_property = gxdp_proxy_resolver_proxy_get_property; - gobject_class->set_property = gxdp_proxy_resolver_proxy_set_property; - - proxy_class = G_DBUS_PROXY_CLASS (klass); - proxy_class->g_signal = gxdp_proxy_resolver_proxy_g_signal; - proxy_class->g_properties_changed = gxdp_proxy_resolver_proxy_g_properties_changed; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpProxyResolverProxyPrivate)); -#endif -} - -static void -gxdp_proxy_resolver_proxy_iface_init (GXdpProxyResolverIface *iface) -{ -} - -/** - * gxdp_proxy_resolver_proxy_new: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.ProxyResolver. See g_dbus_proxy_new() for more details. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_proxy_resolver_proxy_new_finish() to get the result of the operation. - * - * See gxdp_proxy_resolver_proxy_new_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_proxy_resolver_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_PROXY_RESOLVER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); -} - -/** - * gxdp_proxy_resolver_proxy_new_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_proxy_resolver_proxy_new(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_proxy_resolver_proxy_new(). - * - * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpProxyResolver * -gxdp_proxy_resolver_proxy_new_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_PROXY_RESOLVER (ret); - else - return NULL; -} - -/** - * gxdp_proxy_resolver_proxy_new_sync: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.ProxyResolver. See g_dbus_proxy_new_sync() for more details. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_proxy_resolver_proxy_new() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpProxyResolver * -gxdp_proxy_resolver_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_PROXY_RESOLVER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); - if (ret != NULL) - return GXDP_PROXY_RESOLVER (ret); - else - return NULL; -} - - -/** - * gxdp_proxy_resolver_proxy_new_for_bus: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Like gxdp_proxy_resolver_proxy_new() but takes a #GBusType instead of a #GDBusConnection. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_proxy_resolver_proxy_new_for_bus_finish() to get the result of the operation. - * - * See gxdp_proxy_resolver_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_proxy_resolver_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_PROXY_RESOLVER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); -} - -/** - * gxdp_proxy_resolver_proxy_new_for_bus_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_proxy_resolver_proxy_new_for_bus(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_proxy_resolver_proxy_new_for_bus(). - * - * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpProxyResolver * -gxdp_proxy_resolver_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_PROXY_RESOLVER (ret); - else - return NULL; -} - -/** - * gxdp_proxy_resolver_proxy_new_for_bus_sync: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Like gxdp_proxy_resolver_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_proxy_resolver_proxy_new_for_bus() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpProxyResolver * -gxdp_proxy_resolver_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_PROXY_RESOLVER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); - if (ret != NULL) - return GXDP_PROXY_RESOLVER (ret); - else - return NULL; -} - - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpProxyResolverSkeleton: - * - * The #GXdpProxyResolverSkeleton structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpProxyResolverSkeletonClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpProxyResolverSkeleton. - */ - -struct _GXdpProxyResolverSkeletonPrivate -{ - GValue *properties; - GList *changed_properties; - GSource *changed_properties_idle_source; - GMainContext *context; - GMutex lock; -}; - -static void -_gxdp_proxy_resolver_skeleton_handle_method_call ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); - _ExtendedGDBusMethodInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - guint num_extra; - gsize n; - guint signal_id; - GValue return_value = G_VALUE_INIT; - info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); - g_assert (info != NULL); - num_params = g_variant_n_children (parameters); - num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); - n = 0; - g_value_init (¶mv[n], GXDP_TYPE_PROXY_RESOLVER); - g_value_set_object (¶mv[n++], skeleton); - g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); - g_value_set_object (¶mv[n++], invocation); - if (info->pass_fdlist) - { -#ifdef G_OS_UNIX - g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); - g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); -#else - g_assert_not_reached (); -#endif - } - g_variant_iter_init (&iter, parameters); - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_PROXY_RESOLVER); - g_value_init (&return_value, G_TYPE_BOOLEAN); - g_signal_emitv (paramv, signal_id, 0, &return_value); - if (!g_value_get_boolean (&return_value)) - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); - g_value_unset (&return_value); - for (n = 0; n < num_params + num_extra; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static GVariant * -_gxdp_proxy_resolver_skeleton_handle_get_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - GVariant *ret; - ret = NULL; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); - ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_value_unset (&value); - } - return ret; -} - -static gboolean -_gxdp_proxy_resolver_skeleton_handle_set_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GVariant *variant, - GError **error, - gpointer user_data) -{ - GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - gboolean ret; - ret = FALSE; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - if (info->use_gvariant) - g_value_set_variant (&value, variant); - else - g_dbus_gvariant_to_gvalue (variant, &value); - g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); - g_value_unset (&value); - ret = TRUE; - } - return ret; -} - -static const GDBusInterfaceVTable _gxdp_proxy_resolver_skeleton_vtable = -{ - _gxdp_proxy_resolver_skeleton_handle_method_call, - _gxdp_proxy_resolver_skeleton_handle_get_property, - _gxdp_proxy_resolver_skeleton_handle_set_property, - {NULL} -}; - -static GDBusInterfaceInfo * -gxdp_proxy_resolver_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return gxdp_proxy_resolver_interface_info (); -} - -static GDBusInterfaceVTable * -gxdp_proxy_resolver_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return (GDBusInterfaceVTable *) &_gxdp_proxy_resolver_skeleton_vtable; -} - -static GVariant * -gxdp_proxy_resolver_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (_skeleton); - - GVariantBuilder builder; - guint n; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - if (_gxdp_proxy_resolver_interface_info.parent_struct.properties == NULL) - goto out; - for (n = 0; _gxdp_proxy_resolver_interface_info.parent_struct.properties[n] != NULL; n++) - { - GDBusPropertyInfo *info = _gxdp_proxy_resolver_interface_info.parent_struct.properties[n]; - if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) - { - GVariant *value; - value = _gxdp_proxy_resolver_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.ProxyResolver", info->name, NULL, skeleton); - if (value != NULL) - { - g_variant_take_ref (value); - g_variant_builder_add (&builder, "{sv}", info->name, value); - g_variant_unref (value); - } - } - } -out: - return g_variant_builder_end (&builder); -} - -static void -gxdp_proxy_resolver_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) -{ -} - -static void gxdp_proxy_resolver_skeleton_iface_init (GXdpProxyResolverIface *iface); -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverSkeleton, gxdp_proxy_resolver_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_ADD_PRIVATE (GXdpProxyResolverSkeleton) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_skeleton_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverSkeleton, gxdp_proxy_resolver_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_skeleton_iface_init)) - -#endif -static void -gxdp_proxy_resolver_skeleton_finalize (GObject *object) -{ - GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (object); - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - if (skeleton->priv->changed_properties_idle_source != NULL) - g_source_destroy (skeleton->priv->changed_properties_idle_source); - g_main_context_unref (skeleton->priv->context); - g_mutex_clear (&skeleton->priv->lock); - G_OBJECT_CLASS (gxdp_proxy_resolver_skeleton_parent_class)->finalize (object); -} - -static void -gxdp_proxy_resolver_skeleton_init (GXdpProxyResolverSkeleton *skeleton) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - skeleton->priv = gxdp_proxy_resolver_skeleton_get_instance_private (skeleton); -#else - skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeletonPrivate); -#endif - - g_mutex_init (&skeleton->priv->lock); - skeleton->priv->context = g_main_context_ref_thread_default (); -} - -static void -gxdp_proxy_resolver_skeleton_class_init (GXdpProxyResolverSkeletonClass *klass) -{ - GObjectClass *gobject_class; - GDBusInterfaceSkeletonClass *skeleton_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_proxy_resolver_skeleton_finalize; - - skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); - skeleton_class->get_info = gxdp_proxy_resolver_skeleton_dbus_interface_get_info; - skeleton_class->get_properties = gxdp_proxy_resolver_skeleton_dbus_interface_get_properties; - skeleton_class->flush = gxdp_proxy_resolver_skeleton_dbus_interface_flush; - skeleton_class->get_vtable = gxdp_proxy_resolver_skeleton_dbus_interface_get_vtable; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpProxyResolverSkeletonPrivate)); -#endif -} - -static void -gxdp_proxy_resolver_skeleton_iface_init (GXdpProxyResolverIface *iface) -{ -} - -/** - * gxdp_proxy_resolver_skeleton_new: - * - * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.ProxyResolver. - * - * Returns: (transfer full) (type GXdpProxyResolverSkeleton): The skeleton object. - */ -GXdpProxyResolver * -gxdp_proxy_resolver_skeleton_new (void) -{ - return GXDP_PROXY_RESOLVER (g_object_new (GXDP_TYPE_PROXY_RESOLVER_SKELETON, NULL)); -} - -/* ------------------------------------------------------------------------ - * Code for interface org.freedesktop.portal.Trash - * ------------------------------------------------------------------------ - */ - -/** - * SECTION:GXdpTrash - * @title: GXdpTrash - * @short_description: Generated C code for the org.freedesktop.portal.Trash D-Bus interface - * - * This section contains code for working with the org.freedesktop.portal.Trash D-Bus interface in C. - */ - -/* ---- Introspection data for org.freedesktop.portal.Trash ---- */ - -static const _ExtendedGDBusArgInfo _gxdp_trash_method_info_trash_file_IN_ARG_fd = -{ - { - -1, - (gchar *) "fd", - (gchar *) "h", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_trash_method_info_trash_file_IN_ARG_pointers[] = -{ - &_gxdp_trash_method_info_trash_file_IN_ARG_fd.parent_struct, - NULL -}; - -static const _ExtendedGDBusArgInfo _gxdp_trash_method_info_trash_file_OUT_ARG_result = -{ - { - -1, - (gchar *) "result", - (gchar *) "u", - NULL - }, - FALSE -}; - -static const GDBusArgInfo * const _gxdp_trash_method_info_trash_file_OUT_ARG_pointers[] = -{ - &_gxdp_trash_method_info_trash_file_OUT_ARG_result.parent_struct, - NULL -}; - -static const _ExtendedGDBusMethodInfo _gxdp_trash_method_info_trash_file = -{ - { - -1, - (gchar *) "TrashFile", - (GDBusArgInfo **) &_gxdp_trash_method_info_trash_file_IN_ARG_pointers, - (GDBusArgInfo **) &_gxdp_trash_method_info_trash_file_OUT_ARG_pointers, - NULL - }, - "handle-trash-file", - TRUE -}; - -static const GDBusMethodInfo * const _gxdp_trash_method_info_pointers[] = -{ - &_gxdp_trash_method_info_trash_file.parent_struct, - NULL -}; - -static const _ExtendedGDBusPropertyInfo _gxdp_trash_property_info_version = -{ - { - -1, - (gchar *) "version", - (gchar *) "u", - G_DBUS_PROPERTY_INFO_FLAGS_READABLE, - NULL - }, - "version", - FALSE, - TRUE -}; - -static const GDBusPropertyInfo * const _gxdp_trash_property_info_pointers[] = -{ - &_gxdp_trash_property_info_version.parent_struct, - NULL -}; - -static const _ExtendedGDBusInterfaceInfo _gxdp_trash_interface_info = -{ - { - -1, - (gchar *) "org.freedesktop.portal.Trash", - (GDBusMethodInfo **) &_gxdp_trash_method_info_pointers, - NULL, - (GDBusPropertyInfo **) &_gxdp_trash_property_info_pointers, - NULL - }, - "trash", -}; - - -/** - * gxdp_trash_interface_info: - * - * Gets a machine-readable description of the org.freedesktop.portal.Trash D-Bus interface. - * - * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. - */ -GDBusInterfaceInfo * -gxdp_trash_interface_info (void) -{ - return (GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct; -} - -/** - * gxdp_trash_override_properties: - * @klass: The class structure for a #GObject derived class. - * @property_id_begin: The property id to assign to the first overridden property. - * - * Overrides all #GObject properties in the #GXdpTrash interface for a concrete class. - * The properties are overridden in the order they are defined. - * - * Returns: The last property id. - */ -guint -gxdp_trash_override_properties (GObjectClass *klass, guint property_id_begin) -{ - g_object_class_override_property (klass, property_id_begin++, "version"); - return property_id_begin - 1; -} - - - -/** - * GXdpTrash: - * - * Abstract interface type for the D-Bus interface org.freedesktop.portal.Trash. - */ - -/** - * GXdpTrashIface: - * @parent_iface: The parent interface. - * @handle_trash_file: Handler for the #GXdpTrash::handle-trash-file signal. - * @get_version: Getter for the #GXdpTrash:version property. - * - * Virtual table for the D-Bus interface org.freedesktop.portal.Trash. - */ - -typedef GXdpTrashIface GXdpTrashInterface; -G_DEFINE_INTERFACE (GXdpTrash, gxdp_trash, G_TYPE_OBJECT) - -static void -gxdp_trash_default_init (GXdpTrashIface *iface) -{ - /* GObject signals for incoming D-Bus method calls: */ - /** - * GXdpTrash::handle-trash-file: - * @object: A #GXdpTrash. - * @invocation: A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @arg_fd: Argument passed by remote caller. - * - * Signal emitted when a remote caller is invoking the TrashFile() D-Bus method. - * - * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_trash_complete_trash_file() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - * - * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. - */ - g_signal_new ("handle-trash-file", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GXdpTrashIface, handle_trash_file), - g_signal_accumulator_true_handled, - NULL, - g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, - 3, - G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT); - - /* GObject properties for D-Bus properties: */ - /** - * GXdpTrash:version: - * - * Represents the D-Bus property "version". - * - * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. - */ - g_object_interface_install_property (iface, - g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -/** - * gxdp_trash_get_version: (skip) - * @object: A #GXdpTrash. - * - * Gets the value of the "version" D-Bus property. - * - * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. - * - * Returns: The property value. - */ -guint -gxdp_trash_get_version (GXdpTrash *object) -{ - return GXDP_TRASH_GET_IFACE (object)->get_version (object); -} - -/** - * gxdp_trash_set_version: (skip) - * @object: A #GXdpTrash. - * @value: The value to set. - * - * Sets the "version" D-Bus property to @value. - * - * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. - */ -void -gxdp_trash_set_version (GXdpTrash *object, guint value) -{ - g_object_set (G_OBJECT (object), "version", value, NULL); -} - -/** - * gxdp_trash_call_trash_file: - * @proxy: A #GXdpTrashProxy. - * @arg_fd: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. - * @user_data: User data to pass to @callback. - * - * Asynchronously invokes the TrashFile() D-Bus method on @proxy. - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_trash_call_trash_file_finish() to get the result of the operation. - * - * See gxdp_trash_call_trash_file_sync() for the synchronous, blocking version of this method. - */ -void -gxdp_trash_call_trash_file ( - GXdpTrash *proxy, - GVariant *arg_fd, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), - "TrashFile", - g_variant_new ("(@h)", - arg_fd), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - cancellable, - callback, - user_data); -} - -/** - * gxdp_trash_call_trash_file_finish: - * @proxy: A #GXdpTrashProxy. - * @out_result: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_trash_call_trash_file(). - * @error: Return location for error or %NULL. - * - * Finishes an operation started with gxdp_trash_call_trash_file(). - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_trash_call_trash_file_finish ( - GXdpTrash *proxy, - guint *out_result, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_result); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_trash_call_trash_file_sync: - * @proxy: A #GXdpTrashProxy. - * @arg_fd: Argument to pass with the method invocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @out_result: (out) (optional): Return location for return parameter or %NULL to ignore. - * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL. - * - * Synchronously invokes the TrashFile() D-Bus method on @proxy. The calling thread is blocked until a reply is received. - * - * See gxdp_trash_call_trash_file() for the asynchronous version of this method. - * - * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. - */ -gboolean -gxdp_trash_call_trash_file_sync ( - GXdpTrash *proxy, - GVariant *arg_fd, - GUnixFDList *fd_list, - guint *out_result, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error) -{ - GVariant *_ret; - _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), - "TrashFile", - g_variant_new ("(@h)", - arg_fd), - G_DBUS_CALL_FLAGS_NONE, - -1, - fd_list, - out_fd_list, - cancellable, - error); - if (_ret == NULL) - goto _out; - g_variant_get (_ret, - "(u)", - out_result); - g_variant_unref (_ret); -_out: - return _ret != NULL; -} - -/** - * gxdp_trash_complete_trash_file: - * @object: A #GXdpTrash. - * @invocation: (transfer full): A #GDBusMethodInvocation. - * @fd_list: (nullable): A #GUnixFDList or %NULL. - * @result: Parameter to return. - * - * Helper function used in service implementations to finish handling invocations of the TrashFile() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. - * - * This method will free @invocation, you cannot use it afterwards. - */ -void -gxdp_trash_complete_trash_file ( - GXdpTrash *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - guint result) -{ - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(u)", - result), - fd_list); -} - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpTrashProxy: - * - * The #GXdpTrashProxy structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpTrashProxyClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpTrashProxy. - */ - -struct _GXdpTrashProxyPrivate -{ - GData *qdata; -}; - -static void gxdp_trash_proxy_iface_init (GXdpTrashIface *iface); - -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpTrashProxy, gxdp_trash_proxy, G_TYPE_DBUS_PROXY, - G_ADD_PRIVATE (GXdpTrashProxy) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_proxy_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpTrashProxy, gxdp_trash_proxy, G_TYPE_DBUS_PROXY, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_proxy_iface_init)) - -#endif -static void -gxdp_trash_proxy_finalize (GObject *object) -{ - GXdpTrashProxy *proxy = GXDP_TRASH_PROXY (object); - g_datalist_clear (&proxy->priv->qdata); - G_OBJECT_CLASS (gxdp_trash_proxy_parent_class)->finalize (object); -} - -static void -gxdp_trash_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - const _ExtendedGDBusPropertyInfo *info; - GVariant *variant; - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_trash_property_info_pointers[prop_id - 1]; - variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); - if (info->use_gvariant) - { - g_value_set_variant (value, variant); - } - else - { - if (variant != NULL) - g_dbus_gvariant_to_gvalue (variant, value); - } - if (variant != NULL) - g_variant_unref (variant); -} - -static void -gxdp_trash_proxy_set_property_cb (GDBusProxy *proxy, - GAsyncResult *res, - gpointer user_data) -{ - const _ExtendedGDBusPropertyInfo *info = user_data; - GError *error; - GVariant *_ret; - error = NULL; - _ret = g_dbus_proxy_call_finish (proxy, res, &error); - if (!_ret) - { - g_warning ("Error setting property '%s' on interface org.freedesktop.portal.Trash: %s (%s, %d)", - info->parent_struct.name, - error->message, g_quark_to_string (error->domain), error->code); - g_error_free (error); - } - else - { - g_variant_unref (_ret); - } -} - -static void -gxdp_trash_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - const _ExtendedGDBusPropertyInfo *info; - GVariant *variant; - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_trash_property_info_pointers[prop_id - 1]; - variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_dbus_proxy_call (G_DBUS_PROXY (object), - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", "org.freedesktop.portal.Trash", info->parent_struct.name, variant), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, (GAsyncReadyCallback) gxdp_trash_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); - g_variant_unref (variant); -} - -static void -gxdp_trash_proxy_g_signal (GDBusProxy *proxy, - const gchar *sender_name G_GNUC_UNUSED, - const gchar *signal_name, - GVariant *parameters) -{ - _ExtendedGDBusSignalInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - gsize n; - guint signal_id; - info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, signal_name); - if (info == NULL) - return; - num_params = g_variant_n_children (parameters); - paramv = g_new0 (GValue, num_params + 1); - g_value_init (¶mv[0], GXDP_TYPE_TRASH); - g_value_set_object (¶mv[0], proxy); - g_variant_iter_init (&iter, parameters); - n = 1; - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_TRASH); - g_signal_emitv (paramv, signal_id, 0, NULL); - for (n = 0; n < num_params + 1; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static void -gxdp_trash_proxy_g_properties_changed (GDBusProxy *_proxy, - GVariant *changed_properties, - const gchar *const *invalidated_properties) -{ - GXdpTrashProxy *proxy = GXDP_TRASH_PROXY (_proxy); - guint n; - const gchar *key; - GVariantIter *iter; - _ExtendedGDBusPropertyInfo *info; - g_variant_get (changed_properties, "a{sv}", &iter); - while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, key); - g_datalist_remove_data (&proxy->priv->qdata, key); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } - g_variant_iter_free (iter); - for (n = 0; invalidated_properties[n] != NULL; n++) - { - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, invalidated_properties[n]); - g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); - if (info != NULL) - g_object_notify (G_OBJECT (proxy), info->hyphen_name); - } -} - -static guint -gxdp_trash_proxy_get_version (GXdpTrash *object) -{ - GXdpTrashProxy *proxy = GXDP_TRASH_PROXY (object); - GVariant *variant; - guint value = 0; - variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); - if (variant != NULL) - { - value = g_variant_get_uint32 (variant); - g_variant_unref (variant); - } - return value; -} - -static void -gxdp_trash_proxy_init (GXdpTrashProxy *proxy) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - proxy->priv = gxdp_trash_proxy_get_instance_private (proxy); -#else - proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_TRASH_PROXY, GXdpTrashProxyPrivate); -#endif - - g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_trash_interface_info ()); -} - -static void -gxdp_trash_proxy_class_init (GXdpTrashProxyClass *klass) -{ - GObjectClass *gobject_class; - GDBusProxyClass *proxy_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_trash_proxy_finalize; - gobject_class->get_property = gxdp_trash_proxy_get_property; - gobject_class->set_property = gxdp_trash_proxy_set_property; - - proxy_class = G_DBUS_PROXY_CLASS (klass); - proxy_class->g_signal = gxdp_trash_proxy_g_signal; - proxy_class->g_properties_changed = gxdp_trash_proxy_g_properties_changed; - - gxdp_trash_override_properties (gobject_class, 1); - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpTrashProxyPrivate)); -#endif -} - -static void -gxdp_trash_proxy_iface_init (GXdpTrashIface *iface) -{ - iface->get_version = gxdp_trash_proxy_get_version; -} - -/** - * gxdp_trash_proxy_new: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Trash. See g_dbus_proxy_new() for more details. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_trash_proxy_new_finish() to get the result of the operation. - * - * See gxdp_trash_proxy_new_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_trash_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_TRASH_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); -} - -/** - * gxdp_trash_proxy_new_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_trash_proxy_new(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_trash_proxy_new(). - * - * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpTrash * -gxdp_trash_proxy_new_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_TRASH (ret); - else - return NULL; -} - -/** - * gxdp_trash_proxy_new_sync: - * @connection: A #GDBusConnection. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Trash. See g_dbus_proxy_new_sync() for more details. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_trash_proxy_new() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpTrash * -gxdp_trash_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_TRASH_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); - if (ret != NULL) - return GXDP_TRASH (ret); - else - return NULL; -} - - -/** - * gxdp_trash_proxy_new_for_bus: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied. - * @user_data: User data to pass to @callback. - * - * Like gxdp_trash_proxy_new() but takes a #GBusType instead of a #GDBusConnection. - * - * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. - * You can then call gxdp_trash_proxy_new_for_bus_finish() to get the result of the operation. - * - * See gxdp_trash_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. - */ -void -gxdp_trash_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (GXDP_TYPE_TRASH_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); -} - -/** - * gxdp_trash_proxy_new_for_bus_finish: - * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_trash_proxy_new_for_bus(). - * @error: Return location for error or %NULL - * - * Finishes an operation started with gxdp_trash_proxy_new_for_bus(). - * - * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpTrash * -gxdp_trash_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error) -{ - GObject *ret; - GObject *source_object; - source_object = g_async_result_get_source_object (res); - ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); - g_object_unref (source_object); - if (ret != NULL) - return GXDP_TRASH (ret); - else - return NULL; -} - -/** - * gxdp_trash_proxy_new_for_bus_sync: - * @bus_type: A #GBusType. - * @flags: Flags from the #GDBusProxyFlags enumeration. - * @name: A bus name (well-known or unique). - * @object_path: An object path. - * @cancellable: (nullable): A #GCancellable or %NULL. - * @error: Return location for error or %NULL - * - * Like gxdp_trash_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. - * - * The calling thread is blocked until a reply is received. - * - * See gxdp_trash_proxy_new_for_bus() for the asynchronous version of this constructor. - * - * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. - */ -GXdpTrash * -gxdp_trash_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error) -{ - GInitable *ret; - ret = g_initable_new (GXDP_TYPE_TRASH_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); - if (ret != NULL) - return GXDP_TRASH (ret); - else - return NULL; -} - - -/* ------------------------------------------------------------------------ */ - -/** - * GXdpTrashSkeleton: - * - * The #GXdpTrashSkeleton structure contains only private data and should only be accessed using the provided API. - */ - -/** - * GXdpTrashSkeletonClass: - * @parent_class: The parent class. - * - * Class structure for #GXdpTrashSkeleton. - */ - -struct _GXdpTrashSkeletonPrivate -{ - GValue *properties; - GList *changed_properties; - GSource *changed_properties_idle_source; - GMainContext *context; - GMutex lock; -}; - -static void -_gxdp_trash_skeleton_handle_method_call ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); - _ExtendedGDBusMethodInfo *info; - GVariantIter iter; - GVariant *child; - GValue *paramv; - gsize num_params; - guint num_extra; - gsize n; - guint signal_id; - GValue return_value = G_VALUE_INIT; - info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); - g_assert (info != NULL); - num_params = g_variant_n_children (parameters); - num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); - n = 0; - g_value_init (¶mv[n], GXDP_TYPE_TRASH); - g_value_set_object (¶mv[n++], skeleton); - g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); - g_value_set_object (¶mv[n++], invocation); - if (info->pass_fdlist) - { -#ifdef G_OS_UNIX - g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); - g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); -#else - g_assert_not_reached (); -#endif - } - g_variant_iter_init (&iter, parameters); - while ((child = g_variant_iter_next_value (&iter)) != NULL) - { - _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; - if (arg_info->use_gvariant) - { - g_value_init (¶mv[n], G_TYPE_VARIANT); - g_value_set_variant (¶mv[n], child); - n++; - } - else - g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); - g_variant_unref (child); - } - signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_TRASH); - g_value_init (&return_value, G_TYPE_BOOLEAN); - g_signal_emitv (paramv, signal_id, 0, &return_value); - if (!g_value_get_boolean (&return_value)) - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); - g_value_unset (&return_value); - for (n = 0; n < num_params + num_extra; n++) - g_value_unset (¶mv[n]); - g_free (paramv); -} - -static GVariant * -_gxdp_trash_skeleton_handle_get_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - GVariant *ret; - ret = NULL; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); - ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); - g_value_unset (&value); - } - return ret; -} - -static gboolean -_gxdp_trash_skeleton_handle_set_property ( - GDBusConnection *connection G_GNUC_UNUSED, - const gchar *sender G_GNUC_UNUSED, - const gchar *object_path G_GNUC_UNUSED, - const gchar *interface_name G_GNUC_UNUSED, - const gchar *property_name, - GVariant *variant, - GError **error, - gpointer user_data) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - _ExtendedGDBusPropertyInfo *info; - gboolean ret; - ret = FALSE; - info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, property_name); - g_assert (info != NULL); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); - if (pspec == NULL) - { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); - } - else - { - if (info->use_gvariant) - g_value_set_variant (&value, variant); - else - g_dbus_gvariant_to_gvalue (variant, &value); - g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); - g_value_unset (&value); - ret = TRUE; - } - return ret; -} - -static const GDBusInterfaceVTable _gxdp_trash_skeleton_vtable = -{ - _gxdp_trash_skeleton_handle_method_call, - _gxdp_trash_skeleton_handle_get_property, - _gxdp_trash_skeleton_handle_set_property, - {NULL} -}; - -static GDBusInterfaceInfo * -gxdp_trash_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return gxdp_trash_interface_info (); -} - -static GDBusInterfaceVTable * -gxdp_trash_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) -{ - return (GDBusInterfaceVTable *) &_gxdp_trash_skeleton_vtable; -} - -static GVariant * -gxdp_trash_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (_skeleton); - - GVariantBuilder builder; - guint n; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - if (_gxdp_trash_interface_info.parent_struct.properties == NULL) - goto out; - for (n = 0; _gxdp_trash_interface_info.parent_struct.properties[n] != NULL; n++) - { - GDBusPropertyInfo *info = _gxdp_trash_interface_info.parent_struct.properties[n]; - if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) - { - GVariant *value; - value = _gxdp_trash_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.Trash", info->name, NULL, skeleton); - if (value != NULL) - { - g_variant_take_ref (value); - g_variant_builder_add (&builder, "{sv}", info->name, value); - g_variant_unref (value); - } - } - } -out: - return g_variant_builder_end (&builder); -} - -static gboolean _gxdp_trash_emit_changed (gpointer user_data); - -static void -gxdp_trash_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (_skeleton); - gboolean emit_changed = FALSE; - - g_mutex_lock (&skeleton->priv->lock); - if (skeleton->priv->changed_properties_idle_source != NULL) - { - g_source_destroy (skeleton->priv->changed_properties_idle_source); - skeleton->priv->changed_properties_idle_source = NULL; - emit_changed = TRUE; - } - g_mutex_unlock (&skeleton->priv->lock); - - if (emit_changed) - _gxdp_trash_emit_changed (skeleton); -} - -static void gxdp_trash_skeleton_iface_init (GXdpTrashIface *iface); -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 -G_DEFINE_TYPE_WITH_CODE (GXdpTrashSkeleton, gxdp_trash_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_ADD_PRIVATE (GXdpTrashSkeleton) - G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_skeleton_iface_init)) - -#else -G_DEFINE_TYPE_WITH_CODE (GXdpTrashSkeleton, gxdp_trash_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, - G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_skeleton_iface_init)) - -#endif -static void -gxdp_trash_skeleton_finalize (GObject *object) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); - guint n; - for (n = 0; n < 1; n++) - g_value_unset (&skeleton->priv->properties[n]); - g_free (skeleton->priv->properties); - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - if (skeleton->priv->changed_properties_idle_source != NULL) - g_source_destroy (skeleton->priv->changed_properties_idle_source); - g_main_context_unref (skeleton->priv->context); - g_mutex_clear (&skeleton->priv->lock); - G_OBJECT_CLASS (gxdp_trash_skeleton_parent_class)->finalize (object); -} - -static void -gxdp_trash_skeleton_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec G_GNUC_UNUSED) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); - g_assert (prop_id != 0 && prop_id - 1 < 1); - g_mutex_lock (&skeleton->priv->lock); - g_value_copy (&skeleton->priv->properties[prop_id - 1], value); - g_mutex_unlock (&skeleton->priv->lock); -} - -static gboolean -_gxdp_trash_emit_changed (gpointer user_data) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); - GList *l; - GVariantBuilder builder; - GVariantBuilder invalidated_builder; - guint num_changes; - - g_mutex_lock (&skeleton->priv->lock); - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); - for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) - { - ChangedProperty *cp = l->data; - GVariant *variant; - const GValue *cur_value; - - cur_value = &skeleton->priv->properties[cp->prop_id - 1]; - if (!_g_value_equal (cur_value, &cp->orig_value)) - { - variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); - g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); - g_variant_unref (variant); - num_changes++; - } - } - if (num_changes > 0) - { - GList *connections, *ll; - GVariant *signal_variant; - signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.Trash", - &builder, &invalidated_builder)); - connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); - for (ll = connections; ll != NULL; ll = ll->next) - { - GDBusConnection *connection = ll->data; - - g_dbus_connection_emit_signal (connection, - NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - signal_variant, - NULL); - } - g_variant_unref (signal_variant); - g_list_free_full (connections, g_object_unref); - } - else - { - g_variant_builder_clear (&builder); - g_variant_builder_clear (&invalidated_builder); - } - g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); - skeleton->priv->changed_properties = NULL; - skeleton->priv->changed_properties_idle_source = NULL; - g_mutex_unlock (&skeleton->priv->lock); - return FALSE; -} - -static void -_gxdp_trash_schedule_emit_changed (GXdpTrashSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) -{ - ChangedProperty *cp; - GList *l; - cp = NULL; - for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) - { - ChangedProperty *i_cp = l->data; - if (i_cp->info == info) - { - cp = i_cp; - break; - } - } - if (cp == NULL) - { - cp = g_new0 (ChangedProperty, 1); - cp->prop_id = prop_id; - cp->info = info; - skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); - g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); - g_value_copy (orig_value, &cp->orig_value); - } -} - -static void -gxdp_trash_skeleton_notify (GObject *object, - GParamSpec *pspec G_GNUC_UNUSED) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); - g_mutex_lock (&skeleton->priv->lock); - if (skeleton->priv->changed_properties != NULL && - skeleton->priv->changed_properties_idle_source == NULL) - { - skeleton->priv->changed_properties_idle_source = g_idle_source_new (); - g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); - g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_trash_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); - g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_trash_emit_changed"); - g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); - g_source_unref (skeleton->priv->changed_properties_idle_source); - } - g_mutex_unlock (&skeleton->priv->lock); -} - -static void -gxdp_trash_skeleton_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - const _ExtendedGDBusPropertyInfo *info; - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); - g_assert (prop_id != 0 && prop_id - 1 < 1); - info = (const _ExtendedGDBusPropertyInfo *) _gxdp_trash_property_info_pointers[prop_id - 1]; - g_mutex_lock (&skeleton->priv->lock); - g_object_freeze_notify (object); - if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) - { - if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && - info->emits_changed_signal) - _gxdp_trash_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); - g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); - g_object_notify_by_pspec (object, pspec); - } - g_mutex_unlock (&skeleton->priv->lock); - g_object_thaw_notify (object); -} - -static void -gxdp_trash_skeleton_init (GXdpTrashSkeleton *skeleton) -{ -#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 - skeleton->priv = gxdp_trash_skeleton_get_instance_private (skeleton); -#else - skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeletonPrivate); -#endif - - g_mutex_init (&skeleton->priv->lock); - skeleton->priv->context = g_main_context_ref_thread_default (); - skeleton->priv->properties = g_new0 (GValue, 1); - g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); -} - -static guint -gxdp_trash_skeleton_get_version (GXdpTrash *object) -{ - GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); - guint value; - g_mutex_lock (&skeleton->priv->lock); - value = g_value_get_uint (&(skeleton->priv->properties[0])); - g_mutex_unlock (&skeleton->priv->lock); - return value; -} - -static void -gxdp_trash_skeleton_class_init (GXdpTrashSkeletonClass *klass) -{ - GObjectClass *gobject_class; - GDBusInterfaceSkeletonClass *skeleton_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = gxdp_trash_skeleton_finalize; - gobject_class->get_property = gxdp_trash_skeleton_get_property; - gobject_class->set_property = gxdp_trash_skeleton_set_property; - gobject_class->notify = gxdp_trash_skeleton_notify; - - - gxdp_trash_override_properties (gobject_class, 1); - - skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); - skeleton_class->get_info = gxdp_trash_skeleton_dbus_interface_get_info; - skeleton_class->get_properties = gxdp_trash_skeleton_dbus_interface_get_properties; - skeleton_class->flush = gxdp_trash_skeleton_dbus_interface_flush; - skeleton_class->get_vtable = gxdp_trash_skeleton_dbus_interface_get_vtable; - -#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 - g_type_class_add_private (klass, sizeof (GXdpTrashSkeletonPrivate)); -#endif -} - -static void -gxdp_trash_skeleton_iface_init (GXdpTrashIface *iface) -{ - iface->get_version = gxdp_trash_skeleton_get_version; -} - -/** - * gxdp_trash_skeleton_new: - * - * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.Trash. - * - * Returns: (transfer full) (type GXdpTrashSkeleton): The skeleton object. - */ -GXdpTrash * -gxdp_trash_skeleton_new (void) -{ - return GXDP_TRASH (g_object_new (GXDP_TYPE_TRASH_SKELETON, NULL)); -} - +/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "xdp-dbus.h" + +#include +#ifdef G_OS_UNIX +# include +#endif + +typedef struct +{ + GDBusArgInfo parent_struct; + gboolean use_gvariant; +} _ExtendedGDBusArgInfo; + +typedef struct +{ + GDBusMethodInfo parent_struct; + const gchar *signal_name; + gboolean pass_fdlist; +} _ExtendedGDBusMethodInfo; + +typedef struct +{ + GDBusSignalInfo parent_struct; + const gchar *signal_name; +} _ExtendedGDBusSignalInfo; + +typedef struct +{ + GDBusPropertyInfo parent_struct; + const gchar *hyphen_name; + guint use_gvariant : 1; + guint emits_changed_signal : 1; +} _ExtendedGDBusPropertyInfo; + +typedef struct +{ + GDBusInterfaceInfo parent_struct; + const gchar *hyphen_name; +} _ExtendedGDBusInterfaceInfo; + +typedef struct +{ + const _ExtendedGDBusPropertyInfo *info; + guint prop_id; + GValue orig_value; /* the value before the change */ +} ChangedProperty; + +static void +_changed_property_free (ChangedProperty *data) +{ + g_value_unset (&data->orig_value); + g_free (data); +} + +static gboolean +_g_strv_equal0 (gchar **a, gchar **b) +{ + gboolean ret = FALSE; + guint n; + if (a == NULL && b == NULL) + { + ret = TRUE; + goto out; + } + if (a == NULL || b == NULL) + goto out; + if (g_strv_length (a) != g_strv_length (b)) + goto out; + for (n = 0; a[n] != NULL; n++) + if (g_strcmp0 (a[n], b[n]) != 0) + goto out; + ret = TRUE; +out: + return ret; +} + +static gboolean +_g_variant_equal0 (GVariant *a, GVariant *b) +{ + gboolean ret = FALSE; + if (a == NULL && b == NULL) + { + ret = TRUE; + goto out; + } + if (a == NULL || b == NULL) + goto out; + ret = g_variant_equal (a, b); +out: + return ret; +} + +G_GNUC_UNUSED static gboolean +_g_value_equal (const GValue *a, const GValue *b) +{ + gboolean ret = FALSE; + g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b)); + switch (G_VALUE_TYPE (a)) + { + case G_TYPE_BOOLEAN: + ret = (g_value_get_boolean (a) == g_value_get_boolean (b)); + break; + case G_TYPE_UCHAR: + ret = (g_value_get_uchar (a) == g_value_get_uchar (b)); + break; + case G_TYPE_INT: + ret = (g_value_get_int (a) == g_value_get_int (b)); + break; + case G_TYPE_UINT: + ret = (g_value_get_uint (a) == g_value_get_uint (b)); + break; + case G_TYPE_INT64: + ret = (g_value_get_int64 (a) == g_value_get_int64 (b)); + break; + case G_TYPE_UINT64: + ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b)); + break; + case G_TYPE_DOUBLE: + { + /* Avoid -Wfloat-equal warnings by doing a direct bit compare */ + gdouble da = g_value_get_double (a); + gdouble db = g_value_get_double (b); + ret = memcmp (&da, &db, sizeof (gdouble)) == 0; + } + break; + case G_TYPE_STRING: + ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0); + break; + case G_TYPE_VARIANT: + ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b)); + break; + default: + if (G_VALUE_TYPE (a) == G_TYPE_STRV) + ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b)); + else + g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a))); + break; + } + return ret; +} + +/* ------------------------------------------------------------------------ + * Code for interface org.freedesktop.portal.Documents + * ------------------------------------------------------------------------ + */ + +/** + * SECTION:GXdpDocuments + * @title: GXdpDocuments + * @short_description: Generated C code for the org.freedesktop.portal.Documents D-Bus interface + * + * This section contains code for working with the org.freedesktop.portal.Documents D-Bus interface in C. + */ + +/* ---- Introspection data for org.freedesktop.portal.Documents ---- */ + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_get_mount_point_OUT_ARG_path = +{ + { + -1, + (gchar *) "path", + (gchar *) "ay", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_get_mount_point_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_get_mount_point_OUT_ARG_path.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_get_mount_point = +{ + { + -1, + (gchar *) "GetMountPoint", + NULL, + (GDBusArgInfo **) &_gxdp_documents_method_info_get_mount_point_OUT_ARG_pointers, + NULL + }, + "handle-get-mount-point", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_IN_ARG_o_path_fd = +{ + { + -1, + (gchar *) "o_path_fd", + (gchar *) "h", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_IN_ARG_reuse_existing = +{ + { + -1, + (gchar *) "reuse_existing", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_IN_ARG_persistent = +{ + { + -1, + (gchar *) "persistent", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_IN_ARG_o_path_fd.parent_struct, + &_gxdp_documents_method_info_add_IN_ARG_reuse_existing.parent_struct, + &_gxdp_documents_method_info_add_IN_ARG_persistent.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_OUT_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_OUT_ARG_doc_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add = +{ + { + -1, + (gchar *) "Add", + (GDBusArgInfo **) &_gxdp_documents_method_info_add_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_add_OUT_ARG_pointers, + NULL + }, + "handle-add", + TRUE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_o_path_parent_fd = +{ + { + -1, + (gchar *) "o_path_parent_fd", + (gchar *) "h", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_filename = +{ + { + -1, + (gchar *) "filename", + (gchar *) "ay", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_reuse_existing = +{ + { + -1, + (gchar *) "reuse_existing", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_IN_ARG_persistent = +{ + { + -1, + (gchar *) "persistent", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_named_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_named_IN_ARG_o_path_parent_fd.parent_struct, + &_gxdp_documents_method_info_add_named_IN_ARG_filename.parent_struct, + &_gxdp_documents_method_info_add_named_IN_ARG_reuse_existing.parent_struct, + &_gxdp_documents_method_info_add_named_IN_ARG_persistent.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_OUT_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_named_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_named_OUT_ARG_doc_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add_named = +{ + { + -1, + (gchar *) "AddNamed", + (GDBusArgInfo **) &_gxdp_documents_method_info_add_named_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_add_named_OUT_ARG_pointers, + NULL + }, + "handle-add-named", + TRUE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_o_path_fds = +{ + { + -1, + (gchar *) "o_path_fds", + (gchar *) "ah", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_flags = +{ + { + -1, + (gchar *) "flags", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_app_id = +{ + { + -1, + (gchar *) "app_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_IN_ARG_permissions = +{ + { + -1, + (gchar *) "permissions", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_full_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_full_IN_ARG_o_path_fds.parent_struct, + &_gxdp_documents_method_info_add_full_IN_ARG_flags.parent_struct, + &_gxdp_documents_method_info_add_full_IN_ARG_app_id.parent_struct, + &_gxdp_documents_method_info_add_full_IN_ARG_permissions.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_OUT_ARG_doc_ids = +{ + { + -1, + (gchar *) "doc_ids", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_full_OUT_ARG_extra_out = +{ + { + -1, + (gchar *) "extra_out", + (gchar *) "a{sv}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_full_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_full_OUT_ARG_doc_ids.parent_struct, + &_gxdp_documents_method_info_add_full_OUT_ARG_extra_out.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add_full = +{ + { + -1, + (gchar *) "AddFull", + (GDBusArgInfo **) &_gxdp_documents_method_info_add_full_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_add_full_OUT_ARG_pointers, + NULL + }, + "handle-add-full", + TRUE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_IN_ARG_o_path_fd = +{ + { + -1, + (gchar *) "o_path_fd", + (gchar *) "h", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_IN_ARG_filename = +{ + { + -1, + (gchar *) "filename", + (gchar *) "ay", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_IN_ARG_flags = +{ + { + -1, + (gchar *) "flags", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_IN_ARG_app_id = +{ + { + -1, + (gchar *) "app_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_IN_ARG_permissions = +{ + { + -1, + (gchar *) "permissions", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_named_full_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_named_full_IN_ARG_o_path_fd.parent_struct, + &_gxdp_documents_method_info_add_named_full_IN_ARG_filename.parent_struct, + &_gxdp_documents_method_info_add_named_full_IN_ARG_flags.parent_struct, + &_gxdp_documents_method_info_add_named_full_IN_ARG_app_id.parent_struct, + &_gxdp_documents_method_info_add_named_full_IN_ARG_permissions.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_OUT_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_add_named_full_OUT_ARG_extra_out = +{ + { + -1, + (gchar *) "extra_out", + (gchar *) "a{sv}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_add_named_full_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_add_named_full_OUT_ARG_doc_id.parent_struct, + &_gxdp_documents_method_info_add_named_full_OUT_ARG_extra_out.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_add_named_full = +{ + { + -1, + (gchar *) "AddNamedFull", + (GDBusArgInfo **) &_gxdp_documents_method_info_add_named_full_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_add_named_full_OUT_ARG_pointers, + NULL + }, + "handle-add-named-full", + TRUE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_grant_permissions_IN_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_grant_permissions_IN_ARG_app_id = +{ + { + -1, + (gchar *) "app_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_grant_permissions_IN_ARG_permissions = +{ + { + -1, + (gchar *) "permissions", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_grant_permissions_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_grant_permissions_IN_ARG_doc_id.parent_struct, + &_gxdp_documents_method_info_grant_permissions_IN_ARG_app_id.parent_struct, + &_gxdp_documents_method_info_grant_permissions_IN_ARG_permissions.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_grant_permissions = +{ + { + -1, + (gchar *) "GrantPermissions", + (GDBusArgInfo **) &_gxdp_documents_method_info_grant_permissions_IN_ARG_pointers, + NULL, + NULL + }, + "handle-grant-permissions", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_revoke_permissions_IN_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_revoke_permissions_IN_ARG_app_id = +{ + { + -1, + (gchar *) "app_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_revoke_permissions_IN_ARG_permissions = +{ + { + -1, + (gchar *) "permissions", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_revoke_permissions_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_revoke_permissions_IN_ARG_doc_id.parent_struct, + &_gxdp_documents_method_info_revoke_permissions_IN_ARG_app_id.parent_struct, + &_gxdp_documents_method_info_revoke_permissions_IN_ARG_permissions.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_revoke_permissions = +{ + { + -1, + (gchar *) "RevokePermissions", + (GDBusArgInfo **) &_gxdp_documents_method_info_revoke_permissions_IN_ARG_pointers, + NULL, + NULL + }, + "handle-revoke-permissions", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_delete_IN_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_delete_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_delete_IN_ARG_doc_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_delete = +{ + { + -1, + (gchar *) "Delete", + (GDBusArgInfo **) &_gxdp_documents_method_info_delete_IN_ARG_pointers, + NULL, + NULL + }, + "handle-delete", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_lookup_IN_ARG_filename = +{ + { + -1, + (gchar *) "filename", + (gchar *) "ay", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_lookup_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_lookup_IN_ARG_filename.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_lookup_OUT_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_lookup_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_lookup_OUT_ARG_doc_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_lookup = +{ + { + -1, + (gchar *) "Lookup", + (GDBusArgInfo **) &_gxdp_documents_method_info_lookup_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_lookup_OUT_ARG_pointers, + NULL + }, + "handle-lookup", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_info_IN_ARG_doc_id = +{ + { + -1, + (gchar *) "doc_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_info_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_info_IN_ARG_doc_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_info_OUT_ARG_path = +{ + { + -1, + (gchar *) "path", + (gchar *) "ay", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_info_OUT_ARG_apps = +{ + { + -1, + (gchar *) "apps", + (gchar *) "a{sas}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_info_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_info_OUT_ARG_path.parent_struct, + &_gxdp_documents_method_info_info_OUT_ARG_apps.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_info = +{ + { + -1, + (gchar *) "Info", + (GDBusArgInfo **) &_gxdp_documents_method_info_info_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_info_OUT_ARG_pointers, + NULL + }, + "handle-info", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_list_IN_ARG_app_id = +{ + { + -1, + (gchar *) "app_id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_list_IN_ARG_pointers[] = +{ + &_gxdp_documents_method_info_list_IN_ARG_app_id.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_documents_method_info_list_OUT_ARG_docs = +{ + { + -1, + (gchar *) "docs", + (gchar *) "a{say}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_documents_method_info_list_OUT_ARG_pointers[] = +{ + &_gxdp_documents_method_info_list_OUT_ARG_docs.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_documents_method_info_list = +{ + { + -1, + (gchar *) "List", + (GDBusArgInfo **) &_gxdp_documents_method_info_list_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_documents_method_info_list_OUT_ARG_pointers, + NULL + }, + "handle-list", + FALSE +}; + +static const GDBusMethodInfo * const _gxdp_documents_method_info_pointers[] = +{ + &_gxdp_documents_method_info_get_mount_point.parent_struct, + &_gxdp_documents_method_info_add.parent_struct, + &_gxdp_documents_method_info_add_named.parent_struct, + &_gxdp_documents_method_info_add_full.parent_struct, + &_gxdp_documents_method_info_add_named_full.parent_struct, + &_gxdp_documents_method_info_grant_permissions.parent_struct, + &_gxdp_documents_method_info_revoke_permissions.parent_struct, + &_gxdp_documents_method_info_delete.parent_struct, + &_gxdp_documents_method_info_lookup.parent_struct, + &_gxdp_documents_method_info_info.parent_struct, + &_gxdp_documents_method_info_list.parent_struct, + NULL +}; + +static const _ExtendedGDBusPropertyInfo _gxdp_documents_property_info_version = +{ + { + -1, + (gchar *) "version", + (gchar *) "u", + G_DBUS_PROPERTY_INFO_FLAGS_READABLE, + NULL + }, + "version", + FALSE, + TRUE +}; + +static const GDBusPropertyInfo * const _gxdp_documents_property_info_pointers[] = +{ + &_gxdp_documents_property_info_version.parent_struct, + NULL +}; + +static const _ExtendedGDBusInterfaceInfo _gxdp_documents_interface_info = +{ + { + -1, + (gchar *) "org.freedesktop.portal.Documents", + (GDBusMethodInfo **) &_gxdp_documents_method_info_pointers, + NULL, + (GDBusPropertyInfo **) &_gxdp_documents_property_info_pointers, + NULL + }, + "documents", +}; + + +/** + * gxdp_documents_interface_info: + * + * Gets a machine-readable description of the org.freedesktop.portal.Documents D-Bus interface. + * + * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. + */ +GDBusInterfaceInfo * +gxdp_documents_interface_info (void) +{ + return (GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct; +} + +/** + * gxdp_documents_override_properties: + * @klass: The class structure for a #GObject derived class. + * @property_id_begin: The property id to assign to the first overridden property. + * + * Overrides all #GObject properties in the #GXdpDocuments interface for a concrete class. + * The properties are overridden in the order they are defined. + * + * Returns: The last property id. + */ +guint +gxdp_documents_override_properties (GObjectClass *klass, guint property_id_begin) +{ + g_object_class_override_property (klass, property_id_begin++, "version"); + return property_id_begin - 1; +} + + + +/** + * GXdpDocuments: + * + * Abstract interface type for the D-Bus interface org.freedesktop.portal.Documents. + */ + +/** + * GXdpDocumentsIface: + * @parent_iface: The parent interface. + * @handle_add: Handler for the #GXdpDocuments::handle-add signal. + * @handle_add_full: Handler for the #GXdpDocuments::handle-add-full signal. + * @handle_add_named: Handler for the #GXdpDocuments::handle-add-named signal. + * @handle_add_named_full: Handler for the #GXdpDocuments::handle-add-named-full signal. + * @handle_delete: Handler for the #GXdpDocuments::handle-delete signal. + * @handle_get_mount_point: Handler for the #GXdpDocuments::handle-get-mount-point signal. + * @handle_grant_permissions: Handler for the #GXdpDocuments::handle-grant-permissions signal. + * @handle_info: Handler for the #GXdpDocuments::handle-info signal. + * @handle_list: Handler for the #GXdpDocuments::handle-list signal. + * @handle_lookup: Handler for the #GXdpDocuments::handle-lookup signal. + * @handle_revoke_permissions: Handler for the #GXdpDocuments::handle-revoke-permissions signal. + * @get_version: Getter for the #GXdpDocuments:version property. + * + * Virtual table for the D-Bus interface org.freedesktop.portal.Documents. + */ + +typedef GXdpDocumentsIface GXdpDocumentsInterface; +G_DEFINE_INTERFACE (GXdpDocuments, gxdp_documents, G_TYPE_OBJECT) + +static void +gxdp_documents_default_init (GXdpDocumentsIface *iface) +{ + /* GObject signals for incoming D-Bus method calls: */ + /** + * GXdpDocuments::handle-get-mount-point: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * + * Signal emitted when a remote caller is invoking the GetMountPoint() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_get_mount_point() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-get-mount-point", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_get_mount_point), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 1, + G_TYPE_DBUS_METHOD_INVOCATION); + + /** + * GXdpDocuments::handle-add: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_o_path_fd: Argument passed by remote caller. + * @arg_reuse_existing: Argument passed by remote caller. + * @arg_persistent: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the Add() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-add", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 5, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + + /** + * GXdpDocuments::handle-add-named: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_o_path_parent_fd: Argument passed by remote caller. + * @arg_filename: Argument passed by remote caller. + * @arg_reuse_existing: Argument passed by remote caller. + * @arg_persistent: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the AddNamed() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add_named() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-add-named", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add_named), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 6, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + + /** + * GXdpDocuments::handle-add-full: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_o_path_fds: Argument passed by remote caller. + * @arg_flags: Argument passed by remote caller. + * @arg_app_id: Argument passed by remote caller. + * @arg_permissions: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the AddFull() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add_full() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-add-full", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add_full), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 6, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRV); + + /** + * GXdpDocuments::handle-add-named-full: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_o_path_fd: Argument passed by remote caller. + * @arg_filename: Argument passed by remote caller. + * @arg_flags: Argument passed by remote caller. + * @arg_app_id: Argument passed by remote caller. + * @arg_permissions: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the AddNamedFull() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_add_named_full() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-add-named-full", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_add_named_full), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 7, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRV); + + /** + * GXdpDocuments::handle-grant-permissions: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @arg_doc_id: Argument passed by remote caller. + * @arg_app_id: Argument passed by remote caller. + * @arg_permissions: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the GrantPermissions() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_grant_permissions() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-grant-permissions", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_grant_permissions), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 4, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRV); + + /** + * GXdpDocuments::handle-revoke-permissions: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @arg_doc_id: Argument passed by remote caller. + * @arg_app_id: Argument passed by remote caller. + * @arg_permissions: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the RevokePermissions() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_revoke_permissions() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-revoke-permissions", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_revoke_permissions), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 4, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRV); + + /** + * GXdpDocuments::handle-delete: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @arg_doc_id: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the Delete() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_delete() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-delete", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_delete), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * GXdpDocuments::handle-lookup: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @arg_filename: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the Lookup() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_lookup() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-lookup", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_lookup), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * GXdpDocuments::handle-info: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @arg_doc_id: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the Info() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_info() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-info", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_info), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /** + * GXdpDocuments::handle-list: + * @object: A #GXdpDocuments. + * @invocation: A #GDBusMethodInvocation. + * @arg_app_id: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the List() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_documents_complete_list() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-list", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpDocumentsIface, handle_list), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /* GObject properties for D-Bus properties: */ + /** + * GXdpDocuments:version: + * + * Represents the D-Bus property "version". + * + * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. + */ + g_object_interface_install_property (iface, + g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +/** + * gxdp_documents_get_version: (skip) + * @object: A #GXdpDocuments. + * + * Gets the value of the "version" D-Bus property. + * + * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. + * + * Returns: The property value. + */ +guint +gxdp_documents_get_version (GXdpDocuments *object) +{ + return GXDP_DOCUMENTS_GET_IFACE (object)->get_version (object); +} + +/** + * gxdp_documents_set_version: (skip) + * @object: A #GXdpDocuments. + * @value: The value to set. + * + * Sets the "version" D-Bus property to @value. + * + * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. + */ +void +gxdp_documents_set_version (GXdpDocuments *object, guint value) +{ + g_object_set (G_OBJECT (object), "version", value, NULL); +} + +/** + * gxdp_documents_call_get_mount_point: + * @proxy: A #GXdpDocumentsProxy. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GetMountPoint() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_get_mount_point_finish() to get the result of the operation. + * + * See gxdp_documents_call_get_mount_point_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_get_mount_point ( + GXdpDocuments *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GetMountPoint", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_get_mount_point_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_get_mount_point(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_get_mount_point(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_get_mount_point_finish ( + GXdpDocuments *proxy, + gchar **out_path, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^ay)", + out_path); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_get_mount_point_sync: + * @proxy: A #GXdpDocumentsProxy. + * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GetMountPoint() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_get_mount_point() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_get_mount_point_sync ( + GXdpDocuments *proxy, + gchar **out_path, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetMountPoint", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^ay)", + out_path); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_fd: Argument to pass with the method invocation. + * @arg_reuse_existing: Argument to pass with the method invocation. + * @arg_persistent: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the Add() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_add_finish() to get the result of the operation. + * + * See gxdp_documents_call_add_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_add ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "Add", + g_variant_new ("(@hbb)", + arg_o_path_fd, + arg_reuse_existing, + arg_persistent), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_add_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_add(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_doc_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_fd: Argument to pass with the method invocation. + * @arg_reuse_existing: Argument to pass with the method invocation. + * @arg_persistent: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the Add() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_add() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "Add", + g_variant_new ("(@hbb)", + arg_o_path_fd, + arg_reuse_existing, + arg_persistent), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_doc_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_named: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_parent_fd: Argument to pass with the method invocation. + * @arg_filename: Argument to pass with the method invocation. + * @arg_reuse_existing: Argument to pass with the method invocation. + * @arg_persistent: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the AddNamed() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_add_named_finish() to get the result of the operation. + * + * See gxdp_documents_call_add_named_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_add_named ( + GXdpDocuments *proxy, + GVariant *arg_o_path_parent_fd, + const gchar *arg_filename, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "AddNamed", + g_variant_new ("(@h^aybb)", + arg_o_path_parent_fd, + arg_filename, + arg_reuse_existing, + arg_persistent), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_add_named_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add_named(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_add_named(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_named_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_doc_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_named_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_parent_fd: Argument to pass with the method invocation. + * @arg_filename: Argument to pass with the method invocation. + * @arg_reuse_existing: Argument to pass with the method invocation. + * @arg_persistent: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the AddNamed() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_add_named() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_named_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_parent_fd, + const gchar *arg_filename, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "AddNamed", + g_variant_new ("(@h^aybb)", + arg_o_path_parent_fd, + arg_filename, + arg_reuse_existing, + arg_persistent), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_doc_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_full: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_fds: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the AddFull() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_add_full_finish() to get the result of the operation. + * + * See gxdp_documents_call_add_full_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_add_full ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fds, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "AddFull", + g_variant_new ("(@ahus^as)", + arg_o_path_fds, + arg_flags, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_add_full_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_doc_ids: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @out_extra_out: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add_full(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_add_full(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_full_finish ( + GXdpDocuments *proxy, + gchar ***out_doc_ids, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as@a{sv})", + out_doc_ids, + out_extra_out); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_full_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_fds: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_doc_ids: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @out_extra_out: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the AddFull() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_add_full() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_full_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fds, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + gchar ***out_doc_ids, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "AddFull", + g_variant_new ("(@ahus^as)", + arg_o_path_fds, + arg_flags, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as@a{sv})", + out_doc_ids, + out_extra_out); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_named_full: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_fd: Argument to pass with the method invocation. + * @arg_filename: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the AddNamedFull() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_add_named_full_finish() to get the result of the operation. + * + * See gxdp_documents_call_add_named_full_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_add_named_full ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + const gchar *arg_filename, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "AddNamedFull", + g_variant_new ("(@h^ayus^as)", + arg_o_path_fd, + arg_filename, + arg_flags, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_add_named_full_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_extra_out: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_add_named_full(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_add_named_full(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_named_full_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s@a{sv})", + out_doc_id, + out_extra_out); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_add_named_full_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_o_path_fd: Argument to pass with the method invocation. + * @arg_filename: Argument to pass with the method invocation. + * @arg_flags: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_extra_out: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the AddNamedFull() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_add_named_full() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_add_named_full_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + const gchar *arg_filename, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + gchar **out_doc_id, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "AddNamedFull", + g_variant_new ("(@h^ayus^as)", + arg_o_path_fd, + arg_filename, + arg_flags, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s@a{sv})", + out_doc_id, + out_extra_out); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_grant_permissions: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the GrantPermissions() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_grant_permissions_finish() to get the result of the operation. + * + * See gxdp_documents_call_grant_permissions_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_grant_permissions ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "GrantPermissions", + g_variant_new ("(ss^as)", + arg_doc_id, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_grant_permissions_finish: + * @proxy: A #GXdpDocumentsProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_grant_permissions(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_grant_permissions(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_grant_permissions_finish ( + GXdpDocuments *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_grant_permissions_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the GrantPermissions() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_grant_permissions() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_grant_permissions_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GrantPermissions", + g_variant_new ("(ss^as)", + arg_doc_id, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_revoke_permissions: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the RevokePermissions() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_revoke_permissions_finish() to get the result of the operation. + * + * See gxdp_documents_call_revoke_permissions_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_revoke_permissions ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "RevokePermissions", + g_variant_new ("(ss^as)", + arg_doc_id, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_revoke_permissions_finish: + * @proxy: A #GXdpDocumentsProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_revoke_permissions(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_revoke_permissions(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_revoke_permissions_finish ( + GXdpDocuments *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_revoke_permissions_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @arg_app_id: Argument to pass with the method invocation. + * @arg_permissions: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the RevokePermissions() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_revoke_permissions() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_revoke_permissions_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "RevokePermissions", + g_variant_new ("(ss^as)", + arg_doc_id, + arg_app_id, + arg_permissions), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_delete: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the Delete() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_delete_finish() to get the result of the operation. + * + * See gxdp_documents_call_delete_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_delete ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "Delete", + g_variant_new ("(s)", + arg_doc_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_delete_finish: + * @proxy: A #GXdpDocumentsProxy. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_delete(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_delete(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_delete_finish ( + GXdpDocuments *proxy, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_delete_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the Delete() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_delete() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_delete_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "Delete", + g_variant_new ("(s)", + arg_doc_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "()"); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_lookup: + * @proxy: A #GXdpDocumentsProxy. + * @arg_filename: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the Lookup() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_lookup_finish() to get the result of the operation. + * + * See gxdp_documents_call_lookup_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_lookup ( + GXdpDocuments *proxy, + const gchar *arg_filename, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "Lookup", + g_variant_new ("(^ay)", + arg_filename), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_lookup_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_lookup(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_lookup(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_lookup_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_doc_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_lookup_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_filename: Argument to pass with the method invocation. + * @out_doc_id: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the Lookup() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_lookup() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_lookup_sync ( + GXdpDocuments *proxy, + const gchar *arg_filename, + gchar **out_doc_id, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "Lookup", + g_variant_new ("(^ay)", + arg_filename), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(s)", + out_doc_id); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_info: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the Info() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_info_finish() to get the result of the operation. + * + * See gxdp_documents_call_info_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_info ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "Info", + g_variant_new ("(s)", + arg_doc_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_info_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_apps: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_info(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_info(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_info_finish ( + GXdpDocuments *proxy, + gchar **out_path, + GVariant **out_apps, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^ay@a{sas})", + out_path, + out_apps); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_info_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_doc_id: Argument to pass with the method invocation. + * @out_path: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_apps: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the Info() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_info() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_info_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + gchar **out_path, + GVariant **out_apps, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "Info", + g_variant_new ("(s)", + arg_doc_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^ay@a{sas})", + out_path, + out_apps); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_list: + * @proxy: A #GXdpDocumentsProxy. + * @arg_app_id: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the List() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_call_list_finish() to get the result of the operation. + * + * See gxdp_documents_call_list_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_documents_call_list ( + GXdpDocuments *proxy, + const gchar *arg_app_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "List", + g_variant_new ("(s)", + arg_app_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_documents_call_list_finish: + * @proxy: A #GXdpDocumentsProxy. + * @out_docs: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_call_list(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_documents_call_list(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_list_finish ( + GXdpDocuments *proxy, + GVariant **out_docs, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(@a{say})", + out_docs); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_call_list_sync: + * @proxy: A #GXdpDocumentsProxy. + * @arg_app_id: Argument to pass with the method invocation. + * @out_docs: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the List() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_documents_call_list() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_documents_call_list_sync ( + GXdpDocuments *proxy, + const gchar *arg_app_id, + GVariant **out_docs, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "List", + g_variant_new ("(s)", + arg_app_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(@a{say})", + out_docs); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_documents_complete_get_mount_point: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @path: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the GetMountPoint() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_get_mount_point ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *path) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^ay)", + path)); +} + +/** + * gxdp_documents_complete_add: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @doc_id: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the Add() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_add ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *doc_id) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(s)", + doc_id), + fd_list); +} + +/** + * gxdp_documents_complete_add_named: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @doc_id: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the AddNamed() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_add_named ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *doc_id) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(s)", + doc_id), + fd_list); +} + +/** + * gxdp_documents_complete_add_full: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @doc_ids: Parameter to return. + * @extra_out: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the AddFull() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_add_full ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *const *doc_ids, + GVariant *extra_out) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(^as@a{sv})", + doc_ids, + extra_out), + fd_list); +} + +/** + * gxdp_documents_complete_add_named_full: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @doc_id: Parameter to return. + * @extra_out: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the AddNamedFull() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_add_named_full ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *doc_id, + GVariant *extra_out) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(s@a{sv})", + doc_id, + extra_out), + fd_list); +} + +/** + * gxdp_documents_complete_grant_permissions: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the GrantPermissions() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_grant_permissions ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * gxdp_documents_complete_revoke_permissions: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the RevokePermissions() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_revoke_permissions ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * gxdp_documents_complete_delete: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * + * Helper function used in service implementations to finish handling invocations of the Delete() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_delete ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); +} + +/** + * gxdp_documents_complete_lookup: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @doc_id: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the Lookup() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_lookup ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *doc_id) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", + doc_id)); +} + +/** + * gxdp_documents_complete_info: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @path: Parameter to return. + * @apps: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the Info() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_info ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *path, + GVariant *apps) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^ay@a{sas})", + path, + apps)); +} + +/** + * gxdp_documents_complete_list: + * @object: A #GXdpDocuments. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @docs: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the List() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_documents_complete_list ( + GXdpDocuments *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GVariant *docs) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(@a{say})", + docs)); +} + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpDocumentsProxy: + * + * The #GXdpDocumentsProxy structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpDocumentsProxyClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpDocumentsProxy. + */ + +struct _GXdpDocumentsProxyPrivate +{ + GData *qdata; +}; + +static void gxdp_documents_proxy_iface_init (GXdpDocumentsIface *iface); + +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsProxy, gxdp_documents_proxy, G_TYPE_DBUS_PROXY, + G_ADD_PRIVATE (GXdpDocumentsProxy) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_proxy_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsProxy, gxdp_documents_proxy, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_proxy_iface_init)) + +#endif +static void +gxdp_documents_proxy_finalize (GObject *object) +{ + GXdpDocumentsProxy *proxy = GXDP_DOCUMENTS_PROXY (object); + g_datalist_clear (&proxy->priv->qdata); + G_OBJECT_CLASS (gxdp_documents_proxy_parent_class)->finalize (object); +} + +static void +gxdp_documents_proxy_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_documents_property_info_pointers[prop_id - 1]; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); + if (info->use_gvariant) + { + g_value_set_variant (value, variant); + } + else + { + if (variant != NULL) + g_dbus_gvariant_to_gvalue (variant, value); + } + if (variant != NULL) + g_variant_unref (variant); +} + +static void +gxdp_documents_proxy_set_property_cb (GDBusProxy *proxy, + GAsyncResult *res, + gpointer user_data) +{ + const _ExtendedGDBusPropertyInfo *info = user_data; + GError *error; + GVariant *_ret; + error = NULL; + _ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (!_ret) + { + g_warning ("Error setting property '%s' on interface org.freedesktop.portal.Documents: %s (%s, %d)", + info->parent_struct.name, + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + else + { + g_variant_unref (_ret); + } +} + +static void +gxdp_documents_proxy_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_documents_property_info_pointers[prop_id - 1]; + variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_dbus_proxy_call (G_DBUS_PROXY (object), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", "org.freedesktop.portal.Documents", info->parent_struct.name, variant), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, (GAsyncReadyCallback) gxdp_documents_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); + g_variant_unref (variant); +} + +static void +gxdp_documents_proxy_g_signal (GDBusProxy *proxy, + const gchar *sender_name G_GNUC_UNUSED, + const gchar *signal_name, + GVariant *parameters) +{ + _ExtendedGDBusSignalInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + gsize n; + guint signal_id; + info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, signal_name); + if (info == NULL) + return; + num_params = g_variant_n_children (parameters); + paramv = g_new0 (GValue, num_params + 1); + g_value_init (¶mv[0], GXDP_TYPE_DOCUMENTS); + g_value_set_object (¶mv[0], proxy); + g_variant_iter_init (&iter, parameters); + n = 1; + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_DOCUMENTS); + g_signal_emitv (paramv, signal_id, 0, NULL); + for (n = 0; n < num_params + 1; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static void +gxdp_documents_proxy_g_properties_changed (GDBusProxy *_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties) +{ + GXdpDocumentsProxy *proxy = GXDP_DOCUMENTS_PROXY (_proxy); + guint n; + const gchar *key; + GVariantIter *iter; + _ExtendedGDBusPropertyInfo *info; + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, key); + g_datalist_remove_data (&proxy->priv->qdata, key); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } + g_variant_iter_free (iter); + for (n = 0; invalidated_properties[n] != NULL; n++) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, invalidated_properties[n]); + g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } +} + +static guint +gxdp_documents_proxy_get_version (GXdpDocuments *object) +{ + GXdpDocumentsProxy *proxy = GXDP_DOCUMENTS_PROXY (object); + GVariant *variant; + guint value = 0; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); + if (variant != NULL) + { + value = g_variant_get_uint32 (variant); + g_variant_unref (variant); + } + return value; +} + +static void +gxdp_documents_proxy_init (GXdpDocumentsProxy *proxy) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + proxy->priv = gxdp_documents_proxy_get_instance_private (proxy); +#else + proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxyPrivate); +#endif + + g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_documents_interface_info ()); +} + +static void +gxdp_documents_proxy_class_init (GXdpDocumentsProxyClass *klass) +{ + GObjectClass *gobject_class; + GDBusProxyClass *proxy_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_documents_proxy_finalize; + gobject_class->get_property = gxdp_documents_proxy_get_property; + gobject_class->set_property = gxdp_documents_proxy_set_property; + + proxy_class = G_DBUS_PROXY_CLASS (klass); + proxy_class->g_signal = gxdp_documents_proxy_g_signal; + proxy_class->g_properties_changed = gxdp_documents_proxy_g_properties_changed; + + gxdp_documents_override_properties (gobject_class, 1); + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpDocumentsProxyPrivate)); +#endif +} + +static void +gxdp_documents_proxy_iface_init (GXdpDocumentsIface *iface) +{ + iface->get_version = gxdp_documents_proxy_get_version; +} + +/** + * gxdp_documents_proxy_new: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Documents. See g_dbus_proxy_new() for more details. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_proxy_new_finish() to get the result of the operation. + * + * See gxdp_documents_proxy_new_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_documents_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_DOCUMENTS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); +} + +/** + * gxdp_documents_proxy_new_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_proxy_new(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_documents_proxy_new(). + * + * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpDocuments * +gxdp_documents_proxy_new_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_DOCUMENTS (ret); + else + return NULL; +} + +/** + * gxdp_documents_proxy_new_sync: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Documents. See g_dbus_proxy_new_sync() for more details. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_documents_proxy_new() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpDocuments * +gxdp_documents_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_DOCUMENTS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); + if (ret != NULL) + return GXDP_DOCUMENTS (ret); + else + return NULL; +} + + +/** + * gxdp_documents_proxy_new_for_bus: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Like gxdp_documents_proxy_new() but takes a #GBusType instead of a #GDBusConnection. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_documents_proxy_new_for_bus_finish() to get the result of the operation. + * + * See gxdp_documents_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_documents_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_DOCUMENTS_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); +} + +/** + * gxdp_documents_proxy_new_for_bus_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_documents_proxy_new_for_bus(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_documents_proxy_new_for_bus(). + * + * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpDocuments * +gxdp_documents_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_DOCUMENTS (ret); + else + return NULL; +} + +/** + * gxdp_documents_proxy_new_for_bus_sync: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Like gxdp_documents_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_documents_proxy_new_for_bus() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpDocumentsProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpDocuments * +gxdp_documents_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_DOCUMENTS_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Documents", NULL); + if (ret != NULL) + return GXDP_DOCUMENTS (ret); + else + return NULL; +} + + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpDocumentsSkeleton: + * + * The #GXdpDocumentsSkeleton structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpDocumentsSkeletonClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpDocumentsSkeleton. + */ + +struct _GXdpDocumentsSkeletonPrivate +{ + GValue *properties; + GList *changed_properties; + GSource *changed_properties_idle_source; + GMainContext *context; + GMutex lock; +}; + +static void +_gxdp_documents_skeleton_handle_method_call ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); + _ExtendedGDBusMethodInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + guint num_extra; + gsize n; + guint signal_id; + GValue return_value = G_VALUE_INIT; + info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); + g_assert (info != NULL); + num_params = g_variant_n_children (parameters); + num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); + n = 0; + g_value_init (¶mv[n], GXDP_TYPE_DOCUMENTS); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); +#else + g_assert_not_reached (); +#endif + } + g_variant_iter_init (&iter, parameters); + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_DOCUMENTS); + g_value_init (&return_value, G_TYPE_BOOLEAN); + g_signal_emitv (paramv, signal_id, 0, &return_value); + if (!g_value_get_boolean (&return_value)) + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); + g_value_unset (&return_value); + for (n = 0; n < num_params + num_extra; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static GVariant * +_gxdp_documents_skeleton_handle_get_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + GVariant *ret; + ret = NULL; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); + ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_value_unset (&value); + } + return ret; +} + +static gboolean +_gxdp_documents_skeleton_handle_set_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GVariant *variant, + GError **error, + gpointer user_data) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + gboolean ret; + ret = FALSE; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_documents_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + if (info->use_gvariant) + g_value_set_variant (&value, variant); + else + g_dbus_gvariant_to_gvalue (variant, &value); + g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); + g_value_unset (&value); + ret = TRUE; + } + return ret; +} + +static const GDBusInterfaceVTable _gxdp_documents_skeleton_vtable = +{ + _gxdp_documents_skeleton_handle_method_call, + _gxdp_documents_skeleton_handle_get_property, + _gxdp_documents_skeleton_handle_set_property, + {NULL} +}; + +static GDBusInterfaceInfo * +gxdp_documents_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return gxdp_documents_interface_info (); +} + +static GDBusInterfaceVTable * +gxdp_documents_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return (GDBusInterfaceVTable *) &_gxdp_documents_skeleton_vtable; +} + +static GVariant * +gxdp_documents_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (_skeleton); + + GVariantBuilder builder; + guint n; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + if (_gxdp_documents_interface_info.parent_struct.properties == NULL) + goto out; + for (n = 0; _gxdp_documents_interface_info.parent_struct.properties[n] != NULL; n++) + { + GDBusPropertyInfo *info = _gxdp_documents_interface_info.parent_struct.properties[n]; + if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) + { + GVariant *value; + value = _gxdp_documents_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.Documents", info->name, NULL, skeleton); + if (value != NULL) + { + g_variant_take_ref (value); + g_variant_builder_add (&builder, "{sv}", info->name, value); + g_variant_unref (value); + } + } + } +out: + return g_variant_builder_end (&builder); +} + +static gboolean _gxdp_documents_emit_changed (gpointer user_data); + +static void +gxdp_documents_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (_skeleton); + gboolean emit_changed = FALSE; + + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties_idle_source != NULL) + { + g_source_destroy (skeleton->priv->changed_properties_idle_source); + skeleton->priv->changed_properties_idle_source = NULL; + emit_changed = TRUE; + } + g_mutex_unlock (&skeleton->priv->lock); + + if (emit_changed) + _gxdp_documents_emit_changed (skeleton); +} + +static void gxdp_documents_skeleton_iface_init (GXdpDocumentsIface *iface); +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsSkeleton, gxdp_documents_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_ADD_PRIVATE (GXdpDocumentsSkeleton) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_skeleton_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpDocumentsSkeleton, gxdp_documents_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_DOCUMENTS, gxdp_documents_skeleton_iface_init)) + +#endif +static void +gxdp_documents_skeleton_finalize (GObject *object) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); + guint n; + for (n = 0; n < 1; n++) + g_value_unset (&skeleton->priv->properties[n]); + g_free (skeleton->priv->properties); + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + if (skeleton->priv->changed_properties_idle_source != NULL) + g_source_destroy (skeleton->priv->changed_properties_idle_source); + g_main_context_unref (skeleton->priv->context); + g_mutex_clear (&skeleton->priv->lock); + G_OBJECT_CLASS (gxdp_documents_skeleton_parent_class)->finalize (object); +} + +static void +gxdp_documents_skeleton_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + g_mutex_lock (&skeleton->priv->lock); + g_value_copy (&skeleton->priv->properties[prop_id - 1], value); + g_mutex_unlock (&skeleton->priv->lock); +} + +static gboolean +_gxdp_documents_emit_changed (gpointer user_data) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (user_data); + GList *l; + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + guint num_changes; + + g_mutex_lock (&skeleton->priv->lock); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) + { + ChangedProperty *cp = l->data; + GVariant *variant; + const GValue *cur_value; + + cur_value = &skeleton->priv->properties[cp->prop_id - 1]; + if (!_g_value_equal (cur_value, &cp->orig_value)) + { + variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); + g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); + g_variant_unref (variant); + num_changes++; + } + } + if (num_changes > 0) + { + GList *connections, *ll; + GVariant *signal_variant; + signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.Documents", + &builder, &invalidated_builder)); + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + for (ll = connections; ll != NULL; ll = ll->next) + { + GDBusConnection *connection = ll->data; + + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + signal_variant, + NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); + } + else + { + g_variant_builder_clear (&builder); + g_variant_builder_clear (&invalidated_builder); + } + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + skeleton->priv->changed_properties = NULL; + skeleton->priv->changed_properties_idle_source = NULL; + g_mutex_unlock (&skeleton->priv->lock); + return FALSE; +} + +static void +_gxdp_documents_schedule_emit_changed (GXdpDocumentsSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) +{ + ChangedProperty *cp; + GList *l; + cp = NULL; + for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) + { + ChangedProperty *i_cp = l->data; + if (i_cp->info == info) + { + cp = i_cp; + break; + } + } + if (cp == NULL) + { + cp = g_new0 (ChangedProperty, 1); + cp->prop_id = prop_id; + cp->info = info; + skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); + g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); + g_value_copy (orig_value, &cp->orig_value); + } +} + +static void +gxdp_documents_skeleton_notify (GObject *object, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties != NULL && + skeleton->priv->changed_properties_idle_source == NULL) + { + skeleton->priv->changed_properties_idle_source = g_idle_source_new (); + g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); + g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_documents_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); + g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_documents_emit_changed"); + g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); + g_source_unref (skeleton->priv->changed_properties_idle_source); + } + g_mutex_unlock (&skeleton->priv->lock); +} + +static void +gxdp_documents_skeleton_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + const _ExtendedGDBusPropertyInfo *info; + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_documents_property_info_pointers[prop_id - 1]; + g_mutex_lock (&skeleton->priv->lock); + g_object_freeze_notify (object); + if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) + { + if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && + info->emits_changed_signal) + _gxdp_documents_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); + g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); + g_object_notify_by_pspec (object, pspec); + } + g_mutex_unlock (&skeleton->priv->lock); + g_object_thaw_notify (object); +} + +static void +gxdp_documents_skeleton_init (GXdpDocumentsSkeleton *skeleton) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + skeleton->priv = gxdp_documents_skeleton_get_instance_private (skeleton); +#else + skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeletonPrivate); +#endif + + g_mutex_init (&skeleton->priv->lock); + skeleton->priv->context = g_main_context_ref_thread_default (); + skeleton->priv->properties = g_new0 (GValue, 1); + g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); +} + +static guint +gxdp_documents_skeleton_get_version (GXdpDocuments *object) +{ + GXdpDocumentsSkeleton *skeleton = GXDP_DOCUMENTS_SKELETON (object); + guint value; + g_mutex_lock (&skeleton->priv->lock); + value = g_value_get_uint (&(skeleton->priv->properties[0])); + g_mutex_unlock (&skeleton->priv->lock); + return value; +} + +static void +gxdp_documents_skeleton_class_init (GXdpDocumentsSkeletonClass *klass) +{ + GObjectClass *gobject_class; + GDBusInterfaceSkeletonClass *skeleton_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_documents_skeleton_finalize; + gobject_class->get_property = gxdp_documents_skeleton_get_property; + gobject_class->set_property = gxdp_documents_skeleton_set_property; + gobject_class->notify = gxdp_documents_skeleton_notify; + + + gxdp_documents_override_properties (gobject_class, 1); + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_info = gxdp_documents_skeleton_dbus_interface_get_info; + skeleton_class->get_properties = gxdp_documents_skeleton_dbus_interface_get_properties; + skeleton_class->flush = gxdp_documents_skeleton_dbus_interface_flush; + skeleton_class->get_vtable = gxdp_documents_skeleton_dbus_interface_get_vtable; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpDocumentsSkeletonPrivate)); +#endif +} + +static void +gxdp_documents_skeleton_iface_init (GXdpDocumentsIface *iface) +{ + iface->get_version = gxdp_documents_skeleton_get_version; +} + +/** + * gxdp_documents_skeleton_new: + * + * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.Documents. + * + * Returns: (transfer full) (type GXdpDocumentsSkeleton): The skeleton object. + */ +GXdpDocuments * +gxdp_documents_skeleton_new (void) +{ + return GXDP_DOCUMENTS (g_object_new (GXDP_TYPE_DOCUMENTS_SKELETON, NULL)); +} + +/* ------------------------------------------------------------------------ + * Code for interface org.freedesktop.portal.OpenURI + * ------------------------------------------------------------------------ + */ + +/** + * SECTION:GXdpOpenURI + * @title: GXdpOpenURI + * @short_description: Generated C code for the org.freedesktop.portal.OpenURI D-Bus interface + * + * This section contains code for working with the org.freedesktop.portal.OpenURI D-Bus interface in C. + */ + +/* ---- Introspection data for org.freedesktop.portal.OpenURI ---- */ + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_IN_ARG_parent_window = +{ + { + -1, + (gchar *) "parent_window", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_IN_ARG_uri = +{ + { + -1, + (gchar *) "uri", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_IN_ARG_options = +{ + { + -1, + (gchar *) "options", + (gchar *) "a{sv}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_uri_IN_ARG_pointers[] = +{ + &_gxdp_open_uri_method_info_open_uri_IN_ARG_parent_window.parent_struct, + &_gxdp_open_uri_method_info_open_uri_IN_ARG_uri.parent_struct, + &_gxdp_open_uri_method_info_open_uri_IN_ARG_options.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_uri_OUT_ARG_handle = +{ + { + -1, + (gchar *) "handle", + (gchar *) "o", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_uri_OUT_ARG_pointers[] = +{ + &_gxdp_open_uri_method_info_open_uri_OUT_ARG_handle.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_open_uri_method_info_open_uri = +{ + { + -1, + (gchar *) "OpenURI", + (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_uri_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_uri_OUT_ARG_pointers, + NULL + }, + "handle-open-uri", + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_IN_ARG_parent_window = +{ + { + -1, + (gchar *) "parent_window", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_IN_ARG_fd = +{ + { + -1, + (gchar *) "fd", + (gchar *) "h", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_IN_ARG_options = +{ + { + -1, + (gchar *) "options", + (gchar *) "a{sv}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_file_IN_ARG_pointers[] = +{ + &_gxdp_open_uri_method_info_open_file_IN_ARG_parent_window.parent_struct, + &_gxdp_open_uri_method_info_open_file_IN_ARG_fd.parent_struct, + &_gxdp_open_uri_method_info_open_file_IN_ARG_options.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_file_OUT_ARG_handle = +{ + { + -1, + (gchar *) "handle", + (gchar *) "o", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_file_OUT_ARG_pointers[] = +{ + &_gxdp_open_uri_method_info_open_file_OUT_ARG_handle.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_open_uri_method_info_open_file = +{ + { + -1, + (gchar *) "OpenFile", + (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_file_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_file_OUT_ARG_pointers, + NULL + }, + "handle-open-file", + TRUE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_directory_IN_ARG_parent_window = +{ + { + -1, + (gchar *) "parent_window", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_directory_IN_ARG_fd = +{ + { + -1, + (gchar *) "fd", + (gchar *) "h", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_directory_IN_ARG_options = +{ + { + -1, + (gchar *) "options", + (gchar *) "a{sv}", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_directory_IN_ARG_pointers[] = +{ + &_gxdp_open_uri_method_info_open_directory_IN_ARG_parent_window.parent_struct, + &_gxdp_open_uri_method_info_open_directory_IN_ARG_fd.parent_struct, + &_gxdp_open_uri_method_info_open_directory_IN_ARG_options.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_open_uri_method_info_open_directory_OUT_ARG_handle = +{ + { + -1, + (gchar *) "handle", + (gchar *) "o", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_open_uri_method_info_open_directory_OUT_ARG_pointers[] = +{ + &_gxdp_open_uri_method_info_open_directory_OUT_ARG_handle.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_open_uri_method_info_open_directory = +{ + { + -1, + (gchar *) "OpenDirectory", + (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_directory_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_open_uri_method_info_open_directory_OUT_ARG_pointers, + NULL + }, + "handle-open-directory", + TRUE +}; + +static const GDBusMethodInfo * const _gxdp_open_uri_method_info_pointers[] = +{ + &_gxdp_open_uri_method_info_open_uri.parent_struct, + &_gxdp_open_uri_method_info_open_file.parent_struct, + &_gxdp_open_uri_method_info_open_directory.parent_struct, + NULL +}; + +static const _ExtendedGDBusPropertyInfo _gxdp_open_uri_property_info_version = +{ + { + -1, + (gchar *) "version", + (gchar *) "u", + G_DBUS_PROPERTY_INFO_FLAGS_READABLE, + NULL + }, + "version", + FALSE, + TRUE +}; + +static const GDBusPropertyInfo * const _gxdp_open_uri_property_info_pointers[] = +{ + &_gxdp_open_uri_property_info_version.parent_struct, + NULL +}; + +static const _ExtendedGDBusInterfaceInfo _gxdp_open_uri_interface_info = +{ + { + -1, + (gchar *) "org.freedesktop.portal.OpenURI", + (GDBusMethodInfo **) &_gxdp_open_uri_method_info_pointers, + NULL, + (GDBusPropertyInfo **) &_gxdp_open_uri_property_info_pointers, + NULL + }, + "open-uri", +}; + + +/** + * gxdp_open_uri_interface_info: + * + * Gets a machine-readable description of the org.freedesktop.portal.OpenURI D-Bus interface. + * + * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. + */ +GDBusInterfaceInfo * +gxdp_open_uri_interface_info (void) +{ + return (GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct; +} + +/** + * gxdp_open_uri_override_properties: + * @klass: The class structure for a #GObject derived class. + * @property_id_begin: The property id to assign to the first overridden property. + * + * Overrides all #GObject properties in the #GXdpOpenURI interface for a concrete class. + * The properties are overridden in the order they are defined. + * + * Returns: The last property id. + */ +guint +gxdp_open_uri_override_properties (GObjectClass *klass, guint property_id_begin) +{ + g_object_class_override_property (klass, property_id_begin++, "version"); + return property_id_begin - 1; +} + + + +/** + * GXdpOpenURI: + * + * Abstract interface type for the D-Bus interface org.freedesktop.portal.OpenURI. + */ + +/** + * GXdpOpenURIIface: + * @parent_iface: The parent interface. + * @handle_open_directory: Handler for the #GXdpOpenURI::handle-open-directory signal. + * @handle_open_file: Handler for the #GXdpOpenURI::handle-open-file signal. + * @handle_open_uri: Handler for the #GXdpOpenURI::handle-open-uri signal. + * @get_version: Getter for the #GXdpOpenURI:version property. + * + * Virtual table for the D-Bus interface org.freedesktop.portal.OpenURI. + */ + +typedef GXdpOpenURIIface GXdpOpenURIInterface; +G_DEFINE_INTERFACE (GXdpOpenURI, gxdp_open_uri, G_TYPE_OBJECT) + +static void +gxdp_open_uri_default_init (GXdpOpenURIIface *iface) +{ + /* GObject signals for incoming D-Bus method calls: */ + /** + * GXdpOpenURI::handle-open-uri: + * @object: A #GXdpOpenURI. + * @invocation: A #GDBusMethodInvocation. + * @arg_parent_window: Argument passed by remote caller. + * @arg_uri: Argument passed by remote caller. + * @arg_options: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the OpenURI() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_open_uri_complete_open_uri() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-open-uri", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpOpenURIIface, handle_open_uri), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 4, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_VARIANT); + + /** + * GXdpOpenURI::handle-open-file: + * @object: A #GXdpOpenURI. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_parent_window: Argument passed by remote caller. + * @arg_fd: Argument passed by remote caller. + * @arg_options: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the OpenFile() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_open_uri_complete_open_file() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-open-file", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpOpenURIIface, handle_open_file), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 5, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_STRING, G_TYPE_VARIANT, G_TYPE_VARIANT); + + /** + * GXdpOpenURI::handle-open-directory: + * @object: A #GXdpOpenURI. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_parent_window: Argument passed by remote caller. + * @arg_fd: Argument passed by remote caller. + * @arg_options: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the OpenDirectory() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_open_uri_complete_open_directory() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-open-directory", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpOpenURIIface, handle_open_directory), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 5, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_STRING, G_TYPE_VARIANT, G_TYPE_VARIANT); + + /* GObject properties for D-Bus properties: */ + /** + * GXdpOpenURI:version: + * + * Represents the D-Bus property "version". + * + * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. + */ + g_object_interface_install_property (iface, + g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +/** + * gxdp_open_uri_get_version: (skip) + * @object: A #GXdpOpenURI. + * + * Gets the value of the "version" D-Bus property. + * + * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. + * + * Returns: The property value. + */ +guint +gxdp_open_uri_get_version (GXdpOpenURI *object) +{ + return GXDP_OPEN_URI_GET_IFACE (object)->get_version (object); +} + +/** + * gxdp_open_uri_set_version: (skip) + * @object: A #GXdpOpenURI. + * @value: The value to set. + * + * Sets the "version" D-Bus property to @value. + * + * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. + */ +void +gxdp_open_uri_set_version (GXdpOpenURI *object, guint value) +{ + g_object_set (G_OBJECT (object), "version", value, NULL); +} + +/** + * gxdp_open_uri_call_open_uri: + * @proxy: A #GXdpOpenURIProxy. + * @arg_parent_window: Argument to pass with the method invocation. + * @arg_uri: Argument to pass with the method invocation. + * @arg_options: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the OpenURI() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_open_uri_call_open_uri_finish() to get the result of the operation. + * + * See gxdp_open_uri_call_open_uri_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_open_uri_call_open_uri ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + const gchar *arg_uri, + GVariant *arg_options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "OpenURI", + g_variant_new ("(ss@a{sv})", + arg_parent_window, + arg_uri, + arg_options), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_open_uri_call_open_uri_finish: + * @proxy: A #GXdpOpenURIProxy. + * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_call_open_uri(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_open_uri_call_open_uri(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_open_uri_call_open_uri_finish ( + GXdpOpenURI *proxy, + gchar **out_handle, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(o)", + out_handle); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_open_uri_call_open_uri_sync: + * @proxy: A #GXdpOpenURIProxy. + * @arg_parent_window: Argument to pass with the method invocation. + * @arg_uri: Argument to pass with the method invocation. + * @arg_options: Argument to pass with the method invocation. + * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the OpenURI() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_open_uri_call_open_uri() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_open_uri_call_open_uri_sync ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + const gchar *arg_uri, + GVariant *arg_options, + gchar **out_handle, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "OpenURI", + g_variant_new ("(ss@a{sv})", + arg_parent_window, + arg_uri, + arg_options), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(o)", + out_handle); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_open_uri_call_open_file: + * @proxy: A #GXdpOpenURIProxy. + * @arg_parent_window: Argument to pass with the method invocation. + * @arg_fd: Argument to pass with the method invocation. + * @arg_options: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the OpenFile() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_open_uri_call_open_file_finish() to get the result of the operation. + * + * See gxdp_open_uri_call_open_file_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_open_uri_call_open_file ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "OpenFile", + g_variant_new ("(s@h@a{sv})", + arg_parent_window, + arg_fd, + arg_options), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_open_uri_call_open_file_finish: + * @proxy: A #GXdpOpenURIProxy. + * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_call_open_file(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_open_uri_call_open_file(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_open_uri_call_open_file_finish ( + GXdpOpenURI *proxy, + gchar **out_handle, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(o)", + out_handle); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_open_uri_call_open_file_sync: + * @proxy: A #GXdpOpenURIProxy. + * @arg_parent_window: Argument to pass with the method invocation. + * @arg_fd: Argument to pass with the method invocation. + * @arg_options: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the OpenFile() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_open_uri_call_open_file() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_open_uri_call_open_file_sync ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + gchar **out_handle, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "OpenFile", + g_variant_new ("(s@h@a{sv})", + arg_parent_window, + arg_fd, + arg_options), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(o)", + out_handle); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_open_uri_call_open_directory: + * @proxy: A #GXdpOpenURIProxy. + * @arg_parent_window: Argument to pass with the method invocation. + * @arg_fd: Argument to pass with the method invocation. + * @arg_options: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the OpenDirectory() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_open_uri_call_open_directory_finish() to get the result of the operation. + * + * See gxdp_open_uri_call_open_directory_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_open_uri_call_open_directory ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "OpenDirectory", + g_variant_new ("(s@h@a{sv})", + arg_parent_window, + arg_fd, + arg_options), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_open_uri_call_open_directory_finish: + * @proxy: A #GXdpOpenURIProxy. + * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_call_open_directory(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_open_uri_call_open_directory(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_open_uri_call_open_directory_finish ( + GXdpOpenURI *proxy, + gchar **out_handle, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(o)", + out_handle); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_open_uri_call_open_directory_sync: + * @proxy: A #GXdpOpenURIProxy. + * @arg_parent_window: Argument to pass with the method invocation. + * @arg_fd: Argument to pass with the method invocation. + * @arg_options: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_handle: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the OpenDirectory() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_open_uri_call_open_directory() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_open_uri_call_open_directory_sync ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + gchar **out_handle, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "OpenDirectory", + g_variant_new ("(s@h@a{sv})", + arg_parent_window, + arg_fd, + arg_options), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(o)", + out_handle); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_open_uri_complete_open_uri: + * @object: A #GXdpOpenURI. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @handle: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the OpenURI() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_open_uri_complete_open_uri ( + GXdpOpenURI *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *handle) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(o)", + handle)); +} + +/** + * gxdp_open_uri_complete_open_file: + * @object: A #GXdpOpenURI. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @handle: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the OpenFile() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_open_uri_complete_open_file ( + GXdpOpenURI *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *handle) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(o)", + handle), + fd_list); +} + +/** + * gxdp_open_uri_complete_open_directory: + * @object: A #GXdpOpenURI. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @handle: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the OpenDirectory() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_open_uri_complete_open_directory ( + GXdpOpenURI *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *handle) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(o)", + handle), + fd_list); +} + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpOpenURIProxy: + * + * The #GXdpOpenURIProxy structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpOpenURIProxyClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpOpenURIProxy. + */ + +struct _GXdpOpenURIProxyPrivate +{ + GData *qdata; +}; + +static void gxdp_open_uri_proxy_iface_init (GXdpOpenURIIface *iface); + +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpOpenURIProxy, gxdp_open_uri_proxy, G_TYPE_DBUS_PROXY, + G_ADD_PRIVATE (GXdpOpenURIProxy) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_proxy_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpOpenURIProxy, gxdp_open_uri_proxy, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_proxy_iface_init)) + +#endif +static void +gxdp_open_uri_proxy_finalize (GObject *object) +{ + GXdpOpenURIProxy *proxy = GXDP_OPEN_URI_PROXY (object); + g_datalist_clear (&proxy->priv->qdata); + G_OBJECT_CLASS (gxdp_open_uri_proxy_parent_class)->finalize (object); +} + +static void +gxdp_open_uri_proxy_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_open_uri_property_info_pointers[prop_id - 1]; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); + if (info->use_gvariant) + { + g_value_set_variant (value, variant); + } + else + { + if (variant != NULL) + g_dbus_gvariant_to_gvalue (variant, value); + } + if (variant != NULL) + g_variant_unref (variant); +} + +static void +gxdp_open_uri_proxy_set_property_cb (GDBusProxy *proxy, + GAsyncResult *res, + gpointer user_data) +{ + const _ExtendedGDBusPropertyInfo *info = user_data; + GError *error; + GVariant *_ret; + error = NULL; + _ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (!_ret) + { + g_warning ("Error setting property '%s' on interface org.freedesktop.portal.OpenURI: %s (%s, %d)", + info->parent_struct.name, + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + else + { + g_variant_unref (_ret); + } +} + +static void +gxdp_open_uri_proxy_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_open_uri_property_info_pointers[prop_id - 1]; + variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_dbus_proxy_call (G_DBUS_PROXY (object), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", "org.freedesktop.portal.OpenURI", info->parent_struct.name, variant), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, (GAsyncReadyCallback) gxdp_open_uri_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); + g_variant_unref (variant); +} + +static void +gxdp_open_uri_proxy_g_signal (GDBusProxy *proxy, + const gchar *sender_name G_GNUC_UNUSED, + const gchar *signal_name, + GVariant *parameters) +{ + _ExtendedGDBusSignalInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + gsize n; + guint signal_id; + info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, signal_name); + if (info == NULL) + return; + num_params = g_variant_n_children (parameters); + paramv = g_new0 (GValue, num_params + 1); + g_value_init (¶mv[0], GXDP_TYPE_OPEN_URI); + g_value_set_object (¶mv[0], proxy); + g_variant_iter_init (&iter, parameters); + n = 1; + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_OPEN_URI); + g_signal_emitv (paramv, signal_id, 0, NULL); + for (n = 0; n < num_params + 1; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static void +gxdp_open_uri_proxy_g_properties_changed (GDBusProxy *_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties) +{ + GXdpOpenURIProxy *proxy = GXDP_OPEN_URI_PROXY (_proxy); + guint n; + const gchar *key; + GVariantIter *iter; + _ExtendedGDBusPropertyInfo *info; + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, key); + g_datalist_remove_data (&proxy->priv->qdata, key); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } + g_variant_iter_free (iter); + for (n = 0; invalidated_properties[n] != NULL; n++) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, invalidated_properties[n]); + g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } +} + +static guint +gxdp_open_uri_proxy_get_version (GXdpOpenURI *object) +{ + GXdpOpenURIProxy *proxy = GXDP_OPEN_URI_PROXY (object); + GVariant *variant; + guint value = 0; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); + if (variant != NULL) + { + value = g_variant_get_uint32 (variant); + g_variant_unref (variant); + } + return value; +} + +static void +gxdp_open_uri_proxy_init (GXdpOpenURIProxy *proxy) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + proxy->priv = gxdp_open_uri_proxy_get_instance_private (proxy); +#else + proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxyPrivate); +#endif + + g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_open_uri_interface_info ()); +} + +static void +gxdp_open_uri_proxy_class_init (GXdpOpenURIProxyClass *klass) +{ + GObjectClass *gobject_class; + GDBusProxyClass *proxy_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_open_uri_proxy_finalize; + gobject_class->get_property = gxdp_open_uri_proxy_get_property; + gobject_class->set_property = gxdp_open_uri_proxy_set_property; + + proxy_class = G_DBUS_PROXY_CLASS (klass); + proxy_class->g_signal = gxdp_open_uri_proxy_g_signal; + proxy_class->g_properties_changed = gxdp_open_uri_proxy_g_properties_changed; + + gxdp_open_uri_override_properties (gobject_class, 1); + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpOpenURIProxyPrivate)); +#endif +} + +static void +gxdp_open_uri_proxy_iface_init (GXdpOpenURIIface *iface) +{ + iface->get_version = gxdp_open_uri_proxy_get_version; +} + +/** + * gxdp_open_uri_proxy_new: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.OpenURI. See g_dbus_proxy_new() for more details. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_open_uri_proxy_new_finish() to get the result of the operation. + * + * See gxdp_open_uri_proxy_new_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_open_uri_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_OPEN_URI_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); +} + +/** + * gxdp_open_uri_proxy_new_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_proxy_new(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_open_uri_proxy_new(). + * + * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpOpenURI * +gxdp_open_uri_proxy_new_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_OPEN_URI (ret); + else + return NULL; +} + +/** + * gxdp_open_uri_proxy_new_sync: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.OpenURI. See g_dbus_proxy_new_sync() for more details. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_open_uri_proxy_new() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpOpenURI * +gxdp_open_uri_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_OPEN_URI_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); + if (ret != NULL) + return GXDP_OPEN_URI (ret); + else + return NULL; +} + + +/** + * gxdp_open_uri_proxy_new_for_bus: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Like gxdp_open_uri_proxy_new() but takes a #GBusType instead of a #GDBusConnection. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_open_uri_proxy_new_for_bus_finish() to get the result of the operation. + * + * See gxdp_open_uri_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_open_uri_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_OPEN_URI_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); +} + +/** + * gxdp_open_uri_proxy_new_for_bus_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_open_uri_proxy_new_for_bus(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_open_uri_proxy_new_for_bus(). + * + * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpOpenURI * +gxdp_open_uri_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_OPEN_URI (ret); + else + return NULL; +} + +/** + * gxdp_open_uri_proxy_new_for_bus_sync: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Like gxdp_open_uri_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_open_uri_proxy_new_for_bus() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpOpenURIProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpOpenURI * +gxdp_open_uri_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_OPEN_URI_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.OpenURI", NULL); + if (ret != NULL) + return GXDP_OPEN_URI (ret); + else + return NULL; +} + + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpOpenURISkeleton: + * + * The #GXdpOpenURISkeleton structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpOpenURISkeletonClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpOpenURISkeleton. + */ + +struct _GXdpOpenURISkeletonPrivate +{ + GValue *properties; + GList *changed_properties; + GSource *changed_properties_idle_source; + GMainContext *context; + GMutex lock; +}; + +static void +_gxdp_open_uri_skeleton_handle_method_call ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); + _ExtendedGDBusMethodInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + guint num_extra; + gsize n; + guint signal_id; + GValue return_value = G_VALUE_INIT; + info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); + g_assert (info != NULL); + num_params = g_variant_n_children (parameters); + num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); + n = 0; + g_value_init (¶mv[n], GXDP_TYPE_OPEN_URI); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); +#else + g_assert_not_reached (); +#endif + } + g_variant_iter_init (&iter, parameters); + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_OPEN_URI); + g_value_init (&return_value, G_TYPE_BOOLEAN); + g_signal_emitv (paramv, signal_id, 0, &return_value); + if (!g_value_get_boolean (&return_value)) + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); + g_value_unset (&return_value); + for (n = 0; n < num_params + num_extra; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static GVariant * +_gxdp_open_uri_skeleton_handle_get_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + GVariant *ret; + ret = NULL; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); + ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_value_unset (&value); + } + return ret; +} + +static gboolean +_gxdp_open_uri_skeleton_handle_set_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GVariant *variant, + GError **error, + gpointer user_data) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + gboolean ret; + ret = FALSE; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_open_uri_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + if (info->use_gvariant) + g_value_set_variant (&value, variant); + else + g_dbus_gvariant_to_gvalue (variant, &value); + g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); + g_value_unset (&value); + ret = TRUE; + } + return ret; +} + +static const GDBusInterfaceVTable _gxdp_open_uri_skeleton_vtable = +{ + _gxdp_open_uri_skeleton_handle_method_call, + _gxdp_open_uri_skeleton_handle_get_property, + _gxdp_open_uri_skeleton_handle_set_property, + {NULL} +}; + +static GDBusInterfaceInfo * +gxdp_open_uri_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return gxdp_open_uri_interface_info (); +} + +static GDBusInterfaceVTable * +gxdp_open_uri_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return (GDBusInterfaceVTable *) &_gxdp_open_uri_skeleton_vtable; +} + +static GVariant * +gxdp_open_uri_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (_skeleton); + + GVariantBuilder builder; + guint n; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + if (_gxdp_open_uri_interface_info.parent_struct.properties == NULL) + goto out; + for (n = 0; _gxdp_open_uri_interface_info.parent_struct.properties[n] != NULL; n++) + { + GDBusPropertyInfo *info = _gxdp_open_uri_interface_info.parent_struct.properties[n]; + if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) + { + GVariant *value; + value = _gxdp_open_uri_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.OpenURI", info->name, NULL, skeleton); + if (value != NULL) + { + g_variant_take_ref (value); + g_variant_builder_add (&builder, "{sv}", info->name, value); + g_variant_unref (value); + } + } + } +out: + return g_variant_builder_end (&builder); +} + +static gboolean _gxdp_open_uri_emit_changed (gpointer user_data); + +static void +gxdp_open_uri_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (_skeleton); + gboolean emit_changed = FALSE; + + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties_idle_source != NULL) + { + g_source_destroy (skeleton->priv->changed_properties_idle_source); + skeleton->priv->changed_properties_idle_source = NULL; + emit_changed = TRUE; + } + g_mutex_unlock (&skeleton->priv->lock); + + if (emit_changed) + _gxdp_open_uri_emit_changed (skeleton); +} + +static void gxdp_open_uri_skeleton_iface_init (GXdpOpenURIIface *iface); +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpOpenURISkeleton, gxdp_open_uri_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_ADD_PRIVATE (GXdpOpenURISkeleton) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_skeleton_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpOpenURISkeleton, gxdp_open_uri_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_OPEN_URI, gxdp_open_uri_skeleton_iface_init)) + +#endif +static void +gxdp_open_uri_skeleton_finalize (GObject *object) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); + guint n; + for (n = 0; n < 1; n++) + g_value_unset (&skeleton->priv->properties[n]); + g_free (skeleton->priv->properties); + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + if (skeleton->priv->changed_properties_idle_source != NULL) + g_source_destroy (skeleton->priv->changed_properties_idle_source); + g_main_context_unref (skeleton->priv->context); + g_mutex_clear (&skeleton->priv->lock); + G_OBJECT_CLASS (gxdp_open_uri_skeleton_parent_class)->finalize (object); +} + +static void +gxdp_open_uri_skeleton_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + g_mutex_lock (&skeleton->priv->lock); + g_value_copy (&skeleton->priv->properties[prop_id - 1], value); + g_mutex_unlock (&skeleton->priv->lock); +} + +static gboolean +_gxdp_open_uri_emit_changed (gpointer user_data) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (user_data); + GList *l; + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + guint num_changes; + + g_mutex_lock (&skeleton->priv->lock); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) + { + ChangedProperty *cp = l->data; + GVariant *variant; + const GValue *cur_value; + + cur_value = &skeleton->priv->properties[cp->prop_id - 1]; + if (!_g_value_equal (cur_value, &cp->orig_value)) + { + variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); + g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); + g_variant_unref (variant); + num_changes++; + } + } + if (num_changes > 0) + { + GList *connections, *ll; + GVariant *signal_variant; + signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.OpenURI", + &builder, &invalidated_builder)); + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + for (ll = connections; ll != NULL; ll = ll->next) + { + GDBusConnection *connection = ll->data; + + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + signal_variant, + NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); + } + else + { + g_variant_builder_clear (&builder); + g_variant_builder_clear (&invalidated_builder); + } + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + skeleton->priv->changed_properties = NULL; + skeleton->priv->changed_properties_idle_source = NULL; + g_mutex_unlock (&skeleton->priv->lock); + return FALSE; +} + +static void +_gxdp_open_uri_schedule_emit_changed (GXdpOpenURISkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) +{ + ChangedProperty *cp; + GList *l; + cp = NULL; + for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) + { + ChangedProperty *i_cp = l->data; + if (i_cp->info == info) + { + cp = i_cp; + break; + } + } + if (cp == NULL) + { + cp = g_new0 (ChangedProperty, 1); + cp->prop_id = prop_id; + cp->info = info; + skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); + g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); + g_value_copy (orig_value, &cp->orig_value); + } +} + +static void +gxdp_open_uri_skeleton_notify (GObject *object, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties != NULL && + skeleton->priv->changed_properties_idle_source == NULL) + { + skeleton->priv->changed_properties_idle_source = g_idle_source_new (); + g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); + g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_open_uri_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); + g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_open_uri_emit_changed"); + g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); + g_source_unref (skeleton->priv->changed_properties_idle_source); + } + g_mutex_unlock (&skeleton->priv->lock); +} + +static void +gxdp_open_uri_skeleton_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + const _ExtendedGDBusPropertyInfo *info; + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_open_uri_property_info_pointers[prop_id - 1]; + g_mutex_lock (&skeleton->priv->lock); + g_object_freeze_notify (object); + if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) + { + if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && + info->emits_changed_signal) + _gxdp_open_uri_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); + g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); + g_object_notify_by_pspec (object, pspec); + } + g_mutex_unlock (&skeleton->priv->lock); + g_object_thaw_notify (object); +} + +static void +gxdp_open_uri_skeleton_init (GXdpOpenURISkeleton *skeleton) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + skeleton->priv = gxdp_open_uri_skeleton_get_instance_private (skeleton); +#else + skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeletonPrivate); +#endif + + g_mutex_init (&skeleton->priv->lock); + skeleton->priv->context = g_main_context_ref_thread_default (); + skeleton->priv->properties = g_new0 (GValue, 1); + g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); +} + +static guint +gxdp_open_uri_skeleton_get_version (GXdpOpenURI *object) +{ + GXdpOpenURISkeleton *skeleton = GXDP_OPEN_URI_SKELETON (object); + guint value; + g_mutex_lock (&skeleton->priv->lock); + value = g_value_get_uint (&(skeleton->priv->properties[0])); + g_mutex_unlock (&skeleton->priv->lock); + return value; +} + +static void +gxdp_open_uri_skeleton_class_init (GXdpOpenURISkeletonClass *klass) +{ + GObjectClass *gobject_class; + GDBusInterfaceSkeletonClass *skeleton_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_open_uri_skeleton_finalize; + gobject_class->get_property = gxdp_open_uri_skeleton_get_property; + gobject_class->set_property = gxdp_open_uri_skeleton_set_property; + gobject_class->notify = gxdp_open_uri_skeleton_notify; + + + gxdp_open_uri_override_properties (gobject_class, 1); + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_info = gxdp_open_uri_skeleton_dbus_interface_get_info; + skeleton_class->get_properties = gxdp_open_uri_skeleton_dbus_interface_get_properties; + skeleton_class->flush = gxdp_open_uri_skeleton_dbus_interface_flush; + skeleton_class->get_vtable = gxdp_open_uri_skeleton_dbus_interface_get_vtable; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpOpenURISkeletonPrivate)); +#endif +} + +static void +gxdp_open_uri_skeleton_iface_init (GXdpOpenURIIface *iface) +{ + iface->get_version = gxdp_open_uri_skeleton_get_version; +} + +/** + * gxdp_open_uri_skeleton_new: + * + * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.OpenURI. + * + * Returns: (transfer full) (type GXdpOpenURISkeleton): The skeleton object. + */ +GXdpOpenURI * +gxdp_open_uri_skeleton_new (void) +{ + return GXDP_OPEN_URI (g_object_new (GXDP_TYPE_OPEN_URI_SKELETON, NULL)); +} + +/* ------------------------------------------------------------------------ + * Code for interface org.freedesktop.portal.ProxyResolver + * ------------------------------------------------------------------------ + */ + +/** + * SECTION:GXdpProxyResolver + * @title: GXdpProxyResolver + * @short_description: Generated C code for the org.freedesktop.portal.ProxyResolver D-Bus interface + * + * This section contains code for working with the org.freedesktop.portal.ProxyResolver D-Bus interface in C. + */ + +/* ---- Introspection data for org.freedesktop.portal.ProxyResolver ---- */ + +static const _ExtendedGDBusArgInfo _gxdp_proxy_resolver_method_info_lookup_IN_ARG_uri = +{ + { + -1, + (gchar *) "uri", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_proxy_resolver_method_info_lookup_IN_ARG_pointers[] = +{ + &_gxdp_proxy_resolver_method_info_lookup_IN_ARG_uri.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_proxy_resolver_method_info_lookup_OUT_ARG_proxies = +{ + { + -1, + (gchar *) "proxies", + (gchar *) "as", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_proxy_resolver_method_info_lookup_OUT_ARG_pointers[] = +{ + &_gxdp_proxy_resolver_method_info_lookup_OUT_ARG_proxies.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_proxy_resolver_method_info_lookup = +{ + { + -1, + (gchar *) "Lookup", + (GDBusArgInfo **) &_gxdp_proxy_resolver_method_info_lookup_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_proxy_resolver_method_info_lookup_OUT_ARG_pointers, + NULL + }, + "handle-lookup", + FALSE +}; + +static const GDBusMethodInfo * const _gxdp_proxy_resolver_method_info_pointers[] = +{ + &_gxdp_proxy_resolver_method_info_lookup.parent_struct, + NULL +}; + +static const _ExtendedGDBusPropertyInfo _gxdp_proxy_resolver_property_info_version = +{ + { + -1, + (gchar *) "version", + (gchar *) "u", + G_DBUS_PROPERTY_INFO_FLAGS_READABLE, + NULL + }, + "version", + FALSE, + TRUE +}; + +static const GDBusPropertyInfo * const _gxdp_proxy_resolver_property_info_pointers[] = +{ + &_gxdp_proxy_resolver_property_info_version.parent_struct, + NULL +}; + +static const _ExtendedGDBusInterfaceInfo _gxdp_proxy_resolver_interface_info = +{ + { + -1, + (gchar *) "org.freedesktop.portal.ProxyResolver", + (GDBusMethodInfo **) &_gxdp_proxy_resolver_method_info_pointers, + NULL, + (GDBusPropertyInfo **) &_gxdp_proxy_resolver_property_info_pointers, + NULL + }, + "proxy-resolver", +}; + + +/** + * gxdp_proxy_resolver_interface_info: + * + * Gets a machine-readable description of the org.freedesktop.portal.ProxyResolver D-Bus interface. + * + * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. + */ +GDBusInterfaceInfo * +gxdp_proxy_resolver_interface_info (void) +{ + return (GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct; +} + +/** + * gxdp_proxy_resolver_override_properties: + * @klass: The class structure for a #GObject derived class. + * @property_id_begin: The property id to assign to the first overridden property. + * + * Overrides all #GObject properties in the #GXdpProxyResolver interface for a concrete class. + * The properties are overridden in the order they are defined. + * + * Returns: The last property id. + */ +guint +gxdp_proxy_resolver_override_properties (GObjectClass *klass, guint property_id_begin) +{ + g_object_class_override_property (klass, property_id_begin++, "version"); + return property_id_begin - 1; +} + + + +/** + * GXdpProxyResolver: + * + * Abstract interface type for the D-Bus interface org.freedesktop.portal.ProxyResolver. + */ + +/** + * GXdpProxyResolverIface: + * @parent_iface: The parent interface. + * @handle_lookup: Handler for the #GXdpProxyResolver::handle-lookup signal. + * @get_version: Getter for the #GXdpProxyResolver:version property. + * + * Virtual table for the D-Bus interface org.freedesktop.portal.ProxyResolver. + */ + +typedef GXdpProxyResolverIface GXdpProxyResolverInterface; +G_DEFINE_INTERFACE (GXdpProxyResolver, gxdp_proxy_resolver, G_TYPE_OBJECT) + +static void +gxdp_proxy_resolver_default_init (GXdpProxyResolverIface *iface) +{ + /* GObject signals for incoming D-Bus method calls: */ + /** + * GXdpProxyResolver::handle-lookup: + * @object: A #GXdpProxyResolver. + * @invocation: A #GDBusMethodInvocation. + * @arg_uri: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the Lookup() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_proxy_resolver_complete_lookup() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-lookup", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpProxyResolverIface, handle_lookup), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 2, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING); + + /* GObject properties for D-Bus properties: */ + /** + * GXdpProxyResolver:version: + * + * Represents the D-Bus property "version". + * + * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. + */ + g_object_interface_install_property (iface, + g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +/** + * gxdp_proxy_resolver_get_version: (skip) + * @object: A #GXdpProxyResolver. + * + * Gets the value of the "version" D-Bus property. + * + * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. + * + * Returns: The property value. + */ +guint +gxdp_proxy_resolver_get_version (GXdpProxyResolver *object) +{ + return GXDP_PROXY_RESOLVER_GET_IFACE (object)->get_version (object); +} + +/** + * gxdp_proxy_resolver_set_version: (skip) + * @object: A #GXdpProxyResolver. + * @value: The value to set. + * + * Sets the "version" D-Bus property to @value. + * + * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. + */ +void +gxdp_proxy_resolver_set_version (GXdpProxyResolver *object, guint value) +{ + g_object_set (G_OBJECT (object), "version", value, NULL); +} + +/** + * gxdp_proxy_resolver_call_lookup: + * @proxy: A #GXdpProxyResolverProxy. + * @arg_uri: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the Lookup() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_proxy_resolver_call_lookup_finish() to get the result of the operation. + * + * See gxdp_proxy_resolver_call_lookup_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_proxy_resolver_call_lookup ( + GXdpProxyResolver *proxy, + const gchar *arg_uri, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "Lookup", + g_variant_new ("(s)", + arg_uri), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * gxdp_proxy_resolver_call_lookup_finish: + * @proxy: A #GXdpProxyResolverProxy. + * @out_proxies: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_proxy_resolver_call_lookup(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_proxy_resolver_call_lookup(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_proxy_resolver_call_lookup_finish ( + GXdpProxyResolver *proxy, + gchar ***out_proxies, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_proxies); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_proxy_resolver_call_lookup_sync: + * @proxy: A #GXdpProxyResolverProxy. + * @arg_uri: Argument to pass with the method invocation. + * @out_proxies: (out) (optional) (array zero-terminated=1): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the Lookup() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_proxy_resolver_call_lookup() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_proxy_resolver_call_lookup_sync ( + GXdpProxyResolver *proxy, + const gchar *arg_uri, + gchar ***out_proxies, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "Lookup", + g_variant_new ("(s)", + arg_uri), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(^as)", + out_proxies); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_proxy_resolver_complete_lookup: + * @object: A #GXdpProxyResolver. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @proxies: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the Lookup() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_proxy_resolver_complete_lookup ( + GXdpProxyResolver *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + const gchar *const *proxies) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(^as)", + proxies)); +} + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpProxyResolverProxy: + * + * The #GXdpProxyResolverProxy structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpProxyResolverProxyClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpProxyResolverProxy. + */ + +struct _GXdpProxyResolverProxyPrivate +{ + GData *qdata; +}; + +static void gxdp_proxy_resolver_proxy_iface_init (GXdpProxyResolverIface *iface); + +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverProxy, gxdp_proxy_resolver_proxy, G_TYPE_DBUS_PROXY, + G_ADD_PRIVATE (GXdpProxyResolverProxy) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_proxy_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverProxy, gxdp_proxy_resolver_proxy, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_proxy_iface_init)) + +#endif +static void +gxdp_proxy_resolver_proxy_finalize (GObject *object) +{ + GXdpProxyResolverProxy *proxy = GXDP_PROXY_RESOLVER_PROXY (object); + g_datalist_clear (&proxy->priv->qdata); + G_OBJECT_CLASS (gxdp_proxy_resolver_proxy_parent_class)->finalize (object); +} + +static void +gxdp_proxy_resolver_proxy_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_proxy_resolver_property_info_pointers[prop_id - 1]; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); + if (info->use_gvariant) + { + g_value_set_variant (value, variant); + } + else + { + if (variant != NULL) + g_dbus_gvariant_to_gvalue (variant, value); + } + if (variant != NULL) + g_variant_unref (variant); +} + +static void +gxdp_proxy_resolver_proxy_set_property_cb (GDBusProxy *proxy, + GAsyncResult *res, + gpointer user_data) +{ + const _ExtendedGDBusPropertyInfo *info = user_data; + GError *error; + GVariant *_ret; + error = NULL; + _ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (!_ret) + { + g_warning ("Error setting property '%s' on interface org.freedesktop.portal.ProxyResolver: %s (%s, %d)", + info->parent_struct.name, + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + else + { + g_variant_unref (_ret); + } +} + +static void +gxdp_proxy_resolver_proxy_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_proxy_resolver_property_info_pointers[prop_id - 1]; + variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_dbus_proxy_call (G_DBUS_PROXY (object), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", "org.freedesktop.portal.ProxyResolver", info->parent_struct.name, variant), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, (GAsyncReadyCallback) gxdp_proxy_resolver_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); + g_variant_unref (variant); +} + +static void +gxdp_proxy_resolver_proxy_g_signal (GDBusProxy *proxy, + const gchar *sender_name G_GNUC_UNUSED, + const gchar *signal_name, + GVariant *parameters) +{ + _ExtendedGDBusSignalInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + gsize n; + guint signal_id; + info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, signal_name); + if (info == NULL) + return; + num_params = g_variant_n_children (parameters); + paramv = g_new0 (GValue, num_params + 1); + g_value_init (¶mv[0], GXDP_TYPE_PROXY_RESOLVER); + g_value_set_object (¶mv[0], proxy); + g_variant_iter_init (&iter, parameters); + n = 1; + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_PROXY_RESOLVER); + g_signal_emitv (paramv, signal_id, 0, NULL); + for (n = 0; n < num_params + 1; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static void +gxdp_proxy_resolver_proxy_g_properties_changed (GDBusProxy *_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties) +{ + GXdpProxyResolverProxy *proxy = GXDP_PROXY_RESOLVER_PROXY (_proxy); + guint n; + const gchar *key; + GVariantIter *iter; + _ExtendedGDBusPropertyInfo *info; + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, key); + g_datalist_remove_data (&proxy->priv->qdata, key); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } + g_variant_iter_free (iter); + for (n = 0; invalidated_properties[n] != NULL; n++) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, invalidated_properties[n]); + g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } +} + +static guint +gxdp_proxy_resolver_proxy_get_version (GXdpProxyResolver *object) +{ + GXdpProxyResolverProxy *proxy = GXDP_PROXY_RESOLVER_PROXY (object); + GVariant *variant; + guint value = 0; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); + if (variant != NULL) + { + value = g_variant_get_uint32 (variant); + g_variant_unref (variant); + } + return value; +} + +static void +gxdp_proxy_resolver_proxy_init (GXdpProxyResolverProxy *proxy) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + proxy->priv = gxdp_proxy_resolver_proxy_get_instance_private (proxy); +#else + proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxyPrivate); +#endif + + g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_proxy_resolver_interface_info ()); +} + +static void +gxdp_proxy_resolver_proxy_class_init (GXdpProxyResolverProxyClass *klass) +{ + GObjectClass *gobject_class; + GDBusProxyClass *proxy_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_proxy_resolver_proxy_finalize; + gobject_class->get_property = gxdp_proxy_resolver_proxy_get_property; + gobject_class->set_property = gxdp_proxy_resolver_proxy_set_property; + + proxy_class = G_DBUS_PROXY_CLASS (klass); + proxy_class->g_signal = gxdp_proxy_resolver_proxy_g_signal; + proxy_class->g_properties_changed = gxdp_proxy_resolver_proxy_g_properties_changed; + + gxdp_proxy_resolver_override_properties (gobject_class, 1); + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpProxyResolverProxyPrivate)); +#endif +} + +static void +gxdp_proxy_resolver_proxy_iface_init (GXdpProxyResolverIface *iface) +{ + iface->get_version = gxdp_proxy_resolver_proxy_get_version; +} + +/** + * gxdp_proxy_resolver_proxy_new: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.ProxyResolver. See g_dbus_proxy_new() for more details. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_proxy_resolver_proxy_new_finish() to get the result of the operation. + * + * See gxdp_proxy_resolver_proxy_new_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_proxy_resolver_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_PROXY_RESOLVER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); +} + +/** + * gxdp_proxy_resolver_proxy_new_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_proxy_resolver_proxy_new(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_proxy_resolver_proxy_new(). + * + * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpProxyResolver * +gxdp_proxy_resolver_proxy_new_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_PROXY_RESOLVER (ret); + else + return NULL; +} + +/** + * gxdp_proxy_resolver_proxy_new_sync: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.ProxyResolver. See g_dbus_proxy_new_sync() for more details. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_proxy_resolver_proxy_new() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpProxyResolver * +gxdp_proxy_resolver_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_PROXY_RESOLVER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); + if (ret != NULL) + return GXDP_PROXY_RESOLVER (ret); + else + return NULL; +} + + +/** + * gxdp_proxy_resolver_proxy_new_for_bus: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Like gxdp_proxy_resolver_proxy_new() but takes a #GBusType instead of a #GDBusConnection. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_proxy_resolver_proxy_new_for_bus_finish() to get the result of the operation. + * + * See gxdp_proxy_resolver_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_proxy_resolver_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_PROXY_RESOLVER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); +} + +/** + * gxdp_proxy_resolver_proxy_new_for_bus_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_proxy_resolver_proxy_new_for_bus(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_proxy_resolver_proxy_new_for_bus(). + * + * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpProxyResolver * +gxdp_proxy_resolver_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_PROXY_RESOLVER (ret); + else + return NULL; +} + +/** + * gxdp_proxy_resolver_proxy_new_for_bus_sync: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Like gxdp_proxy_resolver_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_proxy_resolver_proxy_new_for_bus() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpProxyResolverProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpProxyResolver * +gxdp_proxy_resolver_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_PROXY_RESOLVER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.ProxyResolver", NULL); + if (ret != NULL) + return GXDP_PROXY_RESOLVER (ret); + else + return NULL; +} + + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpProxyResolverSkeleton: + * + * The #GXdpProxyResolverSkeleton structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpProxyResolverSkeletonClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpProxyResolverSkeleton. + */ + +struct _GXdpProxyResolverSkeletonPrivate +{ + GValue *properties; + GList *changed_properties; + GSource *changed_properties_idle_source; + GMainContext *context; + GMutex lock; +}; + +static void +_gxdp_proxy_resolver_skeleton_handle_method_call ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); + _ExtendedGDBusMethodInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + guint num_extra; + gsize n; + guint signal_id; + GValue return_value = G_VALUE_INIT; + info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); + g_assert (info != NULL); + num_params = g_variant_n_children (parameters); + num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); + n = 0; + g_value_init (¶mv[n], GXDP_TYPE_PROXY_RESOLVER); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); +#else + g_assert_not_reached (); +#endif + } + g_variant_iter_init (&iter, parameters); + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_PROXY_RESOLVER); + g_value_init (&return_value, G_TYPE_BOOLEAN); + g_signal_emitv (paramv, signal_id, 0, &return_value); + if (!g_value_get_boolean (&return_value)) + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); + g_value_unset (&return_value); + for (n = 0; n < num_params + num_extra; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static GVariant * +_gxdp_proxy_resolver_skeleton_handle_get_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + GVariant *ret; + ret = NULL; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); + ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_value_unset (&value); + } + return ret; +} + +static gboolean +_gxdp_proxy_resolver_skeleton_handle_set_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GVariant *variant, + GError **error, + gpointer user_data) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + gboolean ret; + ret = FALSE; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_proxy_resolver_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + if (info->use_gvariant) + g_value_set_variant (&value, variant); + else + g_dbus_gvariant_to_gvalue (variant, &value); + g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); + g_value_unset (&value); + ret = TRUE; + } + return ret; +} + +static const GDBusInterfaceVTable _gxdp_proxy_resolver_skeleton_vtable = +{ + _gxdp_proxy_resolver_skeleton_handle_method_call, + _gxdp_proxy_resolver_skeleton_handle_get_property, + _gxdp_proxy_resolver_skeleton_handle_set_property, + {NULL} +}; + +static GDBusInterfaceInfo * +gxdp_proxy_resolver_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return gxdp_proxy_resolver_interface_info (); +} + +static GDBusInterfaceVTable * +gxdp_proxy_resolver_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return (GDBusInterfaceVTable *) &_gxdp_proxy_resolver_skeleton_vtable; +} + +static GVariant * +gxdp_proxy_resolver_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (_skeleton); + + GVariantBuilder builder; + guint n; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + if (_gxdp_proxy_resolver_interface_info.parent_struct.properties == NULL) + goto out; + for (n = 0; _gxdp_proxy_resolver_interface_info.parent_struct.properties[n] != NULL; n++) + { + GDBusPropertyInfo *info = _gxdp_proxy_resolver_interface_info.parent_struct.properties[n]; + if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) + { + GVariant *value; + value = _gxdp_proxy_resolver_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.ProxyResolver", info->name, NULL, skeleton); + if (value != NULL) + { + g_variant_take_ref (value); + g_variant_builder_add (&builder, "{sv}", info->name, value); + g_variant_unref (value); + } + } + } +out: + return g_variant_builder_end (&builder); +} + +static gboolean _gxdp_proxy_resolver_emit_changed (gpointer user_data); + +static void +gxdp_proxy_resolver_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (_skeleton); + gboolean emit_changed = FALSE; + + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties_idle_source != NULL) + { + g_source_destroy (skeleton->priv->changed_properties_idle_source); + skeleton->priv->changed_properties_idle_source = NULL; + emit_changed = TRUE; + } + g_mutex_unlock (&skeleton->priv->lock); + + if (emit_changed) + _gxdp_proxy_resolver_emit_changed (skeleton); +} + +static void gxdp_proxy_resolver_skeleton_iface_init (GXdpProxyResolverIface *iface); +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverSkeleton, gxdp_proxy_resolver_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_ADD_PRIVATE (GXdpProxyResolverSkeleton) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_skeleton_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpProxyResolverSkeleton, gxdp_proxy_resolver_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_PROXY_RESOLVER, gxdp_proxy_resolver_skeleton_iface_init)) + +#endif +static void +gxdp_proxy_resolver_skeleton_finalize (GObject *object) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (object); + guint n; + for (n = 0; n < 1; n++) + g_value_unset (&skeleton->priv->properties[n]); + g_free (skeleton->priv->properties); + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + if (skeleton->priv->changed_properties_idle_source != NULL) + g_source_destroy (skeleton->priv->changed_properties_idle_source); + g_main_context_unref (skeleton->priv->context); + g_mutex_clear (&skeleton->priv->lock); + G_OBJECT_CLASS (gxdp_proxy_resolver_skeleton_parent_class)->finalize (object); +} + +static void +gxdp_proxy_resolver_skeleton_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + g_mutex_lock (&skeleton->priv->lock); + g_value_copy (&skeleton->priv->properties[prop_id - 1], value); + g_mutex_unlock (&skeleton->priv->lock); +} + +static gboolean +_gxdp_proxy_resolver_emit_changed (gpointer user_data) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (user_data); + GList *l; + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + guint num_changes; + + g_mutex_lock (&skeleton->priv->lock); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) + { + ChangedProperty *cp = l->data; + GVariant *variant; + const GValue *cur_value; + + cur_value = &skeleton->priv->properties[cp->prop_id - 1]; + if (!_g_value_equal (cur_value, &cp->orig_value)) + { + variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); + g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); + g_variant_unref (variant); + num_changes++; + } + } + if (num_changes > 0) + { + GList *connections, *ll; + GVariant *signal_variant; + signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.ProxyResolver", + &builder, &invalidated_builder)); + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + for (ll = connections; ll != NULL; ll = ll->next) + { + GDBusConnection *connection = ll->data; + + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + signal_variant, + NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); + } + else + { + g_variant_builder_clear (&builder); + g_variant_builder_clear (&invalidated_builder); + } + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + skeleton->priv->changed_properties = NULL; + skeleton->priv->changed_properties_idle_source = NULL; + g_mutex_unlock (&skeleton->priv->lock); + return FALSE; +} + +static void +_gxdp_proxy_resolver_schedule_emit_changed (GXdpProxyResolverSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) +{ + ChangedProperty *cp; + GList *l; + cp = NULL; + for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) + { + ChangedProperty *i_cp = l->data; + if (i_cp->info == info) + { + cp = i_cp; + break; + } + } + if (cp == NULL) + { + cp = g_new0 (ChangedProperty, 1); + cp->prop_id = prop_id; + cp->info = info; + skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); + g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); + g_value_copy (orig_value, &cp->orig_value); + } +} + +static void +gxdp_proxy_resolver_skeleton_notify (GObject *object, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (object); + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties != NULL && + skeleton->priv->changed_properties_idle_source == NULL) + { + skeleton->priv->changed_properties_idle_source = g_idle_source_new (); + g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); + g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_proxy_resolver_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); + g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_proxy_resolver_emit_changed"); + g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); + g_source_unref (skeleton->priv->changed_properties_idle_source); + } + g_mutex_unlock (&skeleton->priv->lock); +} + +static void +gxdp_proxy_resolver_skeleton_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + const _ExtendedGDBusPropertyInfo *info; + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_proxy_resolver_property_info_pointers[prop_id - 1]; + g_mutex_lock (&skeleton->priv->lock); + g_object_freeze_notify (object); + if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) + { + if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && + info->emits_changed_signal) + _gxdp_proxy_resolver_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); + g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); + g_object_notify_by_pspec (object, pspec); + } + g_mutex_unlock (&skeleton->priv->lock); + g_object_thaw_notify (object); +} + +static void +gxdp_proxy_resolver_skeleton_init (GXdpProxyResolverSkeleton *skeleton) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + skeleton->priv = gxdp_proxy_resolver_skeleton_get_instance_private (skeleton); +#else + skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeletonPrivate); +#endif + + g_mutex_init (&skeleton->priv->lock); + skeleton->priv->context = g_main_context_ref_thread_default (); + skeleton->priv->properties = g_new0 (GValue, 1); + g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); +} + +static guint +gxdp_proxy_resolver_skeleton_get_version (GXdpProxyResolver *object) +{ + GXdpProxyResolverSkeleton *skeleton = GXDP_PROXY_RESOLVER_SKELETON (object); + guint value; + g_mutex_lock (&skeleton->priv->lock); + value = g_value_get_uint (&(skeleton->priv->properties[0])); + g_mutex_unlock (&skeleton->priv->lock); + return value; +} + +static void +gxdp_proxy_resolver_skeleton_class_init (GXdpProxyResolverSkeletonClass *klass) +{ + GObjectClass *gobject_class; + GDBusInterfaceSkeletonClass *skeleton_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_proxy_resolver_skeleton_finalize; + gobject_class->get_property = gxdp_proxy_resolver_skeleton_get_property; + gobject_class->set_property = gxdp_proxy_resolver_skeleton_set_property; + gobject_class->notify = gxdp_proxy_resolver_skeleton_notify; + + + gxdp_proxy_resolver_override_properties (gobject_class, 1); + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_info = gxdp_proxy_resolver_skeleton_dbus_interface_get_info; + skeleton_class->get_properties = gxdp_proxy_resolver_skeleton_dbus_interface_get_properties; + skeleton_class->flush = gxdp_proxy_resolver_skeleton_dbus_interface_flush; + skeleton_class->get_vtable = gxdp_proxy_resolver_skeleton_dbus_interface_get_vtable; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpProxyResolverSkeletonPrivate)); +#endif +} + +static void +gxdp_proxy_resolver_skeleton_iface_init (GXdpProxyResolverIface *iface) +{ + iface->get_version = gxdp_proxy_resolver_skeleton_get_version; +} + +/** + * gxdp_proxy_resolver_skeleton_new: + * + * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.ProxyResolver. + * + * Returns: (transfer full) (type GXdpProxyResolverSkeleton): The skeleton object. + */ +GXdpProxyResolver * +gxdp_proxy_resolver_skeleton_new (void) +{ + return GXDP_PROXY_RESOLVER (g_object_new (GXDP_TYPE_PROXY_RESOLVER_SKELETON, NULL)); +} + +/* ------------------------------------------------------------------------ + * Code for interface org.freedesktop.portal.Trash + * ------------------------------------------------------------------------ + */ + +/** + * SECTION:GXdpTrash + * @title: GXdpTrash + * @short_description: Generated C code for the org.freedesktop.portal.Trash D-Bus interface + * + * This section contains code for working with the org.freedesktop.portal.Trash D-Bus interface in C. + */ + +/* ---- Introspection data for org.freedesktop.portal.Trash ---- */ + +static const _ExtendedGDBusArgInfo _gxdp_trash_method_info_trash_file_IN_ARG_fd = +{ + { + -1, + (gchar *) "fd", + (gchar *) "h", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_trash_method_info_trash_file_IN_ARG_pointers[] = +{ + &_gxdp_trash_method_info_trash_file_IN_ARG_fd.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _gxdp_trash_method_info_trash_file_OUT_ARG_result = +{ + { + -1, + (gchar *) "result", + (gchar *) "u", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _gxdp_trash_method_info_trash_file_OUT_ARG_pointers[] = +{ + &_gxdp_trash_method_info_trash_file_OUT_ARG_result.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _gxdp_trash_method_info_trash_file = +{ + { + -1, + (gchar *) "TrashFile", + (GDBusArgInfo **) &_gxdp_trash_method_info_trash_file_IN_ARG_pointers, + (GDBusArgInfo **) &_gxdp_trash_method_info_trash_file_OUT_ARG_pointers, + NULL + }, + "handle-trash-file", + TRUE +}; + +static const GDBusMethodInfo * const _gxdp_trash_method_info_pointers[] = +{ + &_gxdp_trash_method_info_trash_file.parent_struct, + NULL +}; + +static const _ExtendedGDBusPropertyInfo _gxdp_trash_property_info_version = +{ + { + -1, + (gchar *) "version", + (gchar *) "u", + G_DBUS_PROPERTY_INFO_FLAGS_READABLE, + NULL + }, + "version", + FALSE, + TRUE +}; + +static const GDBusPropertyInfo * const _gxdp_trash_property_info_pointers[] = +{ + &_gxdp_trash_property_info_version.parent_struct, + NULL +}; + +static const _ExtendedGDBusInterfaceInfo _gxdp_trash_interface_info = +{ + { + -1, + (gchar *) "org.freedesktop.portal.Trash", + (GDBusMethodInfo **) &_gxdp_trash_method_info_pointers, + NULL, + (GDBusPropertyInfo **) &_gxdp_trash_property_info_pointers, + NULL + }, + "trash", +}; + + +/** + * gxdp_trash_interface_info: + * + * Gets a machine-readable description of the org.freedesktop.portal.Trash D-Bus interface. + * + * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. + */ +GDBusInterfaceInfo * +gxdp_trash_interface_info (void) +{ + return (GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct; +} + +/** + * gxdp_trash_override_properties: + * @klass: The class structure for a #GObject derived class. + * @property_id_begin: The property id to assign to the first overridden property. + * + * Overrides all #GObject properties in the #GXdpTrash interface for a concrete class. + * The properties are overridden in the order they are defined. + * + * Returns: The last property id. + */ +guint +gxdp_trash_override_properties (GObjectClass *klass, guint property_id_begin) +{ + g_object_class_override_property (klass, property_id_begin++, "version"); + return property_id_begin - 1; +} + + + +/** + * GXdpTrash: + * + * Abstract interface type for the D-Bus interface org.freedesktop.portal.Trash. + */ + +/** + * GXdpTrashIface: + * @parent_iface: The parent interface. + * @handle_trash_file: Handler for the #GXdpTrash::handle-trash-file signal. + * @get_version: Getter for the #GXdpTrash:version property. + * + * Virtual table for the D-Bus interface org.freedesktop.portal.Trash. + */ + +typedef GXdpTrashIface GXdpTrashInterface; +G_DEFINE_INTERFACE (GXdpTrash, gxdp_trash, G_TYPE_OBJECT) + +static void +gxdp_trash_default_init (GXdpTrashIface *iface) +{ + /* GObject signals for incoming D-Bus method calls: */ + /** + * GXdpTrash::handle-trash-file: + * @object: A #GXdpTrash. + * @invocation: A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @arg_fd: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the TrashFile() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call gxdp_trash_complete_trash_file() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-trash-file", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GXdpTrashIface, handle_trash_file), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 3, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_UNIX_FD_LIST, G_TYPE_VARIANT); + + /* GObject properties for D-Bus properties: */ + /** + * GXdpTrash:version: + * + * Represents the D-Bus property "version". + * + * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side. + */ + g_object_interface_install_property (iface, + g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +/** + * gxdp_trash_get_version: (skip) + * @object: A #GXdpTrash. + * + * Gets the value of the "version" D-Bus property. + * + * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side. + * + * Returns: The property value. + */ +guint +gxdp_trash_get_version (GXdpTrash *object) +{ + return GXDP_TRASH_GET_IFACE (object)->get_version (object); +} + +/** + * gxdp_trash_set_version: (skip) + * @object: A #GXdpTrash. + * @value: The value to set. + * + * Sets the "version" D-Bus property to @value. + * + * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side. + */ +void +gxdp_trash_set_version (GXdpTrash *object, guint value) +{ + g_object_set (G_OBJECT (object), "version", value, NULL); +} + +/** + * gxdp_trash_call_trash_file: + * @proxy: A #GXdpTrashProxy. + * @arg_fd: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the TrashFile() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_trash_call_trash_file_finish() to get the result of the operation. + * + * See gxdp_trash_call_trash_file_sync() for the synchronous, blocking version of this method. + */ +void +gxdp_trash_call_trash_file ( + GXdpTrash *proxy, + GVariant *arg_fd, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy), + "TrashFile", + g_variant_new ("(@h)", + arg_fd), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + cancellable, + callback, + user_data); +} + +/** + * gxdp_trash_call_trash_file_finish: + * @proxy: A #GXdpTrashProxy. + * @out_result: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_trash_call_trash_file(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gxdp_trash_call_trash_file(). + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_trash_call_trash_file_finish ( + GXdpTrash *proxy, + guint *out_result, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_result); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_trash_call_trash_file_sync: + * @proxy: A #GXdpTrashProxy. + * @arg_fd: Argument to pass with the method invocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @out_result: (out) (optional): Return location for return parameter or %NULL to ignore. + * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the TrashFile() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See gxdp_trash_call_trash_file() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeeded, %FALSE if @error is set. + */ +gboolean +gxdp_trash_call_trash_file_sync ( + GXdpTrash *proxy, + GVariant *arg_fd, + GUnixFDList *fd_list, + guint *out_result, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy), + "TrashFile", + g_variant_new ("(@h)", + arg_fd), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + out_fd_list, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(u)", + out_result); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * gxdp_trash_complete_trash_file: + * @object: A #GXdpTrash. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @fd_list: (nullable): A #GUnixFDList or %NULL. + * @result: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the TrashFile() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +gxdp_trash_complete_trash_file ( + GXdpTrash *object G_GNUC_UNUSED, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + guint result) +{ + g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, + g_variant_new ("(u)", + result), + fd_list); +} + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpTrashProxy: + * + * The #GXdpTrashProxy structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpTrashProxyClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpTrashProxy. + */ + +struct _GXdpTrashProxyPrivate +{ + GData *qdata; +}; + +static void gxdp_trash_proxy_iface_init (GXdpTrashIface *iface); + +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpTrashProxy, gxdp_trash_proxy, G_TYPE_DBUS_PROXY, + G_ADD_PRIVATE (GXdpTrashProxy) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_proxy_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpTrashProxy, gxdp_trash_proxy, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_proxy_iface_init)) + +#endif +static void +gxdp_trash_proxy_finalize (GObject *object) +{ + GXdpTrashProxy *proxy = GXDP_TRASH_PROXY (object); + g_datalist_clear (&proxy->priv->qdata); + G_OBJECT_CLASS (gxdp_trash_proxy_parent_class)->finalize (object); +} + +static void +gxdp_trash_proxy_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_trash_property_info_pointers[prop_id - 1]; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name); + if (info->use_gvariant) + { + g_value_set_variant (value, variant); + } + else + { + if (variant != NULL) + g_dbus_gvariant_to_gvalue (variant, value); + } + if (variant != NULL) + g_variant_unref (variant); +} + +static void +gxdp_trash_proxy_set_property_cb (GDBusProxy *proxy, + GAsyncResult *res, + gpointer user_data) +{ + const _ExtendedGDBusPropertyInfo *info = user_data; + GError *error; + GVariant *_ret; + error = NULL; + _ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (!_ret) + { + g_warning ("Error setting property '%s' on interface org.freedesktop.portal.Trash: %s (%s, %d)", + info->parent_struct.name, + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + else + { + g_variant_unref (_ret); + } +} + +static void +gxdp_trash_proxy_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + const _ExtendedGDBusPropertyInfo *info; + GVariant *variant; + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_trash_property_info_pointers[prop_id - 1]; + variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_dbus_proxy_call (G_DBUS_PROXY (object), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", "org.freedesktop.portal.Trash", info->parent_struct.name, variant), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, (GAsyncReadyCallback) gxdp_trash_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct); + g_variant_unref (variant); +} + +static void +gxdp_trash_proxy_g_signal (GDBusProxy *proxy, + const gchar *sender_name G_GNUC_UNUSED, + const gchar *signal_name, + GVariant *parameters) +{ + _ExtendedGDBusSignalInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + gsize n; + guint signal_id; + info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, signal_name); + if (info == NULL) + return; + num_params = g_variant_n_children (parameters); + paramv = g_new0 (GValue, num_params + 1); + g_value_init (¶mv[0], GXDP_TYPE_TRASH); + g_value_set_object (¶mv[0], proxy); + g_variant_iter_init (&iter, parameters); + n = 1; + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_TRASH); + g_signal_emitv (paramv, signal_id, 0, NULL); + for (n = 0; n < num_params + 1; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static void +gxdp_trash_proxy_g_properties_changed (GDBusProxy *_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties) +{ + GXdpTrashProxy *proxy = GXDP_TRASH_PROXY (_proxy); + guint n; + const gchar *key; + GVariantIter *iter; + _ExtendedGDBusPropertyInfo *info; + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, key); + g_datalist_remove_data (&proxy->priv->qdata, key); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } + g_variant_iter_free (iter); + for (n = 0; invalidated_properties[n] != NULL; n++) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, invalidated_properties[n]); + g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } +} + +static guint +gxdp_trash_proxy_get_version (GXdpTrash *object) +{ + GXdpTrashProxy *proxy = GXDP_TRASH_PROXY (object); + GVariant *variant; + guint value = 0; + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "version"); + if (variant != NULL) + { + value = g_variant_get_uint32 (variant); + g_variant_unref (variant); + } + return value; +} + +static void +gxdp_trash_proxy_init (GXdpTrashProxy *proxy) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + proxy->priv = gxdp_trash_proxy_get_instance_private (proxy); +#else + proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, GXDP_TYPE_TRASH_PROXY, GXdpTrashProxyPrivate); +#endif + + g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), gxdp_trash_interface_info ()); +} + +static void +gxdp_trash_proxy_class_init (GXdpTrashProxyClass *klass) +{ + GObjectClass *gobject_class; + GDBusProxyClass *proxy_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_trash_proxy_finalize; + gobject_class->get_property = gxdp_trash_proxy_get_property; + gobject_class->set_property = gxdp_trash_proxy_set_property; + + proxy_class = G_DBUS_PROXY_CLASS (klass); + proxy_class->g_signal = gxdp_trash_proxy_g_signal; + proxy_class->g_properties_changed = gxdp_trash_proxy_g_properties_changed; + + gxdp_trash_override_properties (gobject_class, 1); + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpTrashProxyPrivate)); +#endif +} + +static void +gxdp_trash_proxy_iface_init (GXdpTrashIface *iface) +{ + iface->get_version = gxdp_trash_proxy_get_version; +} + +/** + * gxdp_trash_proxy_new: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Asynchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Trash. See g_dbus_proxy_new() for more details. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_trash_proxy_new_finish() to get the result of the operation. + * + * See gxdp_trash_proxy_new_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_trash_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_TRASH_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); +} + +/** + * gxdp_trash_proxy_new_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_trash_proxy_new(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_trash_proxy_new(). + * + * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpTrash * +gxdp_trash_proxy_new_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_TRASH (ret); + else + return NULL; +} + +/** + * gxdp_trash_proxy_new_sync: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Synchronously creates a proxy for the D-Bus interface org.freedesktop.portal.Trash. See g_dbus_proxy_new_sync() for more details. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_trash_proxy_new() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpTrash * +gxdp_trash_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_TRASH_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); + if (ret != NULL) + return GXDP_TRASH (ret); + else + return NULL; +} + + +/** + * gxdp_trash_proxy_new_for_bus: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Like gxdp_trash_proxy_new() but takes a #GBusType instead of a #GDBusConnection. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call gxdp_trash_proxy_new_for_bus_finish() to get the result of the operation. + * + * See gxdp_trash_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. + */ +void +gxdp_trash_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (GXDP_TYPE_TRASH_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); +} + +/** + * gxdp_trash_proxy_new_for_bus_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gxdp_trash_proxy_new_for_bus(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with gxdp_trash_proxy_new_for_bus(). + * + * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpTrash * +gxdp_trash_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return GXDP_TRASH (ret); + else + return NULL; +} + +/** + * gxdp_trash_proxy_new_for_bus_sync: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Like gxdp_trash_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. + * + * The calling thread is blocked until a reply is received. + * + * See gxdp_trash_proxy_new_for_bus() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type GXdpTrashProxy): The constructed proxy object or %NULL if @error is set. + */ +GXdpTrash * +gxdp_trash_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (GXDP_TYPE_TRASH_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.freedesktop.portal.Trash", NULL); + if (ret != NULL) + return GXDP_TRASH (ret); + else + return NULL; +} + + +/* ------------------------------------------------------------------------ */ + +/** + * GXdpTrashSkeleton: + * + * The #GXdpTrashSkeleton structure contains only private data and should only be accessed using the provided API. + */ + +/** + * GXdpTrashSkeletonClass: + * @parent_class: The parent class. + * + * Class structure for #GXdpTrashSkeleton. + */ + +struct _GXdpTrashSkeletonPrivate +{ + GValue *properties; + GList *changed_properties; + GSource *changed_properties_idle_source; + GMainContext *context; + GMutex lock; +}; + +static void +_gxdp_trash_skeleton_handle_method_call ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); + _ExtendedGDBusMethodInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + guint num_extra; + gsize n; + guint signal_id; + GValue return_value = G_VALUE_INIT; + info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); + g_assert (info != NULL); + num_params = g_variant_n_children (parameters); + num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); + n = 0; + g_value_init (¶mv[n], GXDP_TYPE_TRASH); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); +#else + g_assert_not_reached (); +#endif + } + g_variant_iter_init (&iter, parameters); + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, GXDP_TYPE_TRASH); + g_value_init (&return_value, G_TYPE_BOOLEAN); + g_signal_emitv (paramv, signal_id, 0, &return_value); + if (!g_value_get_boolean (&return_value)) + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); + g_value_unset (&return_value); + for (n = 0; n < num_params + num_extra; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static GVariant * +_gxdp_trash_skeleton_handle_get_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + GVariant *ret; + ret = NULL; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); + ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_value_unset (&value); + } + return ret; +} + +static gboolean +_gxdp_trash_skeleton_handle_set_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GVariant *variant, + GError **error, + gpointer user_data) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + gboolean ret; + ret = FALSE; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_gxdp_trash_interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + if (info->use_gvariant) + g_value_set_variant (&value, variant); + else + g_dbus_gvariant_to_gvalue (variant, &value); + g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); + g_value_unset (&value); + ret = TRUE; + } + return ret; +} + +static const GDBusInterfaceVTable _gxdp_trash_skeleton_vtable = +{ + _gxdp_trash_skeleton_handle_method_call, + _gxdp_trash_skeleton_handle_get_property, + _gxdp_trash_skeleton_handle_set_property, + {NULL} +}; + +static GDBusInterfaceInfo * +gxdp_trash_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return gxdp_trash_interface_info (); +} + +static GDBusInterfaceVTable * +gxdp_trash_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return (GDBusInterfaceVTable *) &_gxdp_trash_skeleton_vtable; +} + +static GVariant * +gxdp_trash_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (_skeleton); + + GVariantBuilder builder; + guint n; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + if (_gxdp_trash_interface_info.parent_struct.properties == NULL) + goto out; + for (n = 0; _gxdp_trash_interface_info.parent_struct.properties[n] != NULL; n++) + { + GDBusPropertyInfo *info = _gxdp_trash_interface_info.parent_struct.properties[n]; + if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) + { + GVariant *value; + value = _gxdp_trash_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.freedesktop.portal.Trash", info->name, NULL, skeleton); + if (value != NULL) + { + g_variant_take_ref (value); + g_variant_builder_add (&builder, "{sv}", info->name, value); + g_variant_unref (value); + } + } + } +out: + return g_variant_builder_end (&builder); +} + +static gboolean _gxdp_trash_emit_changed (gpointer user_data); + +static void +gxdp_trash_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (_skeleton); + gboolean emit_changed = FALSE; + + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties_idle_source != NULL) + { + g_source_destroy (skeleton->priv->changed_properties_idle_source); + skeleton->priv->changed_properties_idle_source = NULL; + emit_changed = TRUE; + } + g_mutex_unlock (&skeleton->priv->lock); + + if (emit_changed) + _gxdp_trash_emit_changed (skeleton); +} + +static void gxdp_trash_skeleton_iface_init (GXdpTrashIface *iface); +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (GXdpTrashSkeleton, gxdp_trash_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_ADD_PRIVATE (GXdpTrashSkeleton) + G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_skeleton_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (GXdpTrashSkeleton, gxdp_trash_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_IMPLEMENT_INTERFACE (GXDP_TYPE_TRASH, gxdp_trash_skeleton_iface_init)) + +#endif +static void +gxdp_trash_skeleton_finalize (GObject *object) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); + guint n; + for (n = 0; n < 1; n++) + g_value_unset (&skeleton->priv->properties[n]); + g_free (skeleton->priv->properties); + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + if (skeleton->priv->changed_properties_idle_source != NULL) + g_source_destroy (skeleton->priv->changed_properties_idle_source); + g_main_context_unref (skeleton->priv->context); + g_mutex_clear (&skeleton->priv->lock); + G_OBJECT_CLASS (gxdp_trash_skeleton_parent_class)->finalize (object); +} + +static void +gxdp_trash_skeleton_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + g_mutex_lock (&skeleton->priv->lock); + g_value_copy (&skeleton->priv->properties[prop_id - 1], value); + g_mutex_unlock (&skeleton->priv->lock); +} + +static gboolean +_gxdp_trash_emit_changed (gpointer user_data) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (user_data); + GList *l; + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + guint num_changes; + + g_mutex_lock (&skeleton->priv->lock); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next) + { + ChangedProperty *cp = l->data; + GVariant *variant; + const GValue *cur_value; + + cur_value = &skeleton->priv->properties[cp->prop_id - 1]; + if (!_g_value_equal (cur_value, &cp->orig_value)) + { + variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature)); + g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant); + g_variant_unref (variant); + num_changes++; + } + } + if (num_changes > 0) + { + GList *connections, *ll; + GVariant *signal_variant; + signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.freedesktop.portal.Trash", + &builder, &invalidated_builder)); + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + for (ll = connections; ll != NULL; ll = ll->next) + { + GDBusConnection *connection = ll->data; + + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + signal_variant, + NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); + } + else + { + g_variant_builder_clear (&builder); + g_variant_builder_clear (&invalidated_builder); + } + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + skeleton->priv->changed_properties = NULL; + skeleton->priv->changed_properties_idle_source = NULL; + g_mutex_unlock (&skeleton->priv->lock); + return FALSE; +} + +static void +_gxdp_trash_schedule_emit_changed (GXdpTrashSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value) +{ + ChangedProperty *cp; + GList *l; + cp = NULL; + for (l = skeleton->priv->changed_properties; l != NULL; l = l->next) + { + ChangedProperty *i_cp = l->data; + if (i_cp->info == info) + { + cp = i_cp; + break; + } + } + if (cp == NULL) + { + cp = g_new0 (ChangedProperty, 1); + cp->prop_id = prop_id; + cp->info = info; + skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp); + g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value)); + g_value_copy (orig_value, &cp->orig_value); + } +} + +static void +gxdp_trash_skeleton_notify (GObject *object, + GParamSpec *pspec G_GNUC_UNUSED) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); + g_mutex_lock (&skeleton->priv->lock); + if (skeleton->priv->changed_properties != NULL && + skeleton->priv->changed_properties_idle_source == NULL) + { + skeleton->priv->changed_properties_idle_source = g_idle_source_new (); + g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT); + g_source_set_callback (skeleton->priv->changed_properties_idle_source, _gxdp_trash_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref); + g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _gxdp_trash_emit_changed"); + g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context); + g_source_unref (skeleton->priv->changed_properties_idle_source); + } + g_mutex_unlock (&skeleton->priv->lock); +} + +static void +gxdp_trash_skeleton_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + const _ExtendedGDBusPropertyInfo *info; + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); + g_assert (prop_id != 0 && prop_id - 1 < 1); + info = (const _ExtendedGDBusPropertyInfo *) _gxdp_trash_property_info_pointers[prop_id - 1]; + g_mutex_lock (&skeleton->priv->lock); + g_object_freeze_notify (object); + if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1])) + { + if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL && + info->emits_changed_signal) + _gxdp_trash_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]); + g_value_copy (value, &skeleton->priv->properties[prop_id - 1]); + g_object_notify_by_pspec (object, pspec); + } + g_mutex_unlock (&skeleton->priv->lock); + g_object_thaw_notify (object); +} + +static void +gxdp_trash_skeleton_init (GXdpTrashSkeleton *skeleton) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + skeleton->priv = gxdp_trash_skeleton_get_instance_private (skeleton); +#else + skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeletonPrivate); +#endif + + g_mutex_init (&skeleton->priv->lock); + skeleton->priv->context = g_main_context_ref_thread_default (); + skeleton->priv->properties = g_new0 (GValue, 1); + g_value_init (&skeleton->priv->properties[0], G_TYPE_UINT); +} + +static guint +gxdp_trash_skeleton_get_version (GXdpTrash *object) +{ + GXdpTrashSkeleton *skeleton = GXDP_TRASH_SKELETON (object); + guint value; + g_mutex_lock (&skeleton->priv->lock); + value = g_value_get_uint (&(skeleton->priv->properties[0])); + g_mutex_unlock (&skeleton->priv->lock); + return value; +} + +static void +gxdp_trash_skeleton_class_init (GXdpTrashSkeletonClass *klass) +{ + GObjectClass *gobject_class; + GDBusInterfaceSkeletonClass *skeleton_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = gxdp_trash_skeleton_finalize; + gobject_class->get_property = gxdp_trash_skeleton_get_property; + gobject_class->set_property = gxdp_trash_skeleton_set_property; + gobject_class->notify = gxdp_trash_skeleton_notify; + + + gxdp_trash_override_properties (gobject_class, 1); + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_info = gxdp_trash_skeleton_dbus_interface_get_info; + skeleton_class->get_properties = gxdp_trash_skeleton_dbus_interface_get_properties; + skeleton_class->flush = gxdp_trash_skeleton_dbus_interface_flush; + skeleton_class->get_vtable = gxdp_trash_skeleton_dbus_interface_get_vtable; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (GXdpTrashSkeletonPrivate)); +#endif +} + +static void +gxdp_trash_skeleton_iface_init (GXdpTrashIface *iface) +{ + iface->get_version = gxdp_trash_skeleton_get_version; +} + +/** + * gxdp_trash_skeleton_new: + * + * Creates a skeleton object for the D-Bus interface org.freedesktop.portal.Trash. + * + * Returns: (transfer full) (type GXdpTrashSkeleton): The skeleton object. + */ +GXdpTrash * +gxdp_trash_skeleton_new (void) +{ + return GXDP_TRASH (g_object_new (GXDP_TYPE_TRASH_SKELETON, NULL)); +} + diff --git a/gio/xdp-dbus.h b/gio/xdp-dbus.h index d5d439875e34c7573f1b48f8fc7447034db28162..6c06210536cfef8f64f806754106228cf04d3697 100644 --- a/gio/xdp-dbus.h +++ b/gio/xdp-dbus.h @@ -1,1070 +1,1172 @@ -/* - * Generated by gdbus-codegen 2.62.5 from org.freedesktop.portal.Documents.xml, org.freedesktop.portal.OpenURI.xml, org.freedesktop.portal.ProxyResolver.xml, org.freedesktop.portal.Trash.xml. DO NOT EDIT. - * - * The license of this code is the same as for the D-Bus interface description - * it was derived from. - */ - -#ifndef __XDP_DBUS_H__ -#define __XDP_DBUS_H__ - -#include - -G_BEGIN_DECLS - - -/* ------------------------------------------------------------------------ */ -/* Declarations for org.freedesktop.portal.Documents */ - -#define GXDP_TYPE_DOCUMENTS (gxdp_documents_get_type ()) -#define GXDP_DOCUMENTS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_DOCUMENTS, GXdpDocuments)) -#define GXDP_IS_DOCUMENTS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_DOCUMENTS)) -#define GXDP_DOCUMENTS_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_DOCUMENTS, GXdpDocumentsIface)) - -struct _GXdpDocuments; -typedef struct _GXdpDocuments GXdpDocuments; -typedef struct _GXdpDocumentsIface GXdpDocumentsIface; - -struct _GXdpDocumentsIface -{ - GTypeInterface parent_iface; - - - gboolean (*handle_add) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - GVariant *arg_o_path_fd, - gboolean arg_reuse_existing, - gboolean arg_persistent); - - gboolean (*handle_add_full) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - GVariant *arg_o_path_fds, - guint arg_flags, - const gchar *arg_app_id, - const gchar *const *arg_permissions); - - gboolean (*handle_add_named) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - GVariant *arg_o_path_parent_fd, - const gchar *arg_filename, - gboolean arg_reuse_existing, - gboolean arg_persistent); - - gboolean (*handle_delete) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *arg_doc_id); - - gboolean (*handle_get_mount_point) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation); - - gboolean (*handle_grant_permissions) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions); - - gboolean (*handle_info) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *arg_doc_id); - - gboolean (*handle_list) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *arg_app_id); - - gboolean (*handle_lookup) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *arg_filename); - - gboolean (*handle_revoke_permissions) ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions); - - guint (*get_version) (GXdpDocuments *object); - -}; - -GType gxdp_documents_get_type (void) G_GNUC_CONST; - -GDBusInterfaceInfo *gxdp_documents_interface_info (void); -guint gxdp_documents_override_properties (GObjectClass *klass, guint property_id_begin); - - -/* D-Bus method call completion functions: */ -void gxdp_documents_complete_get_mount_point ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *path); - -void gxdp_documents_complete_add ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *doc_id); - -void gxdp_documents_complete_add_named ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *doc_id); - -void gxdp_documents_complete_add_full ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *const *doc_ids, - GVariant *extra_out); - -void gxdp_documents_complete_grant_permissions ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation); - -void gxdp_documents_complete_revoke_permissions ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation); - -void gxdp_documents_complete_delete ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation); - -void gxdp_documents_complete_lookup ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *doc_id); - -void gxdp_documents_complete_info ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - const gchar *path, - GVariant *apps); - -void gxdp_documents_complete_list ( - GXdpDocuments *object, - GDBusMethodInvocation *invocation, - GVariant *docs); - - - -/* D-Bus method calls: */ -void gxdp_documents_call_get_mount_point ( - GXdpDocuments *proxy, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_get_mount_point_finish ( - GXdpDocuments *proxy, - gchar **out_path, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_get_mount_point_sync ( - GXdpDocuments *proxy, - gchar **out_path, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_add ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fd, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_add_finish ( - GXdpDocuments *proxy, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_add_sync ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fd, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_add_named ( - GXdpDocuments *proxy, - GVariant *arg_o_path_parent_fd, - const gchar *arg_filename, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_add_named_finish ( - GXdpDocuments *proxy, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_add_named_sync ( - GXdpDocuments *proxy, - GVariant *arg_o_path_parent_fd, - const gchar *arg_filename, - gboolean arg_reuse_existing, - gboolean arg_persistent, - GUnixFDList *fd_list, - gchar **out_doc_id, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_add_full ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fds, - guint arg_flags, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_add_full_finish ( - GXdpDocuments *proxy, - gchar ***out_doc_ids, - GVariant **out_extra_out, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_add_full_sync ( - GXdpDocuments *proxy, - GVariant *arg_o_path_fds, - guint arg_flags, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GUnixFDList *fd_list, - gchar ***out_doc_ids, - GVariant **out_extra_out, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_grant_permissions ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_grant_permissions_finish ( - GXdpDocuments *proxy, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_grant_permissions_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_revoke_permissions ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_revoke_permissions_finish ( - GXdpDocuments *proxy, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_revoke_permissions_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - const gchar *arg_app_id, - const gchar *const *arg_permissions, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_delete ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_delete_finish ( - GXdpDocuments *proxy, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_delete_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_lookup ( - GXdpDocuments *proxy, - const gchar *arg_filename, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_lookup_finish ( - GXdpDocuments *proxy, - gchar **out_doc_id, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_lookup_sync ( - GXdpDocuments *proxy, - const gchar *arg_filename, - gchar **out_doc_id, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_info ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_info_finish ( - GXdpDocuments *proxy, - gchar **out_path, - GVariant **out_apps, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_info_sync ( - GXdpDocuments *proxy, - const gchar *arg_doc_id, - gchar **out_path, - GVariant **out_apps, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_call_list ( - GXdpDocuments *proxy, - const gchar *arg_app_id, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_documents_call_list_finish ( - GXdpDocuments *proxy, - GVariant **out_docs, - GAsyncResult *res, - GError **error); - -gboolean gxdp_documents_call_list_sync ( - GXdpDocuments *proxy, - const gchar *arg_app_id, - GVariant **out_docs, - GCancellable *cancellable, - GError **error); - - - -/* D-Bus property accessors: */ -guint gxdp_documents_get_version (GXdpDocuments *object); -void gxdp_documents_set_version (GXdpDocuments *object, guint value); - - -/* ---- */ - -#define GXDP_TYPE_DOCUMENTS_PROXY (gxdp_documents_proxy_get_type ()) -#define GXDP_DOCUMENTS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxy)) -#define GXDP_DOCUMENTS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxyClass)) -#define GXDP_DOCUMENTS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxyClass)) -#define GXDP_IS_DOCUMENTS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_DOCUMENTS_PROXY)) -#define GXDP_IS_DOCUMENTS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_DOCUMENTS_PROXY)) - -typedef struct _GXdpDocumentsProxy GXdpDocumentsProxy; -typedef struct _GXdpDocumentsProxyClass GXdpDocumentsProxyClass; -typedef struct _GXdpDocumentsProxyPrivate GXdpDocumentsProxyPrivate; - -struct _GXdpDocumentsProxy -{ - /*< private >*/ - GDBusProxy parent_instance; - GXdpDocumentsProxyPrivate *priv; -}; - -struct _GXdpDocumentsProxyClass -{ - GDBusProxyClass parent_class; -}; - -GType gxdp_documents_proxy_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpDocumentsProxy, g_object_unref) -#endif - -void gxdp_documents_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpDocuments *gxdp_documents_proxy_new_finish ( - GAsyncResult *res, - GError **error); -GXdpDocuments *gxdp_documents_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - -void gxdp_documents_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpDocuments *gxdp_documents_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error); -GXdpDocuments *gxdp_documents_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - - -/* ---- */ - -#define GXDP_TYPE_DOCUMENTS_SKELETON (gxdp_documents_skeleton_get_type ()) -#define GXDP_DOCUMENTS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeleton)) -#define GXDP_DOCUMENTS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeletonClass)) -#define GXDP_DOCUMENTS_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeletonClass)) -#define GXDP_IS_DOCUMENTS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_DOCUMENTS_SKELETON)) -#define GXDP_IS_DOCUMENTS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_DOCUMENTS_SKELETON)) - -typedef struct _GXdpDocumentsSkeleton GXdpDocumentsSkeleton; -typedef struct _GXdpDocumentsSkeletonClass GXdpDocumentsSkeletonClass; -typedef struct _GXdpDocumentsSkeletonPrivate GXdpDocumentsSkeletonPrivate; - -struct _GXdpDocumentsSkeleton -{ - /*< private >*/ - GDBusInterfaceSkeleton parent_instance; - GXdpDocumentsSkeletonPrivate *priv; -}; - -struct _GXdpDocumentsSkeletonClass -{ - GDBusInterfaceSkeletonClass parent_class; -}; - -GType gxdp_documents_skeleton_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpDocumentsSkeleton, g_object_unref) -#endif - -GXdpDocuments *gxdp_documents_skeleton_new (void); - - -/* ------------------------------------------------------------------------ */ -/* Declarations for org.freedesktop.portal.OpenURI */ - -#define GXDP_TYPE_OPEN_URI (gxdp_open_uri_get_type ()) -#define GXDP_OPEN_URI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_OPEN_URI, GXdpOpenURI)) -#define GXDP_IS_OPEN_URI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_OPEN_URI)) -#define GXDP_OPEN_URI_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_OPEN_URI, GXdpOpenURIIface)) - -struct _GXdpOpenURI; -typedef struct _GXdpOpenURI GXdpOpenURI; -typedef struct _GXdpOpenURIIface GXdpOpenURIIface; - -struct _GXdpOpenURIIface -{ - GTypeInterface parent_iface; - - - gboolean (*handle_open_file) ( - GXdpOpenURI *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *arg_parent_window, - GVariant *arg_fd, - GVariant *arg_options); - - gboolean (*handle_open_uri) ( - GXdpOpenURI *object, - GDBusMethodInvocation *invocation, - const gchar *arg_parent_window, - const gchar *arg_uri, - GVariant *arg_options); - - guint (*get_version) (GXdpOpenURI *object); - -}; - -GType gxdp_open_uri_get_type (void) G_GNUC_CONST; - -GDBusInterfaceInfo *gxdp_open_uri_interface_info (void); -guint gxdp_open_uri_override_properties (GObjectClass *klass, guint property_id_begin); - - -/* D-Bus method call completion functions: */ -void gxdp_open_uri_complete_open_uri ( - GXdpOpenURI *object, - GDBusMethodInvocation *invocation, - const gchar *handle); - -void gxdp_open_uri_complete_open_file ( - GXdpOpenURI *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - const gchar *handle); - - - -/* D-Bus method calls: */ -void gxdp_open_uri_call_open_uri ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - const gchar *arg_uri, - GVariant *arg_options, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_open_uri_call_open_uri_finish ( - GXdpOpenURI *proxy, - gchar **out_handle, - GAsyncResult *res, - GError **error); - -gboolean gxdp_open_uri_call_open_uri_sync ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - const gchar *arg_uri, - GVariant *arg_options, - gchar **out_handle, - GCancellable *cancellable, - GError **error); - -void gxdp_open_uri_call_open_file ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - GVariant *arg_fd, - GVariant *arg_options, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_open_uri_call_open_file_finish ( - GXdpOpenURI *proxy, - gchar **out_handle, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error); - -gboolean gxdp_open_uri_call_open_file_sync ( - GXdpOpenURI *proxy, - const gchar *arg_parent_window, - GVariant *arg_fd, - GVariant *arg_options, - GUnixFDList *fd_list, - gchar **out_handle, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error); - - - -/* D-Bus property accessors: */ -guint gxdp_open_uri_get_version (GXdpOpenURI *object); -void gxdp_open_uri_set_version (GXdpOpenURI *object, guint value); - - -/* ---- */ - -#define GXDP_TYPE_OPEN_URI_PROXY (gxdp_open_uri_proxy_get_type ()) -#define GXDP_OPEN_URI_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxy)) -#define GXDP_OPEN_URI_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxyClass)) -#define GXDP_OPEN_URI_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxyClass)) -#define GXDP_IS_OPEN_URI_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_OPEN_URI_PROXY)) -#define GXDP_IS_OPEN_URI_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_OPEN_URI_PROXY)) - -typedef struct _GXdpOpenURIProxy GXdpOpenURIProxy; -typedef struct _GXdpOpenURIProxyClass GXdpOpenURIProxyClass; -typedef struct _GXdpOpenURIProxyPrivate GXdpOpenURIProxyPrivate; - -struct _GXdpOpenURIProxy -{ - /*< private >*/ - GDBusProxy parent_instance; - GXdpOpenURIProxyPrivate *priv; -}; - -struct _GXdpOpenURIProxyClass -{ - GDBusProxyClass parent_class; -}; - -GType gxdp_open_uri_proxy_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpOpenURIProxy, g_object_unref) -#endif - -void gxdp_open_uri_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpOpenURI *gxdp_open_uri_proxy_new_finish ( - GAsyncResult *res, - GError **error); -GXdpOpenURI *gxdp_open_uri_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - -void gxdp_open_uri_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpOpenURI *gxdp_open_uri_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error); -GXdpOpenURI *gxdp_open_uri_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - - -/* ---- */ - -#define GXDP_TYPE_OPEN_URI_SKELETON (gxdp_open_uri_skeleton_get_type ()) -#define GXDP_OPEN_URI_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeleton)) -#define GXDP_OPEN_URI_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeletonClass)) -#define GXDP_OPEN_URI_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeletonClass)) -#define GXDP_IS_OPEN_URI_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_OPEN_URI_SKELETON)) -#define GXDP_IS_OPEN_URI_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_OPEN_URI_SKELETON)) - -typedef struct _GXdpOpenURISkeleton GXdpOpenURISkeleton; -typedef struct _GXdpOpenURISkeletonClass GXdpOpenURISkeletonClass; -typedef struct _GXdpOpenURISkeletonPrivate GXdpOpenURISkeletonPrivate; - -struct _GXdpOpenURISkeleton -{ - /*< private >*/ - GDBusInterfaceSkeleton parent_instance; - GXdpOpenURISkeletonPrivate *priv; -}; - -struct _GXdpOpenURISkeletonClass -{ - GDBusInterfaceSkeletonClass parent_class; -}; - -GType gxdp_open_uri_skeleton_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpOpenURISkeleton, g_object_unref) -#endif - -GXdpOpenURI *gxdp_open_uri_skeleton_new (void); - - -/* ------------------------------------------------------------------------ */ -/* Declarations for org.freedesktop.portal.ProxyResolver */ - -#define GXDP_TYPE_PROXY_RESOLVER (gxdp_proxy_resolver_get_type ()) -#define GXDP_PROXY_RESOLVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_PROXY_RESOLVER, GXdpProxyResolver)) -#define GXDP_IS_PROXY_RESOLVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_PROXY_RESOLVER)) -#define GXDP_PROXY_RESOLVER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_PROXY_RESOLVER, GXdpProxyResolverIface)) - -struct _GXdpProxyResolver; -typedef struct _GXdpProxyResolver GXdpProxyResolver; -typedef struct _GXdpProxyResolverIface GXdpProxyResolverIface; - -struct _GXdpProxyResolverIface -{ - GTypeInterface parent_iface; - - gboolean (*handle_lookup) ( - GXdpProxyResolver *object, - GDBusMethodInvocation *invocation, - const gchar *arg_uri); - -}; - -GType gxdp_proxy_resolver_get_type (void) G_GNUC_CONST; - -GDBusInterfaceInfo *gxdp_proxy_resolver_interface_info (void); -guint gxdp_proxy_resolver_override_properties (GObjectClass *klass, guint property_id_begin); - - -/* D-Bus method call completion functions: */ -void gxdp_proxy_resolver_complete_lookup ( - GXdpProxyResolver *object, - GDBusMethodInvocation *invocation, - const gchar *const *proxies); - - - -/* D-Bus method calls: */ -void gxdp_proxy_resolver_call_lookup ( - GXdpProxyResolver *proxy, - const gchar *arg_uri, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_proxy_resolver_call_lookup_finish ( - GXdpProxyResolver *proxy, - gchar ***out_proxies, - GAsyncResult *res, - GError **error); - -gboolean gxdp_proxy_resolver_call_lookup_sync ( - GXdpProxyResolver *proxy, - const gchar *arg_uri, - gchar ***out_proxies, - GCancellable *cancellable, - GError **error); - - - -/* ---- */ - -#define GXDP_TYPE_PROXY_RESOLVER_PROXY (gxdp_proxy_resolver_proxy_get_type ()) -#define GXDP_PROXY_RESOLVER_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxy)) -#define GXDP_PROXY_RESOLVER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxyClass)) -#define GXDP_PROXY_RESOLVER_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxyClass)) -#define GXDP_IS_PROXY_RESOLVER_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_PROXY_RESOLVER_PROXY)) -#define GXDP_IS_PROXY_RESOLVER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_PROXY_RESOLVER_PROXY)) - -typedef struct _GXdpProxyResolverProxy GXdpProxyResolverProxy; -typedef struct _GXdpProxyResolverProxyClass GXdpProxyResolverProxyClass; -typedef struct _GXdpProxyResolverProxyPrivate GXdpProxyResolverProxyPrivate; - -struct _GXdpProxyResolverProxy -{ - /*< private >*/ - GDBusProxy parent_instance; - GXdpProxyResolverProxyPrivate *priv; -}; - -struct _GXdpProxyResolverProxyClass -{ - GDBusProxyClass parent_class; -}; - -GType gxdp_proxy_resolver_proxy_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpProxyResolverProxy, g_object_unref) -#endif - -void gxdp_proxy_resolver_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_finish ( - GAsyncResult *res, - GError **error); -GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - -void gxdp_proxy_resolver_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error); -GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - - -/* ---- */ - -#define GXDP_TYPE_PROXY_RESOLVER_SKELETON (gxdp_proxy_resolver_skeleton_get_type ()) -#define GXDP_PROXY_RESOLVER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeleton)) -#define GXDP_PROXY_RESOLVER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeletonClass)) -#define GXDP_PROXY_RESOLVER_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeletonClass)) -#define GXDP_IS_PROXY_RESOLVER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_PROXY_RESOLVER_SKELETON)) -#define GXDP_IS_PROXY_RESOLVER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_PROXY_RESOLVER_SKELETON)) - -typedef struct _GXdpProxyResolverSkeleton GXdpProxyResolverSkeleton; -typedef struct _GXdpProxyResolverSkeletonClass GXdpProxyResolverSkeletonClass; -typedef struct _GXdpProxyResolverSkeletonPrivate GXdpProxyResolverSkeletonPrivate; - -struct _GXdpProxyResolverSkeleton -{ - /*< private >*/ - GDBusInterfaceSkeleton parent_instance; - GXdpProxyResolverSkeletonPrivate *priv; -}; - -struct _GXdpProxyResolverSkeletonClass -{ - GDBusInterfaceSkeletonClass parent_class; -}; - -GType gxdp_proxy_resolver_skeleton_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpProxyResolverSkeleton, g_object_unref) -#endif - -GXdpProxyResolver *gxdp_proxy_resolver_skeleton_new (void); - - -/* ------------------------------------------------------------------------ */ -/* Declarations for org.freedesktop.portal.Trash */ - -#define GXDP_TYPE_TRASH (gxdp_trash_get_type ()) -#define GXDP_TRASH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_TRASH, GXdpTrash)) -#define GXDP_IS_TRASH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_TRASH)) -#define GXDP_TRASH_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_TRASH, GXdpTrashIface)) - -struct _GXdpTrash; -typedef struct _GXdpTrash GXdpTrash; -typedef struct _GXdpTrashIface GXdpTrashIface; - -struct _GXdpTrashIface -{ - GTypeInterface parent_iface; - - - gboolean (*handle_trash_file) ( - GXdpTrash *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - GVariant *arg_fd); - - guint (*get_version) (GXdpTrash *object); - -}; - -GType gxdp_trash_get_type (void) G_GNUC_CONST; - -GDBusInterfaceInfo *gxdp_trash_interface_info (void); -guint gxdp_trash_override_properties (GObjectClass *klass, guint property_id_begin); - - -/* D-Bus method call completion functions: */ -void gxdp_trash_complete_trash_file ( - GXdpTrash *object, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list, - guint result); - - - -/* D-Bus method calls: */ -void gxdp_trash_call_trash_file ( - GXdpTrash *proxy, - GVariant *arg_fd, - GUnixFDList *fd_list, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean gxdp_trash_call_trash_file_finish ( - GXdpTrash *proxy, - guint *out_result, - GUnixFDList **out_fd_list, - GAsyncResult *res, - GError **error); - -gboolean gxdp_trash_call_trash_file_sync ( - GXdpTrash *proxy, - GVariant *arg_fd, - GUnixFDList *fd_list, - guint *out_result, - GUnixFDList **out_fd_list, - GCancellable *cancellable, - GError **error); - - - -/* D-Bus property accessors: */ -guint gxdp_trash_get_version (GXdpTrash *object); -void gxdp_trash_set_version (GXdpTrash *object, guint value); - - -/* ---- */ - -#define GXDP_TYPE_TRASH_PROXY (gxdp_trash_proxy_get_type ()) -#define GXDP_TRASH_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_TRASH_PROXY, GXdpTrashProxy)) -#define GXDP_TRASH_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_TRASH_PROXY, GXdpTrashProxyClass)) -#define GXDP_TRASH_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_TRASH_PROXY, GXdpTrashProxyClass)) -#define GXDP_IS_TRASH_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_TRASH_PROXY)) -#define GXDP_IS_TRASH_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_TRASH_PROXY)) - -typedef struct _GXdpTrashProxy GXdpTrashProxy; -typedef struct _GXdpTrashProxyClass GXdpTrashProxyClass; -typedef struct _GXdpTrashProxyPrivate GXdpTrashProxyPrivate; - -struct _GXdpTrashProxy -{ - /*< private >*/ - GDBusProxy parent_instance; - GXdpTrashProxyPrivate *priv; -}; - -struct _GXdpTrashProxyClass -{ - GDBusProxyClass parent_class; -}; - -GType gxdp_trash_proxy_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpTrashProxy, g_object_unref) -#endif - -void gxdp_trash_proxy_new ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpTrash *gxdp_trash_proxy_new_finish ( - GAsyncResult *res, - GError **error); -GXdpTrash *gxdp_trash_proxy_new_sync ( - GDBusConnection *connection, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - -void gxdp_trash_proxy_new_for_bus ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GXdpTrash *gxdp_trash_proxy_new_for_bus_finish ( - GAsyncResult *res, - GError **error); -GXdpTrash *gxdp_trash_proxy_new_for_bus_sync ( - GBusType bus_type, - GDBusProxyFlags flags, - const gchar *name, - const gchar *object_path, - GCancellable *cancellable, - GError **error); - - -/* ---- */ - -#define GXDP_TYPE_TRASH_SKELETON (gxdp_trash_skeleton_get_type ()) -#define GXDP_TRASH_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeleton)) -#define GXDP_TRASH_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeletonClass)) -#define GXDP_TRASH_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeletonClass)) -#define GXDP_IS_TRASH_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_TRASH_SKELETON)) -#define GXDP_IS_TRASH_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_TRASH_SKELETON)) - -typedef struct _GXdpTrashSkeleton GXdpTrashSkeleton; -typedef struct _GXdpTrashSkeletonClass GXdpTrashSkeletonClass; -typedef struct _GXdpTrashSkeletonPrivate GXdpTrashSkeletonPrivate; - -struct _GXdpTrashSkeleton -{ - /*< private >*/ - GDBusInterfaceSkeleton parent_instance; - GXdpTrashSkeletonPrivate *priv; -}; - -struct _GXdpTrashSkeletonClass -{ - GDBusInterfaceSkeletonClass parent_class; -}; - -GType gxdp_trash_skeleton_get_type (void) G_GNUC_CONST; - -#if GLIB_CHECK_VERSION(2, 44, 0) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpTrashSkeleton, g_object_unref) -#endif - -GXdpTrash *gxdp_trash_skeleton_new (void); - - -G_END_DECLS - -#endif /* __XDP_DBUS_H__ */ +/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */ + +#ifndef __XDP_DBUS_H__ +#define __XDP_DBUS_H__ + +#include + +G_BEGIN_DECLS + + +/* ------------------------------------------------------------------------ */ +/* Declarations for org.freedesktop.portal.Documents */ + +#define GXDP_TYPE_DOCUMENTS (gxdp_documents_get_type ()) +#define GXDP_DOCUMENTS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_DOCUMENTS, GXdpDocuments)) +#define GXDP_IS_DOCUMENTS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_DOCUMENTS)) +#define GXDP_DOCUMENTS_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_DOCUMENTS, GXdpDocumentsIface)) + +struct _GXdpDocuments; +typedef struct _GXdpDocuments GXdpDocuments; +typedef struct _GXdpDocumentsIface GXdpDocumentsIface; + +struct _GXdpDocumentsIface +{ + GTypeInterface parent_iface; + + + gboolean (*handle_add) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_o_path_fd, + gboolean arg_reuse_existing, + gboolean arg_persistent); + + gboolean (*handle_add_full) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_o_path_fds, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions); + + gboolean (*handle_add_named) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_o_path_parent_fd, + const gchar *arg_filename, + gboolean arg_reuse_existing, + gboolean arg_persistent); + + gboolean (*handle_add_named_full) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_o_path_fd, + const gchar *arg_filename, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions); + + gboolean (*handle_delete) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *arg_doc_id); + + gboolean (*handle_get_mount_point) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation); + + gboolean (*handle_grant_permissions) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions); + + gboolean (*handle_info) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *arg_doc_id); + + gboolean (*handle_list) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *arg_app_id); + + gboolean (*handle_lookup) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *arg_filename); + + gboolean (*handle_revoke_permissions) ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions); + + guint (*get_version) (GXdpDocuments *object); + +}; + +GType gxdp_documents_get_type (void) G_GNUC_CONST; + +GDBusInterfaceInfo *gxdp_documents_interface_info (void); +guint gxdp_documents_override_properties (GObjectClass *klass, guint property_id_begin); + + +/* D-Bus method call completion functions: */ +void gxdp_documents_complete_get_mount_point ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *path); + +void gxdp_documents_complete_add ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *doc_id); + +void gxdp_documents_complete_add_named ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *doc_id); + +void gxdp_documents_complete_add_full ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *const *doc_ids, + GVariant *extra_out); + +void gxdp_documents_complete_add_named_full ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *doc_id, + GVariant *extra_out); + +void gxdp_documents_complete_grant_permissions ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation); + +void gxdp_documents_complete_revoke_permissions ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation); + +void gxdp_documents_complete_delete ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation); + +void gxdp_documents_complete_lookup ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *doc_id); + +void gxdp_documents_complete_info ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + const gchar *path, + GVariant *apps); + +void gxdp_documents_complete_list ( + GXdpDocuments *object, + GDBusMethodInvocation *invocation, + GVariant *docs); + + + +/* D-Bus method calls: */ +void gxdp_documents_call_get_mount_point ( + GXdpDocuments *proxy, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_get_mount_point_finish ( + GXdpDocuments *proxy, + gchar **out_path, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_get_mount_point_sync ( + GXdpDocuments *proxy, + gchar **out_path, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_add ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_add_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_add_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_add_named ( + GXdpDocuments *proxy, + GVariant *arg_o_path_parent_fd, + const gchar *arg_filename, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_add_named_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_add_named_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_parent_fd, + const gchar *arg_filename, + gboolean arg_reuse_existing, + gboolean arg_persistent, + GUnixFDList *fd_list, + gchar **out_doc_id, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_add_full ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fds, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_add_full_finish ( + GXdpDocuments *proxy, + gchar ***out_doc_ids, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_add_full_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fds, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + gchar ***out_doc_ids, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_add_named_full ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + const gchar *arg_filename, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_add_named_full_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_add_named_full_sync ( + GXdpDocuments *proxy, + GVariant *arg_o_path_fd, + const gchar *arg_filename, + guint arg_flags, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GUnixFDList *fd_list, + gchar **out_doc_id, + GVariant **out_extra_out, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_grant_permissions ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_grant_permissions_finish ( + GXdpDocuments *proxy, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_grant_permissions_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_revoke_permissions ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_revoke_permissions_finish ( + GXdpDocuments *proxy, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_revoke_permissions_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + const gchar *arg_app_id, + const gchar *const *arg_permissions, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_delete ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_delete_finish ( + GXdpDocuments *proxy, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_delete_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_lookup ( + GXdpDocuments *proxy, + const gchar *arg_filename, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_lookup_finish ( + GXdpDocuments *proxy, + gchar **out_doc_id, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_lookup_sync ( + GXdpDocuments *proxy, + const gchar *arg_filename, + gchar **out_doc_id, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_info ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_info_finish ( + GXdpDocuments *proxy, + gchar **out_path, + GVariant **out_apps, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_info_sync ( + GXdpDocuments *proxy, + const gchar *arg_doc_id, + gchar **out_path, + GVariant **out_apps, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_call_list ( + GXdpDocuments *proxy, + const gchar *arg_app_id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_documents_call_list_finish ( + GXdpDocuments *proxy, + GVariant **out_docs, + GAsyncResult *res, + GError **error); + +gboolean gxdp_documents_call_list_sync ( + GXdpDocuments *proxy, + const gchar *arg_app_id, + GVariant **out_docs, + GCancellable *cancellable, + GError **error); + + + +/* D-Bus property accessors: */ +guint gxdp_documents_get_version (GXdpDocuments *object); +void gxdp_documents_set_version (GXdpDocuments *object, guint value); + + +/* ---- */ + +#define GXDP_TYPE_DOCUMENTS_PROXY (gxdp_documents_proxy_get_type ()) +#define GXDP_DOCUMENTS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxy)) +#define GXDP_DOCUMENTS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxyClass)) +#define GXDP_DOCUMENTS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_DOCUMENTS_PROXY, GXdpDocumentsProxyClass)) +#define GXDP_IS_DOCUMENTS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_DOCUMENTS_PROXY)) +#define GXDP_IS_DOCUMENTS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_DOCUMENTS_PROXY)) + +typedef struct _GXdpDocumentsProxy GXdpDocumentsProxy; +typedef struct _GXdpDocumentsProxyClass GXdpDocumentsProxyClass; +typedef struct _GXdpDocumentsProxyPrivate GXdpDocumentsProxyPrivate; + +struct _GXdpDocumentsProxy +{ + /*< private >*/ + GDBusProxy parent_instance; + GXdpDocumentsProxyPrivate *priv; +}; + +struct _GXdpDocumentsProxyClass +{ + GDBusProxyClass parent_class; +}; + +GType gxdp_documents_proxy_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpDocumentsProxy, g_object_unref) +#endif + +void gxdp_documents_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpDocuments *gxdp_documents_proxy_new_finish ( + GAsyncResult *res, + GError **error); +GXdpDocuments *gxdp_documents_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + +void gxdp_documents_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpDocuments *gxdp_documents_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error); +GXdpDocuments *gxdp_documents_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + + +/* ---- */ + +#define GXDP_TYPE_DOCUMENTS_SKELETON (gxdp_documents_skeleton_get_type ()) +#define GXDP_DOCUMENTS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeleton)) +#define GXDP_DOCUMENTS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeletonClass)) +#define GXDP_DOCUMENTS_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_DOCUMENTS_SKELETON, GXdpDocumentsSkeletonClass)) +#define GXDP_IS_DOCUMENTS_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_DOCUMENTS_SKELETON)) +#define GXDP_IS_DOCUMENTS_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_DOCUMENTS_SKELETON)) + +typedef struct _GXdpDocumentsSkeleton GXdpDocumentsSkeleton; +typedef struct _GXdpDocumentsSkeletonClass GXdpDocumentsSkeletonClass; +typedef struct _GXdpDocumentsSkeletonPrivate GXdpDocumentsSkeletonPrivate; + +struct _GXdpDocumentsSkeleton +{ + /*< private >*/ + GDBusInterfaceSkeleton parent_instance; + GXdpDocumentsSkeletonPrivate *priv; +}; + +struct _GXdpDocumentsSkeletonClass +{ + GDBusInterfaceSkeletonClass parent_class; +}; + +GType gxdp_documents_skeleton_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpDocumentsSkeleton, g_object_unref) +#endif + +GXdpDocuments *gxdp_documents_skeleton_new (void); + + +/* ------------------------------------------------------------------------ */ +/* Declarations for org.freedesktop.portal.OpenURI */ + +#define GXDP_TYPE_OPEN_URI (gxdp_open_uri_get_type ()) +#define GXDP_OPEN_URI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_OPEN_URI, GXdpOpenURI)) +#define GXDP_IS_OPEN_URI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_OPEN_URI)) +#define GXDP_OPEN_URI_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_OPEN_URI, GXdpOpenURIIface)) + +struct _GXdpOpenURI; +typedef struct _GXdpOpenURI GXdpOpenURI; +typedef struct _GXdpOpenURIIface GXdpOpenURIIface; + +struct _GXdpOpenURIIface +{ + GTypeInterface parent_iface; + + + gboolean (*handle_open_directory) ( + GXdpOpenURI *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options); + + gboolean (*handle_open_file) ( + GXdpOpenURI *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options); + + gboolean (*handle_open_uri) ( + GXdpOpenURI *object, + GDBusMethodInvocation *invocation, + const gchar *arg_parent_window, + const gchar *arg_uri, + GVariant *arg_options); + + guint (*get_version) (GXdpOpenURI *object); + +}; + +GType gxdp_open_uri_get_type (void) G_GNUC_CONST; + +GDBusInterfaceInfo *gxdp_open_uri_interface_info (void); +guint gxdp_open_uri_override_properties (GObjectClass *klass, guint property_id_begin); + + +/* D-Bus method call completion functions: */ +void gxdp_open_uri_complete_open_uri ( + GXdpOpenURI *object, + GDBusMethodInvocation *invocation, + const gchar *handle); + +void gxdp_open_uri_complete_open_file ( + GXdpOpenURI *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *handle); + +void gxdp_open_uri_complete_open_directory ( + GXdpOpenURI *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *handle); + + + +/* D-Bus method calls: */ +void gxdp_open_uri_call_open_uri ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + const gchar *arg_uri, + GVariant *arg_options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_open_uri_call_open_uri_finish ( + GXdpOpenURI *proxy, + gchar **out_handle, + GAsyncResult *res, + GError **error); + +gboolean gxdp_open_uri_call_open_uri_sync ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + const gchar *arg_uri, + GVariant *arg_options, + gchar **out_handle, + GCancellable *cancellable, + GError **error); + +void gxdp_open_uri_call_open_file ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_open_uri_call_open_file_finish ( + GXdpOpenURI *proxy, + gchar **out_handle, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_open_uri_call_open_file_sync ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + gchar **out_handle, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + +void gxdp_open_uri_call_open_directory ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_open_uri_call_open_directory_finish ( + GXdpOpenURI *proxy, + gchar **out_handle, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_open_uri_call_open_directory_sync ( + GXdpOpenURI *proxy, + const gchar *arg_parent_window, + GVariant *arg_fd, + GVariant *arg_options, + GUnixFDList *fd_list, + gchar **out_handle, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + + + +/* D-Bus property accessors: */ +guint gxdp_open_uri_get_version (GXdpOpenURI *object); +void gxdp_open_uri_set_version (GXdpOpenURI *object, guint value); + + +/* ---- */ + +#define GXDP_TYPE_OPEN_URI_PROXY (gxdp_open_uri_proxy_get_type ()) +#define GXDP_OPEN_URI_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxy)) +#define GXDP_OPEN_URI_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxyClass)) +#define GXDP_OPEN_URI_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_OPEN_URI_PROXY, GXdpOpenURIProxyClass)) +#define GXDP_IS_OPEN_URI_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_OPEN_URI_PROXY)) +#define GXDP_IS_OPEN_URI_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_OPEN_URI_PROXY)) + +typedef struct _GXdpOpenURIProxy GXdpOpenURIProxy; +typedef struct _GXdpOpenURIProxyClass GXdpOpenURIProxyClass; +typedef struct _GXdpOpenURIProxyPrivate GXdpOpenURIProxyPrivate; + +struct _GXdpOpenURIProxy +{ + /*< private >*/ + GDBusProxy parent_instance; + GXdpOpenURIProxyPrivate *priv; +}; + +struct _GXdpOpenURIProxyClass +{ + GDBusProxyClass parent_class; +}; + +GType gxdp_open_uri_proxy_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpOpenURIProxy, g_object_unref) +#endif + +void gxdp_open_uri_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpOpenURI *gxdp_open_uri_proxy_new_finish ( + GAsyncResult *res, + GError **error); +GXdpOpenURI *gxdp_open_uri_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + +void gxdp_open_uri_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpOpenURI *gxdp_open_uri_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error); +GXdpOpenURI *gxdp_open_uri_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + + +/* ---- */ + +#define GXDP_TYPE_OPEN_URI_SKELETON (gxdp_open_uri_skeleton_get_type ()) +#define GXDP_OPEN_URI_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeleton)) +#define GXDP_OPEN_URI_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeletonClass)) +#define GXDP_OPEN_URI_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_OPEN_URI_SKELETON, GXdpOpenURISkeletonClass)) +#define GXDP_IS_OPEN_URI_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_OPEN_URI_SKELETON)) +#define GXDP_IS_OPEN_URI_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_OPEN_URI_SKELETON)) + +typedef struct _GXdpOpenURISkeleton GXdpOpenURISkeleton; +typedef struct _GXdpOpenURISkeletonClass GXdpOpenURISkeletonClass; +typedef struct _GXdpOpenURISkeletonPrivate GXdpOpenURISkeletonPrivate; + +struct _GXdpOpenURISkeleton +{ + /*< private >*/ + GDBusInterfaceSkeleton parent_instance; + GXdpOpenURISkeletonPrivate *priv; +}; + +struct _GXdpOpenURISkeletonClass +{ + GDBusInterfaceSkeletonClass parent_class; +}; + +GType gxdp_open_uri_skeleton_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpOpenURISkeleton, g_object_unref) +#endif + +GXdpOpenURI *gxdp_open_uri_skeleton_new (void); + + +/* ------------------------------------------------------------------------ */ +/* Declarations for org.freedesktop.portal.ProxyResolver */ + +#define GXDP_TYPE_PROXY_RESOLVER (gxdp_proxy_resolver_get_type ()) +#define GXDP_PROXY_RESOLVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_PROXY_RESOLVER, GXdpProxyResolver)) +#define GXDP_IS_PROXY_RESOLVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_PROXY_RESOLVER)) +#define GXDP_PROXY_RESOLVER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_PROXY_RESOLVER, GXdpProxyResolverIface)) + +struct _GXdpProxyResolver; +typedef struct _GXdpProxyResolver GXdpProxyResolver; +typedef struct _GXdpProxyResolverIface GXdpProxyResolverIface; + +struct _GXdpProxyResolverIface +{ + GTypeInterface parent_iface; + + + gboolean (*handle_lookup) ( + GXdpProxyResolver *object, + GDBusMethodInvocation *invocation, + const gchar *arg_uri); + + guint (*get_version) (GXdpProxyResolver *object); + +}; + +GType gxdp_proxy_resolver_get_type (void) G_GNUC_CONST; + +GDBusInterfaceInfo *gxdp_proxy_resolver_interface_info (void); +guint gxdp_proxy_resolver_override_properties (GObjectClass *klass, guint property_id_begin); + + +/* D-Bus method call completion functions: */ +void gxdp_proxy_resolver_complete_lookup ( + GXdpProxyResolver *object, + GDBusMethodInvocation *invocation, + const gchar *const *proxies); + + + +/* D-Bus method calls: */ +void gxdp_proxy_resolver_call_lookup ( + GXdpProxyResolver *proxy, + const gchar *arg_uri, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_proxy_resolver_call_lookup_finish ( + GXdpProxyResolver *proxy, + gchar ***out_proxies, + GAsyncResult *res, + GError **error); + +gboolean gxdp_proxy_resolver_call_lookup_sync ( + GXdpProxyResolver *proxy, + const gchar *arg_uri, + gchar ***out_proxies, + GCancellable *cancellable, + GError **error); + + + +/* D-Bus property accessors: */ +guint gxdp_proxy_resolver_get_version (GXdpProxyResolver *object); +void gxdp_proxy_resolver_set_version (GXdpProxyResolver *object, guint value); + + +/* ---- */ + +#define GXDP_TYPE_PROXY_RESOLVER_PROXY (gxdp_proxy_resolver_proxy_get_type ()) +#define GXDP_PROXY_RESOLVER_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxy)) +#define GXDP_PROXY_RESOLVER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxyClass)) +#define GXDP_PROXY_RESOLVER_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_PROXY_RESOLVER_PROXY, GXdpProxyResolverProxyClass)) +#define GXDP_IS_PROXY_RESOLVER_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_PROXY_RESOLVER_PROXY)) +#define GXDP_IS_PROXY_RESOLVER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_PROXY_RESOLVER_PROXY)) + +typedef struct _GXdpProxyResolverProxy GXdpProxyResolverProxy; +typedef struct _GXdpProxyResolverProxyClass GXdpProxyResolverProxyClass; +typedef struct _GXdpProxyResolverProxyPrivate GXdpProxyResolverProxyPrivate; + +struct _GXdpProxyResolverProxy +{ + /*< private >*/ + GDBusProxy parent_instance; + GXdpProxyResolverProxyPrivate *priv; +}; + +struct _GXdpProxyResolverProxyClass +{ + GDBusProxyClass parent_class; +}; + +GType gxdp_proxy_resolver_proxy_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpProxyResolverProxy, g_object_unref) +#endif + +void gxdp_proxy_resolver_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_finish ( + GAsyncResult *res, + GError **error); +GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + +void gxdp_proxy_resolver_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error); +GXdpProxyResolver *gxdp_proxy_resolver_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + + +/* ---- */ + +#define GXDP_TYPE_PROXY_RESOLVER_SKELETON (gxdp_proxy_resolver_skeleton_get_type ()) +#define GXDP_PROXY_RESOLVER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeleton)) +#define GXDP_PROXY_RESOLVER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeletonClass)) +#define GXDP_PROXY_RESOLVER_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_PROXY_RESOLVER_SKELETON, GXdpProxyResolverSkeletonClass)) +#define GXDP_IS_PROXY_RESOLVER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_PROXY_RESOLVER_SKELETON)) +#define GXDP_IS_PROXY_RESOLVER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_PROXY_RESOLVER_SKELETON)) + +typedef struct _GXdpProxyResolverSkeleton GXdpProxyResolverSkeleton; +typedef struct _GXdpProxyResolverSkeletonClass GXdpProxyResolverSkeletonClass; +typedef struct _GXdpProxyResolverSkeletonPrivate GXdpProxyResolverSkeletonPrivate; + +struct _GXdpProxyResolverSkeleton +{ + /*< private >*/ + GDBusInterfaceSkeleton parent_instance; + GXdpProxyResolverSkeletonPrivate *priv; +}; + +struct _GXdpProxyResolverSkeletonClass +{ + GDBusInterfaceSkeletonClass parent_class; +}; + +GType gxdp_proxy_resolver_skeleton_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpProxyResolverSkeleton, g_object_unref) +#endif + +GXdpProxyResolver *gxdp_proxy_resolver_skeleton_new (void); + + +/* ------------------------------------------------------------------------ */ +/* Declarations for org.freedesktop.portal.Trash */ + +#define GXDP_TYPE_TRASH (gxdp_trash_get_type ()) +#define GXDP_TRASH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_TRASH, GXdpTrash)) +#define GXDP_IS_TRASH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_TRASH)) +#define GXDP_TRASH_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GXDP_TYPE_TRASH, GXdpTrashIface)) + +struct _GXdpTrash; +typedef struct _GXdpTrash GXdpTrash; +typedef struct _GXdpTrashIface GXdpTrashIface; + +struct _GXdpTrashIface +{ + GTypeInterface parent_iface; + + + gboolean (*handle_trash_file) ( + GXdpTrash *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_fd); + + guint (*get_version) (GXdpTrash *object); + +}; + +GType gxdp_trash_get_type (void) G_GNUC_CONST; + +GDBusInterfaceInfo *gxdp_trash_interface_info (void); +guint gxdp_trash_override_properties (GObjectClass *klass, guint property_id_begin); + + +/* D-Bus method call completion functions: */ +void gxdp_trash_complete_trash_file ( + GXdpTrash *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + guint result); + + + +/* D-Bus method calls: */ +void gxdp_trash_call_trash_file ( + GXdpTrash *proxy, + GVariant *arg_fd, + GUnixFDList *fd_list, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gxdp_trash_call_trash_file_finish ( + GXdpTrash *proxy, + guint *out_result, + GUnixFDList **out_fd_list, + GAsyncResult *res, + GError **error); + +gboolean gxdp_trash_call_trash_file_sync ( + GXdpTrash *proxy, + GVariant *arg_fd, + GUnixFDList *fd_list, + guint *out_result, + GUnixFDList **out_fd_list, + GCancellable *cancellable, + GError **error); + + + +/* D-Bus property accessors: */ +guint gxdp_trash_get_version (GXdpTrash *object); +void gxdp_trash_set_version (GXdpTrash *object, guint value); + + +/* ---- */ + +#define GXDP_TYPE_TRASH_PROXY (gxdp_trash_proxy_get_type ()) +#define GXDP_TRASH_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_TRASH_PROXY, GXdpTrashProxy)) +#define GXDP_TRASH_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_TRASH_PROXY, GXdpTrashProxyClass)) +#define GXDP_TRASH_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_TRASH_PROXY, GXdpTrashProxyClass)) +#define GXDP_IS_TRASH_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_TRASH_PROXY)) +#define GXDP_IS_TRASH_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_TRASH_PROXY)) + +typedef struct _GXdpTrashProxy GXdpTrashProxy; +typedef struct _GXdpTrashProxyClass GXdpTrashProxyClass; +typedef struct _GXdpTrashProxyPrivate GXdpTrashProxyPrivate; + +struct _GXdpTrashProxy +{ + /*< private >*/ + GDBusProxy parent_instance; + GXdpTrashProxyPrivate *priv; +}; + +struct _GXdpTrashProxyClass +{ + GDBusProxyClass parent_class; +}; + +GType gxdp_trash_proxy_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpTrashProxy, g_object_unref) +#endif + +void gxdp_trash_proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpTrash *gxdp_trash_proxy_new_finish ( + GAsyncResult *res, + GError **error); +GXdpTrash *gxdp_trash_proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + +void gxdp_trash_proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GXdpTrash *gxdp_trash_proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error); +GXdpTrash *gxdp_trash_proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + + +/* ---- */ + +#define GXDP_TYPE_TRASH_SKELETON (gxdp_trash_skeleton_get_type ()) +#define GXDP_TRASH_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeleton)) +#define GXDP_TRASH_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeletonClass)) +#define GXDP_TRASH_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GXDP_TYPE_TRASH_SKELETON, GXdpTrashSkeletonClass)) +#define GXDP_IS_TRASH_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GXDP_TYPE_TRASH_SKELETON)) +#define GXDP_IS_TRASH_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GXDP_TYPE_TRASH_SKELETON)) + +typedef struct _GXdpTrashSkeleton GXdpTrashSkeleton; +typedef struct _GXdpTrashSkeletonClass GXdpTrashSkeletonClass; +typedef struct _GXdpTrashSkeletonPrivate GXdpTrashSkeletonPrivate; + +struct _GXdpTrashSkeleton +{ + /*< private >*/ + GDBusInterfaceSkeleton parent_instance; + GXdpTrashSkeletonPrivate *priv; +}; + +struct _GXdpTrashSkeletonClass +{ + GDBusInterfaceSkeletonClass parent_class; +}; + +GType gxdp_trash_skeleton_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GXdpTrashSkeleton, g_object_unref) +#endif + +GXdpTrash *gxdp_trash_skeleton_new (void); + + +G_END_DECLS + +#endif /* __XDP_DBUS_H__ */ diff --git a/glib-gettextize.in b/glib-gettextize.in old mode 100755 new mode 100644 index af7052f6f7efbb379314ba34330262d5af42b01c..05ec43c1ef9fa3987d4ee7db3a6c1c27d9530314 --- a/glib-gettextize.in +++ b/glib-gettextize.in @@ -73,7 +73,7 @@ This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." $echo "Written by" "Ulrich Drepper" exit 0 ;; - -- ) # Stop option prcessing + -- ) # Stop option processing shift; break ;; -* ) $echo "glib-gettextize: unknown option $1" diff --git a/glib.supp b/glib.supp index 9184052bdc45ad445ed6d28f1351d1d6e637bcce..283166361580f2b5a37cfa4500a419cd7eab6d85 100644 --- a/glib.supp +++ b/glib.supp @@ -73,8 +73,6 @@ fun:malloc ... fun:g_quark_init - ... - fun:glib_init_ctor } { @@ -84,8 +82,6 @@ fun:calloc ... fun:g_quark_init - ... - fun:glib_init_ctor } { @@ -94,7 +90,7 @@ match-leak-kinds:reachable fun:malloc ... - fun:gobject_init_ctor + fun:gobject_init* } { @@ -103,7 +99,7 @@ match-leak-kinds:reachable fun:realloc ... - fun:gobject_init_ctor + fun:gobject_init* } { @@ -112,7 +108,7 @@ match-leak-kinds:possible,reachable fun:calloc ... - fun:gobject_init_ctor + fun:gobject_init* } { @@ -127,7 +123,7 @@ { g-type-register-static Memcheck:Leak - match-leak-kinds:reachable + match-leak-kinds:possible,reachable fun:malloc ... fun:g_type_register_static @@ -145,7 +141,7 @@ { g-type-register-static-calloc Memcheck:Leak - match-leak-kinds:reachable + match-leak-kinds:possible,reachable fun:calloc ... fun:g_type_register_static @@ -218,7 +214,7 @@ } { - g-test-rand-init2 + g-rand-init2 Memcheck:Leak match-leak-kinds:reachable fun:calloc @@ -226,8 +222,6 @@ fun:g_rand_new_with_seed_array ... fun:get_global_random - ... - fun:g_test_init } { @@ -372,6 +366,16 @@ fun:g_type_class_ref } +{ + g-type-class-ref-inlined + Memcheck:Leak + fun:calloc + ... + fun:UnknownInlinedFun + ... + fun:g_type_class_ref +} + { g-io-module-default-singleton-malloc Memcheck:Leak @@ -427,6 +431,14 @@ fun:_g_io_module_get_default* } +{ + g-io-module-default-singleton-weak-ref + Memcheck:Leak + fun:calloc + ... + fun:_g_io_module_get_default +} + { g-get-language-names-malloc Memcheck:Leak @@ -445,6 +457,33 @@ fun:g_get_language_names } +{ + g-get-language_names-with-category-malloc + Memcheck:Leak + match-leak-kinds:reachable + fun:malloc + ... + fun:g_get_language_names_with_category +} + +{ + g-get-language_names-with-category-calloc + Memcheck:Leak + match-leak-kinds:reachable + fun:calloc + ... + fun:g_get_language_names_with_category +} + +{ + g-get-language_names-with-category-realloc + Memcheck:Leak + match-leak-kinds:reachable + fun:realloc + ... + fun:g_get_language_names_with_category +} + { g-static-mutex Memcheck:Leak @@ -463,6 +502,26 @@ fun:g_system_thread_new } +{ + g-system-thread-init-malloc + Memcheck:Leak + match-leak-kinds:possible,reachable + fun:malloc + ... + fun:g_system_thread_new +} + +{ + g-task-thread-pool-init + Memcheck:Leak + match-leak-kinds:possible,reachable,definite + fun:malloc + ... + fun:g_thread_new + ... + fun:g_task_thread_pool_init +} + { g-io-module-default-proxy-resolver-gnome Memcheck:Leak @@ -876,11 +935,21 @@ fun:g_dbus_error_quark } +# g_win32_registry_get_os_dirs_w*() caches an array of strings that is allocated only once. +{ + g_win32_registry_get_os_dirs + Memcheck:Leak + match-leak-kinds:reachable,definite + fun:malloc + ... + fun:g_win32_registry_get_os_dirs* +} + # Thread-private data allocated once per thread { g_private_set_alloc0 Memcheck:Leak - match-leak-kinds:reachable + match-leak-kinds:definite,reachable fun:malloc ... fun:g_private_set_alloc0 @@ -888,17 +957,26 @@ { g_private_set_alloc0-calloc Memcheck:Leak - match-leak-kinds:reachable + match-leak-kinds:definite,reachable fun:calloc ... fun:g_private_set_alloc0 } +# Keys for thread-private data +{ + g_private_key + Memcheck:Leak + match-leak-kinds:reachable + fun:malloc + fun:g_private_impl_new +} + # Thread-private GMainContext stack { g_main_context_push_thread_default Memcheck:Leak - match-leak-kinds:reachable + match-leak-kinds:definite,reachable fun:malloc ... fun:g_queue_new @@ -946,3 +1024,77 @@ ... fun:g_file_* } + +# Cached charset +{ + g_get_charset + Memcheck:Leak + match-leak-kinds:reachable + fun:malloc + ... + fun:g_get_charset +} + +{ + g_get_charset_calloc + Memcheck:Leak + match-leak-kinds:reachable + fun:calloc + ... + fun:g_get_charset +} + +# Global unused thread queue +{ + g_thread_pool_unused_thread_queue + Memcheck:Leak + match-leak-kinds:reachable + fun:malloc + ... + fun:g_async_queue_new_full + ... + fun:g_thread_pool_new +} + +# One-time program name storage +{ + g_set_prgname + Memcheck:Leak + match-leak-kinds:reachable + fun:malloc + ... + fun:g_set_prgname +} + +# Error domains hash +{ + g_error_init + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:g_hash_table_new_full + fun:g_error_init +} + +# Error domain static registration +{ + g_error_domain_register_static + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:g_hash_table_insert + fun:error_domain_register + fun:g_error_domain_register_static +} + +{ + new_quark + Memcheck:Leak + match-leak-kinds:reachable + fun:malloc + ... + fun:g_hash_table_insert + fun:quark_new +} diff --git a/glib/deprecated/gallocator.c b/glib/deprecated/gallocator.c index ad9695aeaedaf954bccc29909f51dcda00068f7f..66483b6323a495cbcadf846859b6a8e286042049 100644 --- a/glib/deprecated/gallocator.c +++ b/glib/deprecated/gallocator.c @@ -16,7 +16,9 @@ #include "config.h" /* we know we are deprecated here, no need for warnings */ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include "gallocator.h" diff --git a/glib/deprecated/gcache.c b/glib/deprecated/gcache.c index 179ad9e17ec5a27d71cdc39ecbd64139bdd5a01d..9e04145be7fad9039c490b3cbff9171eb79679c1 100644 --- a/glib/deprecated/gcache.c +++ b/glib/deprecated/gcache.c @@ -29,7 +29,9 @@ #include "config.h" /* we know we are deprecated here, no need for warnings */ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include "gcache.h" diff --git a/glib/deprecated/gcompletion.c b/glib/deprecated/gcompletion.c index 74342c64f94918c9e072fed4ad6e949b2b377582..d09c1f1fa148ba88433aed059d6d7c5b4526ac15 100644 --- a/glib/deprecated/gcompletion.c +++ b/glib/deprecated/gcompletion.c @@ -29,7 +29,9 @@ #include "config.h" /* we know we are deprecated here, no need for warnings */ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include "gcompletion.h" diff --git a/glib/deprecated/gmain.h b/glib/deprecated/gmain.h index 2199328fd2ae617b104bc6f42a7047c0871d0b7a..5d08eb6b416c92b493f6eb20e5cfbe7db1875c84 100644 --- a/glib/deprecated/gmain.h +++ b/glib/deprecated/gmain.h @@ -115,7 +115,7 @@ G_BEGIN_DECLS * * Returns: %TRUE if any events are pending. * - * Deprected: 2.2: Use g_main_context_pending() instead. + * Deprecated: 2.2: Use g_main_context_pending() instead. */ #define g_main_pending() g_main_context_pending (NULL) GLIB_DEPRECATED_MACRO_IN_2_26_FOR(g_main_context_pending) diff --git a/glib/deprecated/grel.c b/glib/deprecated/grel.c index 32ec37ca89ea9756b11e369521db260a7de7ad41..b48ec11733417433537660a431192458192399e2 100644 --- a/glib/deprecated/grel.c +++ b/glib/deprecated/grel.c @@ -30,7 +30,9 @@ #include "config.h" /* we know we are deprecated here, no need for warnings */ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include "grel.h" diff --git a/glib/deprecated/gthread-deprecated.c b/glib/deprecated/gthread-deprecated.c index b0d67df88f6ebadcf4a6e853bad6c5270b47e399..e7e68fbd68cfa7729cea113a4c119540d0e04b97 100644 --- a/glib/deprecated/gthread-deprecated.c +++ b/glib/deprecated/gthread-deprecated.c @@ -22,7 +22,9 @@ #include "config.h" /* we know we are deprecated here, no need for warnings */ +#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS #define GLIB_DISABLE_DEPRECATION_WARNINGS +#endif #include "gmessages.h" #include "gslice.h" @@ -372,7 +374,7 @@ g_thread_create_full (GThreadFunc func, GThread *thread; thread = g_thread_new_internal (NULL, g_deprecated_thread_proxy, - func, data, stack_size, error); + func, data, stack_size, NULL, error); if (thread && !joinable) { @@ -424,7 +426,7 @@ g_once_init_enter_impl (volatile gsize *location) * want to require prior calling to g_thread_init(), because your code * should also be usable in non-threaded programs, you are not able to * use g_mutex_new() and thus #GMutex, as that requires a prior call to - * g_thread_init(). In theses cases you can also use a #GStaticMutex. + * g_thread_init(). In these cases you can also use a #GStaticMutex. * It must be initialized with g_static_mutex_init() before using it * and freed with with g_static_mutex_free() when not needed anymore to * free up any allocated resources. @@ -669,7 +671,7 @@ g_static_rec_mutex_get_rec_mutex_impl (GStaticRecMutex* mutex) if (!g_thread_supported ()) return NULL; - result = g_atomic_pointer_get (&mutex->mutex.mutex); + result = (GRecMutex *) g_atomic_pointer_get (&mutex->mutex.mutex); if (!result) { @@ -680,7 +682,7 @@ g_static_rec_mutex_get_rec_mutex_impl (GStaticRecMutex* mutex) { result = g_slice_new (GRecMutex); g_rec_mutex_init (result); - g_atomic_pointer_set (&mutex->mutex.mutex, result); + g_atomic_pointer_set (&mutex->mutex.mutex, (GMutex *) result); } G_UNLOCK (g_static_mutex); @@ -1025,7 +1027,7 @@ g_static_rw_lock_reader_lock (GStaticRWLock* lock) * * Returns: %TRUE, if @lock could be locked for reading * - * Deprectated: 2.32: Use g_rw_lock_reader_trylock() instead + * Deprecated: 2.32: Use g_rw_lock_reader_trylock() instead */ gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock) @@ -1055,7 +1057,7 @@ g_static_rw_lock_reader_trylock (GStaticRWLock* lock) * locks for reading have been unlocked, the waiting thread is woken up * and can lock @lock for writing. * - * Deprectated: 2.32: Use g_rw_lock_reader_unlock() instead + * Deprecated: 2.32: Use g_rw_lock_reader_unlock() instead */ void g_static_rw_lock_reader_unlock (GStaticRWLock* lock) @@ -1084,7 +1086,7 @@ g_static_rw_lock_reader_unlock (GStaticRWLock* lock) * @lock (neither for reading nor writing). This lock has to be * unlocked by g_static_rw_lock_writer_unlock(). * - * Deprectated: 2.32: Use g_rw_lock_writer_lock() instead + * Deprecated: 2.32: Use g_rw_lock_writer_lock() instead */ void g_static_rw_lock_writer_lock (GStaticRWLock* lock) @@ -1114,7 +1116,7 @@ g_static_rw_lock_writer_lock (GStaticRWLock* lock) * * Returns: %TRUE, if @lock could be locked for writing * - * Deprectated: 2.32: Use g_rw_lock_writer_trylock() instead + * Deprecated: 2.32: Use g_rw_lock_writer_trylock() instead */ gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock) @@ -1147,7 +1149,7 @@ g_static_rw_lock_writer_trylock (GStaticRWLock* lock) * lock @lock for reading, the waiting threads are woken up and can * lock @lock for reading. * - * Deprectated: 2.32: Use g_rw_lock_writer_unlock() instead + * Deprecated: 2.32: Use g_rw_lock_writer_unlock() instead */ void g_static_rw_lock_writer_unlock (GStaticRWLock* lock) diff --git a/glib/garcbox.c b/glib/garcbox.c index 0fa207c3ffef04ce3a474a4335ca1667d0d21b58..70aebb6eddce209395fcd00ac78f5dd537af7a5f 100644 --- a/glib/garcbox.c +++ b/glib/garcbox.c @@ -144,7 +144,7 @@ * If you need to clear the contents of the data, you will need to use an * ancillary function that calls g_rc_box_release_full(): * - * |[ + * |[ * static void * my_data_struct_release (MyDataStruct *data) * { @@ -188,7 +188,7 @@ g_atomic_rc_box_alloc (gsize block_size) * @block_size: the size of the allocation, must be greater than 0 * * Allocates @block_size bytes of memory, and adds atomic - * referenc counting semantics to it. + * reference counting semantics to it. * * The contents of the returned data is set to zero. * diff --git a/glib/garray.c b/glib/garray.c index d303946f13ad20e57c0c441401be947e63fac1e1..2b66f16a62ec1975f256887daa00584363edb082 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -58,15 +58,20 @@ * * To create a new array use g_array_new(). * - * To add elements to an array, use g_array_append_val(), - * g_array_append_vals(), g_array_prepend_val(), and - * g_array_prepend_vals(). + * To add elements to an array with a cost of O(n) at worst, use + * g_array_append_val(), g_array_append_vals(), g_array_prepend_val(), + * g_array_prepend_vals(), g_array_insert_val() and g_array_insert_vals(). * - * To access an element of an array, use g_array_index(). + * To access an element of an array in O(1) (to read it or to write it), + * use g_array_index(). * * To set the size of an array, use g_array_set_size(). * - * To free an array, use g_array_free(). + * To free an array, use g_array_unref() or g_array_free(). + * + * All the sort functions are internally calling a quick-sort (or similar) + * function with an average cost of O(n log(n)) and a worst case + * cost of O(n^2). * * Here is an example that stores integers in a #GArray: * |[ @@ -117,14 +122,29 @@ struct _GRealArray * @i: the index of the element to return * * Returns the element of a #GArray at the given index. The return - * value is cast to the given type. + * value is cast to the given type. This is the main way to read or write an + * element in a #GArray. * - * This example gets a pointer to an element in a #GArray: + * Writing an element is typically done by reference, as in the following + * example. This example gets a pointer to an element in a #GArray, and then + * writes to a field in it: * |[ * EDayViewEvent *event; * // This gets a pointer to the 4th element in the array of * // EDayViewEvent structs. * event = &g_array_index (events, EDayViewEvent, 3); + * event->start_time = g_get_current_time (); + * ]| + * + * This example reads from and writes to an array of integers: + * |[ + * g_autoptr(GArray) int_array = g_array_new (FALSE, FALSE, sizeof (guint)); + * for (guint i = 0; i < 10; i++) + * g_array_append_val (int_array, i); + * + * guint *my_int = &g_array_index (int_array, guint, 1); + * g_print ("Int at index 1 is %u; decrementing it\n", *my_int); + * *my_int = *my_int - 1; * ]| * * Returns: the element of the #GArray at the index given by @i @@ -165,6 +185,57 @@ g_array_new (gboolean zero_terminated, return g_array_sized_new (zero_terminated, clear, elt_size, 0); } +/** + * g_array_steal: + * @array: a #GArray. + * @len: (optional) (out caller-allocates): pointer to retrieve the number of + * elements of the original array + * + * Frees the data in the array and resets the size to zero, while + * the underlying array is preserved for use elsewhere and returned + * to the caller. + * + * If the array was created with the @zero_terminate property + * set to %TRUE, the returned data is zero terminated too. + * + * If array elements contain dynamically-allocated memory, + * the array elements should also be freed by the caller. + * + * A short example of use: + * |[ + * ... + * gpointer data; + * gsize data_len; + * data = g_array_steal (some_array, &data_len); + * ... + * ]| + + * Returns: (transfer full): the element data, which should be + * freed using g_free(). + * + * Since: 2.64 + */ +gpointer +g_array_steal (GArray *array, + gsize *len) +{ + GRealArray *rarray; + gpointer segment; + + g_return_val_if_fail (array != NULL, NULL); + + rarray = (GRealArray *) array; + segment = (gpointer) rarray->data; + + if (len != NULL) + *len = rarray->len; + + rarray->data = NULL; + rarray->len = 0; + rarray->alloc = 0; + return segment; +} + /** * g_array_sized_new: * @zero_terminated: %TRUE if the array should have an extra element at @@ -512,6 +583,10 @@ g_array_prepend_vals (GArray *farray, * will be initialised to zero if the array was configured to clear elements; * otherwise their values will be undefined. * + * If @index_ is less than the array’s current length, new entries will be + * inserted into the array, and the existing entries above @index_ will be moved + * upwards. + * * @data may be %NULL if (and only if) @len is zero. If @len is zero, this * function is a no-op. * @@ -747,11 +822,12 @@ g_array_sort (GArray *farray, g_return_if_fail (array != NULL); /* Don't use qsort as we want a guaranteed stable sort */ - g_qsort_with_data (array->data, - array->len, - array->elt_size, - (GCompareDataFunc)compare_func, - NULL); + if (array->len > 0) + g_qsort_with_data (array->data, + array->len, + array->elt_size, + (GCompareDataFunc)compare_func, + NULL); } /** @@ -778,11 +854,12 @@ g_array_sort_with_data (GArray *farray, g_return_if_fail (array != NULL); - g_qsort_with_data (array->data, - array->len, - array->elt_size, - compare_func, - user_data); + if (array->len > 0) + g_qsort_with_data (array->data, + array->len, + array->elt_size, + compare_func, + user_data); } /** @@ -1000,6 +1077,27 @@ struct _GRealPtrArray static void g_ptr_array_maybe_expand (GRealPtrArray *array, guint len); +static GPtrArray * +ptr_array_new (guint reserved_size, + GDestroyNotify element_free_func) +{ + GRealPtrArray *array; + + array = g_slice_new (GRealPtrArray); + + array->pdata = NULL; + array->len = 0; + array->alloc = 0; + array->element_free_func = element_free_func; + + g_atomic_ref_count_init (&array->ref_count); + + if (reserved_size != 0) + g_ptr_array_maybe_expand (array, reserved_size); + + return (GPtrArray *) array; +} + /** * g_ptr_array_new: * @@ -1010,7 +1108,80 @@ static void g_ptr_array_maybe_expand (GRealPtrArray *array, GPtrArray* g_ptr_array_new (void) { - return g_ptr_array_sized_new (0); + return ptr_array_new (0, NULL); +} + +/** + * g_ptr_array_steal: + * @array: a #GPtrArray. + * @len: (optional) (out caller-allocates): pointer to retrieve the number of + * elements of the original array + * + * Frees the data in the array and resets the size to zero, while + * the underlying array is preserved for use elsewhere and returned + * to the caller. + * + * Even if set, the #GDestroyNotify function will never be called + * on the current contents of the array and the caller is + * responsible for freeing the array elements. + * + * An example of use: + * |[ + * g_autoptr(GPtrArray) chunk_buffer = g_ptr_array_new_with_free_func (g_bytes_unref); + * + * // Some part of your application appends a number of chunks to the pointer array. + * g_ptr_array_add (chunk_buffer, g_bytes_new_static ("hello", 5)); + * g_ptr_array_add (chunk_buffer, g_bytes_new_static ("world", 5)); + * + * … + * + * // Periodically, the chunks need to be sent as an array-and-length to some + * // other part of the program. + * GBytes **chunks; + * gsize n_chunks; + * + * chunks = g_ptr_array_steal (chunk_buffer, &n_chunks); + * for (gsize i = 0; i < n_chunks; i++) + * { + * // Do something with each chunk here, and then free them, since + * // g_ptr_array_steal() transfers ownership of all the elements and the + * // array to the caller. + * … + * + * g_bytes_unref (chunks[i]); + * } + * + * g_free (chunks); + * + * // After calling g_ptr_array_steal(), the pointer array can be reused for the + * // next set of chunks. + * g_assert (chunk_buffer->len == 0); + * ]| + * + * Returns: (transfer full): the element data, which should be + * freed using g_free(). + * + * Since: 2.64 + */ +gpointer * +g_ptr_array_steal (GPtrArray *array, + gsize *len) +{ + GRealPtrArray *rarray; + gpointer *segment; + + g_return_val_if_fail (array != NULL, NULL); + + rarray = (GRealPtrArray *) array; + segment = (gpointer *) rarray->pdata; + + if (len != NULL) + *len = rarray->len; + + rarray->pdata = NULL; + rarray->len = 0; + rarray->alloc = 0; + return segment; } /** @@ -1042,20 +1213,21 @@ g_ptr_array_copy (GPtrArray *array, GCopyFunc func, gpointer user_data) { - gsize i; GPtrArray *new_array; g_return_val_if_fail (array != NULL, NULL); - new_array = g_ptr_array_sized_new (array->len); - g_ptr_array_set_free_func (new_array, ((GRealPtrArray *) array)->element_free_func); + new_array = ptr_array_new (array->len, + ((GRealPtrArray *) array)->element_free_func); if (func != NULL) { + guint i; + for (i = 0; i < array->len; i++) new_array->pdata[i] = func (array->pdata[i], user_data); } - else + else if (array->len > 0) { memcpy (new_array->pdata, array->pdata, array->len * sizeof (*array->pdata)); @@ -1077,24 +1249,10 @@ g_ptr_array_copy (GPtrArray *array, * * Returns: the new #GPtrArray */ -GPtrArray* +GPtrArray* g_ptr_array_sized_new (guint reserved_size) { - GRealPtrArray *array; - - array = g_slice_new (GRealPtrArray); - - array->pdata = NULL; - array->len = 0; - array->alloc = 0; - array->element_free_func = NULL; - - g_atomic_ref_count_init (&array->ref_count); - - if (reserved_size != 0) - g_ptr_array_maybe_expand (array, reserved_size); - - return (GPtrArray*) array; + return ptr_array_new (reserved_size, NULL); } /** @@ -1118,9 +1276,12 @@ g_array_copy (GArray *array) new_rarray = (GRealArray *) g_array_sized_new (rarray->zero_terminated, rarray->clear, - rarray->elt_size, rarray->len); + rarray->elt_size, rarray->alloc / rarray->elt_size); new_rarray->len = rarray->len; - memcpy (new_rarray->data, rarray->data, rarray->alloc); + if (rarray->len > 0) + memcpy (new_rarray->data, rarray->data, rarray->len * rarray->elt_size); + + g_array_zero_terminate (new_rarray); return (GArray *) new_rarray; } @@ -1142,12 +1303,7 @@ g_array_copy (GArray *array) GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func) { - GPtrArray *array; - - array = g_ptr_array_new (); - g_ptr_array_set_free_func (array, element_free_func); - - return array; + return ptr_array_new (0, element_free_func); } /** @@ -1172,12 +1328,7 @@ GPtrArray* g_ptr_array_new_full (guint reserved_size, GDestroyNotify element_free_func) { - GPtrArray *array; - - array = g_ptr_array_sized_new (reserved_size); - g_ptr_array_set_free_func (array, element_free_func); - - return array; + return ptr_array_new (reserved_size, element_free_func); } /** @@ -1270,8 +1421,8 @@ g_ptr_array_unref (GPtrArray *array) * threads, use only the atomic g_ptr_array_ref() and g_ptr_array_unref() * functions. * - * Returns: the pointer array if @free_seg is %FALSE, otherwise %NULL. - * The pointer array should be freed using g_free(). + * Returns: (transfer full) (nullable): the pointer array if @free_seg is + * %FALSE, otherwise %NULL. The pointer array should be freed using g_free(). */ gpointer* g_ptr_array_free (GPtrArray *array, @@ -1311,7 +1462,8 @@ ptr_array_free (GPtrArray *array, gpointer *stolen_pdata = g_steal_pointer (&rarray->pdata); if (rarray->element_free_func != NULL) { - gsize i; + guint i; + for (i = 0; i < rarray->len; ++i) rarray->element_free_func (stolen_pdata[i]); } @@ -1536,7 +1688,7 @@ g_ptr_array_remove_range (GPtrArray *array, guint length) { GRealPtrArray *rarray = (GRealPtrArray *)array; - guint n; + guint i; g_return_val_if_fail (rarray != NULL, NULL); g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), NULL); @@ -1545,8 +1697,8 @@ g_ptr_array_remove_range (GPtrArray *array, if (rarray->element_free_func != NULL) { - for (n = index_; n < index_ + length; n++) - rarray->element_free_func (rarray->pdata[n]); + for (i = index_; i < index_ + length; i++) + rarray->element_free_func (rarray->pdata[i]); } if (index_ + length != rarray->len) @@ -1559,7 +1711,6 @@ g_ptr_array_remove_range (GPtrArray *array, rarray->len -= length; if (G_UNLIKELY (g_mem_gc_friendly)) { - guint i; for (i = 0; i < length; i++) rarray->pdata[rarray->len + i] = NULL; } @@ -1693,7 +1844,6 @@ g_ptr_array_extend (GPtrArray *array_to_extend, gpointer user_data) { GRealPtrArray *rarray_to_extend = (GRealPtrArray *) array_to_extend; - gsize i; g_return_if_fail (array_to_extend != NULL); g_return_if_fail (array != NULL); @@ -1702,11 +1852,13 @@ g_ptr_array_extend (GPtrArray *array_to_extend, if (func != NULL) { + guint i; + for (i = 0; i < array->len; i++) rarray_to_extend->pdata[i + rarray_to_extend->len] = func (array->pdata[i], user_data); } - else + else if (array->len > 0) { memcpy (rarray_to_extend->pdata + rarray_to_extend->len, array->pdata, array->len * sizeof (*array->pdata)); @@ -1743,6 +1895,7 @@ g_ptr_array_extend_and_steal (GPtrArray *array_to_extend, * to the elements moved from @array to @array_to_extend. */ pdata = g_steal_pointer (&array->pdata); array->len = 0; + ((GRealPtrArray *) array)->alloc = 0; g_ptr_array_unref (array); g_free (pdata); } @@ -1783,6 +1936,8 @@ g_ptr_array_insert (GPtrArray *array, rarray->pdata[index_] = data; } +/* Please keep this doc-comment in sync with pointer_array_sort_example() + * in glib/tests/array-test.c */ /** * g_ptr_array_sort: * @array: a #GPtrArray @@ -1795,7 +1950,32 @@ g_ptr_array_insert (GPtrArray *array, * * Note that the comparison function for g_ptr_array_sort() doesn't * take the pointers from the array as arguments, it takes pointers to - * the pointers in the array. + * the pointers in the array. Here is a full example of usage: + * + * |[ + * typedef struct + * { + * gchar *name; + * gint size; + * } FileListEntry; + * + * static gint + * sort_filelist (gconstpointer a, gconstpointer b) + * { + * const FileListEntry *entry1 = *((FileListEntry **) a); + * const FileListEntry *entry2 = *((FileListEntry **) b); + * + * return g_ascii_strcasecmp (entry1->name, entry2->name); + * } + * + * … + * g_autoptr (GPtrArray) file_list = NULL; + * + * // initialize file_list array and load with many FileListEntry entries + * ... + * // now sort it with + * g_ptr_array_sort (file_list, sort_filelist); + * ]| * * This is guaranteed to be a stable sort since version 2.32. */ @@ -1806,13 +1986,16 @@ g_ptr_array_sort (GPtrArray *array, g_return_if_fail (array != NULL); /* Don't use qsort as we want a guaranteed stable sort */ - g_qsort_with_data (array->pdata, - array->len, - sizeof (gpointer), - (GCompareDataFunc)compare_func, - NULL); + if (array->len > 0) + g_qsort_with_data (array->pdata, + array->len, + sizeof (gpointer), + (GCompareDataFunc)compare_func, + NULL); } +/* Please keep this doc-comment in sync with + * pointer_array_sort_with_data_example() in glib/tests/array-test.c */ /** * g_ptr_array_sort_with_data: * @array: a #GPtrArray @@ -1824,7 +2007,52 @@ g_ptr_array_sort (GPtrArray *array, * * Note that the comparison function for g_ptr_array_sort_with_data() * doesn't take the pointers from the array as arguments, it takes - * pointers to the pointers in the array. + * pointers to the pointers in the array. Here is a full example of use: + * + * |[ + * typedef enum { SORT_NAME, SORT_SIZE } SortMode; + * + * typedef struct + * { + * gchar *name; + * gint size; + * } FileListEntry; + * + * static gint + * sort_filelist (gconstpointer a, gconstpointer b, gpointer user_data) + * { + * gint order; + * const SortMode sort_mode = GPOINTER_TO_INT (user_data); + * const FileListEntry *entry1 = *((FileListEntry **) a); + * const FileListEntry *entry2 = *((FileListEntry **) b); + * + * switch (sort_mode) + * { + * case SORT_NAME: + * order = g_ascii_strcasecmp (entry1->name, entry2->name); + * break; + * case SORT_SIZE: + * order = entry1->size - entry2->size; + * break; + * default: + * order = 0; + * break; + * } + * return order; + * } + * + * ... + * g_autoptr (GPtrArray) file_list = NULL; + * SortMode sort_mode; + * + * // initialize file_list array and load with many FileListEntry entries + * ... + * // now sort it with + * sort_mode = SORT_NAME; + * g_ptr_array_sort_with_data (file_list, + * sort_filelist, + * GINT_TO_POINTER (sort_mode)); + * ]| * * This is guaranteed to be a stable sort since version 2.32. */ @@ -1835,11 +2063,12 @@ g_ptr_array_sort_with_data (GPtrArray *array, { g_return_if_fail (array != NULL); - g_qsort_with_data (array->pdata, - array->len, - sizeof (gpointer), - compare_func, - user_data); + if (array->len > 0) + g_qsort_with_data (array->pdata, + array->len, + sizeof (gpointer), + compare_func, + user_data); } /** @@ -2002,6 +2231,28 @@ g_byte_array_new (void) return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, 0); } +/** + * g_byte_array_steal: + * @array: a #GByteArray. + * @len: (optional) (out caller-allocates): pointer to retrieve the number of + * elements of the original array + * + * Frees the data in the array and resets the size to zero, while + * the underlying array is preserved for use elsewhere and returned + * to the caller. + * + * Returns: (transfer full): the element data, which should be + * freed using g_free(). + * + * Since: 2.64 + */ +guint8 * +g_byte_array_steal (GByteArray *array, + gsize *len) +{ + return (guint8 *) g_array_steal ((GArray *) array, len); +} + /** * g_byte_array_new_take: * @data: (transfer full) (array length=len): byte data for the array diff --git a/glib/garray.h b/glib/garray.h index 3e7ce77321913b1f22e6475cf74c90a52571c9a3..67131b5b3b459f3d940d816bc4edaf44c5afda77 100644 --- a/glib/garray.h +++ b/glib/garray.h @@ -70,6 +70,9 @@ GLIB_AVAILABLE_IN_ALL GArray* g_array_new (gboolean zero_terminated, gboolean clear_, guint element_size); +GLIB_AVAILABLE_IN_2_64 +gpointer g_array_steal (GArray *array, + gsize *len); GLIB_AVAILABLE_IN_ALL GArray* g_array_sized_new (gboolean zero_terminated, gboolean clear_, @@ -137,6 +140,9 @@ GLIB_AVAILABLE_IN_ALL GPtrArray* g_ptr_array_new (void); GLIB_AVAILABLE_IN_ALL GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func); +GLIB_AVAILABLE_IN_2_64 +gpointer* g_ptr_array_steal (GPtrArray *array, + gsize *len); GLIB_AVAILABLE_IN_2_62 GPtrArray *g_ptr_array_copy (GPtrArray *array, GCopyFunc func, @@ -227,6 +233,9 @@ GByteArray* g_byte_array_new (void); GLIB_AVAILABLE_IN_ALL GByteArray* g_byte_array_new_take (guint8 *data, gsize len); +GLIB_AVAILABLE_IN_2_64 +guint8* g_byte_array_steal (GByteArray *array, + gsize *len); GLIB_AVAILABLE_IN_ALL GByteArray* g_byte_array_sized_new (guint reserved_size); GLIB_AVAILABLE_IN_ALL diff --git a/glib/gasyncqueue.c b/glib/gasyncqueue.c index 5719a546110030ce6ef8f183ac533d422d0c26a1..a452617fdb08076d25fa182b55d986cd4db971a0 100644 --- a/glib/gasyncqueue.c +++ b/glib/gasyncqueue.c @@ -482,7 +482,7 @@ g_async_queue_pop_unlocked (GAsyncQueue *queue) * Tries to pop data from the @queue. If no data is available, * %NULL is returned. * - * Returns: data from the queue or %NULL, when no data is + * Returns: (nullable): data from the queue or %NULL, when no data is * available immediately. */ gpointer @@ -508,7 +508,7 @@ g_async_queue_try_pop (GAsyncQueue *queue) * * This function must be called while holding the @queue's lock. * - * Returns: data from the queue or %NULL, when no data is + * Returns: (nullable): data from the queue or %NULL, when no data is * available immediately. */ gpointer @@ -529,7 +529,7 @@ g_async_queue_try_pop_unlocked (GAsyncQueue *queue) * * If no data is received before the timeout, %NULL is returned. * - * Returns: data from the queue or %NULL, when no data is + * Returns: (nullable): data from the queue or %NULL, when no data is * received before the timeout. */ gpointer @@ -560,7 +560,7 @@ g_async_queue_timeout_pop (GAsyncQueue *queue, * * This function must be called while holding the @queue's lock. * - * Returns: data from the queue or %NULL, when no data is + * Returns: (nullable): data from the queue or %NULL, when no data is * received before the timeout. */ gpointer @@ -587,7 +587,7 @@ g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue, * To easily calculate @end_time, a combination of g_get_real_time() * and g_time_val_add() can be used. * - * Returns: data from the queue or %NULL, when no data is + * Returns: (nullable): data from the queue or %NULL, when no data is * received before @end_time. * * Deprecated: use g_async_queue_timeout_pop(). @@ -633,7 +633,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS * * This function must be called while holding the @queue's lock. * - * Returns: data from the queue or %NULL, when no data is + * Returns: (nullable): data from the queue or %NULL, when no data is * received before @end_time. * * Deprecated: use g_async_queue_timeout_pop_unlocked(). diff --git a/glib/gatomic.c b/glib/gatomic.c index c52aaad912a48c5dfe5e75ec065b38839647f919..0bc67aa35e563cd891d6762b92ce3a9817030d9b 100644 --- a/glib/gatomic.c +++ b/glib/gatomic.c @@ -96,15 +96,6 @@ #if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) -#if defined(__ATOMIC_SEQ_CST) && !defined(__clang__) -/* The implementation used in this code path in gatomic.h assumes - * 4-byte int */ -G_STATIC_ASSERT (sizeof (gint) == 4); - -/* The implementations in gatomic.h assume 4- or 8-byte pointers */ -G_STATIC_ASSERT (sizeof (void *) == 4 || sizeof (void *) == 8); -#endif - /** * g_atomic_int_get: * @atomic: a pointer to a #gint or #guint @@ -114,6 +105,9 @@ G_STATIC_ASSERT (sizeof (void *) == 4 || sizeof (void *) == 8); * This call acts as a full compiler and hardware * memory barrier (before the get). * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of the integer * * Since: 2.4 @@ -134,6 +128,9 @@ gint * This call acts as a full compiler and hardware * memory barrier (after the set). * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Since: 2.4 */ void @@ -153,6 +150,9 @@ void * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Since: 2.4 **/ void @@ -172,6 +172,9 @@ void * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: %TRUE if the resultant value is zero * * Since: 2.4 @@ -198,6 +201,9 @@ gboolean * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: %TRUE if the exchange took place * * Since: 2.4 @@ -225,6 +231,9 @@ gboolean * Before version 2.30, this function did not return a value * (but g_atomic_int_exchange_and_add() did, and had the same meaning). * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the add, signed * * Since: 2.4 @@ -249,6 +258,9 @@ gint * Think of this operation as an atomic version of * `{ tmp = *atomic; *atomic &= val; return tmp; }`. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 @@ -273,6 +285,9 @@ guint * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 @@ -297,6 +312,9 @@ guint * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 @@ -318,6 +336,9 @@ guint * This call acts as a full compiler and hardware * memory barrier (before the get). * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of the pointer * * Since: 2.4 @@ -325,7 +346,7 @@ guint gpointer (g_atomic_pointer_get) (const volatile void *atomic) { - return g_atomic_pointer_get ((const volatile gpointer *) atomic); + return g_atomic_pointer_get ((gpointer *) atomic); } /** @@ -338,13 +359,16 @@ gpointer * This call acts as a full compiler and hardware * memory barrier (after the set). * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Since: 2.4 **/ void (g_atomic_pointer_set) (volatile void *atomic, gpointer newval) { - g_atomic_pointer_set ((volatile gpointer *) atomic, newval); + g_atomic_pointer_set ((gpointer *) atomic, newval); } /** @@ -363,6 +387,9 @@ void * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: %TRUE if the exchange took place * * Since: 2.4 @@ -372,7 +399,7 @@ gboolean gpointer oldval, gpointer newval) { - return g_atomic_pointer_compare_and_exchange ((volatile gpointer *) atomic, + return g_atomic_pointer_compare_and_exchange ((gpointer *) atomic, oldval, newval); } @@ -388,6 +415,9 @@ gboolean * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the add, signed * * Since: 2.30 @@ -396,7 +426,7 @@ gssize (g_atomic_pointer_add) (volatile void *atomic, gssize val) { - return g_atomic_pointer_add ((volatile gpointer *) atomic, val); + return g_atomic_pointer_add ((gpointer *) atomic, val); } /** @@ -412,6 +442,9 @@ gssize * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 @@ -420,7 +453,7 @@ gsize (g_atomic_pointer_and) (volatile void *atomic, gsize val) { - return g_atomic_pointer_and ((volatile gpointer *) atomic, val); + return g_atomic_pointer_and ((gpointer *) atomic, val); } /** @@ -436,6 +469,9 @@ gsize * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 @@ -444,7 +480,7 @@ gsize (g_atomic_pointer_or) (volatile void *atomic, gsize val) { - return g_atomic_pointer_or ((volatile gpointer *) atomic, val); + return g_atomic_pointer_or ((gpointer *) atomic, val); } /** @@ -460,6 +496,9 @@ gsize * * This call acts as a full compiler and hardware memory barrier. * + * While @atomic has a `volatile` qualifier, this is a historical artifact and + * the pointer passed to it should not be `volatile`. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 @@ -468,7 +507,7 @@ gsize (g_atomic_pointer_xor) (volatile void *atomic, gsize val) { - return g_atomic_pointer_xor ((volatile gpointer *) atomic, val); + return g_atomic_pointer_xor ((gpointer *) atomic, val); } #elif defined (G_PLATFORM_WIN32) @@ -600,7 +639,7 @@ guint gpointer (g_atomic_pointer_get) (const volatile void *atomic) { - const volatile gpointer *ptr = atomic; + const gpointer *ptr = atomic; MemoryBarrier (); return *ptr; @@ -610,7 +649,7 @@ void (g_atomic_pointer_set) (volatile void *atomic, gpointer newval) { - volatile gpointer *ptr = atomic; + gpointer *ptr = atomic; *ptr = newval; MemoryBarrier (); @@ -806,7 +845,7 @@ guint gpointer (g_atomic_pointer_get) (const volatile void *atomic) { - const volatile gpointer *ptr = atomic; + const gpointer *ptr = atomic; gpointer value; pthread_mutex_lock (&g_atomic_lock); @@ -820,7 +859,7 @@ void (g_atomic_pointer_set) (volatile void *atomic, gpointer newval) { - volatile gpointer *ptr = atomic; + gpointer *ptr = atomic; pthread_mutex_lock (&g_atomic_lock); *ptr = newval; @@ -832,7 +871,7 @@ gboolean gpointer oldval, gpointer newval) { - volatile gpointer *ptr = atomic; + gpointer *ptr = atomic; gboolean success; pthread_mutex_lock (&g_atomic_lock); @@ -849,7 +888,7 @@ gssize (g_atomic_pointer_add) (volatile void *atomic, gssize val) { - volatile gssize *ptr = atomic; + gssize *ptr = atomic; gssize oldval; pthread_mutex_lock (&g_atomic_lock); @@ -864,7 +903,7 @@ gsize (g_atomic_pointer_and) (volatile void *atomic, gsize val) { - volatile gsize *ptr = atomic; + gsize *ptr = atomic; gsize oldval; pthread_mutex_lock (&g_atomic_lock); @@ -879,7 +918,7 @@ gsize (g_atomic_pointer_or) (volatile void *atomic, gsize val) { - volatile gsize *ptr = atomic; + gsize *ptr = atomic; gsize oldval; pthread_mutex_lock (&g_atomic_lock); @@ -894,7 +933,7 @@ gsize (g_atomic_pointer_xor) (volatile void *atomic, gsize val) { - volatile gsize *ptr = atomic; + gsize *ptr = atomic; gsize oldval; pthread_mutex_lock (&g_atomic_lock); @@ -924,5 +963,5 @@ gint g_atomic_int_exchange_and_add (volatile gint *atomic, gint val) { - return (g_atomic_int_add) (atomic, val); + return (g_atomic_int_add) ((gint *) atomic, val); } diff --git a/glib/gatomic.h b/glib/gatomic.h index 971176eb99e967eb4db7f38c273933828a8807a9..c8c00ab71f7204d22a52a4116ed31c85c9e0aadc 100644 --- a/glib/gatomic.h +++ b/glib/gatomic.h @@ -26,6 +26,11 @@ #include +#if defined(glib_typeof_2_68) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68 +/* for glib_typeof */ +#include +#endif + G_BEGIN_DECLS GLIB_AVAILABLE_IN_ALL @@ -85,92 +90,248 @@ G_END_DECLS #if defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) /* We prefer the new C11-style atomic extension of GCC if available */ +/* OHOS_GLIB_COMPATIBLE + * ohos.glib.compatible.001: glib 2.62.5 update 2.68.1 Incompatible with gstreamer 1.16.2 + * static volatile gsize _init_once = 0; // Conflicts with volatile, + * if (g_once_init_enter (&_init_once)) + * add "&& !defined(__clang__)" + */ #if defined(__ATOMIC_SEQ_CST) && !defined(__clang__) -/* This assumes sizeof(int) is 4: gatomic.c statically - * asserts that (using G_STATIC_ASSERT at top-level in a header was - * problematic, see #730932) */ - #define g_atomic_int_get(atomic) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + gint gaig_temp; \ (void) (0 ? *(atomic) ^ *(atomic) : 1); \ - (gint) __atomic_load_4 ((atomic), __ATOMIC_SEQ_CST); \ + __atomic_load ((gint *)(atomic), &gaig_temp, __ATOMIC_SEQ_CST); \ + (gint) gaig_temp; \ })) #define g_atomic_int_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + gint gais_temp = (gint) (newval); \ (void) (0 ? *(atomic) ^ (newval) : 1); \ - __atomic_store_4 ((atomic), (newval), __ATOMIC_SEQ_CST); \ + __atomic_store ((gint *)(atomic), &gais_temp, __ATOMIC_SEQ_CST); \ })) -#if GLIB_SIZEOF_VOID_P == 8 - +#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#define g_atomic_pointer_get(atomic) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + glib_typeof (*(atomic)) gapg_temp_newval; \ + glib_typeof ((atomic)) gapg_temp_atomic = (atomic); \ + __atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \ + gapg_temp_newval; \ + })) +#define g_atomic_pointer_set(atomic, newval) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + glib_typeof ((atomic)) gaps_temp_atomic = (atomic); \ + glib_typeof (*(atomic)) gaps_temp_newval = (newval); \ + (void) (0 ? (gpointer) * (atomic) : NULL); \ + __atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \ + })) +#else /* if !(defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68)) */ #define g_atomic_pointer_get(atomic) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - guint64 gapg_temp = __atomic_load_8 ((atomic), __ATOMIC_SEQ_CST); \ - (gpointer) gapg_temp; \ + gpointer gapg_temp_newval; \ + gpointer *gapg_temp_atomic = (gpointer *)(atomic); \ + __atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \ + gapg_temp_newval; \ })) #define g_atomic_pointer_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + gpointer *gaps_temp_atomic = (gpointer *)(atomic); \ + gpointer gaps_temp_newval = (gpointer)(newval); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ - __atomic_store_8 ((atomic), (gsize) (newval), __ATOMIC_SEQ_CST); \ + __atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \ })) +#endif /* if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) */ -#else /* GLIB_SIZEOF_VOID_P == 8 */ - -/* This assumes that if sizeof(void *) is not 8, then it is 4: - * gatomic.c statically asserts that (using G_STATIC_ASSERT - * at top-level in a header was problematic, see #730932) */ +#define g_atomic_int_inc(atomic) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ *(atomic) : 1); \ + (void) __atomic_fetch_add ((atomic), 1, __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_int_dec_and_test(atomic) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ *(atomic) : 1); \ + __atomic_fetch_sub ((atomic), 1, __ATOMIC_SEQ_CST) == 1; \ + })) +#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \ + (G_GNUC_EXTENSION ({ \ + gint gaicae_oldval = (oldval); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \ + __atomic_compare_exchange_n ((atomic), &gaicae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ + })) +#define g_atomic_int_add(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ (val) : 1); \ + (gint) __atomic_fetch_add ((atomic), (val), __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_int_and(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ (val) : 1); \ + (guint) __atomic_fetch_and ((atomic), (val), __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_int_or(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ (val) : 1); \ + (guint) __atomic_fetch_or ((atomic), (val), __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_int_xor(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ + (void) (0 ? *(atomic) ^ (val) : 1); \ + (guint) __atomic_fetch_xor ((atomic), (val), __ATOMIC_SEQ_CST); \ + })) -#define g_atomic_pointer_get(atomic) \ +#if defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L +/* This is typesafe because we check we can assign oldval to the type of + * (*atomic). Unfortunately it can only be done in C++ because gcc/clang warn + * when atomic is volatile and not oldval, or when atomic is gsize* and oldval + * is NULL. Note that clang++ force us to be typesafe because it is an error if the 2nd + * argument of __atomic_compare_exchange_n() has a different type than the + * first. + * https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1919 + * https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1715#note_1024120. */ +#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \ + glib_typeof (*(atomic)) gapcae_oldval = (oldval); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + (void) (0 ? (gpointer) *(atomic) : NULL); \ + __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ + })) +#else /* if !(defined(glib_typeof) && defined(__cplusplus) && __cplusplus >= 201103L) */ +#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \ (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof (oldval) == sizeof (gpointer)); \ + gpointer gapcae_oldval = (gpointer)(oldval); \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - guint32 gapg_temp = __atomic_load_4 ((atomic), __ATOMIC_SEQ_CST); \ - (gpointer) gapg_temp; \ + (void) (0 ? (gpointer) *(atomic) : NULL); \ + __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ })) -#define g_atomic_pointer_set(atomic, newval) \ +#endif /* defined(glib_typeof) */ +#define g_atomic_pointer_add(atomic, val) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ - __atomic_store_4 ((atomic), (gsize) (newval), __ATOMIC_SEQ_CST); \ + (void) (0 ? (val) ^ (val) : 1); \ + (gssize) __atomic_fetch_add ((atomic), (val), __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_pointer_and(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + gsize *gapa_atomic = (gsize *) (atomic); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \ + (void) (0 ? (gpointer) *(atomic) : NULL); \ + (void) (0 ? (val) ^ (val) : 1); \ + (gsize) __atomic_fetch_and (gapa_atomic, (val), __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_pointer_or(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + gsize *gapo_atomic = (gsize *) (atomic); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \ + (void) (0 ? (gpointer) *(atomic) : NULL); \ + (void) (0 ? (val) ^ (val) : 1); \ + (gsize) __atomic_fetch_or (gapo_atomic, (val), __ATOMIC_SEQ_CST); \ + })) +#define g_atomic_pointer_xor(atomic, val) \ + (G_GNUC_EXTENSION ({ \ + gsize *gapx_atomic = (gsize *) (atomic); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \ + (void) (0 ? (gpointer) *(atomic) : NULL); \ + (void) (0 ? (val) ^ (val) : 1); \ + (gsize) __atomic_fetch_xor (gapx_atomic, (val), __ATOMIC_SEQ_CST); \ })) - -#endif /* GLIB_SIZEOF_VOID_P == 8 */ #else /* defined(__ATOMIC_SEQ_CST) */ +/* We want to achieve __ATOMIC_SEQ_CST semantics here. See + * https://en.cppreference.com/w/c/atomic/memory_order#Constants. For load + * operations, that means performing an *acquire*: + * > A load operation with this memory order performs the acquire operation on + * > the affected memory location: no reads or writes in the current thread can + * > be reordered before this load. All writes in other threads that release + * > the same atomic variable are visible in the current thread. + * + * “no reads or writes in the current thread can be reordered before this load” + * is implemented using a compiler barrier (a no-op `__asm__` section) to + * prevent instruction reordering. Writes in other threads are synchronised + * using `__sync_synchronize()`. It’s unclear from the GCC documentation whether + * `__sync_synchronize()` acts as a compiler barrier, hence our explicit use of + * one. + * + * For store operations, `__ATOMIC_SEQ_CST` means performing a *release*: + * > A store operation with this memory order performs the release operation: + * > no reads or writes in the current thread can be reordered after this store. + * > All writes in the current thread are visible in other threads that acquire + * > the same atomic variable (see Release-Acquire ordering below) and writes + * > that carry a dependency into the atomic variable become visible in other + * > threads that consume the same atomic (see Release-Consume ordering below). + * + * “no reads or writes in the current thread can be reordered after this store” + * is implemented using a compiler barrier to prevent instruction reordering. + * “All writes in the current thread are visible in other threads” is implemented + * using `__sync_synchronize()`; similarly for “writes that carry a dependency”. + */ #define g_atomic_int_get(atomic) \ (G_GNUC_EXTENSION ({ \ + gint gaig_result; \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ (void) (0 ? *(atomic) ^ *(atomic) : 1); \ + gaig_result = (gint) *(atomic); \ __sync_synchronize (); \ - (gint) *(atomic); \ + __asm__ __volatile__ ("" : : : "memory"); \ + gaig_result; \ })) #define g_atomic_int_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ (void) (0 ? *(atomic) ^ (newval) : 1); \ - *(atomic) = (newval); \ __sync_synchronize (); \ + __asm__ __volatile__ ("" : : : "memory"); \ + *(atomic) = (newval); \ })) #define g_atomic_pointer_get(atomic) \ (G_GNUC_EXTENSION ({ \ + gpointer gapg_result; \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + gapg_result = (gpointer) *(atomic); \ __sync_synchronize (); \ - (gpointer) *(atomic); \ + __asm__ __volatile__ ("" : : : "memory"); \ + gapg_result; \ })) +#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) #define g_atomic_pointer_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ - *(atomic) = (__typeof__ (*(atomic))) (gsize) (newval); \ __sync_synchronize (); \ + __asm__ __volatile__ ("" : : : "memory"); \ + *(atomic) = (glib_typeof (*(atomic))) (gsize) (newval); \ })) - -#endif /* !defined(__ATOMIC_SEQ_CST) */ +#else /* if !(defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68)) */ +#define g_atomic_pointer_set(atomic, newval) \ + (G_GNUC_EXTENSION ({ \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ + (void) (0 ? (gpointer) *(atomic) : NULL); \ + __sync_synchronize (); \ + __asm__ __volatile__ ("" : : : "memory"); \ + *(atomic) = (gpointer) (gsize) (newval); \ + })) +#endif /* if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) */ #define g_atomic_int_inc(atomic) \ (G_GNUC_EXTENSION ({ \ @@ -250,6 +411,8 @@ G_END_DECLS (gsize) __sync_fetch_and_xor ((atomic), (val)); \ })) +#endif /* !defined(__ATOMIC_SEQ_CST) */ + #else /* defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */ #define g_atomic_int_get(atomic) \ @@ -271,10 +434,24 @@ G_END_DECLS #define g_atomic_int_dec_and_test(atomic) \ (g_atomic_int_dec_and_test ((gint *) (atomic))) +#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) + /* The (void *) cast in the middle *looks* redundant, because + * g_atomic_pointer_get returns void * already, but it's to silence + * -Werror=bad-function-cast when we're doing something like: + * guintptr a, b; ...; a = g_atomic_pointer_get (&b); + * which would otherwise be assigning the void * result of + * g_atomic_pointer_get directly to the pointer-sized but + * non-pointer-typed result. */ +#define g_atomic_pointer_get(atomic) \ + (glib_typeof (*(atomic))) (void *) ((g_atomic_pointer_get) ((void *) atomic)) +#else /* !(defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68)) */ #define g_atomic_pointer_get(atomic) \ (g_atomic_pointer_get (atomic)) +#endif + #define g_atomic_pointer_set(atomic, newval) \ (g_atomic_pointer_set ((atomic), (gpointer) (newval))) + #define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \ (g_atomic_pointer_compare_and_exchange ((atomic), (gpointer) (oldval), (gpointer) (newval))) #define g_atomic_pointer_add(atomic, val) \ @@ -286,6 +463,6 @@ G_END_DECLS #define g_atomic_pointer_xor(atomic, val) \ (g_atomic_pointer_xor ((atomic), (gsize) (val))) -#endif /* defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS) */ +#endif /* defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */ #endif /* __G_ATOMIC_H__ */ diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c index 86f884170b65ada7ab4092b667fa6f7a500bf80d..61810735f0f53a0df4cd5fc6ee98f80ae7c8ef82 100644 --- a/glib/gbacktrace.c +++ b/glib/gbacktrace.c @@ -66,12 +66,24 @@ #include "gtypes.h" #include "gmain.h" #include "gprintfint.h" +#include "gunicode.h" #include "gutils.h" #ifndef G_OS_WIN32 static void stack_trace (const char * const *args); #endif +/* Default to using LLDB for backtraces on macOS. */ +#ifdef __APPLE__ +#define USE_LLDB +#endif + +#ifdef USE_LLDB +#define DEBUGGER "lldb" +#else +#define DEBUGGER "gdb" +#endif + /* People want to hit this from their debugger... */ GLIB_AVAILABLE_IN_ALL volatile gboolean glib_on_error_halt; volatile gboolean glib_on_error_halt = TRUE; @@ -195,9 +207,20 @@ g_on_error_query (const gchar *prg_name) /* MessageBox is allowed on UWP apps only when building against * the debug CRT, which will set -D_DEBUG */ #if defined(_DEBUG) || !defined(G_WINAPI_ONLY_APP) - MessageBox (NULL, "g_on_error_query called, program terminating", - (prg_name && *prg_name) ? prg_name : NULL, - MB_OK|MB_ICONERROR); + { + WCHAR *caption = NULL; + + if (prg_name && *prg_name) + { + caption = g_utf8_to_utf16 (prg_name, -1, NULL, NULL, NULL); + } + + MessageBoxW (NULL, L"g_on_error_query called, program terminating", + caption, + MB_OK|MB_ICONERROR); + + g_free (caption); + } #else printf ("g_on_error_query called, program '%s' terminating\n", (prg_name && *prg_name) ? prg_name : "(null)"); @@ -231,7 +254,7 @@ g_on_error_stack_trace (const gchar *prg_name) #if defined(G_OS_UNIX) pid_t pid; gchar buf[16]; - const gchar *args[4] = { "gdb", NULL, NULL, NULL }; + const gchar *args[5] = { DEBUGGER, NULL, NULL, NULL, NULL }; int status; if (!prg_name) @@ -239,8 +262,14 @@ g_on_error_stack_trace (const gchar *prg_name) _g_sprintf (buf, "%u", (guint) getpid ()); +#ifdef USE_LLDB + args[1] = prg_name; + args[2] = "-p"; + args[3] = buf; +#else args[1] = prg_name; args[2] = buf; +#endif pid = fork (); if (pid == 0) @@ -250,11 +279,19 @@ g_on_error_stack_trace (const gchar *prg_name) } else if (pid == (pid_t) -1) { - perror ("unable to fork gdb"); + perror ("unable to fork " DEBUGGER); return; } - waitpid (pid, &status, 0); + /* Wait until the child really terminates. On Mac OS X waitpid () + * will also return when the child is being stopped due to tracing. + */ + while (1) + { + pid_t retval = waitpid (pid, &status, 0); + if (WIFEXITED (retval) || WIFSIGNALED (retval)) + break; + } #else if (IsDebuggerPresent ()) G_BREAKPOINT (); @@ -273,6 +310,8 @@ stack_trace_sigchld (int signum) stack_trace_done = TRUE; } +#define BUFSIZE 1024 + static void stack_trace (const char * const *args) { @@ -282,8 +321,8 @@ stack_trace (const char * const *args) fd_set fdset; fd_set readset; struct timeval tv; - int sel, idx, state; - char buffer[256]; + int sel, idx, state, line_idx; + char buffer[BUFSIZE]; char c; stack_trace_done = FALSE; @@ -315,7 +354,7 @@ stack_trace (const char * const *args) close (2); dup (old_err); } - perror ("exec gdb failed"); + perror ("exec " DEBUGGER " failed"); _exit (0); } else if (pid == (pid_t) -1) @@ -327,11 +366,19 @@ stack_trace (const char * const *args) FD_ZERO (&fdset); FD_SET (out_fd[0], &fdset); +#ifdef USE_LLDB + write (in_fd[1], "bt\n", 3); + write (in_fd[1], "p x = 0\n", 8); + write (in_fd[1], "process detach\n", 15); + write (in_fd[1], "quit\n", 5); +#else write (in_fd[1], "backtrace\n", 10); write (in_fd[1], "p x = 0\n", 8); write (in_fd[1], "quit\n", 5); +#endif idx = 0; + line_idx = 0; state = 0; while (1) @@ -348,10 +395,15 @@ stack_trace (const char * const *args) { if (read (out_fd[0], &c, 1)) { + line_idx += 1; switch (state) { case 0: +#ifdef USE_LLDB + if (c == '*' || (c == ' ' && line_idx == 1)) +#else if (c == '#') +#endif { state = 1; idx = 0; @@ -359,13 +411,15 @@ stack_trace (const char * const *args) } break; case 1: - buffer[idx++] = c; + if (idx < BUFSIZE) + buffer[idx++] = c; if ((c == '\n') || (c == '\r')) { buffer[idx] = 0; _g_fprintf (stdout, "%s", buffer); state = 0; idx = 0; + line_idx = 0; } break; default: diff --git a/glib/gbacktrace.h b/glib/gbacktrace.h index 9e9cba151cb84cf438a12b336ab8899a87cfacbc..09b8ccbd3d87e3064f4952a86af89e3933f4b57e 100644 --- a/glib/gbacktrace.h +++ b/glib/gbacktrace.h @@ -61,7 +61,7 @@ void g_on_error_stack_trace (const gchar *prg_name); # define G_BREAKPOINT() G_STMT_START{ __debugbreak(); }G_STMT_END #elif defined (__alpha__) && !defined(__osf__) && defined (__GNUC__) && __GNUC__ >= 2 # define G_BREAKPOINT() G_STMT_START{ __asm__ __volatile__ ("bpt"); }G_STMT_END -#elif defined (__APPLE__) +#elif defined (__APPLE__) || (defined(_WIN32) && (defined(__clang__) || defined(__GNUC__))) # define G_BREAKPOINT() G_STMT_START{ __builtin_trap(); }G_STMT_END #else /* !__i386__ && !__alpha__ */ # define G_BREAKPOINT() G_STMT_START{ raise (SIGTRAP); }G_STMT_END diff --git a/glib/gbase64.c b/glib/gbase64.c index dd7ed20ac86028b51b522500203b42081995fad9..f2d110e2e9a1c0e14d9b0552e073b1dd4ae6c26c 100644 --- a/glib/gbase64.c +++ b/glib/gbase64.c @@ -76,10 +76,10 @@ static const char base64_alphabet[] = * be written to it. Due to the way base64 encodes you will need * at least: (@len / 3 + 1) * 4 + 4 bytes (+ 4 may be needed in case of * non-zero state). If you enable line-breaking you will need at least: - * ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space. + * ((@len / 3 + 1) * 4 + 4) / 76 + 1 bytes of extra space. * * @break_lines is typically used when putting base64-encoded data in emails. - * It breaks the lines at 72 columns instead of putting all of the text on + * It breaks the lines at 76 columns instead of putting all of the text on * the same line. This avoids problems with long lines in the email system. * Note however that it breaks the lines with `LF` characters, not * `CR LF` sequences, so the result cannot be passed directly to SMTP diff --git a/glib/gbitlock.c b/glib/gbitlock.c index 46e5f7d0615bc5c02071d5a2c5b81567642664c8..45fb50999bdd6f116be07ac533aeacdc68f74523 100644 --- a/glib/gbitlock.c +++ b/glib/gbitlock.c @@ -88,7 +88,7 @@ g_futex_wait (const volatile gint *address, * Nominally, wakes one thread that is blocked in g_futex_wait() on * @address (if any thread is currently waiting). * - * As mentioned in the documention for g_futex_wait(), spurious + * As mentioned in the documentation for g_futex_wait(), spurious * wakeups may occur. As such, this call may result in more than one * thread being woken up. */ @@ -224,7 +224,7 @@ g_bit_lock (volatile gint *address, guint mask = 1u << lock_bit; guint v; - v = g_atomic_int_get (address); + v = (guint) g_atomic_int_get (address); if (v & mask) { guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); @@ -322,10 +322,10 @@ g_bit_unlock (volatile gint *address, gint lock_bit) { #ifdef USE_ASM_GOTO - asm volatile ("lock btr %1, (%0)" - : /* no output */ - : "r" (address), "r" (lock_bit) - : "cc", "memory"); + __asm__ volatile ("lock btr %1, (%0)" + : /* no output */ + : "r" (address), "r" (lock_bit) + : "cc", "memory"); #else guint mask = 1u << lock_bit; @@ -405,12 +405,12 @@ void { #ifdef USE_ASM_GOTO retry: - asm volatile goto ("lock bts %1, (%0)\n" - "jc %l[contended]" - : /* no output */ - : "r" (address), "r" ((gsize) lock_bit) - : "cc", "memory" - : contended); + __asm__ volatile goto ("lock bts %1, (%0)\n" + "jc %l[contended]" + : /* no output */ + : "r" (address), "r" ((gsize) lock_bit) + : "cc", "memory" + : contended); return; contended: @@ -477,12 +477,12 @@ gboolean #ifdef USE_ASM_GOTO gboolean result; - asm volatile ("lock bts %2, (%1)\n" - "setnc %%al\n" - "movzx %%al, %0" - : "=r" (result) - : "r" (address), "r" ((gsize) lock_bit) - : "cc", "memory"); + __asm__ volatile ("lock bts %2, (%1)\n" + "setnc %%al\n" + "movzx %%al, %0" + : "=r" (result) + : "r" (address), "r" ((gsize) lock_bit) + : "cc", "memory"); return result; #else @@ -520,10 +520,10 @@ void { #ifdef USE_ASM_GOTO - asm volatile ("lock btr %1, (%0)" - : /* no output */ - : "r" (address), "r" ((gsize) lock_bit) - : "cc", "memory"); + __asm__ volatile ("lock btr %1, (%0)" + : /* no output */ + : "r" (address), "r" ((gsize) lock_bit) + : "cc", "memory"); #else volatile gsize *pointer_address = address; gsize mask = 1u << lock_bit; diff --git a/glib/gbookmarkfile.c b/glib/gbookmarkfile.c index 25f1234d700bbb7db0e5144e1679f1ce0534f182..ff74a2e2db7390e52179193b5b88d923b73b4700 100644 --- a/glib/gbookmarkfile.c +++ b/glib/gbookmarkfile.c @@ -31,6 +31,7 @@ #include "gconvert.h" #include "gdataset.h" +#include "gdatetime.h" #include "gerror.h" #include "gfileutils.h" #include "ghash.h" @@ -86,7 +87,7 @@ * * The important caveat of bookmark files is that when you add a new * bookmark you must also add the application that is registering it, using - * g_bookmark_file_add_application() or g_bookmark_file_set_app_info(). + * g_bookmark_file_add_application() or g_bookmark_file_set_application_info(). * If a bookmark has no applications then it won't be dumped when creating * the on disk representation, using g_bookmark_file_to_data() or * g_bookmark_file_to_file(). @@ -165,7 +166,7 @@ struct _BookmarkAppInfo guint count; - time_t stamp; + GDateTime *stamp; /* (owned) */ }; struct _BookmarkMetadata @@ -190,9 +191,9 @@ struct _BookmarkItem gchar *title; gchar *description; - time_t added; - time_t modified; - time_t visited; + GDateTime *added; /* (owned) */ + GDateTime *modified; /* (owned) */ + GDateTime *visited; /* (owned) */ BookmarkMetadata *metadata; }; @@ -245,10 +246,9 @@ static void g_bookmark_file_add_item (GBookmarkFile *bookmark, BookmarkItem *item, GError **error); -static gboolean timestamp_from_iso8601 (const gchar *iso_date, - time_t *out_timestamp, - GError **error); -static gchar *timestamp_to_iso8601 (time_t timestamp); +static gboolean timestamp_from_iso8601 (const gchar *iso_date, + GDateTime **out_date_time, + GError **error); /******************************** * BookmarkAppInfo * @@ -267,7 +267,7 @@ bookmark_app_info_new (const gchar *name) retval->name = g_strdup (name); retval->exec = NULL; retval->count = 0; - retval->stamp = 0; + retval->stamp = NULL; return retval; } @@ -280,6 +280,7 @@ bookmark_app_info_free (BookmarkAppInfo *app_info) g_free (app_info->name); g_free (app_info->exec); + g_clear_pointer (&app_info->stamp, g_date_time_unref); g_slice_free (BookmarkAppInfo, app_info); } @@ -297,7 +298,7 @@ bookmark_app_info_dump (BookmarkAppInfo *app_info) name = g_markup_escape_text (app_info->name, -1); exec = g_markup_escape_text (app_info->exec, -1); - modified = timestamp_to_iso8601 (app_info->stamp); + modified = g_date_time_format_iso8601 (app_info->stamp); count = g_strdup_printf ("%u", app_info->count); retval = g_strconcat (" " @@ -511,9 +512,9 @@ bookmark_item_new (const gchar *uri) item->title = NULL; item->description = NULL; - item->added = (time_t) -1; - item->modified = (time_t) -1; - item->visited = (time_t) -1; + item->added = NULL; + item->modified = NULL; + item->visited = NULL; item->metadata = NULL; @@ -533,9 +534,20 @@ bookmark_item_free (BookmarkItem *item) if (item->metadata) bookmark_metadata_free (item->metadata); + g_clear_pointer (&item->added, g_date_time_unref); + g_clear_pointer (&item->modified, g_date_time_unref); + g_clear_pointer (&item->visited, g_date_time_unref); + g_slice_free (BookmarkItem, item); } +static void +bookmark_item_touch_modified (BookmarkItem *item) +{ + g_clear_pointer (&item->modified, g_date_time_unref); + item->modified = g_date_time_new_now_utc (); +} + static gchar * bookmark_item_dump (BookmarkItem *item) { @@ -555,9 +567,9 @@ bookmark_item_dump (BookmarkItem *item) retval = g_string_sized_new (4096); - added = timestamp_to_iso8601 (item->added); - modified = timestamp_to_iso8601 (item->modified); - visited = timestamp_to_iso8601 (item->visited); + added = g_date_time_format_iso8601 (item->added); + modified = g_date_time_format_iso8601 (item->modified); + visited = g_date_time_format_iso8601 (item->visited); escaped_uri = g_markup_escape_text (item->uri, -1); @@ -775,13 +787,22 @@ parse_bookmark_element (GMarkupParseContext *context, item = bookmark_item_new (uri); if (added != NULL && !timestamp_from_iso8601 (added, &item->added, error)) - return; + { + bookmark_item_free (item); + return; + } if (modified != NULL && !timestamp_from_iso8601 (modified, &item->modified, error)) - return; + { + bookmark_item_free (item); + return; + } if (visited != NULL && !timestamp_from_iso8601 (visited, &item->visited, error)) - return; + { + bookmark_item_free (item); + return; + } add_error = NULL; g_bookmark_file_add_item (parse_data->bookmark_file, @@ -874,6 +895,7 @@ parse_application_element (GMarkupParseContext *context, else ai->count = 1; + g_clear_pointer (&ai->stamp, g_date_time_unref); if (modified != NULL) { if (!timestamp_from_iso8601 (modified, &ai->stamp, error)) @@ -885,9 +907,9 @@ parse_application_element (GMarkupParseContext *context, * it for backward compatibility */ if (stamp) - ai->stamp = (time_t) atol (stamp); + ai->stamp = g_date_time_new_from_unix_utc (atol (stamp)); else - ai->stamp = time (NULL); + ai->stamp = g_date_time_new_now_utc (); } } @@ -1590,25 +1612,11 @@ out: * Misc * **************/ -/* converts a Unix timestamp in a ISO 8601 compliant string; you - * should free the returned string. - */ -static gchar * -timestamp_to_iso8601 (time_t timestamp) -{ - GDateTime *dt = g_date_time_new_from_unix_utc (timestamp); - gchar *iso8601_string = g_date_time_format_iso8601 (dt); - g_date_time_unref (dt); - - return g_steal_pointer (&iso8601_string); -} - static gboolean timestamp_from_iso8601 (const gchar *iso_date, - time_t *out_timestamp, + GDateTime **out_date_time, GError **error) { - gint64 time_val; GDateTime *dt = g_date_time_new_from_iso8601 (iso_date, NULL); if (dt == NULL) { @@ -1617,10 +1625,7 @@ timestamp_from_iso8601 (const gchar *iso_date, return FALSE; } - time_val = g_date_time_to_unix (dt); - g_date_time_unref (dt); - - *out_timestamp = time_val; + *out_date_time = g_steal_pointer (&dt); return TRUE; } @@ -1918,7 +1923,7 @@ g_bookmark_file_load_from_data_dirs (GBookmarkFile *bookmark, * * This function outputs @bookmark as a string. * - * Returns: (array length=length) (element-type guint8): + * Returns: (transfer full) (array length=length) (element-type guint8): * a newly allocated string holding the contents of the #GBookmarkFile * * Since: 2.12 @@ -2031,11 +2036,14 @@ g_bookmark_file_add_item (GBookmarkFile *bookmark, item->uri, item); - if (item->added == (time_t) -1) - item->added = time (NULL); + if (item->added == NULL) + item->added = g_date_time_new_now_utc (); + + if (item->modified == NULL) + item->modified = g_date_time_new_now_utc (); - if (item->modified == (time_t) -1) - item->modified = time (NULL); + if (item->visited == NULL) + item->visited = g_date_time_new_now_utc (); } /** @@ -2185,7 +2193,7 @@ g_bookmark_file_set_title (GBookmarkFile *bookmark, g_free (item->title); item->title = g_strdup (title); - item->modified = time (NULL); + bookmark_item_touch_modified (item); } } @@ -2202,7 +2210,7 @@ g_bookmark_file_set_title (GBookmarkFile *bookmark, * In the event the URI cannot be found, %NULL is returned and * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. * - * Returns: a newly allocated string or %NULL if the specified + * Returns: (transfer full): a newly allocated string or %NULL if the specified * URI cannot be found. * * Since: 2.12 @@ -2272,7 +2280,7 @@ g_bookmark_file_set_description (GBookmarkFile *bookmark, g_free (item->description); item->description = g_strdup (description); - item->modified = time (NULL); + bookmark_item_touch_modified (item); } } @@ -2287,7 +2295,7 @@ g_bookmark_file_set_description (GBookmarkFile *bookmark, * In the event the URI cannot be found, %NULL is returned and * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. * - * Returns: a newly allocated string or %NULL if the specified + * Returns: (transfer full): a newly allocated string or %NULL if the specified * URI cannot be found. * * Since: 2.12 @@ -2353,7 +2361,7 @@ g_bookmark_file_set_mime_type (GBookmarkFile *bookmark, g_free (item->metadata->mime_type); item->metadata->mime_type = g_strdup (mime_type); - item->modified = time (NULL); + bookmark_item_touch_modified (item); } /** @@ -2369,7 +2377,7 @@ g_bookmark_file_set_mime_type (GBookmarkFile *bookmark, * event that the MIME type cannot be found, %NULL is returned and * @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE. * - * Returns: a newly allocated string or %NULL if the specified + * Returns: (transfer full): a newly allocated string or %NULL if the specified * URI cannot be found. * * Since: 2.12 @@ -2439,7 +2447,7 @@ g_bookmark_file_set_is_private (GBookmarkFile *bookmark, item->metadata = bookmark_metadata_new (); item->metadata->is_private = (is_private == TRUE); - item->modified = time (NULL); + bookmark_item_touch_modified (item); } /** @@ -2502,16 +2510,41 @@ g_bookmark_file_get_is_private (GBookmarkFile *bookmark, * If no bookmark for @uri is found then it is created. * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_set_added_date_time() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ void g_bookmark_file_set_added (GBookmarkFile *bookmark, const gchar *uri, time_t added) +{ + GDateTime *added_dt = (added != (time_t) -1) ? g_date_time_new_from_unix_utc (added) : g_date_time_new_now_utc (); + g_bookmark_file_set_added_date_time (bookmark, uri, added_dt); + g_date_time_unref (added_dt); +} + +/** + * g_bookmark_file_set_added_date_time: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @added: a #GDateTime + * + * Sets the time the bookmark for @uri was added into @bookmark. + * + * If no bookmark for @uri is found then it is created. + * + * Since: 2.66 + */ +void +g_bookmark_file_set_added_date_time (GBookmarkFile *bookmark, + const char *uri, + GDateTime *added) { BookmarkItem *item; g_return_if_fail (bookmark != NULL); g_return_if_fail (uri != NULL); + g_return_if_fail (added != NULL); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) @@ -2520,11 +2553,10 @@ g_bookmark_file_set_added (GBookmarkFile *bookmark, g_bookmark_file_add_item (bookmark, item, NULL); } - if (added == (time_t) -1) - time (&added); - - item->added = added; - item->modified = added; + g_clear_pointer (&item->added, g_date_time_unref); + item->added = g_date_time_ref (added); + g_clear_pointer (&item->modified, g_date_time_unref); + item->modified = g_date_time_ref (added); } /** @@ -2541,25 +2573,52 @@ g_bookmark_file_set_added (GBookmarkFile *bookmark, * Returns: a timestamp * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_get_added_date_time() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ time_t g_bookmark_file_get_added (GBookmarkFile *bookmark, const gchar *uri, GError **error) +{ + GDateTime *added = g_bookmark_file_get_added_date_time (bookmark, uri, error); + return (added != NULL) ? g_date_time_to_unix (added) : (time_t) -1; +} + +/** + * g_bookmark_file_get_added_date_time: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @error: return location for a #GError, or %NULL + * + * Gets the time the bookmark for @uri was added to @bookmark + * + * In the event the URI cannot be found, %NULL is returned and + * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. + * + * Returns: (transfer none): a #GDateTime + * + * Since: 2.66 + */ +GDateTime * +g_bookmark_file_get_added_date_time (GBookmarkFile *bookmark, + const char *uri, + GError **error) { BookmarkItem *item; - g_return_val_if_fail (bookmark != NULL, (time_t) -1); - g_return_val_if_fail (uri != NULL, (time_t) -1); + g_return_val_if_fail (bookmark != NULL, NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) { g_set_error (error, G_BOOKMARK_FILE_ERROR, - G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, - _("No bookmark found for URI “%s”"), - uri); - return (time_t) -1; + G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, + _("No bookmark found for URI “%s”"), + uri); + return NULL; } return item->added; @@ -2578,19 +2637,49 @@ g_bookmark_file_get_added (GBookmarkFile *bookmark, * The "modified" time should only be set when the bookmark's meta-data * was actually changed. Every function of #GBookmarkFile that * modifies a bookmark also changes the modification time, except for - * g_bookmark_file_set_visited(). + * g_bookmark_file_set_visited_date_time(). * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_set_modified_date_time() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ void g_bookmark_file_set_modified (GBookmarkFile *bookmark, const gchar *uri, time_t modified) +{ + GDateTime *modified_dt = (modified != (time_t) -1) ? g_date_time_new_from_unix_utc (modified) : g_date_time_new_now_utc (); + g_bookmark_file_set_modified_date_time (bookmark, uri, modified_dt); + g_date_time_unref (modified_dt); +} + +/** + * g_bookmark_file_set_modified_date_time: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @modified: a #GDateTime + * + * Sets the last time the bookmark for @uri was last modified. + * + * If no bookmark for @uri is found then it is created. + * + * The "modified" time should only be set when the bookmark's meta-data + * was actually changed. Every function of #GBookmarkFile that + * modifies a bookmark also changes the modification time, except for + * g_bookmark_file_set_visited_date_time(). + * + * Since: 2.66 + */ +void +g_bookmark_file_set_modified_date_time (GBookmarkFile *bookmark, + const char *uri, + GDateTime *modified) { BookmarkItem *item; g_return_if_fail (bookmark != NULL); g_return_if_fail (uri != NULL); + g_return_if_fail (modified != NULL); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) @@ -2599,10 +2688,8 @@ g_bookmark_file_set_modified (GBookmarkFile *bookmark, g_bookmark_file_add_item (bookmark, item, NULL); } - if (modified == (time_t) -1) - time (&modified); - - item->modified = modified; + g_clear_pointer (&item->modified, g_date_time_unref); + item->modified = g_date_time_ref (modified); } /** @@ -2619,25 +2706,52 @@ g_bookmark_file_set_modified (GBookmarkFile *bookmark, * Returns: a timestamp * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_get_modified_date_time() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ time_t g_bookmark_file_get_modified (GBookmarkFile *bookmark, const gchar *uri, GError **error) +{ + GDateTime *modified = g_bookmark_file_get_modified_date_time (bookmark, uri, error); + return (modified != NULL) ? g_date_time_to_unix (modified) : (time_t) -1; +} + +/** + * g_bookmark_file_get_modified_date_time: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @error: return location for a #GError, or %NULL + * + * Gets the time when the bookmark for @uri was last modified. + * + * In the event the URI cannot be found, %NULL is returned and + * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. + * + * Returns: (transfer none): a #GDateTime + * + * Since: 2.66 + */ +GDateTime * +g_bookmark_file_get_modified_date_time (GBookmarkFile *bookmark, + const char *uri, + GError **error) { BookmarkItem *item; - g_return_val_if_fail (bookmark != NULL, (time_t) -1); - g_return_val_if_fail (uri != NULL, (time_t) -1); + g_return_val_if_fail (bookmark != NULL, NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) { g_set_error (error, G_BOOKMARK_FILE_ERROR, - G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, - _("No bookmark found for URI “%s”"), - uri); - return (time_t) -1; + G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, + _("No bookmark found for URI “%s”"), + uri); + return NULL; } return item->modified; @@ -2654,22 +2768,53 @@ g_bookmark_file_get_modified (GBookmarkFile *bookmark, * If no bookmark for @uri is found then it is created. * * The "visited" time should only be set if the bookmark was launched, - * either using the command line retrieved by g_bookmark_file_get_app_info() + * either using the command line retrieved by g_bookmark_file_get_application_info() * or by the default application for the bookmark's MIME type, retrieved * using g_bookmark_file_get_mime_type(). Changing the "visited" time * does not affect the "modified" time. * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_set_visited_date_time() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ void g_bookmark_file_set_visited (GBookmarkFile *bookmark, const gchar *uri, time_t visited) +{ + GDateTime *visited_dt = (visited != (time_t) -1) ? g_date_time_new_from_unix_utc (visited) : g_date_time_new_now_utc (); + g_bookmark_file_set_visited_date_time (bookmark, uri, visited_dt); + g_date_time_unref (visited_dt); +} + +/** + * g_bookmark_file_set_visited_date_time: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @visited: a #GDateTime + * + * Sets the time the bookmark for @uri was last visited. + * + * If no bookmark for @uri is found then it is created. + * + * The "visited" time should only be set if the bookmark was launched, + * either using the command line retrieved by g_bookmark_file_get_application_info() + * or by the default application for the bookmark's MIME type, retrieved + * using g_bookmark_file_get_mime_type(). Changing the "visited" time + * does not affect the "modified" time. + * + * Since: 2.66 + */ +void +g_bookmark_file_set_visited_date_time (GBookmarkFile *bookmark, + const char *uri, + GDateTime *visited) { BookmarkItem *item; g_return_if_fail (bookmark != NULL); g_return_if_fail (uri != NULL); + g_return_if_fail (visited != NULL); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) @@ -2678,10 +2823,8 @@ g_bookmark_file_set_visited (GBookmarkFile *bookmark, g_bookmark_file_add_item (bookmark, item, NULL); } - if (visited == (time_t) -1) - time (&visited); - - item->visited = visited; + g_clear_pointer (&item->visited, g_date_time_unref); + item->visited = g_date_time_ref (visited); } /** @@ -2698,25 +2841,52 @@ g_bookmark_file_set_visited (GBookmarkFile *bookmark, * Returns: a timestamp. * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_get_visited_date_time() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ time_t g_bookmark_file_get_visited (GBookmarkFile *bookmark, const gchar *uri, GError **error) +{ + GDateTime *visited = g_bookmark_file_get_visited_date_time (bookmark, uri, error); + return (visited != NULL) ? g_date_time_to_unix (visited) : (time_t) -1; +} + +/** + * g_bookmark_file_get_visited_date_time: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @error: return location for a #GError, or %NULL + * + * Gets the time the bookmark for @uri was last visited. + * + * In the event the URI cannot be found, %NULL is returned and + * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. + * + * Returns: (transfer none): a #GDateTime + * + * Since: 2.66 + */ +GDateTime * +g_bookmark_file_get_visited_date_time (GBookmarkFile *bookmark, + const char *uri, + GError **error) { BookmarkItem *item; - g_return_val_if_fail (bookmark != NULL, (time_t) -1); - g_return_val_if_fail (uri != NULL, (time_t) -1); + g_return_val_if_fail (bookmark != NULL, NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) { g_set_error (error, G_BOOKMARK_FILE_ERROR, - G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, - _("No bookmark found for URI “%s”"), - uri); - return (time_t) -1; + G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND, + _("No bookmark found for URI “%s”"), + uri); + return NULL; } return item->visited; @@ -2813,7 +2983,7 @@ g_bookmark_file_add_group (GBookmarkFile *bookmark, item->metadata->groups = g_list_prepend (item->metadata->groups, g_strdup (group)); - item->modified = time (NULL); + bookmark_item_touch_modified (item); } } @@ -2875,7 +3045,7 @@ g_bookmark_file_remove_group (GBookmarkFile *bookmark, g_free (l->data); g_list_free_1 (l); - item->modified = time (NULL); + bookmark_item_touch_modified (item); return TRUE; } @@ -2932,7 +3102,7 @@ g_bookmark_file_set_groups (GBookmarkFile *bookmark, g_strdup (groups[i])); } - item->modified = time (NULL); + bookmark_item_touch_modified (item); } /** @@ -3048,6 +3218,7 @@ g_bookmark_file_add_application (GBookmarkFile *bookmark, { BookmarkItem *item; gchar *app_name, *app_exec; + GDateTime *stamp; g_return_if_fail (bookmark != NULL); g_return_if_fail (uri != NULL); @@ -3069,13 +3240,16 @@ g_bookmark_file_add_application (GBookmarkFile *bookmark, else app_exec = g_strjoin (" ", g_get_prgname(), "%u", NULL); - g_bookmark_file_set_app_info (bookmark, uri, - app_name, - app_exec, - -1, - (time_t) -1, - NULL); + stamp = g_date_time_new_now_utc (); + + g_bookmark_file_set_application_info (bookmark, uri, + app_name, + app_exec, + -1, + stamp, + NULL); + g_date_time_unref (stamp); g_free (app_exec); g_free (app_name); } @@ -3114,12 +3288,12 @@ g_bookmark_file_remove_application (GBookmarkFile *bookmark, g_return_val_if_fail (name != NULL, FALSE); set_error = NULL; - retval = g_bookmark_file_set_app_info (bookmark, uri, - name, - "", - 0, - (time_t) -1, - &set_error); + retval = g_bookmark_file_set_application_info (bookmark, uri, + name, + "", + 0, + NULL, + &set_error); if (set_error) { g_propagate_error (error, set_error); @@ -3195,7 +3369,7 @@ g_bookmark_file_has_application (GBookmarkFile *bookmark, * be expanded as the local file name retrieved from the bookmark's * URI; "\%u", which will be expanded as the bookmark's URI. * The expansion is done automatically when retrieving the stored - * command line using the g_bookmark_file_get_app_info() function. + * command line using the g_bookmark_file_get_application_info() function. * @count is the number of times the application has registered the * bookmark; if is < 0, the current registration count will be increased * by one, if is 0, the application with @name will be removed from @@ -3215,6 +3389,8 @@ g_bookmark_file_has_application (GBookmarkFile *bookmark, * changed. * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_set_application_info() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ gboolean g_bookmark_file_set_app_info (GBookmarkFile *bookmark, @@ -3224,6 +3400,67 @@ g_bookmark_file_set_app_info (GBookmarkFile *bookmark, gint count, time_t stamp, GError **error) +{ + GDateTime *stamp_dt = (stamp != (time_t) -1) ? g_date_time_new_from_unix_utc (stamp) : g_date_time_new_now_utc (); + gboolean retval; + retval = g_bookmark_file_set_application_info (bookmark, uri, name, exec, count, + stamp_dt, error); + g_date_time_unref (stamp_dt); + return retval; +} + +/** + * g_bookmark_file_set_application_info: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @name: an application's name + * @exec: an application's command line + * @count: the number of registrations done for this application + * @stamp: (nullable): the time of the last registration for this application, + * which may be %NULL if @count is 0 + * @error: return location for a #GError or %NULL + * + * Sets the meta-data of application @name inside the list of + * applications that have registered a bookmark for @uri inside + * @bookmark. + * + * You should rarely use this function; use g_bookmark_file_add_application() + * and g_bookmark_file_remove_application() instead. + * + * @name can be any UTF-8 encoded string used to identify an + * application. + * @exec can have one of these two modifiers: "\%f", which will + * be expanded as the local file name retrieved from the bookmark's + * URI; "\%u", which will be expanded as the bookmark's URI. + * The expansion is done automatically when retrieving the stored + * command line using the g_bookmark_file_get_application_info() function. + * @count is the number of times the application has registered the + * bookmark; if is < 0, the current registration count will be increased + * by one, if is 0, the application with @name will be removed from + * the list of registered applications. + * @stamp is the Unix time of the last registration. + * + * If you try to remove an application by setting its registration count to + * zero, and no bookmark for @uri is found, %FALSE is returned and + * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND; similarly, + * in the event that no application @name has registered a bookmark + * for @uri, %FALSE is returned and error is set to + * #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED. Otherwise, if no bookmark + * for @uri is found, one is created. + * + * Returns: %TRUE if the application's meta-data was successfully + * changed. + * + * Since: 2.66 + */ +gboolean +g_bookmark_file_set_application_info (GBookmarkFile *bookmark, + const char *uri, + const char *name, + const char *exec, + int count, + GDateTime *stamp, + GError **error) { BookmarkItem *item; BookmarkAppInfo *ai; @@ -3232,6 +3469,8 @@ g_bookmark_file_set_app_info (GBookmarkFile *bookmark, g_return_val_if_fail (uri != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (exec != NULL, FALSE); + g_return_val_if_fail (count == 0 || stamp != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) @@ -3281,7 +3520,7 @@ g_bookmark_file_set_app_info (GBookmarkFile *bookmark, g_hash_table_remove (item->metadata->apps_by_name, ai->name); bookmark_app_info_free (ai); - item->modified = time (NULL); + bookmark_item_touch_modified (item); return TRUE; } @@ -3290,10 +3529,8 @@ g_bookmark_file_set_app_info (GBookmarkFile *bookmark, else ai->count += 1; - if (stamp != (time_t) -1) - ai->stamp = stamp; - else - ai->stamp = time (NULL); + g_clear_pointer (&ai->stamp, g_date_time_unref); + ai->stamp = g_date_time_ref (stamp); if (exec && exec[0] != '\0') { @@ -3301,7 +3538,7 @@ g_bookmark_file_set_app_info (GBookmarkFile *bookmark, ai->exec = g_shell_quote (exec); } - item->modified = time (NULL); + bookmark_item_touch_modified (item); return TRUE; } @@ -3370,7 +3607,7 @@ expand_exec_line (const gchar *exec_fmt, * @error: return location for a #GError, or %NULL * * Gets the registration information of @app_name for the bookmark for - * @uri. See g_bookmark_file_set_app_info() for more information about + * @uri. See g_bookmark_file_set_application_info() for more information about * the returned data. * * The string returned in @app_exec must be freed. @@ -3386,6 +3623,8 @@ expand_exec_line (const gchar *exec_fmt, * Returns: %TRUE on success. * * Since: 2.12 + * Deprecated: 2.66: Use g_bookmark_file_get_application_info() instead, as + * `time_t` is deprecated due to the year 2038 problem. */ gboolean g_bookmark_file_get_app_info (GBookmarkFile *bookmark, @@ -3395,6 +3634,56 @@ g_bookmark_file_get_app_info (GBookmarkFile *bookmark, guint *count, time_t *stamp, GError **error) +{ + GDateTime *stamp_dt = NULL; + gboolean retval; + + retval = g_bookmark_file_get_application_info (bookmark, uri, name, exec, count, &stamp_dt, error); + if (!retval) + return FALSE; + + if (stamp != NULL) + *stamp = g_date_time_to_unix (stamp_dt); + + return TRUE; +} + +/** + * g_bookmark_file_get_application_info: + * @bookmark: a #GBookmarkFile + * @uri: a valid URI + * @name: an application's name + * @exec: (out) (optional): return location for the command line of the application, or %NULL + * @count: (out) (optional): return location for the registration count, or %NULL + * @stamp: (out) (optional) (transfer none): return location for the last registration time, or %NULL + * @error: return location for a #GError, or %NULL + * + * Gets the registration information of @app_name for the bookmark for + * @uri. See g_bookmark_file_set_application_info() for more information about + * the returned data. + * + * The string returned in @app_exec must be freed. + * + * In the event the URI cannot be found, %FALSE is returned and + * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the + * event that no application with name @app_name has registered a bookmark + * for @uri, %FALSE is returned and error is set to + * #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED. In the event that unquoting + * the command line fails, an error of the #G_SHELL_ERROR domain is + * set and %FALSE is returned. + * + * Returns: %TRUE on success. + * + * Since: 2.66 + */ +gboolean +g_bookmark_file_get_application_info (GBookmarkFile *bookmark, + const char *uri, + const char *name, + char **exec, + unsigned int *count, + GDateTime **stamp, + GError **error) { BookmarkItem *item; BookmarkAppInfo *ai; @@ -3402,6 +3691,7 @@ g_bookmark_file_get_app_info (GBookmarkFile *bookmark, g_return_val_if_fail (bookmark != NULL, FALSE); g_return_val_if_fail (uri != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); item = g_bookmark_file_lookup_item (bookmark, uri); if (!item) @@ -3606,7 +3896,7 @@ g_bookmark_file_move_item (GBookmarkFile *bookmark, g_free (item->uri); item->uri = g_strdup (new_uri); - item->modified = time (NULL); + bookmark_item_touch_modified (item); g_hash_table_replace (bookmark->items_by_uri, item->uri, item); @@ -3667,7 +3957,7 @@ g_bookmark_file_set_icon (GBookmarkFile *bookmark, else item->metadata->icon_mime = g_strdup ("application/octet-stream"); - item->modified = time (NULL); + bookmark_item_touch_modified (item); } /** diff --git a/glib/gbookmarkfile.h b/glib/gbookmarkfile.h index 8dd93a1dcc5e901580e4c0717d33778d87681f0f..e9cfbf12ba70cea96863223c5039fc21257eef5d 100644 --- a/glib/gbookmarkfile.h +++ b/glib/gbookmarkfile.h @@ -23,6 +23,7 @@ #error "Only can be included directly." #endif +#include #include #include @@ -162,7 +163,7 @@ gchar ** g_bookmark_file_get_applications (GBookmarkFile *bookmark, const gchar *uri, gsize *length, GError **error); -GLIB_AVAILABLE_IN_ALL +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_set_application_info) gboolean g_bookmark_file_set_app_info (GBookmarkFile *bookmark, const gchar *uri, const gchar *name, @@ -170,7 +171,15 @@ gboolean g_bookmark_file_set_app_info (GBookmarkFile *bookmark, gint count, time_t stamp, GError **error); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_66 +gboolean g_bookmark_file_set_application_info (GBookmarkFile *bookmark, + const char *uri, + const char *name, + const char *exec, + int count, + GDateTime *stamp, + GError **error); +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_get_application_info) gboolean g_bookmark_file_get_app_info (GBookmarkFile *bookmark, const gchar *uri, const gchar *name, @@ -178,6 +187,14 @@ gboolean g_bookmark_file_get_app_info (GBookmarkFile *bookmark, guint *count, time_t *stamp, GError **error); +GLIB_AVAILABLE_IN_2_66 +gboolean g_bookmark_file_get_application_info (GBookmarkFile *bookmark, + const char *uri, + const char *name, + char **exec, + unsigned int *count, + GDateTime **stamp, + GError **error); GLIB_AVAILABLE_IN_ALL void g_bookmark_file_set_is_private (GBookmarkFile *bookmark, const gchar *uri, @@ -197,30 +214,54 @@ gboolean g_bookmark_file_get_icon (GBookmarkFile *bookmark, gchar **href, gchar **mime_type, GError **error); -GLIB_AVAILABLE_IN_ALL +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_set_added_date_time) void g_bookmark_file_set_added (GBookmarkFile *bookmark, const gchar *uri, time_t added); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_66 +void g_bookmark_file_set_added_date_time (GBookmarkFile *bookmark, + const char *uri, + GDateTime *added); +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_get_added_date_time) time_t g_bookmark_file_get_added (GBookmarkFile *bookmark, const gchar *uri, GError **error); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_66 +GDateTime *g_bookmark_file_get_added_date_time (GBookmarkFile *bookmark, + const char *uri, + GError **error); +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_set_modified_date_time) void g_bookmark_file_set_modified (GBookmarkFile *bookmark, const gchar *uri, time_t modified); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_66 +void g_bookmark_file_set_modified_date_time (GBookmarkFile *bookmark, + const char *uri, + GDateTime *modified); +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_get_modified_date_time) time_t g_bookmark_file_get_modified (GBookmarkFile *bookmark, const gchar *uri, GError **error); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_66 +GDateTime *g_bookmark_file_get_modified_date_time (GBookmarkFile *bookmark, + const char *uri, + GError **error); +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_set_visited_date_time) void g_bookmark_file_set_visited (GBookmarkFile *bookmark, const gchar *uri, time_t visited); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_66 +void g_bookmark_file_set_visited_date_time (GBookmarkFile *bookmark, + const char *uri, + GDateTime *visited); +GLIB_DEPRECATED_IN_2_66_FOR(g_bookmark_file_get_visited_date_time) time_t g_bookmark_file_get_visited (GBookmarkFile *bookmark, const gchar *uri, GError **error); +GLIB_AVAILABLE_IN_2_66 +GDateTime *g_bookmark_file_get_visited_date_time (GBookmarkFile *bookmark, + const char *uri, + GError **error); GLIB_AVAILABLE_IN_ALL gboolean g_bookmark_file_has_item (GBookmarkFile *bookmark, const gchar *uri); diff --git a/glib/gbytes.c b/glib/gbytes.c index d56abe6c3327f91882ec9f5df0511c4badac5c0c..aaadf451bf40937994b7fa9985f4335cbc374dd0 100644 --- a/glib/gbytes.c +++ b/glib/gbytes.c @@ -95,7 +95,7 @@ g_bytes_new (gconstpointer data, { g_return_val_if_fail (data != NULL || size == 0, NULL); - return g_bytes_new_take (g_memdup (data, size), size); + return g_bytes_new_take (g_memdup2 (data, size), size); } /** @@ -365,7 +365,7 @@ g_bytes_equal (gconstpointer bytes1, g_return_val_if_fail (bytes2 != NULL, FALSE); return b1->size == b2->size && - memcmp (b1->data, b2->data, b1->size) == 0; + (b1->size == 0 || memcmp (b1->data, b2->data, b1->size) == 0); } /** @@ -499,7 +499,7 @@ g_bytes_unref_to_data (GBytes *bytes, * Copy: Non g_malloc (or compatible) allocator, or static memory, * so we have to copy, and then unref. */ - result = g_memdup (bytes->data, bytes->size); + result = g_memdup2 (bytes->data, bytes->size); *size = bytes->size; g_bytes_unref (bytes); } diff --git a/glib/gcharset.c b/glib/gcharset.c index 7bce2a15ae5082881b268a195b5ff796f9c78f60..bb775bda44f07b6507804824ecf0ce13509f4372 100644 --- a/glib/gcharset.c +++ b/glib/gcharset.c @@ -315,7 +315,7 @@ g_get_console_charset (const char **charset) g_free (emsg); } } - /* fall-back to UTF-8 if the rest failed (it's a sane and universal default) */ + /* fall-back to UTF-8 if the rest failed (it's a universal default) */ if (raw == NULL) raw = "UTF-8"; @@ -549,10 +549,15 @@ append_locale_variants (GPtrArray *array, * Returns a list of derived variants of @locale, which can be used to * e.g. construct locale-dependent filenames or search paths. The returned * list is sorted from most desirable to least desirable. - * This function handles territory, charset and extra locale modifiers. + * This function handles territory, charset and extra locale modifiers. See + * [`setlocale(3)`](man:setlocale) for information about locales and their format. * - * For example, if @locale is "fr_BE", then the returned list - * is "fr_BE", "fr". + * @locale itself is guaranteed to be returned in the output. + * + * For example, if @locale is `fr_BE`, then the returned list + * is `fr_BE`, `fr`. If @locale is `en_GB.UTF-8@euro`, then the returned list + * is `en_GB.UTF-8@euro`, `en_GB.UTF-8`, `en_GB@euro`, `en_GB`, `en.UTF-8@euro`, + * `en.UTF-8`, `en@euro`, `en`. * * If you need the list of variants for the current locale, * use g_get_language_names(). diff --git a/glib/gchecksum.c b/glib/gchecksum.c index 1ad21fff84b711477b7b91c8f470ddcc62e1cd77..29b479bc66ba90414fc3df82ab43f4b841d3bba0 100644 --- a/glib/gchecksum.c +++ b/glib/gchecksum.c @@ -1344,6 +1344,7 @@ sha512_sum_close (Sha512sum *sha512) memset (pad + pad_len, 0x00, zeros / 8); pad_len += zeros / 8; zeros = zeros % 8; + (void) zeros; /* don’t care about the dead store */ /* put message bit length at the end of padding */ PUT_UINT64 (sha512->data_len[1], pad, pad_len); @@ -1460,7 +1461,7 @@ g_checksum_type_get_length (GChecksumType checksum_type) * will be closed and it won't be possible to call g_checksum_update() * on it anymore. * - * Returns: (transfer full): the newly created #GChecksum, or %NULL. + * Returns: (transfer full) (nullable): the newly created #GChecksum, or %NULL. * Use g_checksum_free() to free the memory allocated by it. * * Since: 2.16 @@ -1528,8 +1529,8 @@ g_checksum_reset (GChecksum *checksum) * g_checksum_get_string() or g_checksum_get_digest(), the copied * checksum will be closed as well. * - * Returns: the copy of the passed #GChecksum. Use g_checksum_free() - * when finished using it. + * Returns: (transfer full): the copy of the passed #GChecksum. Use + * g_checksum_free() when finished using it. * * Since: 2.16 */ @@ -1774,8 +1775,10 @@ g_checksum_get_digest (GChecksum *checksum, * * The hexadecimal string returned will be in lower case. * - * Returns: the digest of the binary data as a string in hexadecimal. - * The returned string should be freed with g_free() when done using it. + * Returns: (transfer full) (nullable): the digest of the binary data as a + * string in hexadecimal, or %NULL if g_checksum_new() fails for + * @checksum_type. The returned string should be freed with g_free() when + * done using it. * * Since: 2.16 */ @@ -1787,7 +1790,6 @@ g_compute_checksum_for_data (GChecksumType checksum_type, GChecksum *checksum; gchar *retval; - g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL); g_return_val_if_fail (length == 0 || data != NULL, NULL); checksum = g_checksum_new (checksum_type); @@ -1811,7 +1813,8 @@ g_compute_checksum_for_data (GChecksumType checksum_type, * * The hexadecimal string returned will be in lower case. * - * Returns: the checksum as a hexadecimal string. The returned string + * Returns: (transfer full) (nullable): the checksum as a hexadecimal string, + * or %NULL if g_checksum_new() fails for @checksum_type. The returned string * should be freed with g_free() when done using it. * * Since: 2.16 @@ -1821,7 +1824,6 @@ g_compute_checksum_for_string (GChecksumType checksum_type, const gchar *str, gssize length) { - g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL); g_return_val_if_fail (length == 0 || str != NULL, NULL); if (length < 0) @@ -1841,8 +1843,10 @@ g_compute_checksum_for_string (GChecksumType checksum_type, * * The hexadecimal string returned will be in lower case. * - * Returns: the digest of the binary data as a string in hexadecimal. - * The returned string should be freed with g_free() when done using it. + * Returns: (transfer full) (nullable): the digest of the binary data as a + * string in hexadecimal, or %NULL if g_checksum_new() fails for + * @checksum_type. The returned string should be freed with g_free() when + * done using it. * * Since: 2.34 */ @@ -1853,7 +1857,6 @@ g_compute_checksum_for_bytes (GChecksumType checksum_type, gconstpointer byte_data; gsize length; - g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL); g_return_val_if_fail (data != NULL, NULL); byte_data = g_bytes_get_data (data, &length); diff --git a/glib/gconstructor.h b/glib/gconstructor.h index 603c2dde68572501f819a5e9cbab61e6f04c6a51..4072021673aed058ca1ab624907c0c01457b5289 100644 --- a/glib/gconstructor.h +++ b/glib/gconstructor.h @@ -1,6 +1,6 @@ /* If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and - destructors, in a sane way, including e.g. on library unload. If not you're on + destructors, in a usable way, including e.g. on library unload. If not you're on your own. Some compilers need #pragma to handle this, which does not work with macros, @@ -42,13 +42,13 @@ */ /* We need to account for differences between the mangling of symbols - * for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed - * with an underscore but symbols on x64 are not. + * for x86 and x64/ARM/ARM64 programs, as symbols on x86 are prefixed + * with an underscore but symbols on x64/ARM/ARM64 are not. */ -#ifdef _WIN64 -#define G_MSVC_SYMBOL_PREFIX "" -#else +#ifdef _M_IX86 #define G_MSVC_SYMBOL_PREFIX "_" +#else +#define G_MSVC_SYMBOL_PREFIX "" #endif #define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX) diff --git a/glib/gconvert.c b/glib/gconvert.c index c5857df1c07f9a990aab026ff634ed53ae62086f..f78cff01dbf2bfbf049ac5585995ecd47a860d5b 100644 --- a/glib/gconvert.c +++ b/glib/gconvert.c @@ -49,6 +49,7 @@ #include "gthreadprivate.h" #include "gunicode.h" #include "gfileutils.h" +#include "genviron.h" #include "glibintl.h" @@ -1131,14 +1132,14 @@ g_get_filename_charsets (const gchar ***filename_charsets) if (!(cache->charset && strcmp (cache->charset, charset) == 0)) { const gchar *new_charset; - gchar *p; + const gchar *p; gint i; g_free (cache->charset); g_strfreev (cache->filename_charsets); cache->charset = g_strdup (charset); - p = getenv ("G_FILENAME_ENCODING"); + p = g_getenv ("G_FILENAME_ENCODING"); if (p != NULL && p[0] != '\0') { cache->filename_charsets = g_strsplit (p, ",", 0); @@ -1154,7 +1155,7 @@ g_get_filename_charsets (const gchar ***filename_charsets) } } } - else if (getenv ("G_BROKEN_FILENAMES") != NULL) + else if (g_getenv ("G_BROKEN_FILENAMES") != NULL) { cache->filename_charsets = g_new0 (gchar *, 2); cache->is_utf8 = g_get_charset (&new_charset); @@ -1806,12 +1807,10 @@ g_filename_to_uri (const gchar *filename, gchar ** g_uri_list_extract_uris (const gchar *uri_list) { - GSList *uris, *u; + GPtrArray *uris; const gchar *p, *q; - gchar **result; - gint n_uris = 0; - uris = NULL; + uris = g_ptr_array_new (); p = uri_list; @@ -1840,26 +1839,17 @@ g_uri_list_extract_uris (const gchar *uri_list) q--; if (q > p) - { - uris = g_slist_prepend (uris, g_strndup (p, q - p + 1)); - n_uris++; - } - } - } + g_ptr_array_add (uris, g_strndup (p, q - p + 1)); + } + } p = strchr (p, '\n'); if (p) p++; } - result = g_new (gchar *, n_uris + 1); - - result[n_uris--] = NULL; - for (u = uris; u; u = u->next) - result[n_uris--] = u->data; + g_ptr_array_add (uris, NULL); - g_slist_free (uris); - - return result; + return (gchar **) g_ptr_array_free (uris, FALSE); } /** diff --git a/glib/gdate.c b/glib/gdate.c index 26b3f598ec92a23815d2c5efa2223f89e55c9a18..253ab6524c56cb43c7cafd417491ca7445642bb3 100644 --- a/glib/gdate.c +++ b/glib/gdate.c @@ -83,8 +83,8 @@ * * #GDate is simple to use. First you need a "blank" date; you can get a * dynamically allocated date from g_date_new(), or you can declare an - * automatic variable or array and initialize it to a sane state by - * calling g_date_clear(). A cleared date is sane; it's safe to call + * automatic variable or array and initialize it by + * calling g_date_clear(). A cleared date is safe; it's safe to call * g_date_set_dmy() and the other mutator functions to initialize the * value of a cleared date. However, a cleared date is initially * invalid, meaning that it doesn't represent a day that exists. @@ -146,7 +146,7 @@ * * If it's declared on the stack, it will contain garbage so must be * initialized with g_date_clear(). g_date_clear() makes the date invalid - * but sane. An invalid date doesn't represent a day, it's "empty." A date + * but safe. An invalid date doesn't represent a day, it's "empty." A date * becomes valid after you set it to a Julian day or you set a day, month, * and year. */ @@ -259,7 +259,7 @@ * g_date_new: * * Allocates a #GDate and initializes - * it to a sane state. The new date will + * it to a safe state. The new date will * be cleared (as if you'd called g_date_clear()) but invalid (it won't * represent an existing day). Free the return value with g_date_free(). * @@ -420,7 +420,7 @@ static const guint16 days_in_year[2][14] = gboolean g_date_valid_month (GDateMonth m) { - return ( (m > G_DATE_BAD_MONTH) && (m < 13) ); + return (((gint) m > G_DATE_BAD_MONTH) && ((gint) m < 13)); } /** @@ -466,7 +466,7 @@ g_date_valid_day (GDateDay d) gboolean g_date_valid_weekday (GDateWeekday w) { - return ( (w > G_DATE_BAD_WEEKDAY) && (w < 8) ); + return (((gint) w > G_DATE_BAD_WEEKDAY) && ((gint) w < 8)); } /** @@ -862,7 +862,7 @@ g_date_days_between (const GDate *d1, * @date: pointer to one or more dates to clear * @n_dates: number of dates to clear * - * Initializes one or more #GDate structs to a sane but invalid + * Initializes one or more #GDate structs to a safe but invalid * state. The cleared dates will not represent an existing date, but will * not contain garbage. Useful to init a date declared on the stack. * Validity can be tested with g_date_valid(). @@ -1142,7 +1142,8 @@ g_date_prepare_to_parse (const gchar *str, dmy_order[i] = G_DATE_DAY; break; case 76: - using_twodigit_years = TRUE; /* FALL THRU */ + using_twodigit_years = TRUE; + G_GNUC_FALLTHROUGH; case 1976: dmy_order[i] = G_DATE_YEAR; break; @@ -1228,12 +1229,23 @@ g_date_set_parse (GDate *d, { GDateParseTokens pt; guint m = G_DATE_BAD_MONTH, day = G_DATE_BAD_DAY, y = G_DATE_BAD_YEAR; + gsize str_len; g_return_if_fail (d != NULL); /* set invalid */ g_date_clear (d, 1); - + + /* Anything longer than this is ridiculous and could take a while to normalize. + * This limit is chosen arbitrarily. */ + str_len = strlen (str); + if (str_len > 200) + return; + + /* The input has to be valid UTF-8. */ + if (!g_utf8_validate_len (str, str_len, NULL)) + return; + G_LOCK (g_date_global); g_date_prepare_to_parse (str, &pt); @@ -2055,7 +2067,7 @@ g_date_compare (const GDate *lhs, * @tm: (not nullable): struct tm to fill * * Fills in the date-related bits of a struct tm using the @date value. - * Initializes the non-date parts with something sane but meaningless. + * Initializes the non-date parts with something safe but meaningless. */ void g_date_to_struct_tm (const GDate *d, @@ -2153,7 +2165,7 @@ g_date_order (GDate *date1, } #ifdef G_OS_WIN32 -static void +static gboolean append_month_name (GArray *result, LCID lcid, SYSTEMTIME *systemtime, @@ -2168,9 +2180,14 @@ append_month_name (GArray *result, { base = abbreviated ? LOCALE_SABBREVMONTHNAME1 : LOCALE_SMONTHNAME1; n = GetLocaleInfoW (lcid, base + systemtime->wMonth - 1, NULL, 0); + if (n == 0) + return FALSE; + g_array_set_size (result, result->len + n); - GetLocaleInfoW (lcid, base + systemtime->wMonth - 1, - ((wchar_t *) result->data) + result->len - n, n); + if (GetLocaleInfoW (lcid, base + systemtime->wMonth - 1, + ((wchar_t *) result->data) + result->len - n, n) != n) + return FALSE; + g_array_set_size (result, result->len - 1); } else @@ -2178,12 +2195,20 @@ append_month_name (GArray *result, /* According to MSDN, this is the correct method to obtain * the form of the month name used when formatting a full * date; it must be a genitive case in some languages. + * + * (n == 0) indicates an error, whereas (n < 2) is something we’d never + * expect from the given format string, and would break the subsequent code. */ lpFormat = abbreviated ? L"ddMMM" : L"ddMMMM"; n = GetDateFormatW (lcid, 0, systemtime, lpFormat, NULL, 0); + if (n < 2) + return FALSE; + g_array_set_size (result, result->len + n); - GetDateFormatW (lcid, 0, systemtime, lpFormat, - ((wchar_t *) result->data) + result->len - n, n); + if (GetDateFormatW (lcid, 0, systemtime, lpFormat, + ((wchar_t *) result->data) + result->len - n, n) != n) + return FALSE; + /* We have obtained a day number as two digits and the month name. * Now let's get rid of those two digits: overwrite them with the * month name. @@ -2193,6 +2218,8 @@ append_month_name (GArray *result, (n - 2) * sizeof (wchar_t)); g_array_set_size (result, result->len - 3); } + + return TRUE; } static gsize @@ -2285,12 +2312,16 @@ win32_strftime_helper (const GDate *d, break; case 'b': case 'h': - append_month_name (result, lcid, &systemtime, TRUE, - modifier == 'O'); + if (!append_month_name (result, lcid, &systemtime, TRUE, modifier == 'O')) + { + /* Ignore the error; this placeholder will be replaced with nothing */ + } break; case 'B': - append_month_name (result, lcid, &systemtime, FALSE, - modifier == 'O'); + if (!append_month_name (result, lcid, &systemtime, FALSE, modifier == 'O')) + { + /* Ignore the error; this placeholder will be replaced with nothing */ + } break; case 'c': n = GetDateFormatW (lcid, 0, &systemtime, NULL, NULL, 0); diff --git a/glib/gdate.h b/glib/gdate.h index 3bc07bf5c310474cd91e2bc7a7423a3db20f2912..65fe811fa9289ed1158934c7b02b65f5a47cdb90 100644 --- a/glib/gdate.h +++ b/glib/gdate.h @@ -178,7 +178,7 @@ GLIB_AVAILABLE_IN_ALL guint g_date_get_iso8601_week_of_year (const GDate *date); /* If you create a static date struct you need to clear it to get it - * in a sane state before use. You can clear a whole array at + * in a safe state before use. You can clear a whole array at * once with the ndates argument. */ GLIB_AVAILABLE_IN_ALL diff --git a/glib/gdatetime.c b/glib/gdatetime.c index f8bf31c439c7762d34fa1d4c305f3097298f8ae1..ffdeddd814932fd5339d4a80fe7baa19f86fd42a 100644 --- a/glib/gdatetime.c +++ b/glib/gdatetime.c @@ -52,6 +52,7 @@ #define _GNU_SOURCE 1 #endif +#include #include #include @@ -79,6 +80,11 @@ #ifndef G_OS_WIN32 #include #include +#else +#if defined (_MSC_VER) && (_MSC_VER < 1800) +/* fallback implementation for isnan() on VS2012 and earlier */ +#define isnan _isnan +#endif #endif /* !G_OS_WIN32 */ /** @@ -126,7 +132,7 @@ struct _GDateTime /* 1 is 0001-01-01 in Proleptic Gregorian */ gint32 days; - volatile gint ref_count; + gint ref_count; /* (atomic) */ }; /* Time conversion {{{1 */ @@ -598,7 +604,7 @@ ymd_to_days (gint year, { gint64 days; - days = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100) + days = ((gint64) year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400); days += days_in_year[0][month - 1]; @@ -928,21 +934,20 @@ g_date_time_new_from_unix (GTimeZone *tz, } /** - * g_date_time_new_now: + * g_date_time_new_now: (constructor) * @tz: a #GTimeZone * * Creates a #GDateTime corresponding to this exact instant in the given * time zone @tz. The time is as accurate as the system allows, to a * maximum accuracy of 1 microsecond. * - * This function will always succeed unless the system clock is set to - * truly insane values (or unless GLib is still being used after the - * year 9999). + * This function will always succeed unless GLib is still being used after the + * year 9999. * * You should release the return value by calling g_date_time_unref() * when you are done with it. * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 **/ @@ -957,7 +962,7 @@ g_date_time_new_now (GTimeZone *tz) } /** - * g_date_time_new_now_local: + * g_date_time_new_now_local: (constructor) * * Creates a #GDateTime corresponding to this exact instant in the local * time zone. @@ -965,7 +970,7 @@ g_date_time_new_now (GTimeZone *tz) * This is equivalent to calling g_date_time_new_now() with the time * zone returned by g_time_zone_new_local(). * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 **/ @@ -983,14 +988,14 @@ g_date_time_new_now_local (void) } /** - * g_date_time_new_now_utc: + * g_date_time_new_now_utc: (constructor) * * Creates a #GDateTime corresponding to this exact instant in UTC. * * This is equivalent to calling g_date_time_new_now() with the time * zone returned by g_time_zone_new_utc(). * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 **/ @@ -1008,7 +1013,7 @@ g_date_time_new_now_utc (void) } /** - * g_date_time_new_from_unix_local: + * g_date_time_new_from_unix_local: (constructor) * @t: the Unix time * * Creates a #GDateTime corresponding to the given Unix time @t in the @@ -1023,7 +1028,7 @@ g_date_time_new_now_utc (void) * You should release the return value by calling g_date_time_unref() * when you are done with it. * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 **/ @@ -1033,7 +1038,8 @@ g_date_time_new_from_unix_local (gint64 t) GDateTime *datetime; GTimeZone *local; - if (t > G_MAXINT64 / USEC_PER_SECOND) + if (t > G_MAXINT64 / USEC_PER_SECOND || + t < G_MININT64 / USEC_PER_SECOND) return NULL; local = g_time_zone_new_local (); @@ -1044,7 +1050,7 @@ g_date_time_new_from_unix_local (gint64 t) } /** - * g_date_time_new_from_unix_utc: + * g_date_time_new_from_unix_utc: (constructor) * @t: the Unix time * * Creates a #GDateTime corresponding to the given Unix time @t in UTC. @@ -1058,7 +1064,7 @@ g_date_time_new_from_unix_local (gint64 t) * You should release the return value by calling g_date_time_unref() * when you are done with it. * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 **/ @@ -1068,7 +1074,8 @@ g_date_time_new_from_unix_utc (gint64 t) GDateTime *datetime; GTimeZone *utc; - if (t > G_MAXINT64 / USEC_PER_SECOND) + if (t > G_MAXINT64 / USEC_PER_SECOND || + t < G_MININT64 / USEC_PER_SECOND) return NULL; utc = g_time_zone_new_utc (); @@ -1079,7 +1086,7 @@ g_date_time_new_from_unix_utc (gint64 t) } /** - * g_date_time_new_from_timeval_local: + * g_date_time_new_from_timeval_local: (constructor) * @tv: a #GTimeVal * * Creates a #GDateTime corresponding to the given #GTimeVal @tv in the @@ -1095,7 +1102,7 @@ g_date_time_new_from_unix_utc (gint64 t) * You should release the return value by calling g_date_time_unref() * when you are done with it. * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 * Deprecated: 2.62: #GTimeVal is not year-2038-safe. Use @@ -1117,7 +1124,7 @@ g_date_time_new_from_timeval_local (const GTimeVal *tv) G_GNUC_END_IGNORE_DEPRECATIONS /** - * g_date_time_new_from_timeval_utc: + * g_date_time_new_from_timeval_utc: (constructor) * @tv: a #GTimeVal * * Creates a #GDateTime corresponding to the given #GTimeVal @tv in UTC. @@ -1131,7 +1138,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS * You should release the return value by calling g_date_time_unref() * when you are done with it. * - * Returns: a new #GDateTime, or %NULL + * Returns: (transfer full) (nullable): a new #GDateTime, or %NULL * * Since: 2.26 * Deprecated: 2.62: #GTimeVal is not year-2038-safe. Use @@ -1179,7 +1186,7 @@ static gboolean get_iso8601_seconds (const gchar *text, gsize length, gdouble *value) { gsize i; - gdouble divisor = 1, v = 0; + guint64 divisor = 1, v = 0; if (length < 2) return FALSE; @@ -1206,13 +1213,15 @@ get_iso8601_seconds (const gchar *text, gsize length, gdouble *value) for (; i < length; i++) { const gchar c = text[i]; - if (c < '0' || c > '9') + if (c < '0' || c > '9' || + v > (G_MAXUINT64 - (c - '0')) / 10 || + divisor > G_MAXUINT64 / 10) return FALSE; v = v * 10 + (c - '0'); divisor *= 10; } - *value = v / divisor; + *value = (gdouble) v / divisor; return TRUE; } @@ -1382,15 +1391,15 @@ parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset) return NULL; *tz_offset = i; - tz = g_time_zone_new (text + i); + tz = g_time_zone_new_identifier (text + i); /* Double-check that the GTimeZone matches our interpretation of the timezone. * This can fail because our interpretation is less strict than (for example) * parse_time() in gtimezone.c, which restricts the range of the parsed * integers. */ - if (g_time_zone_get_offset (tz, 0) != offset_sign * (offset_hours * 3600 + offset_minutes * 60)) + if (tz == NULL || g_time_zone_get_offset (tz, 0) != offset_sign * (offset_hours * 3600 + offset_minutes * 60)) { - g_time_zone_unref (tz); + g_clear_pointer (&tz, g_time_zone_unref); return NULL; } @@ -1427,20 +1436,24 @@ parse_iso8601_time (const gchar *text, gsize length, } /** - * g_date_time_new_from_iso8601: + * g_date_time_new_from_iso8601: (constructor) * @text: an ISO 8601 formatted time string. * @default_tz: (nullable): a #GTimeZone to use if the text doesn't contain a * timezone, or %NULL. * * Creates a #GDateTime corresponding to the given * [ISO 8601 formatted string](https://en.wikipedia.org/wiki/ISO_8601) - * @text. ISO 8601 strings of the form