All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH for-9.1 0/9] Switch to glib URI parsing code
@ 2024-03-28 14:05 Thomas Huth
  2024-03-28 14:05 ` [PATCH for-9.1 1/9] tests: Remove Ubuntu 20.04 container Thomas Huth
                   ` (9 more replies)
  0 siblings, 10 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:05 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

In the QEMU 9.1 development cycle, we can drop the support for
Ubuntu 20.04 and CentOS 8 since the following major versions of
these distributions are available since 2 years already.

This allows us to bump the minimum version of glib to 2.66 which
comes with a nice set of URI parsing functions. By switching to
these parsing functions, we can finally drop our own URI parsing
code in util/uri.c.

NB: We also need to update some of the custom runners in our CI
environment first (since they still use Ubuntu 20.04).

Thomas Huth (9):
  tests: Remove Ubuntu 20.04 container
  tests/lcitool/libvirt-ci: Update to the latest master branch
  tests: Update our CI to use CentOS Stream 9 instead of 8
  Bump minimum glib version to v2.66
  block/gluster: Use URI parsing code from glib
  block/nbd: Use URI parsing code from glib
  block/nfs: Use URI parsing code from glib
  block/ssh: Use URI parsing code from glib
  util/uri: Remove the old URI parsing code

 meson.build                                   |   16 +-
 include/glib-compat.h                         |   27 +-
 include/qemu/uri.h                            |   99 --
 block/gluster.c                               |   63 +-
 block/nbd.c                                   |   66 +-
 block/nfs.c                                   |  102 +-
 block/ssh.c                                   |   69 +-
 qga/commands-posix-ssh.c                      |    4 +-
 util/uri.c                                    | 1466 -----------------
 .gitlab-ci.d/buildtest.yml                    |   16 +-
 .gitlab-ci.d/container-core.yml               |    4 +-
 .../{centos8.docker => centos9.docker}        |   34 +-
 tests/docker/dockerfiles/ubuntu2004.docker    |  157 --
 tests/lcitool/libvirt-ci                      |    2 +-
 tests/lcitool/mappings.yml                    |   20 -
 tests/lcitool/refresh                         |    3 +-
 tests/vm/centos                               |    4 +-
 util/meson.build                              |    2 +-
 18 files changed, 200 insertions(+), 1954 deletions(-)
 delete mode 100644 include/qemu/uri.h
 delete mode 100644 util/uri.c
 rename tests/docker/dockerfiles/{centos8.docker => centos9.docker} (82%)
 delete mode 100644 tests/docker/dockerfiles/ubuntu2004.docker

-- 
2.44.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 1/9] tests: Remove Ubuntu 20.04 container
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
@ 2024-03-28 14:05 ` Thomas Huth
  2024-03-28 14:05 ` [PATCH for-9.1 2/9] tests/lcitool/libvirt-ci: Update to the latest master branch Thomas Huth
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:05 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Since Ubuntu 22.04 is now available since two years, we can stop
actively supporting the previous LTS version of Ubuntu now.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 tests/docker/dockerfiles/ubuntu2004.docker | 157 ---------------------
 tests/lcitool/refresh                      |   1 -
 2 files changed, 158 deletions(-)
 delete mode 100644 tests/docker/dockerfiles/ubuntu2004.docker

diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker
deleted file mode 100644
index d3e212060c..0000000000
--- a/tests/docker/dockerfiles/ubuntu2004.docker
+++ /dev/null
@@ -1,157 +0,0 @@
-# THIS FILE WAS AUTO-GENERATED
-#
-#  $ lcitool dockerfile --layers all ubuntu-2004 qemu
-#
-# https://gitlab.com/libvirt/libvirt-ci
-
-FROM docker.io/library/ubuntu:20.04
-
-RUN export DEBIAN_FRONTEND=noninteractive && \
-    apt-get update && \
-    apt-get install -y eatmydata && \
-    eatmydata apt-get dist-upgrade -y && \
-    eatmydata apt-get install --no-install-recommends -y \
-                      bash \
-                      bc \
-                      bison \
-                      bsdmainutils \
-                      bzip2 \
-                      ca-certificates \
-                      ccache \
-                      clang \
-                      dbus \
-                      debianutils \
-                      diffutils \
-                      exuberant-ctags \
-                      findutils \
-                      flex \
-                      g++ \
-                      gcc \
-                      gcovr \
-                      gettext \
-                      git \
-                      hostname \
-                      libaio-dev \
-                      libasan6 \
-                      libasound2-dev \
-                      libattr1-dev \
-                      libbrlapi-dev \
-                      libbz2-dev \
-                      libc6-dev \
-                      libcacard-dev \
-                      libcap-ng-dev \
-                      libcapstone-dev \
-                      libcmocka-dev \
-                      libcurl4-gnutls-dev \
-                      libdaxctl-dev \
-                      libdrm-dev \
-                      libepoxy-dev \
-                      libfdt-dev \
-                      libffi-dev \
-                      libfuse3-dev \
-                      libgbm-dev \
-                      libgcrypt20-dev \
-                      libglib2.0-dev \
-                      libglusterfs-dev \
-                      libgnutls28-dev \
-                      libgtk-3-dev \
-                      libibumad-dev \
-                      libibverbs-dev \
-                      libiscsi-dev \
-                      libjemalloc-dev \
-                      libjpeg-turbo8-dev \
-                      libjson-c-dev \
-                      liblttng-ust-dev \
-                      liblzo2-dev \
-                      libncursesw5-dev \
-                      libnfs-dev \
-                      libnuma-dev \
-                      libpam0g-dev \
-                      libpcre2-dev \
-                      libpixman-1-dev \
-                      libpmem-dev \
-                      libpng-dev \
-                      libpulse-dev \
-                      librbd-dev \
-                      librdmacm-dev \
-                      libsasl2-dev \
-                      libsdl2-dev \
-                      libsdl2-image-dev \
-                      libseccomp-dev \
-                      libselinux1-dev \
-                      libslirp-dev \
-                      libsnappy-dev \
-                      libsndio-dev \
-                      libspice-protocol-dev \
-                      libspice-server-dev \
-                      libssh-dev \
-                      libsystemd-dev \
-                      libtasn1-6-dev \
-                      libubsan1 \
-                      libudev-dev \
-                      libusb-1.0-0-dev \
-                      libusbredirhost-dev \
-                      libvdeplug-dev \
-                      libvirglrenderer-dev \
-                      libvte-2.91-dev \
-                      libxen-dev \
-                      libzstd-dev \
-                      llvm \
-                      locales \
-                      make \
-                      mtools \
-                      multipath-tools \
-                      ncat \
-                      nettle-dev \
-                      ninja-build \
-                      openssh-client \
-                      pkgconf \
-                      python3 \
-                      python3-numpy \
-                      python3-opencv \
-                      python3-pillow \
-                      python3-pip \
-                      python3-setuptools \
-                      python3-sphinx \
-                      python3-sphinx-rtd-theme \
-                      python3-venv \
-                      python3-wheel \
-                      python3-yaml \
-                      rpm2cpio \
-                      sed \
-                      socat \
-                      sparse \
-                      systemtap-sdt-dev \
-                      tar \
-                      tesseract-ocr \
-                      tesseract-ocr-eng \
-                      xfslibs-dev \
-                      xorriso \
-                      zlib1g-dev \
-                      zstd && \
-    eatmydata apt-get autoremove -y && \
-    eatmydata apt-get autoclean -y && \
-    sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
-    dpkg-reconfigure locales && \
-    dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
-    mkdir -p /usr/libexec/ccache-wrappers && \
-    ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
-    ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \
-    ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \
-    ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
-    ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
-
-RUN /usr/bin/pip3 install \
-                            meson==0.63.2 \
-                            tomli
-
-ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
-ENV LANG "en_US.UTF-8"
-ENV MAKE "/usr/bin/make"
-ENV NINJA "/usr/bin/ninja"
-ENV PYTHON "/usr/bin/python3"
-# As a final step configure the user (if env is defined)
-ARG USER
-ARG UID
-RUN if [ "${USER}" ]; then \
-  id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index fe7692c500..692752a3df 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -130,7 +130,6 @@ try:
                         trailer="".join(debian12_extras))
     generate_dockerfile("fedora", "fedora-38")
     generate_dockerfile("opensuse-leap", "opensuse-leap-15")
-    generate_dockerfile("ubuntu2004", "ubuntu-2004")
     generate_dockerfile("ubuntu2204", "ubuntu-2204")
 
     #
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 2/9] tests/lcitool/libvirt-ci: Update to the latest master branch
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
  2024-03-28 14:05 ` [PATCH for-9.1 1/9] tests: Remove Ubuntu 20.04 container Thomas Huth
@ 2024-03-28 14:05 ` Thomas Huth
  2024-03-28 14:06 ` [PATCH for-9.1 3/9] tests: Update our CI to use CentOS Stream 9 instead of 8 Thomas Huth
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:05 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

We need the latest fixes for the lcitool to be able to properly
update our CentOS docker file to CentOS Stream 9.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 tests/lcitool/libvirt-ci | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci
index 77c800186f..e25d813a62 160000
--- a/tests/lcitool/libvirt-ci
+++ b/tests/lcitool/libvirt-ci
@@ -1 +1 @@
-Subproject commit 77c800186f34b21be7660750577cc5582a914deb
+Subproject commit e25d813a62fb8fa0ee7aa0748cf720b59a187e71
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 3/9] tests: Update our CI to use CentOS Stream 9 instead of 8
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
  2024-03-28 14:05 ` [PATCH for-9.1 1/9] tests: Remove Ubuntu 20.04 container Thomas Huth
  2024-03-28 14:05 ` [PATCH for-9.1 2/9] tests/lcitool/libvirt-ci: Update to the latest master branch Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-03-28 14:06 ` [PATCH for-9.1 4/9] Bump minimum glib version to v2.66 Thomas Huth
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

RHEL 9 (and thus also the derivatives) are available since two years
now, so according to QEMU's support policy, we can drop the active
support for the previous major version 8 now.
Thus upgrade our CentOS Stream container to major version 9 now.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 .gitlab-ci.d/buildtest.yml                    | 16 ++++-----
 .gitlab-ci.d/container-core.yml               |  4 +--
 .../{centos8.docker => centos9.docker}        | 34 +++++++------------
 tests/lcitool/mappings.yml                    | 20 -----------
 tests/lcitool/refresh                         |  2 +-
 tests/vm/centos                               |  4 +--
 6 files changed, 26 insertions(+), 54 deletions(-)
 rename tests/docker/dockerfiles/{centos8.docker => centos9.docker} (82%)

diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index cfdff175c3..9f34c650d6 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -158,9 +158,9 @@ build-system-centos:
     - .native_build_job_template
     - .native_build_artifact_template
   needs:
-    job: amd64-centos8-container
+    job: amd64-centos9-container
   variables:
-    IMAGE: centos8
+    IMAGE: centos9
     CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
       --enable-modules --enable-trace-backends=dtrace --enable-docs
     TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
@@ -242,7 +242,7 @@ check-system-centos:
     - job: build-system-centos
       artifacts: true
   variables:
-    IMAGE: centos8
+    IMAGE: centos9
     MAKE_CHECK_ARGS: check
 
 avocado-system-centos:
@@ -251,7 +251,7 @@ avocado-system-centos:
     - job: build-system-centos
       artifacts: true
   variables:
-    IMAGE: centos8
+    IMAGE: centos9
     MAKE_CHECK_ARGS: check-avocado
     AVOCADO_TAGS: arch:ppc64 arch:or1k arch:s390x arch:x86_64 arch:rx
       arch:sh4 arch:nios2
@@ -327,9 +327,9 @@ avocado-system-flaky:
 build-tcg-disabled:
   extends: .native_build_job_template
   needs:
-    job: amd64-centos8-container
+    job: amd64-centos9-container
   variables:
-    IMAGE: centos8
+    IMAGE: centos9
   script:
     - mkdir build
     - cd build
@@ -651,9 +651,9 @@ build-tci:
 build-without-defaults:
   extends: .native_build_job_template
   needs:
-    job: amd64-centos8-container
+    job: amd64-centos9-container
   variables:
-    IMAGE: centos8
+    IMAGE: centos9
     CONFIGURE_ARGS:
       --without-default-devices
       --without-default-features
diff --git a/.gitlab-ci.d/container-core.yml b/.gitlab-ci.d/container-core.yml
index 08f8450fa1..5459447676 100644
--- a/.gitlab-ci.d/container-core.yml
+++ b/.gitlab-ci.d/container-core.yml
@@ -1,10 +1,10 @@
 include:
   - local: '/.gitlab-ci.d/container-template.yml'
 
-amd64-centos8-container:
+amd64-centos9-container:
   extends: .container_job_template
   variables:
-    NAME: centos8
+    NAME: centos9
 
 amd64-fedora-container:
   extends: .container_job_template
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos9.docker
similarity index 82%
rename from tests/docker/dockerfiles/centos8.docker
rename to tests/docker/dockerfiles/centos9.docker
index d97c30e96a..9fc9b27eb7 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos9.docker
@@ -1,15 +1,14 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all centos-stream-8 qemu
+#  $ lcitool dockerfile --layers all centos-stream-9 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
-FROM quay.io/centos/centos:stream8
+FROM quay.io/centos/centos:stream9
 
 RUN dnf distro-sync -y && \
     dnf install 'dnf-command(config-manager)' -y && \
-    dnf config-manager --set-enabled -y powertools && \
-    dnf install -y centos-release-advanced-virtualization && \
+    dnf config-manager --set-enabled -y crb && \
     dnf install -y epel-release && \
     dnf install -y epel-next-release && \
     dnf install -y \
@@ -42,7 +41,6 @@ RUN dnf distro-sync -y && \
         glib2-static \
         glibc-langpack-en \
         glibc-static \
-        glusterfs-api-devel \
         gnutls-devel \
         gtk3-devel \
         hostname \
@@ -82,6 +80,7 @@ RUN dnf distro-sync -y && \
         lzo-devel \
         make \
         mesa-libgbm-devel \
+        meson \
         mtools \
         ncurses-devel \
         nettle-devel \
@@ -95,25 +94,25 @@ RUN dnf distro-sync -y && \
         pixman-devel \
         pkgconfig \
         pulseaudio-libs-devel \
-        python38 \
-        python38-PyYAML \
-        python38-numpy \
-        python38-pip \
-        python38-setuptools \
-        python38-wheel \
+        python3 \
+        python3-PyYAML \
+        python3-numpy \
+        python3-pillow \
+        python3-pip \
+        python3-sphinx \
+        python3-sphinx_rtd_theme \
+        python3-tomli \
         rdma-core-devel \
         sed \
         snappy-devel \
         socat \
         spice-protocol \
-        spice-server-devel \
         swtpm \
         systemd-devel \
         systemtap-sdt-devel \
         tar \
         usbredir-devel \
         util-linux \
-        virglrenderer-devel \
         vte291-devel \
         which \
         xfsprogs-devel \
@@ -131,18 +130,11 @@ RUN dnf distro-sync -y && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
 
-RUN /usr/bin/pip3.8 install \
-                    meson==0.63.2 \
-                    pillow \
-                    sphinx \
-                    sphinx-rtd-theme \
-                    tomli
-
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
 ENV NINJA "/usr/bin/ninja"
-ENV PYTHON "/usr/bin/python3.8"
+ENV PYTHON "/usr/bin/python3"
 # As a final step configure the user (if env is defined)
 ARG USER
 ARG UID
diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
index 407c03301b..03b974ad02 100644
--- a/tests/lcitool/mappings.yml
+++ b/tests/lcitool/mappings.yml
@@ -1,66 +1,50 @@
 mappings:
   flake8:
-    CentOSStream8:
     OpenSUSELeap15:
 
   meson:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3:
-    CentOSStream8: python38
     OpenSUSELeap15: python311-base
 
   python3-PyYAML:
-    CentOSStream8: python38-PyYAML
     OpenSUSELeap15:
 
   python3-devel:
-    CentOSStream8: python38-devel
     OpenSUSELeap15: python311-devel
 
   python3-docutils:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-numpy:
-    CentOSStream8: python38-numpy
     OpenSUSELeap15:
 
   python3-opencv:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-pillow:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-pip:
-    CentOSStream8: python38-pip
     OpenSUSELeap15: python311-pip
 
   python3-pillow:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-selinux:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-setuptools:
-    CentOSStream8: python38-setuptools
     OpenSUSELeap15: python311-setuptools
 
   python3-sphinx:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-sphinx-rtd-theme:
-    CentOSStream8:
     OpenSUSELeap15:
 
   python3-sqlite3:
-    CentOSStream8: python38
     OpenSUSELeap15: python311
 
   python3-tomli:
@@ -69,15 +53,11 @@ mappings:
     Fedora:
     Debian12:
     OpenSUSELeap15:
-    # Not available for Python 3.8
-    CentOSStream8:
 
   python3-venv:
-    CentOSStream8: python38
     OpenSUSELeap15: python311-base
 
   python3-wheel:
-    CentOSStream8: python38-wheel
     OpenSUSELeap15: python311-pip
 
 pypi_mappings:
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index 692752a3df..24a735a3f2 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -125,7 +125,7 @@ try:
     # Standard native builds
     #
     generate_dockerfile("alpine", "alpine-318")
-    generate_dockerfile("centos8", "centos-stream-8")
+    generate_dockerfile("centos9", "centos-stream-9")
     generate_dockerfile("debian", "debian-12",
                         trailer="".join(debian12_extras))
     generate_dockerfile("fedora", "fedora-38")
diff --git a/tests/vm/centos b/tests/vm/centos
index 097a9ca14d..d25c8f8b5b 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -26,8 +26,8 @@ class CentosVM(basevm.BaseVM):
         export SRC_ARCHIVE=/dev/vdb;
         sudo chmod a+r $SRC_ARCHIVE;
         tar -xf $SRC_ARCHIVE;
-        make docker-test-block@centos8 {verbose} J={jobs} NETWORK=1;
-        make docker-test-quick@centos8 {verbose} J={jobs} NETWORK=1;
+        make docker-test-block@centos9 {verbose} J={jobs} NETWORK=1;
+        make docker-test-quick@centos9 {verbose} J={jobs} NETWORK=1;
     """
 
     def build_image(self, img):
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 4/9] Bump minimum glib version to v2.66
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (2 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 3/9] tests: Update our CI to use CentOS Stream 9 instead of 8 Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-04-12 10:16   ` Paolo Bonzini
  2024-03-28 14:06 ` [PATCH for-9.1 5/9] block/gluster: Use URI parsing code from glib Thomas Huth
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Now that we dropped support for CentOS 8 and Ubuntu 20.04, we can
look into bumping the glib version to a new minimum for further
clean-ups. According to repology.org, available versions are:

 CentOS Stream 9:       2.66.7
 Debian 11:             2.66.8
 Fedora 38:             2.74.1
 Freebsd:               2.78.4
 Homebrew:              2.80.0
 Openbsd:               2.78.4
 OpenSuse leap 15.5:    2.70.5
 pkgsrc_current:        2.78.4
 Ubuntu 22.04:          2.72.1

Thus it should be safe to bump the minimum glib version to 2.66 now.
Version 2.66 comes with new functions for URI parsing which will
allow further clean-ups in the following patches.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 meson.build              | 16 +---------------
 include/glib-compat.h    | 27 ++-------------------------
 qga/commands-posix-ssh.c |  4 ++--
 3 files changed, 5 insertions(+), 42 deletions(-)

diff --git a/meson.build b/meson.build
index c9c3217ba4..c0aaceffc0 100644
--- a/meson.build
+++ b/meson.build
@@ -865,7 +865,7 @@ have_xen_pci_passthrough = get_option('xen_pci_passthrough') \
 
 # When bumping glib minimum version, please check also whether to increase
 # the _WIN32_WINNT setting in osdep.h according to the value from glib
-glib_req_ver = '>=2.56.0'
+glib_req_ver = '>=2.66.0'
 glib_pc = dependency('glib-2.0', version: glib_req_ver, required: true,
                     method: 'pkg-config')
 glib_cflags = []
@@ -906,20 +906,6 @@ if not cc.compiles('''
         to the right pkg-config files for your build target.''')
 endif
 
-# Silence clang warnings triggered by glib < 2.57.2
-if not cc.compiles('''
-  #include <glib.h>
-  typedef struct Foo {
-    int i;
-  } Foo;
-  static void foo_free(Foo *f)
-  {
-    g_free(f);
-  }
-  G_DEFINE_AUTOPTR_CLEANUP_FUNC(Foo, foo_free)
-  int main(void) { return 0; }''', dependencies: glib_pc, args: ['-Wunused-function', '-Werror'])
-  glib_cflags += cc.get_supported_arguments('-Wno-unused-function')
-endif
 glib = declare_dependency(dependencies: [glib_pc, gmodule],
                           compile_args: glib_cflags,
                           version: glib_pc.version())
diff --git a/include/glib-compat.h b/include/glib-compat.h
index 43a562974d..86be439ba0 100644
--- a/include/glib-compat.h
+++ b/include/glib-compat.h
@@ -19,12 +19,12 @@
 /* Ask for warnings for anything that was marked deprecated in
  * the defined version, or before. It is a candidate for rewrite.
  */
-#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_56
+#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_66
 
 /* Ask for warnings if code tries to use function that did not
  * exist in the defined version. These risk breaking builds
  */
-#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_56
+#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_66
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -105,29 +105,6 @@ static inline gpointer g_memdup2_qemu(gconstpointer mem, gsize byte_size)
 }
 #define g_memdup2(m, s) g_memdup2_qemu(m, s)
 
-#if defined(G_OS_UNIX)
-/*
- * Note: The fallback implementation is not MT-safe, and it returns a copy of
- * the libc passwd (must be g_free() after use) but not the content. Because of
- * these important differences the caller must be aware of, it's not #define for
- * GLib API substitution.
- */
-static inline struct passwd *
-g_unix_get_passwd_entry_qemu(const gchar *user_name, GError **error)
-{
-#if GLIB_CHECK_VERSION(2, 64, 0)
-    return g_unix_get_passwd_entry(user_name, error);
-#else
-    struct passwd *p = getpwnam(user_name);
-    if (!p) {
-        g_set_error_literal(error, G_UNIX_ERROR, 0, g_strerror(errno));
-        return NULL;
-    }
-    return (struct passwd *)g_memdup(p, sizeof(*p));
-#endif
-}
-#endif /* G_OS_UNIX */
-
 static inline bool
 qemu_g_test_slow(void)
 {
diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c
index 236f80de44..b0e0b1d674 100644
--- a/qga/commands-posix-ssh.c
+++ b/qga/commands-posix-ssh.c
@@ -35,7 +35,7 @@ test_get_passwd_entry(const gchar *user_name, GError **error)
     return p;
 }
 
-#define g_unix_get_passwd_entry_qemu(username, err) \
+#define g_unix_get_passwd_entry(username, err) \
    test_get_passwd_entry(username, err)
 #endif
 
@@ -45,7 +45,7 @@ get_passwd_entry(const char *username, Error **errp)
     g_autoptr(GError) err = NULL;
     struct passwd *p;
 
-    p = g_unix_get_passwd_entry_qemu(username, &err);
+    p = g_unix_get_passwd_entry(username, &err);
     if (p == NULL) {
         error_setg(errp, "failed to lookup user '%s': %s",
                    username, err->message);
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 5/9] block/gluster: Use URI parsing code from glib
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (3 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 4/9] Bump minimum glib version to v2.66 Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-03-28 14:06 ` [PATCH for-9.1 6/9] block/nbd: " Thomas Huth
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Since version 2.66, glib has useful URI parsing functions, too.
Use those instead of the QEMU-internal ones to be finally able
to get rid of the latter.

Cc: integration@gluster.org
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 block/gluster.c | 63 +++++++++++++++++++++++++++++--------------------
 1 file changed, 37 insertions(+), 26 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index cc74af06dc..f4cb95360e 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -17,7 +17,6 @@
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
-#include "qemu/uri.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
@@ -289,9 +288,9 @@ static void glfs_clear_preopened(glfs_t *fs)
     }
 }
 
-static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
+static int parse_volume_options(BlockdevOptionsGluster *gconf, const char *path)
 {
-    char *p, *q;
+    const char *p, *q;
 
     if (!path) {
         return -EINVAL;
@@ -350,12 +349,15 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
                                   const char *filename)
 {
     SocketAddress *gsconf;
-    URI *uri;
-    QueryParams *qp = NULL;
+    GUri *uri;
+    GHashTable *qp = NULL;
+    int qp_n;
     bool is_unix = false;
     int ret = 0;
+    const char *uri_scheme, *uri_query, *uri_server;
+    int uri_port;
 
-    uri = uri_parse(filename);
+    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
     if (!uri) {
         return -EINVAL;
     }
@@ -364,14 +366,15 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
     QAPI_LIST_PREPEND(gconf->server, gsconf);
 
     /* transport */
-    if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
+    uri_scheme = g_uri_get_scheme(uri);
+    if (!uri_scheme || !strcmp(uri_scheme, "gluster")) {
         gsconf->type = SOCKET_ADDRESS_TYPE_INET;
-    } else if (!strcmp(uri->scheme, "gluster+tcp")) {
+    } else if (!strcmp(uri_scheme, "gluster+tcp")) {
         gsconf->type = SOCKET_ADDRESS_TYPE_INET;
-    } else if (!strcmp(uri->scheme, "gluster+unix")) {
+    } else if (!strcmp(uri_scheme, "gluster+unix")) {
         gsconf->type = SOCKET_ADDRESS_TYPE_UNIX;
         is_unix = true;
-    } else if (!strcmp(uri->scheme, "gluster+rdma")) {
+    } else if (!strcmp(uri_scheme, "gluster+rdma")) {
         gsconf->type = SOCKET_ADDRESS_TYPE_INET;
         warn_report("rdma feature is not supported, falling back to tcp");
     } else {
@@ -379,31 +382,39 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
         goto out;
     }
 
-    ret = parse_volume_options(gconf, uri->path);
+    ret = parse_volume_options(gconf, g_uri_get_path(uri));
     if (ret < 0) {
         goto out;
     }
 
-    qp = query_params_parse(uri->query);
-    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
-        ret = -EINVAL;
-        goto out;
-    }
-
-    if (is_unix) {
-        if (uri->server || uri->port) {
+    uri_query = g_uri_get_query(uri);
+    if (uri_query) {
+        qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
+        if (!qp) {
+            ret = -EINVAL;
+            goto out;
+        }
+        qp_n = g_hash_table_size(qp);
+        if (qp_n > 1 || (is_unix && !qp_n) || (!is_unix && qp_n)) {
             ret = -EINVAL;
             goto out;
         }
-        if (strcmp(qp->p[0].name, "socket")) {
+    }
+
+    uri_server = g_uri_get_host(uri);
+    uri_port = g_uri_get_port(uri);
+
+    if (is_unix) {
+        char *uri_socket = g_hash_table_lookup(qp, "socket");
+        if (uri_server || uri_port != -1 || !uri_socket) {
             ret = -EINVAL;
             goto out;
         }
-        gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
+        gsconf->u.q_unix.path = g_strdup(uri_socket);
     } else {
-        gsconf->u.inet.host = g_strdup(uri->server ? uri->server : "localhost");
-        if (uri->port) {
-            gsconf->u.inet.port = g_strdup_printf("%d", uri->port);
+        gsconf->u.inet.host = g_strdup(uri_server ? uri_server : "localhost");
+        if (uri_port != -1) {
+            gsconf->u.inet.port = g_strdup_printf("%d", uri_port);
         } else {
             gsconf->u.inet.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
         }
@@ -411,9 +422,9 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
 
 out:
     if (qp) {
-        query_params_free(qp);
+        g_hash_table_destroy(qp);
     }
-    uri_free(uri);
+    g_uri_unref(uri);
     return ret;
 }
 
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (4 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 5/9] block/gluster: Use URI parsing code from glib Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-03-28 14:13   ` Richard W.M. Jones
  2024-03-28 14:54   ` Eric Blake
  2024-03-28 14:06 ` [PATCH for-9.1 7/9] block/nfs: " Thomas Huth
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Since version 2.66, glib has useful URI parsing functions, too.
Use those instead of the QEMU-internal ones to be finally able
to get rid of the latter. The g_uri_get_host() also takes care
of removing the square brackets from IPv6 addresses, so we can
drop that part of the QEMU code now, too.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 block/nbd.c | 66 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index ef05f7cdfd..95b507f872 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -31,7 +31,6 @@
 #include "qemu/osdep.h"
 
 #include "trace.h"
-#include "qemu/uri.h"
 #include "qemu/option.h"
 #include "qemu/cutils.h"
 #include "qemu/main-loop.h"
@@ -1514,30 +1513,34 @@ static void nbd_client_close(BlockDriverState *bs)
 
 static int nbd_parse_uri(const char *filename, QDict *options)
 {
-    URI *uri;
+    GUri *uri;
     const char *p;
-    QueryParams *qp = NULL;
+    GHashTable *qp = NULL;
+    int qp_n;
     int ret = 0;
     bool is_unix;
+    const char *uri_scheme, *uri_query, *uri_server;
+    int uri_port;
 
-    uri = uri_parse(filename);
+    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
     if (!uri) {
         return -EINVAL;
     }
 
     /* transport */
-    if (!g_strcmp0(uri->scheme, "nbd")) {
+    uri_scheme = g_uri_get_scheme(uri);
+    if (!g_strcmp0(uri_scheme, "nbd")) {
         is_unix = false;
-    } else if (!g_strcmp0(uri->scheme, "nbd+tcp")) {
+    } else if (!g_strcmp0(uri_scheme, "nbd+tcp")) {
         is_unix = false;
-    } else if (!g_strcmp0(uri->scheme, "nbd+unix")) {
+    } else if (!g_strcmp0(uri_scheme, "nbd+unix")) {
         is_unix = true;
     } else {
         ret = -EINVAL;
         goto out;
     }
 
-    p = uri->path ? uri->path : "";
+    p = g_uri_get_path(uri) ?: "";
     if (p[0] == '/') {
         p++;
     }
@@ -1545,51 +1548,58 @@ static int nbd_parse_uri(const char *filename, QDict *options)
         qdict_put_str(options, "export", p);
     }
 
-    qp = query_params_parse(uri->query);
-    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
-        ret = -EINVAL;
-        goto out;
+    uri_query = g_uri_get_query(uri);
+    if (uri_query) {
+        qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
+        if (!qp) {
+            ret = -EINVAL;
+            goto out;
+        }
+        qp_n = g_hash_table_size(qp);
+        if (qp_n > 1 || (is_unix && !qp_n) || (!is_unix && qp_n)) {
+            ret = -EINVAL;
+            goto out;
+        }
+     }
+
+    uri_server = g_uri_get_host(uri);
+    if (uri_server && !uri_server[0]) {
+        uri_server = NULL;
     }
+    uri_port = g_uri_get_port(uri);
 
     if (is_unix) {
         /* nbd+unix:///export?socket=path */
-        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
+        const char *uri_socket = g_hash_table_lookup(qp, "socket");
+        if (uri_server || uri_port != -1 || !uri_socket) {
             ret = -EINVAL;
             goto out;
         }
         qdict_put_str(options, "server.type", "unix");
-        qdict_put_str(options, "server.path", qp->p[0].value);
+        qdict_put_str(options, "server.path", uri_socket);
     } else {
-        QString *host;
         char *port_str;
 
         /* nbd[+tcp]://host[:port]/export */
-        if (!uri->server) {
+        if (!uri_server) {
             ret = -EINVAL;
             goto out;
         }
 
-        /* strip braces from literal IPv6 address */
-        if (uri->server[0] == '[') {
-            host = qstring_from_substr(uri->server, 1,
-                                       strlen(uri->server) - 1);
-        } else {
-            host = qstring_from_str(uri->server);
-        }
-
         qdict_put_str(options, "server.type", "inet");
-        qdict_put(options, "server.host", host);
+        qdict_put_str(options, "server.host", uri_server);
 
-        port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
+        port_str = g_strdup_printf("%d", uri_port != -1 ? uri_port
+                                                        : NBD_DEFAULT_PORT);
         qdict_put_str(options, "server.port", port_str);
         g_free(port_str);
     }
 
 out:
     if (qp) {
-        query_params_free(qp);
+        g_hash_table_destroy(qp);
     }
-    uri_free(uri);
+    g_uri_unref(uri);
     return ret;
 }
 
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 7/9] block/nfs: Use URI parsing code from glib
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (5 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 6/9] block/nbd: " Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-03-28 14:06 ` [PATCH for-9.1 8/9] block/ssh: " Thomas Huth
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Since version 2.66, glib has useful URI parsing functions, too.
Use those instead of the QEMU-internal ones to be finally able
to get rid of the latter.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 block/nfs.c | 102 ++++++++++++++++++++++++++--------------------------
 1 file changed, 52 insertions(+), 50 deletions(-)

diff --git a/block/nfs.c b/block/nfs.c
index f737e19cd3..9550063695 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -38,7 +38,6 @@
 #include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
-#include "qemu/uri.h"
 #include "qemu/cutils.h"
 #include "sysemu/replay.h"
 #include "qapi/qapi-visit-block-core.h"
@@ -79,76 +78,79 @@ typedef struct NFSRPC {
 
 static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
 {
-    URI *uri = NULL;
-    QueryParams *qp = NULL;
-    int ret = -EINVAL, i;
-
-    uri = uri_parse(filename);
+    GUri *uri;
+    GUriParamsIter qp;
+    const char *uri_server, *uri_path, *uri_query;
+    char *qp_name, *qp_value;
+    GError *gerror = NULL;
+    int ret = -EINVAL;
+
+    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
     if (!uri) {
         error_setg(errp, "Invalid URI specified");
         goto out;
     }
-    if (g_strcmp0(uri->scheme, "nfs") != 0) {
+    if (!g_str_equal(g_uri_get_scheme(uri), "nfs")) {
         error_setg(errp, "URI scheme must be 'nfs'");
         goto out;
     }
 
-    if (!uri->server) {
+    uri_server = g_uri_get_host(uri);
+    if (!uri_server || !uri_server[0]) {
         error_setg(errp, "missing hostname in URI");
         goto out;
     }
 
-    if (!uri->path) {
+    uri_path = g_uri_get_path(uri);
+    if (!uri_path || !uri_path[0]) {
         error_setg(errp, "missing file path in URI");
         goto out;
     }
 
-    qp = query_params_parse(uri->query);
-    if (!qp) {
-        error_setg(errp, "could not parse query parameters");
-        goto out;
-    }
-
-    qdict_put_str(options, "server.host", uri->server);
+    qdict_put_str(options, "server.host", uri_server);
     qdict_put_str(options, "server.type", "inet");
-    qdict_put_str(options, "path", uri->path);
-
-    for (i = 0; i < qp->n; i++) {
-        uint64_t val;
-        if (!qp->p[i].value) {
-            error_setg(errp, "Value for NFS parameter expected: %s",
-                       qp->p[i].name);
-            goto out;
-        }
-        if (parse_uint_full(qp->p[i].value, 0, &val)) {
-            error_setg(errp, "Illegal value for NFS parameter: %s",
-                       qp->p[i].name);
-            goto out;
-        }
-        if (!strcmp(qp->p[i].name, "uid")) {
-            qdict_put_str(options, "user", qp->p[i].value);
-        } else if (!strcmp(qp->p[i].name, "gid")) {
-            qdict_put_str(options, "group", qp->p[i].value);
-        } else if (!strcmp(qp->p[i].name, "tcp-syncnt")) {
-            qdict_put_str(options, "tcp-syn-count", qp->p[i].value);
-        } else if (!strcmp(qp->p[i].name, "readahead")) {
-            qdict_put_str(options, "readahead-size", qp->p[i].value);
-        } else if (!strcmp(qp->p[i].name, "pagecache")) {
-            qdict_put_str(options, "page-cache-size", qp->p[i].value);
-        } else if (!strcmp(qp->p[i].name, "debug")) {
-            qdict_put_str(options, "debug", qp->p[i].value);
-        } else {
-            error_setg(errp, "Unknown NFS parameter name: %s",
-                       qp->p[i].name);
-            goto out;
+    qdict_put_str(options, "path", uri_path);
+
+    uri_query = g_uri_get_query(uri);
+    if (uri_query) {
+        g_uri_params_iter_init(&qp, uri_query, -1, "&", G_URI_PARAMS_NONE);
+        while (g_uri_params_iter_next(&qp, &qp_name, &qp_value, &gerror)) {
+            uint64_t val;
+            if (!qp_name || gerror) {
+                error_setg(errp, "Failed to parse NFS parameter");
+                goto out;
+            }
+            if (!qp_value) {
+                error_setg(errp, "Value for NFS parameter expected: %s",
+                           qp_name);
+                goto out;
+            }
+            if (parse_uint_full(qp_value, 0, &val)) {
+                error_setg(errp, "Illegal value for NFS parameter: %s",
+                           qp_name);
+                goto out;
+            }
+            if (g_str_equal(qp_name, "uid")) {
+                qdict_put_str(options, "user", qp_value);
+            } else if (g_str_equal(qp_name, "gid")) {
+                qdict_put_str(options, "group", qp_value);
+            } else if (g_str_equal(qp_name, "tcp-syncnt")) {
+                qdict_put_str(options, "tcp-syn-count", qp_value);
+            } else if (g_str_equal(qp_name, "readahead")) {
+                qdict_put_str(options, "readahead-size", qp_value);
+            } else if (g_str_equal(qp_name, "pagecache")) {
+                qdict_put_str(options, "page-cache-size", qp_value);
+            } else if (g_str_equal(qp_name, "debug")) {
+                qdict_put_str(options, "debug", qp_value);
+            } else {
+                error_setg(errp, "Unknown NFS parameter name: %s", qp_name);
+                goto out;
+            }
         }
     }
     ret = 0;
 out:
-    if (qp) {
-        query_params_free(qp);
-    }
-    uri_free(uri);
+    g_uri_unref(uri);
     return ret;
 }
 
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 8/9] block/ssh: Use URI parsing code from glib
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (6 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 7/9] block/nfs: " Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-03-28 14:15   ` Richard W.M. Jones
  2024-03-28 14:06 ` [PATCH for-9.1 9/9] util/uri: Remove the old URI parsing code Thomas Huth
  2024-04-15 14:16 ` MAINTAINERS tweak [was: [PATCH for-9.1 0/9] Switch to glib URI parsing code] Eric Blake
  9 siblings, 1 reply; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Since version 2.66, glib has useful URI parsing functions, too.
Use those instead of the QEMU-internal ones to be finally able
to get rid of the latter.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 block/ssh.c | 69 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/block/ssh.c b/block/ssh.c
index 2748253d4a..c0caf59793 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -37,7 +37,6 @@
 #include "qemu/ctype.h"
 #include "qemu/cutils.h"
 #include "qemu/sockets.h"
-#include "qemu/uri.h"
 #include "qapi/qapi-visit-sockets.h"
 #include "qapi/qapi-visit-block-core.h"
 #include "qapi/qmp/qdict.h"
@@ -181,64 +180,76 @@ static void sftp_error_trace(BDRVSSHState *s, const char *op)
 
 static int parse_uri(const char *filename, QDict *options, Error **errp)
 {
-    URI *uri = NULL;
-    QueryParams *qp;
+    GUri *uri;
+    const char *uri_host, *uri_path, *uri_user, *uri_query;
     char *port_str;
-    int i;
+    int port;
+    g_autoptr(GError) gerror = NULL;
+    char *qp_name, *qp_value;
+    GUriParamsIter qp;
 
-    uri = uri_parse(filename);
+    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
     if (!uri) {
         return -EINVAL;
     }
 
-    if (g_strcmp0(uri->scheme, "ssh") != 0) {
+    if (g_strcmp0(g_uri_get_scheme(uri), "ssh") != 0) {
         error_setg(errp, "URI scheme must be 'ssh'");
         goto err;
     }
 
-    if (!uri->server || strcmp(uri->server, "") == 0) {
+    uri_host = g_uri_get_host(uri);
+    if (!uri_host || g_str_equal(uri_host, "")) {
         error_setg(errp, "missing hostname in URI");
         goto err;
     }
 
-    if (!uri->path || strcmp(uri->path, "") == 0) {
+    uri_path = g_uri_get_path(uri);
+    if (!uri_path || g_str_equal(uri_path, "")) {
         error_setg(errp, "missing remote path in URI");
         goto err;
     }
 
-    qp = query_params_parse(uri->query);
-    if (!qp) {
-        error_setg(errp, "could not parse query parameters");
-        goto err;
-    }
-
-    if(uri->user && strcmp(uri->user, "") != 0) {
-        qdict_put_str(options, "user", uri->user);
+    uri_user = g_uri_get_user(uri);
+    if (uri_user && !g_str_equal(uri_user, "")) {
+        qdict_put_str(options, "user", uri_user);
     }
 
-    qdict_put_str(options, "server.host", uri->server);
+    qdict_put_str(options, "server.host", uri_host);
 
-    port_str = g_strdup_printf("%d", uri->port ?: 22);
+    port = g_uri_get_port(uri);
+    port_str = g_strdup_printf("%d", port != -1 ? port : 22);
     qdict_put_str(options, "server.port", port_str);
     g_free(port_str);
 
-    qdict_put_str(options, "path", uri->path);
-
-    /* Pick out any query parameters that we understand, and ignore
-     * the rest.
-     */
-    for (i = 0; i < qp->n; ++i) {
-        if (strcmp(qp->p[i].name, "host_key_check") == 0) {
-            qdict_put_str(options, "host_key_check", qp->p[i].value);
+    qdict_put_str(options, "path", uri_path);
+
+    uri_query = g_uri_get_query(uri);
+    if (uri_query) {
+        g_uri_params_iter_init(&qp, uri_query, -1, "&", G_URI_PARAMS_NONE);
+        while (g_uri_params_iter_next(&qp, &qp_name, &qp_value, &gerror)) {
+            if (!qp_name || !qp_value || gerror) {
+                warn_report("Failed to parse SSH URI parameters '%s'.",
+                            uri_query);
+                break;
+            }
+            /*
+             * Pick out the query parameters that we understand, and ignore
+             * (or rather warn about) the rest.
+             */
+            if (g_str_equal(qp_name, "host_key_check")) {
+                qdict_put_str(options, "host_key_check", qp_value);
+            } else {
+                warn_report("Unsupported parameter '%s' in URI.", qp_name);
+            }
         }
     }
 
-    query_params_free(qp);
-    uri_free(uri);
+    g_uri_unref(uri);
     return 0;
 
  err:
-    uri_free(uri);
+    g_uri_unref(uri);
     return -EINVAL;
 }
 
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH for-9.1 9/9] util/uri: Remove the old URI parsing code
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (7 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 8/9] block/ssh: " Thomas Huth
@ 2024-03-28 14:06 ` Thomas Huth
  2024-04-15 14:16 ` MAINTAINERS tweak [was: [PATCH for-9.1 0/9] Switch to glib URI parsing code] Eric Blake
  9 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 14:06 UTC (permalink / raw)
  To: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel
  Cc: Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

Now that we switched all consumers of the URI code to use the URI
parsing functions from glib instead, we can remove our internal
URI parsing code since it is not used anymore.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 include/qemu/uri.h |   99 ---
 util/uri.c         | 1466 --------------------------------------------
 util/meson.build   |    2 +-
 3 files changed, 1 insertion(+), 1566 deletions(-)
 delete mode 100644 include/qemu/uri.h
 delete mode 100644 util/uri.c

diff --git a/include/qemu/uri.h b/include/qemu/uri.h
deleted file mode 100644
index 255e61f452..0000000000
--- a/include/qemu/uri.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Summary: library of generic URI related routines
- * Description: library of generic URI related routines
- *              Implements RFC 2396
- *
- * Copyright (C) 1998-2003 Daniel Veillard.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * DANIEL VEILLARD 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.
- *
- * Except as contained in this notice, the name of Daniel Veillard shall not
- * be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from him.
- *
- * Author: Daniel Veillard
- **
- * Copyright (C) 2007 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 <https://www.gnu.org/licenses/>.
- *
- * Authors:
- *    Richard W.M. Jones <rjones@redhat.com>
- *
- * Utility functions to help parse and assemble query strings.
- */
-
-#ifndef QEMU_URI_H
-#define QEMU_URI_H
-
-/**
- * URI:
- *
- * A parsed URI reference. This is a struct containing the various fields
- * as described in RFC 2396 but separated for further processing.
- */
-typedef struct URI {
-    char *scheme;      /* the URI scheme */
-    char *opaque;      /* opaque part */
-    char *authority;   /* the authority part */
-    char *server;      /* the server part */
-    char *user;        /* the user part */
-    int port;          /* the port number */
-    char *path;        /* the path string */
-    char *fragment;    /* the fragment identifier */
-    int cleanup;       /* parsing potentially unclean URI */
-    char *query;       /* the query string (as it appears in the URI) */
-} URI;
-
-URI *uri_new(void);
-URI *uri_parse(const char *str);
-URI *uri_parse_raw(const char *str, int raw);
-int uri_parse_into(URI *uri, const char *str);
-char *uri_to_string(URI *uri);
-void uri_free(URI *uri);
-
-/* Single web service query parameter 'name=value'. */
-typedef struct QueryParam {
-  char *name;          /* Name (unescaped). */
-  char *value;         /* Value (unescaped). */
-  int ignore;          /* Ignore this field in qparam_get_query */
-} QueryParam;
-
-/* Set of parameters. */
-typedef struct QueryParams {
-  int n;               /* number of parameters used */
-  int alloc;           /* allocated space */
-  QueryParam *p;       /* array of parameters */
-} QueryParams;
-
-QueryParams *query_params_new(int init_alloc);
-QueryParams *query_params_parse(const char *query);
-void query_params_free(QueryParams *ps);
-
-#endif /* QEMU_URI_H */
diff --git a/util/uri.c b/util/uri.c
deleted file mode 100644
index 573174bf47..0000000000
--- a/util/uri.c
+++ /dev/null
@@ -1,1466 +0,0 @@
-/**
- * uri.c: set of generic URI related routines
- *
- * Reference: RFCs 3986, 2732 and 2373
- *
- * Copyright (C) 1998-2003 Daniel Veillard.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * DANIEL VEILLARD 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.
- *
- * Except as contained in this notice, the name of Daniel Veillard shall not
- * be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization from him.
- *
- * daniel@veillard.com
- *
- **
- *
- * Copyright (C) 2007, 2009-2010 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 <https://www.gnu.org/licenses/>.
- *
- * Authors:
- *    Richard W.M. Jones <rjones@redhat.com>
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/cutils.h"
-
-#include "qemu/uri.h"
-
-static void uri_clean(URI *uri);
-
-/*
- * Old rule from 2396 used in legacy handling code
- * alpha    = lowalpha | upalpha
- */
-#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
-
-/*
- * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
- *            "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
- *            "u" | "v" | "w" | "x" | "y" | "z"
- */
-
-#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
-
-/*
- * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
- *           "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
- *           "U" | "V" | "W" | "X" | "Y" | "Z"
- */
-#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
-
-#ifdef IS_DIGIT
-#undef IS_DIGIT
-#endif
-/*
- * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
- */
-#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
-
-/*
- * alphanum = alpha | digit
- */
-
-#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
-
-/*
- * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
- */
-
-#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') ||            \
-    ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') ||           \
-    ((x) == '(') || ((x) == ')'))
-
-/*
- * unwise = "{" | "}" | "|" | "\" | "^" | "`"
- */
-
-#define IS_UNWISE(p)                                                           \
-    (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) ||                  \
-     ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) ||                 \
-     ((*(p) == ']')) || ((*(p) == '`')))
-/*
- * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
- *            "[" | "]"
- */
-
-#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') ||        \
-    ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') ||            \
-    ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') ||            \
-    ((x) == ']'))
-
-/*
- * unreserved = alphanum | mark
- */
-
-#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
-
-/*
- * Skip to next pointer char, handle escaped sequences
- */
-
-#define NEXT(p) ((*p == '%') ? p += 3 : p++)
-
-/*
- * Productions from the spec.
- *
- *    authority     = server | reg_name
- *    reg_name      = 1*( unreserved | escaped | "$" | "," |
- *                        ";" | ":" | "@" | "&" | "=" | "+" )
- *
- * path          = [ abs_path | opaque_part ]
- */
-
-/************************************************************************
- *                                                                      *
- *                         RFC 3986 parser                              *
- *                                                                      *
- ************************************************************************/
-
-#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9'))
-#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) ||                      \
-                      ((*(p) >= 'A') && (*(p) <= 'Z')))
-#define ISA_HEXDIG(p)                                                          \
-    (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) ||                       \
-     ((*(p) >= 'A') && (*(p) <= 'F')))
-
-/*
- *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
- *                     / "*" / "+" / "," / ";" / "="
- */
-#define ISA_SUB_DELIM(p)                                                       \
-    (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) ||                  \
-     ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) ||                  \
-     ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) ||                  \
-     ((*(p) == '=')) || ((*(p) == '\'')))
-
-/*
- *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
- */
-#define ISA_UNRESERVED(p)                                                      \
-    ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) ||                    \
-     ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
-
-/*
- *    pct-encoded   = "%" HEXDIG HEXDIG
- */
-#define ISA_PCT_ENCODED(p)                                                     \
-    ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2)))
-
-/*
- *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
- */
-#define ISA_PCHAR(p)                                                           \
-    (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||            \
-     ((*(p) == ':')) || ((*(p) == '@')))
-
-/**
- * rfc3986_parse_scheme:
- * @uri:  pointer to an URI structure
- * @str:  pointer to the string to analyze
- *
- * Parse an URI scheme
- *
- * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_scheme(URI *uri, const char **str)
-{
-    const char *cur;
-
-    if (str == NULL) {
-        return -1;
-    }
-
-    cur = *str;
-    if (!ISA_ALPHA(cur)) {
-        return 2;
-    }
-    cur++;
-    while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || (*cur == '+') || (*cur == '-') ||
-           (*cur == '.')) {
-        cur++;
-    }
-    if (uri != NULL) {
-        g_free(uri->scheme);
-        uri->scheme = g_strndup(*str, cur - *str);
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_fragment:
- * @uri:  pointer to an URI structure
- * @str:  pointer to the string to analyze
- *
- * Parse the query part of an URI
- *
- * fragment      = *( pchar / "/" / "?" )
- * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']'
- *       in the fragment identifier but this is used very broadly for
- *       xpointer scheme selection, so we are allowing it here to not break
- *       for example all the DocBook processing chains.
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_fragment(URI *uri, const char **str)
-{
-    const char *cur;
-
-    if (str == NULL) {
-        return -1;
-    }
-
-    cur = *str;
-
-    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
-           (*cur == '[') || (*cur == ']') ||
-           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) {
-        NEXT(cur);
-    }
-    if (uri != NULL) {
-        g_free(uri->fragment);
-        if (uri->cleanup & 2) {
-            uri->fragment = g_strndup(*str, cur - *str);
-        } else {
-            uri->fragment = g_uri_unescape_segment(*str, cur, NULL);
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_query:
- * @uri:  pointer to an URI structure
- * @str:  pointer to the string to analyze
- *
- * Parse the query part of an URI
- *
- * query = *uric
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_query(URI *uri, const char **str)
-{
-    const char *cur;
-
-    if (str == NULL) {
-        return -1;
-    }
-
-    cur = *str;
-
-    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
-           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) {
-        NEXT(cur);
-    }
-    if (uri != NULL) {
-        g_free(uri->query);
-        uri->query = g_strndup(*str, cur - *str);
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_port:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse a port  part and fills in the appropriate fields
- * of the @uri structure
- *
- * port          = *DIGIT
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_port(URI *uri, const char **str)
-{
-    const char *cur = *str;
-    int port = 0;
-
-    if (ISA_DIGIT(cur)) {
-        while (ISA_DIGIT(cur)) {
-            port = port * 10 + (*cur - '0');
-            if (port > 65535) {
-                return 1;
-            }
-            cur++;
-        }
-        if (uri) {
-            uri->port = port;
-        }
-        *str = cur;
-        return 0;
-    }
-    return 1;
-}
-
-/**
- * rfc3986_parse_user_info:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse a user information part and fill in the appropriate fields
- * of the @uri structure
- *
- * userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_user_info(URI *uri, const char **str)
-{
-    const char *cur;
-
-    cur = *str;
-    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur) ||
-           (*cur == ':')) {
-        NEXT(cur);
-    }
-    if (*cur == '@') {
-        if (uri != NULL) {
-            g_free(uri->user);
-            if (uri->cleanup & 2) {
-                uri->user = g_strndup(*str, cur - *str);
-            } else {
-                uri->user = g_uri_unescape_segment(*str, cur, NULL);
-            }
-        }
-        *str = cur;
-        return 0;
-    }
-    return 1;
-}
-
-/**
- * rfc3986_parse_dec_octet:
- * @str:  the string to analyze
- *
- *    dec-octet     = DIGIT                 ; 0-9
- *                  / %x31-39 DIGIT         ; 10-99
- *                  / "1" 2DIGIT            ; 100-199
- *                  / "2" %x30-34 DIGIT     ; 200-249
- *                  / "25" %x30-35          ; 250-255
- *
- * Skip a dec-octet.
- *
- * Returns 0 if found and skipped, 1 otherwise
- */
-static int rfc3986_parse_dec_octet(const char **str)
-{
-    const char *cur = *str;
-
-    if (!(ISA_DIGIT(cur))) {
-        return 1;
-    }
-    if (!ISA_DIGIT(cur + 1)) {
-        cur++;
-    } else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur + 2))) {
-        cur += 2;
-    } else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2))) {
-        cur += 3;
-    } else if ((*cur == '2') && (*(cur + 1) >= '0') && (*(cur + 1) <= '4') &&
-             (ISA_DIGIT(cur + 2))) {
-        cur += 3;
-    } else if ((*cur == '2') && (*(cur + 1) == '5') && (*(cur + 2) >= '0') &&
-             (*(cur + 1) <= '5')) {
-        cur += 3;
-    } else {
-        return 1;
-    }
-    *str = cur;
-    return 0;
-}
-/**
- * rfc3986_parse_host:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an host part and fills in the appropriate fields
- * of the @uri structure
- *
- * host          = IP-literal / IPv4address / reg-name
- * IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
- * IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
- * reg-name      = *( unreserved / pct-encoded / sub-delims )
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_host(URI *uri, const char **str)
-{
-    const char *cur = *str;
-    const char *host;
-
-    host = cur;
-    /*
-     * IPv6 and future addressing scheme are enclosed between brackets
-     */
-    if (*cur == '[') {
-        cur++;
-        while ((*cur != ']') && (*cur != 0)) {
-            cur++;
-        }
-        if (*cur != ']') {
-            return 1;
-        }
-        cur++;
-        goto found;
-    }
-    /*
-     * try to parse an IPv4
-     */
-    if (ISA_DIGIT(cur)) {
-        if (rfc3986_parse_dec_octet(&cur) != 0) {
-            goto not_ipv4;
-        }
-        if (*cur != '.') {
-            goto not_ipv4;
-        }
-        cur++;
-        if (rfc3986_parse_dec_octet(&cur) != 0) {
-            goto not_ipv4;
-        }
-        if (*cur != '.') {
-            goto not_ipv4;
-        }
-        if (rfc3986_parse_dec_octet(&cur) != 0) {
-            goto not_ipv4;
-        }
-        if (*cur != '.') {
-            goto not_ipv4;
-        }
-        if (rfc3986_parse_dec_octet(&cur) != 0) {
-            goto not_ipv4;
-        }
-        goto found;
-    not_ipv4:
-        cur = *str;
-    }
-    /*
-     * then this should be a hostname which can be empty
-     */
-    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) {
-        NEXT(cur);
-    }
-found:
-    if (uri != NULL) {
-        g_free(uri->authority);
-        uri->authority = NULL;
-        g_free(uri->server);
-        if (cur != host) {
-            if (uri->cleanup & 2) {
-                uri->server = g_strndup(host, cur - host);
-            } else {
-                uri->server = g_uri_unescape_segment(host, cur, NULL);
-            }
-        } else {
-            uri->server = NULL;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_authority:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an authority part and fills in the appropriate fields
- * of the @uri structure
- *
- * authority     = [ userinfo "@" ] host [ ":" port ]
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_authority(URI *uri, const char **str)
-{
-    const char *cur;
-    int ret;
-
-    cur = *str;
-    /*
-     * try to parse a userinfo and check for the trailing @
-     */
-    ret = rfc3986_parse_user_info(uri, &cur);
-    if ((ret != 0) || (*cur != '@')) {
-        cur = *str;
-    } else {
-        cur++;
-    }
-    ret = rfc3986_parse_host(uri, &cur);
-    if (ret != 0) {
-        return ret;
-    }
-    if (*cur == ':') {
-        cur++;
-        ret = rfc3986_parse_port(uri, &cur);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_segment:
- * @str:  the string to analyze
- * @forbid: an optional forbidden character
- * @empty: allow an empty segment
- *
- * Parse a segment and fills in the appropriate fields
- * of the @uri structure
- *
- * segment       = *pchar
- * segment-nz    = 1*pchar
- * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
- *               ; non-zero-length segment without any colon ":"
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_segment(const char **str, char forbid, int empty)
-{
-    const char *cur;
-
-    cur = *str;
-    if (!ISA_PCHAR(cur)) {
-        if (empty) {
-            return 0;
-        }
-        return 1;
-    }
-    while (ISA_PCHAR(cur) && (*cur != forbid)) {
-        NEXT(cur);
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_path_ab_empty:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an path absolute or empty and fills in the appropriate fields
- * of the @uri structure
- *
- * path-abempty  = *( "/" segment )
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_path_ab_empty(URI *uri, const char **str)
-{
-    const char *cur;
-    int ret;
-
-    cur = *str;
-
-    while (*cur == '/') {
-        cur++;
-        ret = rfc3986_parse_segment(&cur, 0, 1);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (uri != NULL) {
-        g_free(uri->path);
-        if (*str != cur) {
-            if (uri->cleanup & 2) {
-                uri->path = g_strndup(*str, cur - *str);
-            } else {
-                uri->path = g_uri_unescape_segment(*str, cur, NULL);
-            }
-        } else {
-            uri->path = NULL;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_path_absolute:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an path absolute and fills in the appropriate fields
- * of the @uri structure
- *
- * path-absolute = "/" [ segment-nz *( "/" segment ) ]
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_path_absolute(URI *uri, const char **str)
-{
-    const char *cur;
-    int ret;
-
-    cur = *str;
-
-    if (*cur != '/') {
-        return 1;
-    }
-    cur++;
-    ret = rfc3986_parse_segment(&cur, 0, 0);
-    if (ret == 0) {
-        while (*cur == '/') {
-            cur++;
-            ret = rfc3986_parse_segment(&cur, 0, 1);
-            if (ret != 0) {
-                return ret;
-            }
-        }
-    }
-    if (uri != NULL) {
-        g_free(uri->path);
-        if (cur != *str) {
-            if (uri->cleanup & 2) {
-                uri->path = g_strndup(*str, cur - *str);
-            } else {
-                uri->path = g_uri_unescape_segment(*str, cur, NULL);
-            }
-        } else {
-            uri->path = NULL;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_path_rootless:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an path without root and fills in the appropriate fields
- * of the @uri structure
- *
- * path-rootless = segment-nz *( "/" segment )
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_path_rootless(URI *uri, const char **str)
-{
-    const char *cur;
-    int ret;
-
-    cur = *str;
-
-    ret = rfc3986_parse_segment(&cur, 0, 0);
-    if (ret != 0) {
-        return ret;
-    }
-    while (*cur == '/') {
-        cur++;
-        ret = rfc3986_parse_segment(&cur, 0, 1);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (uri != NULL) {
-        g_free(uri->path);
-        if (cur != *str) {
-            if (uri->cleanup & 2) {
-                uri->path = g_strndup(*str, cur - *str);
-            } else {
-                uri->path = g_uri_unescape_segment(*str, cur, NULL);
-            }
-        } else {
-            uri->path = NULL;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_path_no_scheme:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an path which is not a scheme and fills in the appropriate fields
- * of the @uri structure
- *
- * path-noscheme = segment-nz-nc *( "/" segment )
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_path_no_scheme(URI *uri, const char **str)
-{
-    const char *cur;
-    int ret;
-
-    cur = *str;
-
-    ret = rfc3986_parse_segment(&cur, ':', 0);
-    if (ret != 0) {
-        return ret;
-    }
-    while (*cur == '/') {
-        cur++;
-        ret = rfc3986_parse_segment(&cur, 0, 1);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (uri != NULL) {
-        g_free(uri->path);
-        if (cur != *str) {
-            if (uri->cleanup & 2) {
-                uri->path = g_strndup(*str, cur - *str);
-            } else {
-                uri->path = g_uri_unescape_segment(*str, cur, NULL);
-            }
-        } else {
-            uri->path = NULL;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_hier_part:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an hierarchical part and fills in the appropriate fields
- * of the @uri structure
- *
- * hier-part     = "//" authority path-abempty
- *                / path-absolute
- *                / path-rootless
- *                / path-empty
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_hier_part(URI *uri, const char **str)
-{
-    const char *cur;
-    int ret;
-
-    cur = *str;
-
-    if ((*cur == '/') && (*(cur + 1) == '/')) {
-        cur += 2;
-        ret = rfc3986_parse_authority(uri, &cur);
-        if (ret != 0) {
-            return ret;
-        }
-        ret = rfc3986_parse_path_ab_empty(uri, &cur);
-        if (ret != 0) {
-            return ret;
-        }
-        *str = cur;
-        return 0;
-    } else if (*cur == '/') {
-        ret = rfc3986_parse_path_absolute(uri, &cur);
-        if (ret != 0) {
-            return ret;
-        }
-    } else if (ISA_PCHAR(cur)) {
-        ret = rfc3986_parse_path_rootless(uri, &cur);
-        if (ret != 0) {
-            return ret;
-        }
-    } else {
-        /* path-empty is effectively empty */
-        if (uri != NULL) {
-            g_free(uri->path);
-            uri->path = NULL;
-        }
-    }
-    *str = cur;
-    return 0;
-}
-
-/**
- * rfc3986_parse_relative_ref:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an URI string and fills in the appropriate fields
- * of the @uri structure
- *
- * relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
- * relative-part = "//" authority path-abempty
- *               / path-absolute
- *               / path-noscheme
- *               / path-empty
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_relative_ref(URI *uri, const char *str)
-{
-    int ret;
-
-    if ((*str == '/') && (*(str + 1) == '/')) {
-        str += 2;
-        ret = rfc3986_parse_authority(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-        ret = rfc3986_parse_path_ab_empty(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    } else if (*str == '/') {
-        ret = rfc3986_parse_path_absolute(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    } else if (ISA_PCHAR(str)) {
-        ret = rfc3986_parse_path_no_scheme(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    } else {
-        /* path-empty is effectively empty */
-        if (uri != NULL) {
-            g_free(uri->path);
-            uri->path = NULL;
-        }
-    }
-
-    if (*str == '?') {
-        str++;
-        ret = rfc3986_parse_query(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (*str == '#') {
-        str++;
-        ret = rfc3986_parse_fragment(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (*str != 0) {
-        uri_clean(uri);
-        return 1;
-    }
-    return 0;
-}
-
-/**
- * rfc3986_parse:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an URI string and fills in the appropriate fields
- * of the @uri structure
- *
- * scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse(URI *uri, const char *str)
-{
-    int ret;
-
-    ret = rfc3986_parse_scheme(uri, &str);
-    if (ret != 0) {
-        return ret;
-    }
-    if (*str != ':') {
-        return 1;
-    }
-    str++;
-    ret = rfc3986_parse_hier_part(uri, &str);
-    if (ret != 0) {
-        return ret;
-    }
-    if (*str == '?') {
-        str++;
-        ret = rfc3986_parse_query(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (*str == '#') {
-        str++;
-        ret = rfc3986_parse_fragment(uri, &str);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-    if (*str != 0) {
-        uri_clean(uri);
-        return 1;
-    }
-    return 0;
-}
-
-/**
- * rfc3986_parse_uri_reference:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an URI reference string and fills in the appropriate fields
- * of the @uri structure
- *
- * URI-reference = URI / relative-ref
- *
- * Returns 0 or the error code
- */
-static int rfc3986_parse_uri_reference(URI *uri, const char *str)
-{
-    int ret;
-
-    if (str == NULL) {
-        return -1;
-    }
-    uri_clean(uri);
-
-    /*
-     * Try first to parse absolute refs, then fallback to relative if
-     * it fails.
-     */
-    ret = rfc3986_parse(uri, str);
-    if (ret != 0) {
-        uri_clean(uri);
-        ret = rfc3986_parse_relative_ref(uri, str);
-        if (ret != 0) {
-            uri_clean(uri);
-            return ret;
-        }
-    }
-    return 0;
-}
-
-/**
- * uri_parse:
- * @str:  the URI string to analyze
- *
- * Parse an URI based on RFC 3986
- *
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- *
- * Returns a newly built URI or NULL in case of error
- */
-URI *uri_parse(const char *str)
-{
-    URI *uri;
-    int ret;
-
-    if (str == NULL) {
-        return NULL;
-    }
-    uri = uri_new();
-    ret = rfc3986_parse_uri_reference(uri, str);
-    if (ret) {
-        uri_free(uri);
-        return NULL;
-    }
-    return uri;
-}
-
-/**
- * uri_parse_into:
- * @uri:  pointer to an URI structure
- * @str:  the string to analyze
- *
- * Parse an URI reference string based on RFC 3986 and fills in the
- * appropriate fields of the @uri structure
- *
- * URI-reference = URI / relative-ref
- *
- * Returns 0 or the error code
- */
-int uri_parse_into(URI *uri, const char *str)
-{
-    return rfc3986_parse_uri_reference(uri, str);
-}
-
-/**
- * uri_parse_raw:
- * @str:  the URI string to analyze
- * @raw:  if 1 unescaping of URI pieces are disabled
- *
- * Parse an URI but allows to keep intact the original fragments.
- *
- * URI-reference = URI / relative-ref
- *
- * Returns a newly built URI or NULL in case of error
- */
-URI *uri_parse_raw(const char *str, int raw)
-{
-    URI *uri;
-    int ret;
-
-    if (str == NULL) {
-        return NULL;
-    }
-    uri = uri_new();
-    if (raw) {
-        uri->cleanup |= 2;
-    }
-    ret = uri_parse_into(uri, str);
-    if (ret) {
-        uri_free(uri);
-        return NULL;
-    }
-    return uri;
-}
-
-/************************************************************************
- *                                                                      *
- *                    Generic URI structure functions                   *
- *                                                                      *
- ************************************************************************/
-
-/**
- * uri_new:
- *
- * Simply creates an empty URI
- *
- * Returns the new structure or NULL in case of error
- */
-URI *uri_new(void)
-{
-    return g_new0(URI, 1);
-}
-
-/**
- * realloc2n:
- *
- * Function to handle properly a reallocation when saving an URI
- * Also imposes some limit on the length of an URI string output
- */
-static char *realloc2n(char *ret, int *max)
-{
-    char *temp;
-    int tmp;
-
-    tmp = *max * 2;
-    temp = g_realloc(ret, (tmp + 1));
-    *max = tmp;
-    return temp;
-}
-
-/**
- * uri_to_string:
- * @uri:  pointer to an URI
- *
- * Save the URI as an escaped string
- *
- * Returns a new string (to be deallocated by caller)
- */
-char *uri_to_string(URI *uri)
-{
-    char *ret = NULL;
-    char *temp;
-    const char *p;
-    int len;
-    int max;
-
-    if (uri == NULL) {
-        return NULL;
-    }
-
-    max = 80;
-    ret = g_malloc(max + 1);
-    len = 0;
-
-    if (uri->scheme != NULL) {
-        p = uri->scheme;
-        while (*p != 0) {
-            if (len >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            ret[len++] = *p++;
-        }
-        if (len >= max) {
-            temp = realloc2n(ret, &max);
-            ret = temp;
-        }
-        ret[len++] = ':';
-    }
-    if (uri->opaque != NULL) {
-        p = uri->opaque;
-        while (*p != 0) {
-            if (len + 3 >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) {
-                ret[len++] = *p++;
-            } else {
-                int val = *(unsigned char *)p++;
-                int hi = val / 0x10, lo = val % 0x10;
-                ret[len++] = '%';
-                ret[len++] = hi + (hi > 9 ? 'A' - 10 : '0');
-                ret[len++] = lo + (lo > 9 ? 'A' - 10 : '0');
-            }
-        }
-    } else {
-        if (uri->server != NULL) {
-            if (len + 3 >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            ret[len++] = '/';
-            ret[len++] = '/';
-            if (uri->user != NULL) {
-                p = uri->user;
-                while (*p != 0) {
-                    if (len + 3 >= max) {
-                        temp = realloc2n(ret, &max);
-                        ret = temp;
-                    }
-                    if ((IS_UNRESERVED(*(p))) || ((*(p) == ';')) ||
-                        ((*(p) == ':')) || ((*(p) == '&')) || ((*(p) == '=')) ||
-                        ((*(p) == '+')) || ((*(p) == '$')) || ((*(p) == ','))) {
-                        ret[len++] = *p++;
-                    } else {
-                        int val = *(unsigned char *)p++;
-                        int hi = val / 0x10, lo = val % 0x10;
-                        ret[len++] = '%';
-                        ret[len++] = hi + (hi > 9 ? 'A' - 10 : '0');
-                        ret[len++] = lo + (lo > 9 ? 'A' - 10 : '0');
-                    }
-                }
-                if (len + 3 >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                ret[len++] = '@';
-            }
-            p = uri->server;
-            while (*p != 0) {
-                if (len >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                ret[len++] = *p++;
-            }
-            if (uri->port > 0) {
-                if (len + 10 >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                len += snprintf(&ret[len], max - len, ":%d", uri->port);
-            }
-        } else if (uri->authority != NULL) {
-            if (len + 3 >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            ret[len++] = '/';
-            ret[len++] = '/';
-            p = uri->authority;
-            while (*p != 0) {
-                if (len + 3 >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                if ((IS_UNRESERVED(*(p))) || ((*(p) == '$')) ||
-                    ((*(p) == ',')) || ((*(p) == ';')) || ((*(p) == ':')) ||
-                    ((*(p) == '@')) || ((*(p) == '&')) || ((*(p) == '=')) ||
-                    ((*(p) == '+'))) {
-                    ret[len++] = *p++;
-                } else {
-                    int val = *(unsigned char *)p++;
-                    int hi = val / 0x10, lo = val % 0x10;
-                    ret[len++] = '%';
-                    ret[len++] = hi + (hi > 9 ? 'A' - 10 : '0');
-                    ret[len++] = lo + (lo > 9 ? 'A' - 10 : '0');
-                }
-            }
-        } else if (uri->scheme != NULL) {
-            if (len + 3 >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            ret[len++] = '/';
-            ret[len++] = '/';
-        }
-        if (uri->path != NULL) {
-            p = uri->path;
-            /*
-             * the colon in file:///d: should not be escaped or
-             * Windows accesses fail later.
-             */
-            if ((uri->scheme != NULL) && (p[0] == '/') &&
-                (((p[1] >= 'a') && (p[1] <= 'z')) ||
-                 ((p[1] >= 'A') && (p[1] <= 'Z'))) &&
-                (p[2] == ':') && (!strcmp(uri->scheme, "file"))) {
-                if (len + 3 >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                ret[len++] = *p++;
-                ret[len++] = *p++;
-                ret[len++] = *p++;
-            }
-            while (*p != 0) {
-                if (len + 3 >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
-                    ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
-                    ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
-                    ((*(p) == ','))) {
-                    ret[len++] = *p++;
-                } else {
-                    int val = *(unsigned char *)p++;
-                    int hi = val / 0x10, lo = val % 0x10;
-                    ret[len++] = '%';
-                    ret[len++] = hi + (hi > 9 ? 'A' - 10 : '0');
-                    ret[len++] = lo + (lo > 9 ? 'A' - 10 : '0');
-                }
-            }
-        }
-        if (uri->query != NULL) {
-            if (len + 1 >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            ret[len++] = '?';
-            p = uri->query;
-            while (*p != 0) {
-                if (len + 1 >= max) {
-                    temp = realloc2n(ret, &max);
-                    ret = temp;
-                }
-                ret[len++] = *p++;
-            }
-        }
-    }
-    if (uri->fragment != NULL) {
-        if (len + 3 >= max) {
-            temp = realloc2n(ret, &max);
-            ret = temp;
-        }
-        ret[len++] = '#';
-        p = uri->fragment;
-        while (*p != 0) {
-            if (len + 3 >= max) {
-                temp = realloc2n(ret, &max);
-                ret = temp;
-            }
-            if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) {
-                ret[len++] = *p++;
-            } else {
-                int val = *(unsigned char *)p++;
-                int hi = val / 0x10, lo = val % 0x10;
-                ret[len++] = '%';
-                ret[len++] = hi + (hi > 9 ? 'A' - 10 : '0');
-                ret[len++] = lo + (lo > 9 ? 'A' - 10 : '0');
-            }
-        }
-    }
-    if (len >= max) {
-        temp = realloc2n(ret, &max);
-        ret = temp;
-    }
-    ret[len] = 0;
-    return ret;
-}
-
-/**
- * uri_clean:
- * @uri:  pointer to an URI
- *
- * Make sure the URI struct is free of content
- */
-static void uri_clean(URI *uri)
-{
-    if (uri == NULL) {
-        return;
-    }
-
-    g_free(uri->scheme);
-    uri->scheme = NULL;
-    g_free(uri->server);
-    uri->server = NULL;
-    g_free(uri->user);
-    uri->user = NULL;
-    g_free(uri->path);
-    uri->path = NULL;
-    g_free(uri->fragment);
-    uri->fragment = NULL;
-    g_free(uri->opaque);
-    uri->opaque = NULL;
-    g_free(uri->authority);
-    uri->authority = NULL;
-    g_free(uri->query);
-    uri->query = NULL;
-}
-
-/**
- * uri_free:
- * @uri:  pointer to an URI, NULL is ignored
- *
- * Free up the URI struct
- */
-void uri_free(URI *uri)
-{
-    uri_clean(uri);
-    g_free(uri);
-}
-
-/************************************************************************
- *                                                                      *
- *                           Public functions                           *
- *                                                                      *
- ************************************************************************/
-
-/*
- * Utility functions to help parse and assemble query strings.
- */
-
-struct QueryParams *query_params_new(int init_alloc)
-{
-    struct QueryParams *ps;
-
-    if (init_alloc <= 0) {
-        init_alloc = 1;
-    }
-
-    ps = g_new(QueryParams, 1);
-    ps->n = 0;
-    ps->alloc = init_alloc;
-    ps->p = g_new(QueryParam, ps->alloc);
-
-    return ps;
-}
-
-/* Ensure there is space to store at least one more parameter
- * at the end of the set.
- */
-static int query_params_append(struct QueryParams *ps, const char *name,
-                               const char *value)
-{
-    if (ps->n >= ps->alloc) {
-        ps->p = g_renew(QueryParam, ps->p, ps->alloc * 2);
-        ps->alloc *= 2;
-    }
-
-    ps->p[ps->n].name = g_strdup(name);
-    ps->p[ps->n].value = g_strdup(value);
-    ps->p[ps->n].ignore = 0;
-    ps->n++;
-
-    return 0;
-}
-
-void query_params_free(struct QueryParams *ps)
-{
-    int i;
-
-    for (i = 0; i < ps->n; ++i) {
-        g_free(ps->p[i].name);
-        g_free(ps->p[i].value);
-    }
-    g_free(ps->p);
-    g_free(ps);
-}
-
-struct QueryParams *query_params_parse(const char *query)
-{
-    struct QueryParams *ps;
-    const char *end, *eq;
-
-    ps = query_params_new(0);
-    if (!query || query[0] == '\0') {
-        return ps;
-    }
-
-    while (*query) {
-        char *name = NULL, *value = NULL;
-
-        /* Find the next separator, or end of the string. */
-        end = strchr(query, '&');
-        if (!end) {
-            end = qemu_strchrnul(query, ';');
-        }
-
-        /* Find the first '=' character between here and end. */
-        eq = strchr(query, '=');
-        if (eq && eq >= end) {
-            eq = NULL;
-        }
-
-        /* Empty section (eg. "&&"). */
-        if (end == query) {
-            goto next;
-        }
-
-        /* If there is no '=' character, then we have just "name"
-         * and consistent with CGI.pm we assume value is "".
-         */
-        else if (!eq) {
-            name = g_uri_unescape_segment(query, end, NULL);
-            value = NULL;
-        }
-        /* Or if we have "name=" here (works around annoying
-         * problem when calling uri_string_unescape with len = 0).
-         */
-        else if (eq + 1 == end) {
-            name = g_uri_unescape_segment(query, eq, NULL);
-            value = g_new0(char, 1);
-        }
-        /* If the '=' character is at the beginning then we have
-         * "=value" and consistent with CGI.pm we _ignore_ this.
-         */
-        else if (query == eq) {
-            goto next;
-        }
-
-        /* Otherwise it's "name=value". */
-        else {
-            name = g_uri_unescape_segment(query, eq, NULL);
-            value = g_uri_unescape_segment(eq + 1, end, NULL);
-        }
-
-        /* Append to the parameter set. */
-        query_params_append(ps, name, value);
-        g_free(name);
-        g_free(value);
-
-    next:
-        query = end;
-        if (*query) {
-            query++; /* skip '&' separator */
-        }
-    }
-
-    return ps;
-}
diff --git a/util/meson.build b/util/meson.build
index 0ef9886be0..e6a2c9acc8 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -94,7 +94,7 @@ if have_block
   util_ss.add(files('hbitmap.c'))
   util_ss.add(files('hexdump.c'))
   util_ss.add(files('iova-tree.c'))
-  util_ss.add(files('iov.c', 'uri.c'))
+  util_ss.add(files('iov.c'))
   util_ss.add(files('nvdimm-utils.c'))
   util_ss.add(files('block-helpers.c'))
   util_ss.add(files('qemu-coroutine-sleep.c'))
-- 
2.44.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 14:06 ` [PATCH for-9.1 6/9] block/nbd: " Thomas Huth
@ 2024-03-28 14:13   ` Richard W.M. Jones
  2024-03-28 15:06     ` Eric Blake
  2024-03-28 14:54   ` Eric Blake
  1 sibling, 1 reply; 22+ messages in thread
From: Richard W.M. Jones @ 2024-03-28 14:13 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	qemu-devel, Kevin Wolf, Hanna Reitz, Paolo Bonzini,
	Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

On Thu, Mar 28, 2024 at 03:06:03PM +0100, Thomas Huth wrote:
> Since version 2.66, glib has useful URI parsing functions, too.
> Use those instead of the QEMU-internal ones to be finally able
> to get rid of the latter. The g_uri_get_host() also takes care
> of removing the square brackets from IPv6 addresses, so we can
> drop that part of the QEMU code now, too.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>  block/nbd.c | 66 ++++++++++++++++++++++++++++++-----------------------
>  1 file changed, 38 insertions(+), 28 deletions(-)
> 
> diff --git a/block/nbd.c b/block/nbd.c
> index ef05f7cdfd..95b507f872 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -31,7 +31,6 @@
>  #include "qemu/osdep.h"
>  
>  #include "trace.h"
> -#include "qemu/uri.h"
>  #include "qemu/option.h"
>  #include "qemu/cutils.h"
>  #include "qemu/main-loop.h"
> @@ -1514,30 +1513,34 @@ static void nbd_client_close(BlockDriverState *bs)
>  
>  static int nbd_parse_uri(const char *filename, QDict *options)
>  {
> -    URI *uri;
> +    GUri *uri;
>      const char *p;
> -    QueryParams *qp = NULL;
> +    GHashTable *qp = NULL;
> +    int qp_n;
>      int ret = 0;
>      bool is_unix;
> +    const char *uri_scheme, *uri_query, *uri_server;
> +    int uri_port;
>  
> -    uri = uri_parse(filename);
> +    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
>      if (!uri) {
>          return -EINVAL;
>      }
>  
>      /* transport */
> -    if (!g_strcmp0(uri->scheme, "nbd")) {
> +    uri_scheme = g_uri_get_scheme(uri);
> +    if (!g_strcmp0(uri_scheme, "nbd")) {
>          is_unix = false;
> -    } else if (!g_strcmp0(uri->scheme, "nbd+tcp")) {
> +    } else if (!g_strcmp0(uri_scheme, "nbd+tcp")) {
>          is_unix = false;
> -    } else if (!g_strcmp0(uri->scheme, "nbd+unix")) {
> +    } else if (!g_strcmp0(uri_scheme, "nbd+unix")) {
>          is_unix = true;
>      } else {
>          ret = -EINVAL;
>          goto out;
>      }
>  
> -    p = uri->path ? uri->path : "";
> +    p = g_uri_get_path(uri) ?: "";
>      if (p[0] == '/') {
>          p++;
>      }
> @@ -1545,51 +1548,58 @@ static int nbd_parse_uri(const char *filename, QDict *options)
>          qdict_put_str(options, "export", p);
>      }
>  
> -    qp = query_params_parse(uri->query);
> -    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
> -        ret = -EINVAL;
> -        goto out;
> +    uri_query = g_uri_get_query(uri);
> +    if (uri_query) {
> +        qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
> +        if (!qp) {
> +            ret = -EINVAL;
> +            goto out;
> +        }
> +        qp_n = g_hash_table_size(qp);
> +        if (qp_n > 1 || (is_unix && !qp_n) || (!is_unix && qp_n)) {
> +            ret = -EINVAL;
> +            goto out;
> +        }
> +     }
> +
> +    uri_server = g_uri_get_host(uri);
> +    if (uri_server && !uri_server[0]) {
> +        uri_server = NULL;
>      }
> +    uri_port = g_uri_get_port(uri);
>  
>      if (is_unix) {
>          /* nbd+unix:///export?socket=path */
> -        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
> +        const char *uri_socket = g_hash_table_lookup(qp, "socket");
> +        if (uri_server || uri_port != -1 || !uri_socket) {
>              ret = -EINVAL;
>              goto out;
>          }
>          qdict_put_str(options, "server.type", "unix");
> -        qdict_put_str(options, "server.path", qp->p[0].value);
> +        qdict_put_str(options, "server.path", uri_socket);
>      } else {
> -        QString *host;
>          char *port_str;
>  
>          /* nbd[+tcp]://host[:port]/export */
> -        if (!uri->server) {
> +        if (!uri_server) {
>              ret = -EINVAL;
>              goto out;
>          }
>  
> -        /* strip braces from literal IPv6 address */
> -        if (uri->server[0] == '[') {
> -            host = qstring_from_substr(uri->server, 1,
> -                                       strlen(uri->server) - 1);
> -        } else {
> -            host = qstring_from_str(uri->server);
> -        }
> -
>          qdict_put_str(options, "server.type", "inet");
> -        qdict_put(options, "server.host", host);
> +        qdict_put_str(options, "server.host", uri_server);
>  
> -        port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
> +        port_str = g_strdup_printf("%d", uri_port != -1 ? uri_port
> +                                                        : NBD_DEFAULT_PORT);
>          qdict_put_str(options, "server.port", port_str);
>          g_free(port_str);
>      }
>  
>  out:
>      if (qp) {
> -        query_params_free(qp);
> +        g_hash_table_destroy(qp);
>      }
> -    uri_free(uri);
> +    g_uri_unref(uri);
>      return ret;
>  }

Looks ok,

Reviewed-by: Richard W.M. Jones <rjones@redhat.com>

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 8/9] block/ssh: Use URI parsing code from glib
  2024-03-28 14:06 ` [PATCH for-9.1 8/9] block/ssh: " Thomas Huth
@ 2024-03-28 14:15   ` Richard W.M. Jones
  0 siblings, 0 replies; 22+ messages in thread
From: Richard W.M. Jones @ 2024-03-28 14:15 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	qemu-devel, Kevin Wolf, Hanna Reitz, Paolo Bonzini,
	Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

On Thu, Mar 28, 2024 at 03:06:05PM +0100, Thomas Huth wrote:
> Since version 2.66, glib has useful URI parsing functions, too.
> Use those instead of the QEMU-internal ones to be finally able
> to get rid of the latter.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>  block/ssh.c | 69 +++++++++++++++++++++++++++++++----------------------
>  1 file changed, 40 insertions(+), 29 deletions(-)
> 
> diff --git a/block/ssh.c b/block/ssh.c
> index 2748253d4a..c0caf59793 100644
> --- a/block/ssh.c
> +++ b/block/ssh.c
> @@ -37,7 +37,6 @@
>  #include "qemu/ctype.h"
>  #include "qemu/cutils.h"
>  #include "qemu/sockets.h"
> -#include "qemu/uri.h"
>  #include "qapi/qapi-visit-sockets.h"
>  #include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qmp/qdict.h"
> @@ -181,64 +180,76 @@ static void sftp_error_trace(BDRVSSHState *s, const char *op)
>  
>  static int parse_uri(const char *filename, QDict *options, Error **errp)
>  {
> -    URI *uri = NULL;
> -    QueryParams *qp;
> +    GUri *uri;
> +    const char *uri_host, *uri_path, *uri_user, *uri_query;
>      char *port_str;
> -    int i;
> +    int port;
> +    g_autoptr(GError) gerror = NULL;
> +    char *qp_name, *qp_value;
> +    GUriParamsIter qp;
>  
> -    uri = uri_parse(filename);
> +    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
>      if (!uri) {
>          return -EINVAL;
>      }
>  
> -    if (g_strcmp0(uri->scheme, "ssh") != 0) {
> +    if (g_strcmp0(g_uri_get_scheme(uri), "ssh") != 0) {
>          error_setg(errp, "URI scheme must be 'ssh'");
>          goto err;
>      }
>  
> -    if (!uri->server || strcmp(uri->server, "") == 0) {
> +    uri_host = g_uri_get_host(uri);
> +    if (!uri_host || g_str_equal(uri_host, "")) {
>          error_setg(errp, "missing hostname in URI");
>          goto err;
>      }
>  
> -    if (!uri->path || strcmp(uri->path, "") == 0) {
> +    uri_path = g_uri_get_path(uri);
> +    if (!uri_path || g_str_equal(uri_path, "")) {
>          error_setg(errp, "missing remote path in URI");
>          goto err;
>      }
>  
> -    qp = query_params_parse(uri->query);
> -    if (!qp) {
> -        error_setg(errp, "could not parse query parameters");
> -        goto err;
> -    }
> -
> -    if(uri->user && strcmp(uri->user, "") != 0) {
> -        qdict_put_str(options, "user", uri->user);
> +    uri_user = g_uri_get_user(uri);
> +    if (uri_user && !g_str_equal(uri_user, "")) {
> +        qdict_put_str(options, "user", uri_user);
>      }
>  
> -    qdict_put_str(options, "server.host", uri->server);
> +    qdict_put_str(options, "server.host", uri_host);
>  
> -    port_str = g_strdup_printf("%d", uri->port ?: 22);
> +    port = g_uri_get_port(uri);
> +    port_str = g_strdup_printf("%d", port != -1 ? port : 22);
>      qdict_put_str(options, "server.port", port_str);
>      g_free(port_str);
>  
> -    qdict_put_str(options, "path", uri->path);
> -
> -    /* Pick out any query parameters that we understand, and ignore
> -     * the rest.
> -     */
> -    for (i = 0; i < qp->n; ++i) {
> -        if (strcmp(qp->p[i].name, "host_key_check") == 0) {
> -            qdict_put_str(options, "host_key_check", qp->p[i].value);
> +    qdict_put_str(options, "path", uri_path);
> +
> +    uri_query = g_uri_get_query(uri);
> +    if (uri_query) {
> +        g_uri_params_iter_init(&qp, uri_query, -1, "&", G_URI_PARAMS_NONE);
> +        while (g_uri_params_iter_next(&qp, &qp_name, &qp_value, &gerror)) {
> +            if (!qp_name || !qp_value || gerror) {
> +                warn_report("Failed to parse SSH URI parameters '%s'.",
> +                            uri_query);
> +                break;
> +            }
> +            /*
> +             * Pick out the query parameters that we understand, and ignore
> +             * (or rather warn about) the rest.
> +             */
> +            if (g_str_equal(qp_name, "host_key_check")) {
> +                qdict_put_str(options, "host_key_check", qp_value);
> +            } else {
> +                warn_report("Unsupported parameter '%s' in URI.", qp_name);
> +            }
>          }
>      }
>  
> -    query_params_free(qp);
> -    uri_free(uri);
> +    g_uri_unref(uri);
>      return 0;
>  
>   err:
> -    uri_free(uri);
> +    g_uri_unref(uri);
>      return -EINVAL;
>  }

Seems reasonable too,

Reviewed-by: Richard W.M. Jones <rjones@redhat.com>


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 14:06 ` [PATCH for-9.1 6/9] block/nbd: " Thomas Huth
  2024-03-28 14:13   ` Richard W.M. Jones
@ 2024-03-28 14:54   ` Eric Blake
  2024-03-28 14:59     ` Daniel P. Berrangé
  1 sibling, 1 reply; 22+ messages in thread
From: Eric Blake @ 2024-03-28 14:54 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Vladimir Sementsov-Ogievskiy, Peter Lieven, Richard W.M. Jones,
	qemu-devel, Kevin Wolf, Hanna Reitz, Paolo Bonzini,
	Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

On Thu, Mar 28, 2024 at 03:06:03PM +0100, Thomas Huth wrote:
> Since version 2.66, glib has useful URI parsing functions, too.
> Use those instead of the QEMU-internal ones to be finally able
> to get rid of the latter. The g_uri_get_host() also takes care
> of removing the square brackets from IPv6 addresses, so we can
> drop that part of the QEMU code now, too.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>  block/nbd.c | 66 ++++++++++++++++++++++++++++++-----------------------
>  1 file changed, 38 insertions(+), 28 deletions(-)
> 
> diff --git a/block/nbd.c b/block/nbd.c
> index ef05f7cdfd..95b507f872 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -31,7 +31,6 @@
>  #include "qemu/osdep.h"
>  
>  #include "trace.h"
> -#include "qemu/uri.h"
>  #include "qemu/option.h"
>  #include "qemu/cutils.h"
>  #include "qemu/main-loop.h"
> @@ -1514,30 +1513,34 @@ static void nbd_client_close(BlockDriverState *bs)
>  
>  static int nbd_parse_uri(const char *filename, QDict *options)
>  {
> -    URI *uri;
> +    GUri *uri;

Is it worth using 'g_autoptr(GUri) uri = NULL;' here, to simplify cleanup later?

>      const char *p;
> -    QueryParams *qp = NULL;
> +    GHashTable *qp = NULL;

Presumably would be easier if qp is also auto-free.

> +    int qp_n;
>      int ret = 0;
>      bool is_unix;
> +    const char *uri_scheme, *uri_query, *uri_server;
> +    int uri_port;
>  
> -    uri = uri_parse(filename);
> +    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);

The glib API is fairly close to what we have in qemu, making this a
nice switchover.

>          /* nbd[+tcp]://host[:port]/export */
> -        if (!uri->server) {
> +        if (!uri_server) {
>              ret = -EINVAL;
>              goto out;
>          }
>  
> -        /* strip braces from literal IPv6 address */
> -        if (uri->server[0] == '[') {
> -            host = qstring_from_substr(uri->server, 1,
> -                                       strlen(uri->server) - 1);
> -        } else {
> -            host = qstring_from_str(uri->server);
> -        }
> -
>          qdict_put_str(options, "server.type", "inet");
> -        qdict_put(options, "server.host", host);
> +        qdict_put_str(options, "server.host", uri_server);
>  
> -        port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
> +        port_str = g_strdup_printf("%d", uri_port != -1 ? uri_port
> +                                                        : NBD_DEFAULT_PORT);
>          qdict_put_str(options, "server.port", port_str);

If a user requests nbd://hostname:0/export, this now sets server.port
to "0" instead of "10809".  Is that an intentional change?  No one
actually passes an explicit ":0" port on purpose, but we do have to
worry about malicious URIs.

>          g_free(port_str);
>      }
>  
>  out:
>      if (qp) {
> -        query_params_free(qp);
> +        g_hash_table_destroy(qp);
>      }
> -    uri_free(uri);
> +    g_uri_unref(uri);
>      return ret;

It may be possible to eliminate the out label altogether, if
GHashTable has the appropriate auto-free magic.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 14:54   ` Eric Blake
@ 2024-03-28 14:59     ` Daniel P. Berrangé
  2024-03-28 15:34       ` Thomas Huth
  0 siblings, 1 reply; 22+ messages in thread
From: Daniel P. Berrangé @ 2024-03-28 14:59 UTC (permalink / raw)
  To: Eric Blake
  Cc: Thomas Huth, Alex Bennée, Philippe Mathieu-Daudé,
	Vladimir Sementsov-Ogievskiy, Peter Lieven, Richard W.M. Jones,
	qemu-devel, Kevin Wolf, Hanna Reitz, Paolo Bonzini,
	Konstantin Kostiuk, qemu-block

On Thu, Mar 28, 2024 at 09:54:49AM -0500, Eric Blake wrote:
> On Thu, Mar 28, 2024 at 03:06:03PM +0100, Thomas Huth wrote:
> > Since version 2.66, glib has useful URI parsing functions, too.
> > Use those instead of the QEMU-internal ones to be finally able
> > to get rid of the latter. The g_uri_get_host() also takes care
> > of removing the square brackets from IPv6 addresses, so we can
> > drop that part of the QEMU code now, too.
> > 
> > Signed-off-by: Thomas Huth <thuth@redhat.com>
> > ---
> >  block/nbd.c | 66 ++++++++++++++++++++++++++++++-----------------------
> >  1 file changed, 38 insertions(+), 28 deletions(-)
> > 
> > diff --git a/block/nbd.c b/block/nbd.c
> > index ef05f7cdfd..95b507f872 100644
> > --- a/block/nbd.c
> > +++ b/block/nbd.c
> > @@ -31,7 +31,6 @@
> >  #include "qemu/osdep.h"
> >  
> >  #include "trace.h"
> > -#include "qemu/uri.h"
> >  #include "qemu/option.h"
> >  #include "qemu/cutils.h"
> >  #include "qemu/main-loop.h"
> > @@ -1514,30 +1513,34 @@ static void nbd_client_close(BlockDriverState *bs)
> >  
> >  static int nbd_parse_uri(const char *filename, QDict *options)
> >  {
> > -    URI *uri;
> > +    GUri *uri;
> 
> Is it worth using 'g_autoptr(GUri) uri = NULL;' here, to simplify cleanup later?
> 
> >      const char *p;
> > -    QueryParams *qp = NULL;
> > +    GHashTable *qp = NULL;
> 
> Presumably would be easier if qp is also auto-free.
> 
> > +    int qp_n;
> >      int ret = 0;
> >      bool is_unix;
> > +    const char *uri_scheme, *uri_query, *uri_server;
> > +    int uri_port;
> >  
> > -    uri = uri_parse(filename);
> > +    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
> 
> The glib API is fairly close to what we have in qemu, making this a
> nice switchover.
> 
> >          /* nbd[+tcp]://host[:port]/export */
> > -        if (!uri->server) {
> > +        if (!uri_server) {
> >              ret = -EINVAL;
> >              goto out;
> >          }
> >  
> > -        /* strip braces from literal IPv6 address */
> > -        if (uri->server[0] == '[') {
> > -            host = qstring_from_substr(uri->server, 1,
> > -                                       strlen(uri->server) - 1);
> > -        } else {
> > -            host = qstring_from_str(uri->server);
> > -        }
> > -
> >          qdict_put_str(options, "server.type", "inet");
> > -        qdict_put(options, "server.host", host);
> > +        qdict_put_str(options, "server.host", uri_server);
> >  
> > -        port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
> > +        port_str = g_strdup_printf("%d", uri_port != -1 ? uri_port
> > +                                                        : NBD_DEFAULT_PORT);
> >          qdict_put_str(options, "server.port", port_str);
> 
> If a user requests nbd://hostname:0/export, this now sets server.port
> to "0" instead of "10809".  Is that an intentional change?  No one
> actually passes an explicit ":0" port on purpose, but we do have to
> worry about malicious URIs.

Passing '0' will cause the kernel to allocate a random free
port, so that is potentially introducing new semantics ?


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 14:13   ` Richard W.M. Jones
@ 2024-03-28 15:06     ` Eric Blake
  2024-03-28 16:40       ` Richard W.M. Jones
  0 siblings, 1 reply; 22+ messages in thread
From: Eric Blake @ 2024-03-28 15:06 UTC (permalink / raw)
  To: Richard W.M. Jones
  Cc: Thomas Huth, Vladimir Sementsov-Ogievskiy, qemu-devel,
	Daniel P. Berrangé,
	qemu-block, nbd

Adjusting cc list to add upstream NBD and drop developers unrelated to
this part of the qemu series...

On Thu, Mar 28, 2024 at 02:13:42PM +0000, Richard W.M. Jones wrote:
> On Thu, Mar 28, 2024 at 03:06:03PM +0100, Thomas Huth wrote:
> > Since version 2.66, glib has useful URI parsing functions, too.
> > Use those instead of the QEMU-internal ones to be finally able
> > to get rid of the latter. The g_uri_get_host() also takes care
> > of removing the square brackets from IPv6 addresses, so we can
> > drop that part of the QEMU code now, too.
> > 

> >  
> >      if (is_unix) {
> >          /* nbd+unix:///export?socket=path */
> > -        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
> > +        const char *uri_socket = g_hash_table_lookup(qp, "socket");
> > +        if (uri_server || uri_port != -1 || !uri_socket) {
> >              ret = -EINVAL;
> >              goto out;
> >          }

The spec for NBD URIs is at:

https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md

Should any of this spec mention case-insensitive concerns, such as
whether 'NBD://' may be equivalent to 'nbd://', and whether
'nbd+unix:///?socket=x' is equivalent to 'nbd+unix:///?Socket=x'?
Right now, I think that most implementations of NBD servers and
clients happen to use case-sensitive parsing; but glib provides the
option to do case-insensitive query parsing.

If I read https://docs.gtk.org/glib/type_func.Uri.parse_params.html
correctly, passing G_URI_PARAMS_CASE_INSENSITIVE (which you did not
do) would mean that 'nbd+unix:///?socket=ignore&Socket=/for/real'
would result in this g_hash_table_lookup finding only "Socket", not
"socket".  Maybe it is worth an explicit addition to the NBD URI spec
to mention that we intend to be case-sensitive (in the parts where it
can be; I'm not sure if the schema part must be handled
case-insensitively without re-reading the RFCs), and therefore that
'Socket=' does NOT have the same meaning as 'socket='.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 14:59     ` Daniel P. Berrangé
@ 2024-03-28 15:34       ` Thomas Huth
  0 siblings, 0 replies; 22+ messages in thread
From: Thomas Huth @ 2024-03-28 15:34 UTC (permalink / raw)
  To: Daniel P. Berrangé, Eric Blake
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Vladimir Sementsov-Ogievskiy, Peter Lieven, Richard W.M. Jones,
	qemu-devel, Kevin Wolf, Hanna Reitz, Paolo Bonzini,
	Konstantin Kostiuk, qemu-block

On 28/03/2024 15.59, Daniel P. Berrangé wrote:
> On Thu, Mar 28, 2024 at 09:54:49AM -0500, Eric Blake wrote:
>> On Thu, Mar 28, 2024 at 03:06:03PM +0100, Thomas Huth wrote:
>>> Since version 2.66, glib has useful URI parsing functions, too.
>>> Use those instead of the QEMU-internal ones to be finally able
>>> to get rid of the latter. The g_uri_get_host() also takes care
>>> of removing the square brackets from IPv6 addresses, so we can
>>> drop that part of the QEMU code now, too.
>>>
>>> Signed-off-by: Thomas Huth <thuth@redhat.com>
>>> ---
>>>   block/nbd.c | 66 ++++++++++++++++++++++++++++++-----------------------
>>>   1 file changed, 38 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/block/nbd.c b/block/nbd.c
>>> index ef05f7cdfd..95b507f872 100644
>>> --- a/block/nbd.c
>>> +++ b/block/nbd.c
>>> @@ -31,7 +31,6 @@
>>>   #include "qemu/osdep.h"
>>>   
>>>   #include "trace.h"
>>> -#include "qemu/uri.h"
>>>   #include "qemu/option.h"
>>>   #include "qemu/cutils.h"
>>>   #include "qemu/main-loop.h"
>>> @@ -1514,30 +1513,34 @@ static void nbd_client_close(BlockDriverState *bs)
>>>   
>>>   static int nbd_parse_uri(const char *filename, QDict *options)
>>>   {
>>> -    URI *uri;
>>> +    GUri *uri;
>>
>> Is it worth using 'g_autoptr(GUri) uri = NULL;' here, to simplify cleanup later?

Sounds like a good idea, I'll give it a try!

>>>       const char *p;
>>> -    QueryParams *qp = NULL;
>>> +    GHashTable *qp = NULL;
>>
>> Presumably would be easier if qp is also auto-free.
>>
>>> +    int qp_n;
>>>       int ret = 0;
>>>       bool is_unix;
>>> +    const char *uri_scheme, *uri_query, *uri_server;
>>> +    int uri_port;
>>>   
>>> -    uri = uri_parse(filename);
>>> +    uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
>>
>> The glib API is fairly close to what we have in qemu, making this a
>> nice switchover.
>>
>>>           /* nbd[+tcp]://host[:port]/export */
>>> -        if (!uri->server) {
>>> +        if (!uri_server) {
>>>               ret = -EINVAL;
>>>               goto out;
>>>           }
>>>   
>>> -        /* strip braces from literal IPv6 address */
>>> -        if (uri->server[0] == '[') {
>>> -            host = qstring_from_substr(uri->server, 1,
>>> -                                       strlen(uri->server) - 1);
>>> -        } else {
>>> -            host = qstring_from_str(uri->server);
>>> -        }
>>> -
>>>           qdict_put_str(options, "server.type", "inet");
>>> -        qdict_put(options, "server.host", host);
>>> +        qdict_put_str(options, "server.host", uri_server);
>>>   
>>> -        port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
>>> +        port_str = g_strdup_printf("%d", uri_port != -1 ? uri_port
>>> +                                                        : NBD_DEFAULT_PORT);
>>>           qdict_put_str(options, "server.port", port_str);
>>
>> If a user requests nbd://hostname:0/export, this now sets server.port
>> to "0" instead of "10809".  Is that an intentional change?  No one
>> actually passes an explicit ":0" port on purpose, but we do have to
>> worry about malicious URIs.
> 
> Passing '0' will cause the kernel to allocate a random free
> port, so that is potentially introducing new semantics ?

Ok, so passing a 0 does not really make sense, since QEMU needs to know the 
exact port. I'll change the check from "uri_port != -1" to "uri_port > 0" in 
the next version.

  Thomas




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 15:06     ` Eric Blake
@ 2024-03-28 16:40       ` Richard W.M. Jones
  2024-04-04  9:47         ` Richard W.M. Jones
  0 siblings, 1 reply; 22+ messages in thread
From: Richard W.M. Jones @ 2024-03-28 16:40 UTC (permalink / raw)
  To: Eric Blake
  Cc: Thomas Huth, Vladimir Sementsov-Ogievskiy, qemu-devel,
	Daniel P. Berrangé,
	qemu-block, nbd

On Thu, Mar 28, 2024 at 10:06:01AM -0500, Eric Blake wrote:
> Adjusting cc list to add upstream NBD and drop developers unrelated to
> this part of the qemu series...
> 
> On Thu, Mar 28, 2024 at 02:13:42PM +0000, Richard W.M. Jones wrote:
> > On Thu, Mar 28, 2024 at 03:06:03PM +0100, Thomas Huth wrote:
> > > Since version 2.66, glib has useful URI parsing functions, too.
> > > Use those instead of the QEMU-internal ones to be finally able
> > > to get rid of the latter. The g_uri_get_host() also takes care
> > > of removing the square brackets from IPv6 addresses, so we can
> > > drop that part of the QEMU code now, too.
> > > 
> 
> > >  
> > >      if (is_unix) {
> > >          /* nbd+unix:///export?socket=path */
> > > -        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
> > > +        const char *uri_socket = g_hash_table_lookup(qp, "socket");
> > > +        if (uri_server || uri_port != -1 || !uri_socket) {
> > >              ret = -EINVAL;
> > >              goto out;
> > >          }
> 
> The spec for NBD URIs is at:
> 
> https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md
> 
> Should any of this spec mention case-insensitive concerns, such as
> whether 'NBD://' may be equivalent to 'nbd://', and whether
> 'nbd+unix:///?socket=x' is equivalent to 'nbd+unix:///?Socket=x'?
> Right now, I think that most implementations of NBD servers and
> clients happen to use case-sensitive parsing; but glib provides the
> option to do case-insensitive query parsing.

I haven't thought about this before, but do note that the NBD URI spec
defers to "IETF standards describing URIs" for all unanswered
questions.  RFC3986 does talk about this incidentally.  About the
scheme field it says (section 3.1):

   Although schemes are case-
   insensitive, the canonical form is lowercase and documents that
   specify schemes must do so with lowercase letters.  An implementation
   should accept uppercase letters as equivalent to lowercase in scheme
   names (e.g., allow "HTTP" as well as "http") for the sake of
   robustness but should only produce lowercase scheme names for
   consistency.

Hostname is also (obviously) case insensitive.  There's also a section
(6.2.3) which talks about normalization of URIs.

Overall it seems the intention of the RFC writer is that parsers
should handle any case; but when generating URIs (and for examples,
documentation etc) we should only generate lowercase.

libnbd absolutely does *not* get this right, eg:

  $ nbdinfo NBD://localhost
  nbdinfo: nbd_connect_uri: unknown NBD URI scheme: NBD: Invalid argument

so that's a bug too.

> If I read https://docs.gtk.org/glib/type_func.Uri.parse_params.html
> correctly, passing G_URI_PARAMS_CASE_INSENSITIVE (which you did not
> do) would mean that 'nbd+unix:///?socket=ignore&Socket=/for/real'
> would result in this g_hash_table_lookup finding only "Socket", not
> "socket".  Maybe it is worth an explicit addition to the NBD URI spec
> to mention that we intend to be case-sensitive (in the parts where it
> can be; I'm not sure if the schema part must be handled
> case-insensitively without re-reading the RFCs), and therefore that
> 'Socket=' does NOT have the same meaning as 'socket='.

We could mention this in the spec for clarity, but the current meaning
(as above) would be that case-insensitive parsing is recommended.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 6/9] block/nbd: Use URI parsing code from glib
  2024-03-28 16:40       ` Richard W.M. Jones
@ 2024-04-04  9:47         ` Richard W.M. Jones
  0 siblings, 0 replies; 22+ messages in thread
From: Richard W.M. Jones @ 2024-04-04  9:47 UTC (permalink / raw)
  To: Eric Blake
  Cc: Thomas Huth, Vladimir Sementsov-Ogievskiy, qemu-devel,
	Daniel P. Berrangé,
	qemu-block, nbd

On Thu, Mar 28, 2024 at 04:40:10PM +0000, Richard W.M. Jones wrote:
> libnbd absolutely does *not* get this right, eg:
> 
>   $ nbdinfo NBD://localhost
>   nbdinfo: nbd_connect_uri: unknown NBD URI scheme: NBD: Invalid argument
> 
> so that's a bug too.

Proposed fix:
https://gitlab.com/nbdkit/libnbd/-/merge_requests/6

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 4/9] Bump minimum glib version to v2.66
  2024-03-28 14:06 ` [PATCH for-9.1 4/9] Bump minimum glib version to v2.66 Thomas Huth
@ 2024-04-12 10:16   ` Paolo Bonzini
  2024-04-12 10:58     ` Thomas Huth
  0 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2024-04-12 10:16 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel, Kevin Wolf, Hanna Reitz,
	Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

On Thu, Mar 28, 2024 at 3:06 PM Thomas Huth <thuth@redhat.com> wrote:
>
> Now that we dropped support for CentOS 8 and Ubuntu 20.04, we can
> look into bumping the glib version to a new minimum for further
> clean-ups. According to repology.org, available versions are:
>
>  CentOS Stream 9:       2.66.7
>  Debian 11:             2.66.8
>  Fedora 38:             2.74.1
>  Freebsd:               2.78.4
>  Homebrew:              2.80.0
>  Openbsd:               2.78.4
>  OpenSuse leap 15.5:    2.70.5
>  pkgsrc_current:        2.78.4
>  Ubuntu 22.04:          2.72.1
>
> Thus it should be safe to bump the minimum glib version to 2.66 now.
> Version 2.66 comes with new functions for URI parsing which will
> allow further clean-ups in the following patches.

Missing:

diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c
index b0e0b1d674f..cc1f5a708e4 100644
--- a/qga/commands-posix-ssh.c
+++ b/qga/commands-posix-ssh.c
@@ -288,7 +288,6 @@ qmp_guest_ssh_get_authorized_keys(
 }

 #ifdef QGA_BUILD_UNIT_TEST
-#if GLIB_CHECK_VERSION(2, 60, 0)
 static const strList test_key2 = {
     .value = (char *)"algo key2 comments"
 };
@@ -484,11 +483,4 @@ int main(int argc, char *argv[])

     return g_test_run();
 }
-#else
-int main(int argc, char *argv[])
-{
-    g_test_message("test skipped, needs glib >= 2.60");
-    return 0;
-}
-#endif /* GLIB_2_60 */
 #endif /* BUILD_UNIT_TEST */

Paolo



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 4/9] Bump minimum glib version to v2.66
  2024-04-12 10:16   ` Paolo Bonzini
@ 2024-04-12 10:58     ` Thomas Huth
  2024-04-12 12:01       ` Paolo Bonzini
  0 siblings, 1 reply; 22+ messages in thread
From: Thomas Huth @ 2024-04-12 10:58 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel, Kevin Wolf, Hanna Reitz,
	Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

On 12/04/2024 12.16, Paolo Bonzini wrote:
> On Thu, Mar 28, 2024 at 3:06 PM Thomas Huth <thuth@redhat.com> wrote:
>>
>> Now that we dropped support for CentOS 8 and Ubuntu 20.04, we can
>> look into bumping the glib version to a new minimum for further
>> clean-ups. According to repology.org, available versions are:
>>
>>   CentOS Stream 9:       2.66.7
>>   Debian 11:             2.66.8
>>   Fedora 38:             2.74.1
>>   Freebsd:               2.78.4
>>   Homebrew:              2.80.0
>>   Openbsd:               2.78.4
>>   OpenSuse leap 15.5:    2.70.5
>>   pkgsrc_current:        2.78.4
>>   Ubuntu 22.04:          2.72.1
>>
>> Thus it should be safe to bump the minimum glib version to 2.66 now.
>> Version 2.66 comes with new functions for URI parsing which will
>> allow further clean-ups in the following patches.
> 
> Missing:
> 
> diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c
> index b0e0b1d674f..cc1f5a708e4 100644
> --- a/qga/commands-posix-ssh.c
> +++ b/qga/commands-posix-ssh.c
> @@ -288,7 +288,6 @@ qmp_guest_ssh_get_authorized_keys(
>   }
> 
>   #ifdef QGA_BUILD_UNIT_TEST
> -#if GLIB_CHECK_VERSION(2, 60, 0)
>   static const strList test_key2 = {
>       .value = (char *)"algo key2 comments"
>   };
> @@ -484,11 +483,4 @@ int main(int argc, char *argv[])
> 
>       return g_test_run();
>   }
> -#else
> -int main(int argc, char *argv[])
> -{
> -    g_test_message("test skipped, needs glib >= 2.60");
> -    return 0;
> -}
> -#endif /* GLIB_2_60 */
>   #endif /* BUILD_UNIT_TEST */

Indeed! And there seems to be another GLIB_CHECK_VERSION(2,62,0) check in 
util/error-report.c which we likely can clean up now, too!

  Thomas




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH for-9.1 4/9] Bump minimum glib version to v2.66
  2024-04-12 10:58     ` Thomas Huth
@ 2024-04-12 12:01       ` Paolo Bonzini
  0 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2024-04-12 12:01 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Alex Bennée, Philippe Mathieu-Daudé,
	Eric Blake, Vladimir Sementsov-Ogievskiy, Peter Lieven,
	Richard W.M. Jones, qemu-devel, Kevin Wolf, Hanna Reitz,
	Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

On 4/12/24 12:58, Thomas Huth wrote:
> On 12/04/2024 12.16, Paolo Bonzini wrote:
>> On Thu, Mar 28, 2024 at 3:06 PM Thomas Huth <thuth@redhat.com> wrote:
>>>
>>> Now that we dropped support for CentOS 8 and Ubuntu 20.04, we can
>>> look into bumping the glib version to a new minimum for further
>>> clean-ups. According to repology.org, available versions are:
>>>
>>>   CentOS Stream 9:       2.66.7
>>>   Debian 11:             2.66.8
>>>   Fedora 38:             2.74.1
>>>   Freebsd:               2.78.4
>>>   Homebrew:              2.80.0
>>>   Openbsd:               2.78.4
>>>   OpenSuse leap 15.5:    2.70.5
>>>   pkgsrc_current:        2.78.4
>>>   Ubuntu 22.04:          2.72.1
>>>
>>> Thus it should be safe to bump the minimum glib version to 2.66 now.
>>> Version 2.66 comes with new functions for URI parsing which will
>>> allow further clean-ups in the following patches.
>>
>> Missing:
>>
>> diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c
>> index b0e0b1d674f..cc1f5a708e4 100644
>> --- a/qga/commands-posix-ssh.c
>> +++ b/qga/commands-posix-ssh.c
>> @@ -288,7 +288,6 @@ qmp_guest_ssh_get_authorized_keys(
>>   }
>>
>>   #ifdef QGA_BUILD_UNIT_TEST
>> -#if GLIB_CHECK_VERSION(2, 60, 0)
>>   static const strList test_key2 = {
>>       .value = (char *)"algo key2 comments"
>>   };
>> @@ -484,11 +483,4 @@ int main(int argc, char *argv[])
>>
>>       return g_test_run();
>>   }
>> -#else
>> -int main(int argc, char *argv[])
>> -{
>> -    g_test_message("test skipped, needs glib >= 2.60");
>> -    return 0;
>> -}
>> -#endif /* GLIB_2_60 */
>>   #endif /* BUILD_UNIT_TEST */
> 
> Indeed! And there seems to be another GLIB_CHECK_VERSION(2,62,0) check 
> in util/error-report.c which we likely can clean up now, too!

Ok, I'll squash the above and

diff --git a/util/error-report.c b/util/error-report.c
index 6e44a557321..1b17c11de19 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -172,18 +172,8 @@ static void print_loc(void)
  static char *
  real_time_iso8601(void)
  {
-#if GLIB_CHECK_VERSION(2,62,0)
      g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
-    /* ignore deprecation warning, since GLIB_VERSION_MAX_ALLOWED is 2.56 */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
      return g_date_time_format_iso8601(dt);
-#pragma GCC diagnostic pop
-#else
-    GTimeVal tv;
-    g_get_current_time(&tv);
-    return g_time_val_to_iso8601(&tv);
-#endif
  }
  
  /*

then.  As an aside, we probably can also drop:

             /*
              * gtk_widget_set_double_buffered() was deprecated in 3.14.
              * It is required for opengl rendering on X11 though.  A
              * proper replacement (native opengl support) is only
              * available in 3.16+.  Silence the warning if possible.
              */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
             gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE);
#pragma GCC diagnostic pop


and


#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     /*
      * check if RBD image is a clone (= has a parent).
      *
      * rbd_get_parent_info is deprecated from Nautilus onwards, but the
      * replacement rbd_get_parent is not present in Luminous and Mimic.
      */
     if (rbd_get_parent_info(s->image, NULL, 0, NULL, 0, NULL, 0) != -ENOENT) {
         return status;
     }
#pragma GCC diagnostic pop


(Nautilus is Ceph 14, it's in all of CentOS Stream 9, Ubuntu 20.04 and
Debian 11) but I have no idea what the replacement would be. :/

Paolo



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* MAINTAINERS tweak [was: [PATCH for-9.1 0/9] Switch to glib URI parsing code]
  2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
                   ` (8 preceding siblings ...)
  2024-03-28 14:06 ` [PATCH for-9.1 9/9] util/uri: Remove the old URI parsing code Thomas Huth
@ 2024-04-15 14:16 ` Eric Blake
  9 siblings, 0 replies; 22+ messages in thread
From: Eric Blake @ 2024-04-15 14:16 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Alex Bennée, Peter Lieven, Philippe Mathieu-Daudé,
	Vladimir Sementsov-Ogievskiy, Richard W.M. Jones, qemu-devel,
	Kevin Wolf, Hanna Reitz, Paolo Bonzini, Daniel P. Berrangé,
	Konstantin Kostiuk, qemu-block

[Trying Peter Lieven's alternate address...]

On Thu, Mar 28, 2024 at 03:05:57PM +0100, Thomas Huth wrote:
> In the QEMU 9.1 development cycle, we can drop the support for
> Ubuntu 20.04 and CentOS 8 since the following major versions of
> these distributions are available since 2 years already.

Every time I've replied to any message in this thread, I've gotten a
response:

| +Your message to pl@kamp.de couldn't be delivered.
| kamp.de couldn't confirm that your message was sent from a trusted location.
| eblake  Office 365      pl
| Action Required                 Recipient
| SPF validation error
| 
| How to Fix It
| Your organization's email admin will have to diagnose and fix your domain's email settings. Please forward this message to your
| +email admin.
| 
| ________________________________
| 
| More Info for Email Admins
| Status code: 550 5.7.23
| 
| This error occurs when Sender Policy Framework (SPF) validation for the sender's domain fails. If you're the sender's email
| +admin, make sure the SPF records for your domain at your domain registrar are set up correctly. Office 365 supports only one
| +SPF record (a TXT record that defines SPF) for your domain. Include the following domain name: spf.protection.outlook.com. If
| +you have a hybrid configuration (some mailboxes in the cloud, and some mailboxes on premises) or if you're an Exchange Online
| +Protection standalone customer, add the outbound IP address of your on-premises servers to the TXT record.

Red Hat IT says that it is unlikely to be Red Hat's SPF settings, and
suspects that it is instead something caused by whatever Peter is
using to bounce mail from his alias Peter Lieven <pl@kamp.de> to his
Office 365 account.  As I appear to be unable to contact Peter (even
my use of direct email, bypassing the list, and using a personal
account instead of my Red Hat email) about this issue, I'm wondering
if Peter is still an active contributor to the project.

But while typing this email, to see if RBD, iSCSI, and NFS need a new
entry in MAINTAINERS, I did a search through the list archives, where
the last email I found from Peter was
https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg00574.html,
which asked to update MAINTAINERS to his new address, and that has not
made it in so far...

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org



^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2024-04-15 14:17 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-28 14:05 [PATCH for-9.1 0/9] Switch to glib URI parsing code Thomas Huth
2024-03-28 14:05 ` [PATCH for-9.1 1/9] tests: Remove Ubuntu 20.04 container Thomas Huth
2024-03-28 14:05 ` [PATCH for-9.1 2/9] tests/lcitool/libvirt-ci: Update to the latest master branch Thomas Huth
2024-03-28 14:06 ` [PATCH for-9.1 3/9] tests: Update our CI to use CentOS Stream 9 instead of 8 Thomas Huth
2024-03-28 14:06 ` [PATCH for-9.1 4/9] Bump minimum glib version to v2.66 Thomas Huth
2024-04-12 10:16   ` Paolo Bonzini
2024-04-12 10:58     ` Thomas Huth
2024-04-12 12:01       ` Paolo Bonzini
2024-03-28 14:06 ` [PATCH for-9.1 5/9] block/gluster: Use URI parsing code from glib Thomas Huth
2024-03-28 14:06 ` [PATCH for-9.1 6/9] block/nbd: " Thomas Huth
2024-03-28 14:13   ` Richard W.M. Jones
2024-03-28 15:06     ` Eric Blake
2024-03-28 16:40       ` Richard W.M. Jones
2024-04-04  9:47         ` Richard W.M. Jones
2024-03-28 14:54   ` Eric Blake
2024-03-28 14:59     ` Daniel P. Berrangé
2024-03-28 15:34       ` Thomas Huth
2024-03-28 14:06 ` [PATCH for-9.1 7/9] block/nfs: " Thomas Huth
2024-03-28 14:06 ` [PATCH for-9.1 8/9] block/ssh: " Thomas Huth
2024-03-28 14:15   ` Richard W.M. Jones
2024-03-28 14:06 ` [PATCH for-9.1 9/9] util/uri: Remove the old URI parsing code Thomas Huth
2024-04-15 14:16 ` MAINTAINERS tweak [was: [PATCH for-9.1 0/9] Switch to glib URI parsing code] Eric Blake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.