From 9d4dc80d1464c073554d6816992036babadad25a Mon Sep 17 00:00:00 2001 From: Hyunjee Kim Date: Tue, 3 Dec 2019 10:36:55 +0900 Subject: Imported Upstream version 2.57.2 --- .gitignore | 2 - .gitlab-ci.yml | 125 +- .gitlab-ci/Dockerfile | 23 +- .gitlab-ci/android-download-ndk.sh | 31 + .gitlab-ci/android-setup-env.sh | 100 + .gitlab-ci/coverage-docker.sh | 4 +- .gitlab-ci/cross_file_mingw64.txt | 17 + .gitlab-ci/run-docker.sh | 16 +- .gitlab-ci/test-msvc.bat | 19 + .gitlab-ci/test-msys2.sh | 33 +- AUTHORS | 4 +- CONTRIBUTING.md | 72 + HACKING | 2 +- Makefile.am | 16 +- NEWS | 29 + README | 1 + README.commits | 72 - README.in | 366 -- README.md | 365 ++ README.win32 | 100 +- autogen.sh | 8 +- build/win32/vs8/Makefile.am | 11 - build/win32/vs8/README | 4 - build/win32/vs8/gio.vcproj | 486 --- build/win32/vs8/glib-genmarshal.vcproj | 199 - build/win32/vs8/glib.sln | 84 - build/win32/vs8/glib.vcproj | 605 --- build/win32/vs8/gmodule.vcproj | 217 - build/win32/vs8/gobject.vcproj | 295 -- build/win32/vs8/gspawn-win32-helper-console.vcproj | 201 - build/win32/vs8/gspawn-win32-helper.vcproj | 201 - build/win32/vs8/gthread.vcproj | 215 - config.h.meson | 840 ---- config.h.win32.in | 872 ---- configure.ac | 166 +- docs/macros.txt | 24 - docs/reference/gio/Makefile.am | 188 +- docs/reference/gio/gdbus-codegen.xml | 67 +- docs/reference/gio/gdbus.xml | 2 +- docs/reference/gio/gio-sections.txt | 9 + docs/reference/gio/gio.types | 156 - docs/reference/gio/gio.xml | 15 + docs/reference/gio/meson.build | 1 - docs/reference/gio/migrating-gnome-vfs.xml | 2 +- docs/reference/gio/xml/meson.build | 2 +- docs/reference/glib/Makefile.am | 6 +- docs/reference/glib/building.xml | 101 - docs/reference/glib/glib-docs.xml | 8 + docs/reference/glib/glib-sections.txt | 55 + docs/reference/glib/glib.types | 0 docs/reference/glib/gvariant-text.xml | 7 +- docs/reference/glib/gvariant-varargs.xml | 2 +- docs/reference/glib/meson.build | 2 +- docs/reference/glib/resources.xml | 31 +- docs/reference/glib/xml/meson.build | 2 +- docs/reference/gobject/Makefile.am | 4 +- docs/reference/gobject/gobject-docs.xml | 8 + docs/reference/gobject/gobject.cI | 11 - docs/reference/gobject/gobject.types | 7 - docs/reference/gobject/meson.build | 2 +- docs/reference/gobject/tut_howto.xml | 14 + docs/reference/gobject/xml/meson.build | 2 +- gio/Makefile.am | 113 +- gio/completion/.gitignore | 1 + gio/completion/gio | 120 + gio/fam/gfamfilemonitor.map | 8 + gio/fam/meson.build | 36 + gio/gbufferedoutputstream.c | 4 +- gio/gcocoanotificationbackend.c | 278 -- gio/gcocoanotificationbackend.m | 278 ++ gio/gcontenttype.c | 4 +- gio/gdbus-2.0/codegen/codegen.py | 282 +- gio/gdbus-2.0/codegen/codegen_main.py | 57 +- gio/gdbus-2.0/codegen/dbustypes.py | 35 +- gio/gdbus-2.0/codegen/meson.build | 7 +- gio/gdbus-2.0/codegen/utils.py | 6 +- gio/gdbusaddress.c | 4 + gio/gdbusauthmechanismsha1.c | 10 +- gio/gdbusconnection.c | 41 +- gio/gdbusdaemon.c | 4 +- gio/gdbusmessage.c | 2 + gio/gdesktopappinfo.c | 207 +- gio/gdesktopappinfo.h | 14 + gio/gdrive.c | 10 +- gio/gdrive.h | 9 + gio/gfdonotificationbackend.c | 56 +- gio/gfile.c | 7 +- gio/gfileinfo.h | 3 +- gio/ginetaddress.c | 92 - gio/gio-autocleanups.h | 1 + gio/gio-launch-desktop.c | 52 + gio/gio-querymodules-wrapper.py | 9 + gio/gio-tool-cat.c | 2 +- gio/gio-tool-copy.c | 2 +- gio/gio-tool-info.c | 2 +- gio/gio-tool-list.c | 2 +- gio/gio-tool-mkdir.c | 2 +- gio/gio-tool-monitor.c | 2 +- gio/gio-tool-mount.c | 108 +- gio/gio-tool-move.c | 3 +- gio/gio-tool-open.c | 2 +- gio/gio-tool-remove.c | 2 +- gio/gio-tool-set.c | 2 +- gio/gio-tool-trash.c | 13 +- gio/gio-tool-tree.c | 2 +- gio/gio-tool.c | 2 +- gio/gioenums.h | 12 +- gio/giomodule.c | 23 +- gio/glib-compile-resources.c | 34 +- gio/glib-compile-schemas.c | 100 +- gio/glocalfile.c | 72 +- gio/glocalfileinfo.c | 27 +- gio/glocalfileinfo.h | 1 + gio/glocalfilemonitor.c | 2 + gio/gmount.c | 13 +- gio/gmountoperation.c | 219 +- gio/gmountoperation.h | 15 + gio/gnetworking.h.win32 | 81 - gio/gnetworkmonitorportal.c | 236 +- gio/gnextstepsettingsbackend.c | 480 --- gio/gnextstepsettingsbackend.m | 480 +++ gio/gosxappinfo.c | 759 ---- gio/gosxappinfo.m | 759 ++++ gio/gosxcontenttype.c | 582 --- gio/gosxcontenttype.m | 582 +++ gio/gresource.c | 21 +- gio/gsettings.c | 49 +- gio/gsettingsschema-internal.h | 2 + gio/gsettingsschema.c | 41 + gio/gsocket.c | 28 +- gio/gtask.c | 1 + gio/gthreadedresolver.c | 4 +- gio/gunixmounts.c | 4 - gio/gunixsocketaddress.c | 2 + gio/gvolume.c | 19 +- gio/gvolume.h | 4 + gio/gwin32notificationbackend.c | 8 +- gio/inotify/Makefile.am | 4 + gio/inotify/meson.build | 2 +- gio/kqueue/gkqueuefilemonitor.c | 290 +- gio/kqueue/kqueue-helper.c | 21 +- gio/kqueue/kqueue-helper.h | 13 +- gio/kqueue/kqueue-missing.c | 45 +- gio/meson.build | 60 +- gio/org.freedesktop.portal.NetworkMonitor.xml | 29 - gio/tests/Makefile.am | 11 +- gio/tests/appinfo.c | 8 +- gio/tests/dbus-appinfo.c | 9 +- gio/tests/desktop-app-info.c | 50 + gio/tests/file.c | 48 +- gio/tests/g-file-info-filesystem-readonly.c | 2 + gio/tests/gapplication.c | 2 + gio/tests/gdbus-addresses.c | 79 +- gio/tests/gdbus-connection-loss.c | 3 + gio/tests/gdbus-example-peer.c | 3 +- gio/tests/gdbus-example-unix-fd-client.c | 13 +- gio/tests/gdbus-export.c | 10 +- gio/tests/gdbus-peer-object-manager.c | 2 + gio/tests/gdbus-peer.c | 4 + gio/tests/gdbus-serialization.c | 1 + gio/tests/gdbus-unix-addresses.c | 1 - gio/tests/gsettings.c | 118 +- gio/tests/live-g-file.c | 48 + gio/tests/meson.build | 58 +- gio/tests/monitor.c | 16 +- gio/tests/mount-operation.c | 132 + gio/tests/org.gtk.test.gschema.override.orig | 2 + gio/tests/org.gtk.test.gschema.xml.orig | 6 + gio/tests/resources.c | 70 +- gio/tests/simple-proxy.c | 1 + gio/tests/task.c | 1 + gio/tests/testfilemonitor.c | 359 +- gio/tests/trash.c | 105 + gio/tests/unix-mounts.c | 6 + gio/tests/unix-streams.c | 2 + gio/thumbnail-verify.c | 2 +- glib-gettextize.in | 2 +- glib-zip.in | 94 - glib.doap | 2 +- glib.supp | 24 +- glib/.gitignore | 1 - glib/Makefile.am | 78 +- glib/docs.c | 20 + glib/garcbox.c | 373 ++ glib/garray.c | 77 +- glib/gasyncqueue.c | 4 + glib/gatomic.h | 10 +- glib/gbacktrace.c | 16 +- glib/gbookmarkfile.c | 62 +- glib/gbsearcharray.h | 4 - glib/gbytes.c | 11 +- glib/gchecksum.c | 112 +- glib/gconvert.h | 2 +- glib/gdate.c | 7 +- glib/gfileutils.c | 11 + glib/ghash.c | 18 +- glib/glib-autocleanups.h | 1 + glib/glib-init.c | 7 +- glib/glib-init.h | 1 + glib/glib.h | 3 + glib/glib.stp.in | 45 + glib/glib_gdb.py | 4 +- glib/glib_probes.d | 4 + glib/glibconfig.h.win32.in | 262 -- glib/gmacros.h | 21 +- glib/gmain.c | 174 +- glib/gmain.h | 27 +- glib/gmarkup.c | 93 +- glib/gmem.h | 17 + glib/gmessages.c | 68 - glib/goption.c | 4 +- glib/gpoll.c | 15 +- glib/gqueue.c | 6 +- glib/grand.c | 2 +- glib/grcbox.c | 450 ++ glib/grcbox.h | 88 + glib/grcboxprivate.h | 61 + glib/grefcount.c | 285 ++ glib/grefcount.h | 122 + glib/grefstring.c | 303 ++ glib/grefstring.h | 44 + glib/gscripttable.h | 127 +- glib/gslice.c | 40 +- glib/gspawn-private.h | 115 + glib/gspawn-win32-helper.c | 7 +- glib/gspawn-win32.c | 194 +- glib/gspawn.c | 660 ++- glib/gspawn.h | 13 + glib/gstdio.c | 32 +- glib/gtester.c | 2 +- glib/gtestutils.c | 62 +- glib/gtestutils.h | 32 +- glib/gthread-win32.c | 597 +-- glib/gtimer.c | 3 +- glib/gtimezone.c | 5 +- glib/gtranslit.c | 4 +- glib/gtypes.h | 3 + glib/gunibreak.h | 1440 +++++-- glib/gunichartables.h | 1446 +++++-- glib/gunicode.h | 18 +- glib/gunidecomp.h | 133 +- glib/guniprop.c | 9 + glib/gutils.c | 26 +- glib/gutils.h | 2 +- glib/gvalgrind.h | 32 + glib/gvariant.c | 40 +- glib/gvariant.h | 4 +- glib/gvarianttype.c | 11 +- glib/gwin32.c | 215 + glib/meson.build | 12 +- glib/tests/Makefile.am | 26 +- glib/tests/array-test.c | 309 +- glib/tests/atomic.c | 8 +- glib/tests/autoptr.c | 14 + glib/tests/bookmarks/fail-18.xbel | 1 + glib/tests/bookmarks/fail-19.xbel | 1 + glib/tests/bookmarks/fail-20.xbel | 1 + glib/tests/bookmarks/fail-21.xbel | 1 + glib/tests/bookmarks/fail-22.xbel | 1 + glib/tests/bookmarks/fail-23.xbel | 1 + glib/tests/bookmarks/fail-24.xbel | 1 + glib/tests/bookmarks/fail-25.xbel | 1 + glib/tests/bookmarks/fail-26.xbel | 1 + glib/tests/bookmarks/fail-27.xbel | 1 + glib/tests/bookmarks/fail-28.xbel | 1 + glib/tests/bookmarks/fail-29.xbel | 1 + glib/tests/bookmarks/fail-30.xbel | 1 + glib/tests/bookmarks/fail-31.xbel | 1 + glib/tests/bookmarks/fail-32.xbel | 1 + glib/tests/bookmarks/fail-33.xbel | 1 + glib/tests/bookmarks/fail-34.xbel | 1 + glib/tests/bookmarks/fail-35.xbel | 1 + glib/tests/bookmarks/fail-36.xbel | 1 + glib/tests/bookmarks/fail-37.xbel | 1 + glib/tests/bookmarks/fail-38.xbel | 1 + glib/tests/date.c | 32 +- glib/tests/fileutils.c | 72 +- glib/tests/gdatetime.c | 15 + glib/tests/logging.c | 11 +- glib/tests/mainloop.c | 16 +- glib/tests/markups/fail-10.expected | 2 +- glib/tests/markups/fail-11.expected | 2 +- glib/tests/markups/fail-12.expected | 2 +- glib/tests/markups/fail-13.expected | 2 +- glib/tests/markups/fail-14.expected | 2 +- glib/tests/markups/fail-15.expected | 2 +- glib/tests/markups/fail-22.expected | 2 +- glib/tests/markups/fail-26.expected | 2 +- glib/tests/markups/fail-27.expected | 2 +- glib/tests/markups/fail-28.expected | 2 +- glib/tests/markups/fail-29.expected | 2 +- glib/tests/markups/fail-3.expected | 4 +- glib/tests/markups/fail-30.expected | 2 +- glib/tests/markups/fail-31.expected | 2 +- glib/tests/markups/fail-32.expected | 2 +- glib/tests/markups/fail-33.expected | 2 +- glib/tests/markups/fail-34.expected | 2 +- glib/tests/markups/fail-35.expected | 2 +- glib/tests/markups/fail-36.expected | 2 +- glib/tests/markups/fail-37.expected | 2 +- glib/tests/markups/fail-38.expected | 2 +- glib/tests/markups/fail-39.expected | 2 +- glib/tests/markups/fail-40.expected | 2 +- glib/tests/markups/fail-41.expected | 2 +- glib/tests/markups/fail-42.expected | 2 +- glib/tests/markups/fail-43.expected | 2 +- glib/tests/markups/fail-44.expected | 2 +- glib/tests/markups/fail-45.expected | 2 +- glib/tests/markups/fail-46.expected | 2 +- glib/tests/markups/fail-47.expected | 2 +- glib/tests/markups/fail-48.expected | 2 +- glib/tests/markups/fail-49.expected | 2 +- glib/tests/markups/fail-5.expected | 2 +- glib/tests/markups/fail-50.expected | 1 + glib/tests/markups/fail-50.gmarkup | 1 + glib/tests/markups/fail-51.expected | 1 + glib/tests/markups/fail-51.gmarkup | 1 + glib/tests/markups/fail-6.expected | 2 +- glib/tests/markups/fail-7.expected | 2 +- glib/tests/markups/fail-8.expected | 2 +- glib/tests/markups/fail-9.expected | 2 +- glib/tests/meson.build | 346 +- glib/tests/option-context.c | 45 + glib/tests/rcbox.c | 238 ++ glib/tests/refcount.c | 221 + glib/tests/refstring.c | 122 + glib/tests/sequence.c | 2 + glib/tests/spawn-singlethread.c | 207 + glib/tests/strfuncs.c | 21 +- glib/tests/test-printf.c | 31 +- glib/tests/testing.c | 14 + glib/tests/thread.c | 7 +- glib/tests/unicode.c | 16 + glib/tests/utils.c | 17 + glib/update-gtranslit.py | 4 +- gmodule/Makefile.am | 1 - gmodule/gmoduleconf.h.win32 | 39 - gobject/Makefile.am | 14 +- gobject/gbinding.c | 2 +- gobject/gclosure.c | 6 +- gobject/glib-mkenums.in | 2 +- gobject/gobject.c | 4 +- gobject/gobject.h | 4 +- gobject/gobject_gdb.py | 10 +- gobject/gtype.c | 14 +- gobject/gtype.h | 4 +- gobject/gvaluearray.c | 20 +- gobject/gvaluecollector.h | 98 +- gobject/meson.build | 4 +- gobject/tests/meson.build | 26 +- gobject/tests/mkenums.py | 378 ++ gobject/tests/private.c | 2 + gobject/tests/properties.c | 18 +- gobject/tests/reference.c | 14 +- gobject/tests/taptestrunner.py | 176 + gobject/tests/threadtests.c | 6 + meson.build | 361 +- meson_options.txt | 10 + po/cs.po | 279 +- po/de.po | 1194 +++--- po/es.po | 2704 ++++++------ po/fur.po | 1391 ++++--- po/lt.po | 2767 +++++++------ po/ro.po | 4321 ++++++++++---------- po/sl.po | 366 +- po/tr.po | 1325 +++--- sanity_check | 2 +- subprojects/Makefile.am | 5 + subprojects/proxy-libintl.wrap | 4 +- subprojects/zlib.wrap | 14 +- template.test.in | 3 + tests/Makefile.am | 4 +- tests/casefold.txt | 83 +- tests/casemap.txt | 165 +- tests/gen-casefold-txt.pl | 82 - tests/gen-casefold-txt.py | 78 + tests/gen-casemap-txt.pl | 256 -- tests/gen-casemap-txt.py | 200 + tests/gio-ls.c | 114 - tests/gobject/Makefile.am | 19 +- tests/gobject/ifacecheck.c | 163 - tests/gobject/ifaceinherit.c | 230 -- tests/gobject/ifaceinit.c | 421 -- tests/gobject/meson.build | 3 +- tests/gobject/run-performance.sh | 6 - tests/gobject/testgobject.c | 38 +- tests/meson.build | 11 +- tests/refcount/meson.build | 7 +- tests/refcount/objects.c | 1 + tests/testglib.c | 24 +- tests/unicode-caseconv.c | 2 +- win32/Makefile-newvs.am | 55 - win32/Makefile.am | 7 - win32/Makefile.msvcproj | 153 - win32/detectenv-msvc.mak | 78 - win32/gen_util_scripts.py | 37 - win32/glibpc.py | 89 - win32/pc_base.py | 124 - win32/replace.py | 115 - win32/setup.py | 347 -- win32/vs10/.gitignore | 12 - win32/vs10/Makefile.am | 66 - win32/vs10/README.txt | 96 - win32/vs10/gdbus.vcxproj | 178 - win32/vs10/gdbus.vcxproj.filters | 14 - win32/vs10/gio-querymodules.vcxproj | 183 - win32/vs10/gio-querymodules.vcxproj.filters | 17 - win32/vs10/gio-tool.vcxproj.filtersin | 12 - win32/vs10/gio-tool.vcxprojin | 186 - win32/vs10/gio.vcxproj.filtersin | 28 - win32/vs10/gio.vcxprojin | 206 - win32/vs10/glib-build-defines.props | 88 - .../vs10/glib-compile-resources.vcxproj.filtersin | 12 - win32/vs10/glib-compile-resources.vcxprojin | 178 - win32/vs10/glib-compile-schemas.vcxproj.filtersin | 12 - win32/vs10/glib-compile-schemas.vcxprojin | 178 - win32/vs10/glib-gen-srcs.props | 29 - win32/vs10/glib-install.propsin | 121 - win32/vs10/glib-install.vcxproj | 188 - win32/vs10/glib-install.vcxproj.filters | 16 - win32/vs10/glib-version-paths.props.in | 46 - win32/vs10/glib.sln | 289 -- win32/vs10/glib.vcxproj.filtersin | 66 - win32/vs10/glib.vcxprojin | 525 --- win32/vs10/gmodule.vcxproj | 192 - win32/vs10/gmodule.vcxproj.filters | 30 - win32/vs10/gobject.vcxproj.filtersin | 23 - win32/vs10/gobject.vcxprojin | 186 - win32/vs10/gresource.vcxproj | 178 - win32/vs10/gresource.vcxproj.filters | 14 - win32/vs10/gsettings.vcxproj | 179 - win32/vs10/gsettings.vcxproj.filters | 14 - win32/vs10/gspawn-win32-helper-console.vcxproj | 173 - .../gspawn-win32-helper-console.vcxproj.filters | 22 - win32/vs10/gspawn-win32-helper.vcxproj | 173 - win32/vs10/gspawn-win32-helper.vcxproj.filters | 22 - win32/vs10/gthread.vcxproj | 184 - win32/vs10/gthread.vcxproj.filters | 23 - win32/vs11/.gitignore | 31 - win32/vs11/Makefile.am | 46 - win32/vs12/.gitignore | 31 - win32/vs12/Makefile.am | 46 - win32/vs14/Makefile.am | 46 - win32/vs15/Makefile.am | 47 - win32/vs9/.gitignore | 7 - win32/vs9/Makefile.am | 41 - win32/vs9/README.txt | 95 - win32/vs9/gdbus.vcproj | 153 - win32/vs9/gio-querymodules.vcproj | 154 - win32/vs9/gio-tool.vcprojin | 173 - win32/vs9/gio.vcprojin | 204 - win32/vs9/glib-build-defines.vsprops | 78 - win32/vs9/glib-compile-resources.vcprojin | 153 - win32/vs9/glib-compile-schemas.vcprojin | 153 - win32/vs9/glib-gen-srcs.vsprops | 24 - win32/vs9/glib-install.vcproj | 221 - win32/vs9/glib-install.vspropsin | 103 - win32/vs9/glib-version-paths.vsprops.in | 39 - win32/vs9/glib.sln | 362 -- win32/vs9/glib.vcprojin | 634 --- win32/vs9/gmodule.vcproj | 197 - win32/vs9/gobject.vcprojin | 163 - win32/vs9/gresource.vcproj | 153 - win32/vs9/gsettings.vcproj | 154 - win32/vs9/gspawn-win32-helper-console.vcproj | 159 - win32/vs9/gspawn-win32-helper.vcproj | 156 - win32/vs9/gthread.vcproj | 163 - 467 files changed, 22616 insertions(+), 28964 deletions(-) create mode 100755 .gitlab-ci/android-download-ndk.sh create mode 100755 .gitlab-ci/android-setup-env.sh create mode 100644 .gitlab-ci/cross_file_mingw64.txt create mode 100644 .gitlab-ci/test-msvc.bat create mode 100644 CONTRIBUTING.md create mode 100644 README delete mode 100644 README.commits delete mode 100644 README.in create mode 100644 README.md delete mode 100644 build/win32/vs8/Makefile.am delete mode 100644 build/win32/vs8/README delete mode 100644 build/win32/vs8/gio.vcproj delete mode 100644 build/win32/vs8/glib-genmarshal.vcproj delete mode 100644 build/win32/vs8/glib.sln delete mode 100644 build/win32/vs8/glib.vcproj delete mode 100644 build/win32/vs8/gmodule.vcproj delete mode 100644 build/win32/vs8/gobject.vcproj delete mode 100644 build/win32/vs8/gspawn-win32-helper-console.vcproj delete mode 100644 build/win32/vs8/gspawn-win32-helper.vcproj delete mode 100644 build/win32/vs8/gthread.vcproj delete mode 100644 config.h.meson delete mode 100644 config.h.win32.in delete mode 100644 docs/reference/gio/gio.types delete mode 100644 docs/reference/glib/glib.types delete mode 100644 docs/reference/gobject/gobject.cI delete mode 100644 docs/reference/gobject/gobject.types create mode 100644 gio/completion/.gitignore create mode 100755 gio/completion/gio create mode 100644 gio/fam/gfamfilemonitor.map create mode 100644 gio/fam/meson.build delete mode 100644 gio/gcocoanotificationbackend.c create mode 100644 gio/gcocoanotificationbackend.m create mode 100644 gio/gio-launch-desktop.c create mode 100644 gio/gio-querymodules-wrapper.py delete mode 100644 gio/gnetworking.h.win32 delete mode 100644 gio/gnextstepsettingsbackend.c create mode 100644 gio/gnextstepsettingsbackend.m delete mode 100644 gio/gosxappinfo.c create mode 100644 gio/gosxappinfo.m delete mode 100644 gio/gosxcontenttype.c create mode 100644 gio/gosxcontenttype.m delete mode 100644 gio/org.freedesktop.portal.NetworkMonitor.xml create mode 100644 gio/tests/mount-operation.c create mode 100644 gio/tests/org.gtk.test.gschema.override.orig create mode 100644 gio/tests/trash.c delete mode 100755 glib-zip.in create mode 100644 glib/garcbox.c delete mode 100644 glib/glibconfig.h.win32.in create mode 100644 glib/grcbox.c create mode 100644 glib/grcbox.h create mode 100644 glib/grcboxprivate.h create mode 100644 glib/grefcount.c create mode 100644 glib/grefcount.h create mode 100644 glib/grefstring.c create mode 100644 glib/grefstring.h create mode 100644 glib/gspawn-private.h create mode 100644 glib/gvalgrind.h create mode 100644 glib/tests/bookmarks/fail-18.xbel create mode 100644 glib/tests/bookmarks/fail-19.xbel create mode 100644 glib/tests/bookmarks/fail-20.xbel create mode 100644 glib/tests/bookmarks/fail-21.xbel create mode 100644 glib/tests/bookmarks/fail-22.xbel create mode 100644 glib/tests/bookmarks/fail-23.xbel create mode 100644 glib/tests/bookmarks/fail-24.xbel create mode 100644 glib/tests/bookmarks/fail-25.xbel create mode 100644 glib/tests/bookmarks/fail-26.xbel create mode 100644 glib/tests/bookmarks/fail-27.xbel create mode 100644 glib/tests/bookmarks/fail-28.xbel create mode 100644 glib/tests/bookmarks/fail-29.xbel create mode 100644 glib/tests/bookmarks/fail-30.xbel create mode 100644 glib/tests/bookmarks/fail-31.xbel create mode 100644 glib/tests/bookmarks/fail-32.xbel create mode 100644 glib/tests/bookmarks/fail-33.xbel create mode 100644 glib/tests/bookmarks/fail-34.xbel create mode 100644 glib/tests/bookmarks/fail-35.xbel create mode 100644 glib/tests/bookmarks/fail-36.xbel create mode 100644 glib/tests/bookmarks/fail-37.xbel create mode 100644 glib/tests/bookmarks/fail-38.xbel create mode 100644 glib/tests/markups/fail-50.expected create mode 100644 glib/tests/markups/fail-50.gmarkup create mode 100644 glib/tests/markups/fail-51.expected create mode 100644 glib/tests/markups/fail-51.gmarkup create mode 100644 glib/tests/rcbox.c create mode 100644 glib/tests/refcount.c create mode 100644 glib/tests/refstring.c delete mode 100644 gmodule/gmoduleconf.h.win32 create mode 100644 gobject/tests/mkenums.py create mode 100644 gobject/tests/taptestrunner.py create mode 100644 subprojects/Makefile.am create mode 100644 template.test.in delete mode 100755 tests/gen-casefold-txt.pl create mode 100755 tests/gen-casefold-txt.py delete mode 100755 tests/gen-casemap-txt.pl create mode 100755 tests/gen-casemap-txt.py delete mode 100644 tests/gio-ls.c delete mode 100644 tests/gobject/ifacecheck.c delete mode 100644 tests/gobject/ifaceinherit.c delete mode 100644 tests/gobject/ifaceinit.c delete mode 100755 tests/gobject/run-performance.sh delete mode 100644 win32/Makefile-newvs.am delete mode 100644 win32/Makefile.am delete mode 100644 win32/Makefile.msvcproj delete mode 100644 win32/detectenv-msvc.mak delete mode 100644 win32/gen_util_scripts.py delete mode 100644 win32/glibpc.py delete mode 100644 win32/pc_base.py delete mode 100644 win32/replace.py delete mode 100644 win32/setup.py delete mode 100644 win32/vs10/.gitignore delete mode 100644 win32/vs10/Makefile.am delete mode 100644 win32/vs10/README.txt delete mode 100644 win32/vs10/gdbus.vcxproj delete mode 100644 win32/vs10/gdbus.vcxproj.filters delete mode 100644 win32/vs10/gio-querymodules.vcxproj delete mode 100644 win32/vs10/gio-querymodules.vcxproj.filters delete mode 100644 win32/vs10/gio-tool.vcxproj.filtersin delete mode 100644 win32/vs10/gio-tool.vcxprojin delete mode 100644 win32/vs10/gio.vcxproj.filtersin delete mode 100644 win32/vs10/gio.vcxprojin delete mode 100644 win32/vs10/glib-build-defines.props delete mode 100644 win32/vs10/glib-compile-resources.vcxproj.filtersin delete mode 100644 win32/vs10/glib-compile-resources.vcxprojin delete mode 100644 win32/vs10/glib-compile-schemas.vcxproj.filtersin delete mode 100644 win32/vs10/glib-compile-schemas.vcxprojin delete mode 100644 win32/vs10/glib-gen-srcs.props delete mode 100644 win32/vs10/glib-install.propsin delete mode 100644 win32/vs10/glib-install.vcxproj delete mode 100644 win32/vs10/glib-install.vcxproj.filters delete mode 100644 win32/vs10/glib-version-paths.props.in delete mode 100644 win32/vs10/glib.sln delete mode 100644 win32/vs10/glib.vcxproj.filtersin delete mode 100644 win32/vs10/glib.vcxprojin delete mode 100644 win32/vs10/gmodule.vcxproj delete mode 100644 win32/vs10/gmodule.vcxproj.filters delete mode 100644 win32/vs10/gobject.vcxproj.filtersin delete mode 100644 win32/vs10/gobject.vcxprojin delete mode 100644 win32/vs10/gresource.vcxproj delete mode 100644 win32/vs10/gresource.vcxproj.filters delete mode 100644 win32/vs10/gsettings.vcxproj delete mode 100644 win32/vs10/gsettings.vcxproj.filters delete mode 100644 win32/vs10/gspawn-win32-helper-console.vcxproj delete mode 100644 win32/vs10/gspawn-win32-helper-console.vcxproj.filters delete mode 100644 win32/vs10/gspawn-win32-helper.vcxproj delete mode 100644 win32/vs10/gspawn-win32-helper.vcxproj.filters delete mode 100644 win32/vs10/gthread.vcxproj delete mode 100644 win32/vs10/gthread.vcxproj.filters delete mode 100644 win32/vs11/.gitignore delete mode 100644 win32/vs11/Makefile.am delete mode 100644 win32/vs12/.gitignore delete mode 100644 win32/vs12/Makefile.am delete mode 100644 win32/vs14/Makefile.am delete mode 100644 win32/vs15/Makefile.am delete mode 100644 win32/vs9/.gitignore delete mode 100644 win32/vs9/Makefile.am delete mode 100644 win32/vs9/README.txt delete mode 100644 win32/vs9/gdbus.vcproj delete mode 100644 win32/vs9/gio-querymodules.vcproj delete mode 100644 win32/vs9/gio-tool.vcprojin delete mode 100644 win32/vs9/gio.vcprojin delete mode 100644 win32/vs9/glib-build-defines.vsprops delete mode 100644 win32/vs9/glib-compile-resources.vcprojin delete mode 100644 win32/vs9/glib-compile-schemas.vcprojin delete mode 100644 win32/vs9/glib-gen-srcs.vsprops delete mode 100644 win32/vs9/glib-install.vcproj delete mode 100644 win32/vs9/glib-install.vspropsin delete mode 100644 win32/vs9/glib-version-paths.vsprops.in delete mode 100644 win32/vs9/glib.sln delete mode 100644 win32/vs9/glib.vcprojin delete mode 100644 win32/vs9/gmodule.vcproj delete mode 100644 win32/vs9/gobject.vcprojin delete mode 100644 win32/vs9/gresource.vcproj delete mode 100644 win32/vs9/gsettings.vcproj delete mode 100644 win32/vs9/gspawn-win32-helper-console.vcproj delete mode 100644 win32/vs9/gspawn-win32-helper.vcproj delete mode 100644 win32/vs9/gthread.vcproj diff --git a/.gitignore b/.gitignore index 4443f04d3..0caa0c05d 100644 --- a/.gitignore +++ b/.gitignore @@ -46,13 +46,11 @@ mingw32-config.cache missing install-sh glib-gettextize -glib-zip gtk-doc.make py-compile test-driver INSTALL -README ChangeLog /glib-lcov.info /glib-lcov/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6f63a7e1e..916f41e16 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: registry.gitlab.gnome.org/gnome/glib/master:v1 +image: registry.gitlab.gnome.org/gnome/glib/master:v6 stages: - build @@ -9,28 +9,64 @@ cache: paths: - _ccache/ -fedora-meson-x86_64: +variables: + MESON_TEST_TIMEOUT_MULTIPLIER: 2 + +fedora-x86_64: stage: build + except: + - tags variables: - CFLAGS: "-coverage -ftest-coverage -fprofile-arcs" + CFLAGS: "-coverage -ftest-coverage -fprofile-arcs" script: - - meson --prefix /usr --libdir /usr/lib64 --buildtype debug --werror -Dsystemtap=true -Ddtrace=true _build . - - cd _build - - ninja - - meson test --timeout-multiplier 2 - - cd .. + - meson --buildtype debug --werror -Dsystemtap=true -Ddtrace=true -Dfam=true _build . + - ninja -C _build - mkdir -p _coverage - - lcov --rc lcov_branch_coverage=1 --directory . --capture --no-external --output-file "_coverage/${CI_JOB_NAME}.lcov" + - lcov --rc lcov_branch_coverage=1 --directory _build --capture --initial --output-file "_coverage/${CI_JOB_NAME}-baseline.lcov" + - meson test -C _build --timeout-multiplier ${MESON_TEST_TIMEOUT_MULTIPLIER} + - lcov --rc lcov_branch_coverage=1 --directory _build --capture --output-file "_coverage/${CI_JOB_NAME}.lcov" + artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/meson-logs" + - "_coverage" + +.cross-template: &cross-template + stage: build except: - tags artifacts: - name: "glib-_${CI_COMMIT_REF_NAME}" + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always paths: - - "${CI_PROJECT_DIR}/_build/meson-logs" - - "${CI_PROJECT_DIR}/_coverage" + - "_build/meson-logs" + +cross-android_api21_arm64: + <<: *cross-template + script: + # FIXME: add --werror + - meson --cross-file=/opt/cross_file_android_arm64_21.txt -Diconv=gnu -Dinternal_pcre=true --buildtype debug _build + - ninja -C _build + +cross-android_api28_arm64: + <<: *cross-template + script: + # FIXME: add --werror + - meson --cross-file=/opt/cross_file_android_arm64_28.txt -Dinternal_pcre=true --buildtype debug _build + - ninja -C _build + +cross-mingw64: + <<: *cross-template + script: + # FIXME: Add --werror + - meson --cross-file=/opt/cross_file_mingw64.txt --buildtype debug _build + - ninja -C _build msys2-mingw32: stage: build + except: + - tags tags: - win32 variables: @@ -40,36 +76,93 @@ msys2-mingw32: - C:\msys64\usr\bin\pacman --noconfirm -Syyuu --ask 20 - C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh" artifacts: + name: "glib-%CI_JOB_NAME%-%CI_COMMIT_REF_NAME%" + when: always paths: + - _build/meson-logs - _coverage/ +vs2017-x64: + stage: build + except: + - tags + tags: + - win32 + script: + - .gitlab-ci/test-msvc.bat + artifacts: + name: "glib-%CI_JOB_NAME%-%CI_COMMIT_REF_NAME%" + when: always + paths: + - _build/meson-logs + +freebsd-11-x86_64: + when: manual + stage: build + tags: + # To run a FreeBSD builder, install gitlab-runner package and start both + # gitlab-runner and dbus service because we need /var/lib/dbus/machine-id. + # To compile GLib, you still have to install the following packages: + # desktop-file-utils gettext libiconv meson pkgconf python3 shared-mime-info + - freebsd-11 + variables: + # CPPFLAGS is required because libintl doesn't use pkg-config. + CPPFLAGS: -I/usr/local/include + # FIXME: Workaround meson inability to set LD_LIBRARY_PATH. + # https://github.com/mesonbuild/meson/issues/1383 + # https://github.com/mesonbuild/meson/issues/1635 + # https://github.com/mesonbuild/meson/issues/2881 + LDFLAGS: -L/usr/local/lib -Wl,--disable-new-dtags + # FreeBSD doesn't have C.UTF-8 locale. + LANG: en_US.UTF-8 + script: + # We cannot use -Wl,--no-undefined because GLib uses 'environ' variable. + # FreeBSD iconv doesn't handle transliteration, so we use GNU libiconv here. + # FreeBSD supports xattr, but its API is different from Linux xattr. + # FIXME: extattr(2) support: https://gitlab.gnome.org/GNOME/glib/issues/1404 + - meson -Db_lundef=false -Diconv=gnu -Dxattr=false --buildtype debug _build + - ninja -C _build + - meson test -C _build --timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" + # FIXME: Remove this when we have a stable FreeBSD runner + # https://gitlab.gnome.org/Infrastructure/GitLab/issues/286 + allow_failure: true + except: + - tags + artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_build/meson-logs" + coverage: stage: coverage artifacts: + name: "glib-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" paths: - _coverage/ script: - bash -x ./.gitlab-ci/coverage-docker.sh + coverage: '/^\s+lines\.+:\s+([\d.]+\%)\s+/' pages: stage: deploy + only: + - master script: - mv _coverage/ public/ artifacts: paths: - public - only: - - master dist-job: stage: build only: - tags script: - - meson --prefix /usr --libdir /usr/lib64 --buildtype release -Dgtk_doc=true -Dman=true _build . + - meson --buildtype release -Dgtk_doc=true -Dman=true _build - cd _build - ninja dist - - ninja glib-doc + - ninja glib-doc gobject-doc gio-doc - tar -c -f "glib-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/glib html - tar -c -f "gobject-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/gobject html - tar -c -f "gio-docs-$CI_COMMIT_TAG.tar.xz" -C docs/reference/gio html diff --git a/.gitlab-ci/Dockerfile b/.gitlab-ci/Dockerfile index dab235166..06d3a4ae3 100644 --- a/.gitlab-ci/Dockerfile +++ b/.gitlab-ci/Dockerfile @@ -4,6 +4,7 @@ RUN dnf -y install \ desktop-file-utils \ elfutils-libelf-devel \ findutils \ + gamin-devel \ gcc \ gcc-c++ \ gettext \ @@ -18,16 +19,36 @@ RUN dnf -y install \ libmount-devel \ libselinux-devel \ libxslt \ + make \ + mingw64-gcc \ + mingw64-gcc-c++ \ + mingw64-gettext \ + mingw64-libffi \ + mingw64-zlib \ + ncurses-compat-libs \ ninja-build \ pcre-devel \ python3 \ python3-pip \ python3-wheel \ systemtap-sdt-devel \ + unzip \ + wget \ zlib-devel \ && dnf clean all -RUN pip3 install meson +WORKDIR /opt +ENV ANDROID_NDK_PATH /opt/android-ndk +COPY android-download-ndk.sh . +RUN ./android-download-ndk.sh +COPY android-setup-env.sh . +RUN ./android-setup-env.sh arm64 21 +RUN ./android-setup-env.sh arm64 28 +RUN rm -rf $ANDROID_NDK_PATH + +COPY cross_file_mingw64.txt /opt + +RUN pip3 install meson==0.47.0 ARG HOST_USER_ID=5555 ENV HOST_USER_ID ${HOST_USER_ID} diff --git a/.gitlab-ci/android-download-ndk.sh b/.gitlab-ci/android-download-ndk.sh new file mode 100755 index 000000000..785ee0189 --- /dev/null +++ b/.gitlab-ci/android-download-ndk.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Copyright 2018 Collabora ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# +# Author: Xavier Claessens +# + +set -e + +# Download Android NDK +ANDROID_NDK_VERSION="r17b" +ANDROID_NDK_SHA512="062fac12f747730f5563995089a8b4abab683fbbc621aa8582fdf35fe327daee5d69ed2437af257c10ec4ef54ecd3805a8f134a1400eb8f34ee76f55c8dc9ae9" +wget --quiet https://dl.google.com/android/repository/android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip +echo "$ANDROID_NDK_SHA512 android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip" | sha512sum -c +unzip android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip +rm android-ndk-$ANDROID_NDK_VERSION-linux-x86_64.zip +mv android-ndk-$ANDROID_NDK_VERSION $ANDROID_NDK_PATH diff --git a/.gitlab-ci/android-setup-env.sh b/.gitlab-ci/android-setup-env.sh new file mode 100755 index 000000000..510056f66 --- /dev/null +++ b/.gitlab-ci/android-setup-env.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# +# Copyright 2018 Collabora ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# +# Author: Xavier Claessens +# + +set -e + +arch=$1 +api=$2 +toolchain_path=$(pwd)/android-toolchain-$arch-$api +prefix_path=$(pwd)/android-$arch-$api + +# Create standalone toolchains +$ANDROID_NDK_PATH/build/tools/make_standalone_toolchain.py --arch $arch --api $api --install-dir $toolchain_path + +target_host=aarch64-linux-android +export AR=$target_host-ar +export AS=$target_host-clang +export CC=$target_host-clang +export CXX=$target_host-clang++ +export LD=$target_host-ld +export STRIP=$target_host-strip +export PATH=$PATH:$toolchain_path/bin + +# Cross build libiconv when using API level <= 28. +# Newer Android has it in its libc already. +if [ "$api" -lt "28" ]; then + wget --quiet http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz + echo "1233fe3ca09341b53354fd4bfe342a7589181145a1232c9919583a8c9979636855839049f3406f253a9d9829908816bb71fd6d34dd544ba290d6f04251376b1a libiconv-1.15.tar.gz" | sha512sum -c + tar xzf libiconv-1.15.tar.gz + pushd libiconv-1.15 + ./configure --host=$target_host --prefix=$prefix_path --libdir=$prefix_path/lib64 + make + make install + popd + rm libiconv-1.15.tar.gz + rm -r libiconv-1.15 +fi + +# Cross build libffi +wget --quiet https://github.com/libffi/libffi/releases/download/v3.3-rc0/libffi-3.3-rc0.tar.gz +echo "e6e695d32cd6eb7d65983f32986fccdfc786a593d2ea18af30ce741f58cfa1eb264b1a8d09df5084cb916001aea15187b005c2149a0620a44397a4453b6137d4 libffi-3.3-rc0.tar.gz" | sha512sum -c +tar xzf libffi-3.3-rc0.tar.gz +pushd libffi-3.3-rc0 +./configure --host=$target_host --prefix=$prefix_path --libdir=$prefix_path/lib64 +make +make install +popd +rm libffi-3.3-rc0.tar.gz +rm -r libffi-3.3-rc0 + +# Create a pkg-config wrapper that won't pick fedora libraries +mkdir -p $prefix_path/bin +export PKG_CONFIG=$prefix_path/bin/pkg-config +cat > $PKG_CONFIG <<- EOM +#!/bin/sh +SYSROOT=${prefix_path} +export PKG_CONFIG_DIR= +export PKG_CONFIG_LIBDIR=\${SYSROOT}/lib64/pkgconfig +export PKG_CONFIG_SYSROOT_DIR=\${SYSROOT} +exec pkg-config "\$@" +EOM +chmod +x $PKG_CONFIG + +# Create a cross file that can be passed to meson +cat > cross_file_android_${arch}_${api}.txt <<- EOM +[host_machine] +system = 'android' +cpu_family = 'arm64' +cpu = 'arm64' +endian = 'little' + +[properties] +c_args = ['-I${prefix_path}/include'] +c_link_args = ['-L${prefix_path}/lib64', + '-fuse-ld=gold'] + +[binaries] +c = '${toolchain_path}/bin/${CC}' +cpp = '${toolchain_path}/bin/${CXX}' +ar = '${toolchain_path}/bin/${AR}' +strip = '${toolchain_path}/bin/${STRIP}' +pkgconfig = '${PKG_CONFIG}' +EOM diff --git a/.gitlab-ci/coverage-docker.sh b/.gitlab-ci/coverage-docker.sh index 49118d606..63e305147 100755 --- a/.gitlab-ci/coverage-docker.sh +++ b/.gitlab-ci/coverage-docker.sh @@ -5,9 +5,11 @@ set -e # Fixup Windows paths python3 ./.gitlab-ci/fixup-cov-paths.py _coverage/*.lcov -# Remove coverage from generated code in the build directory for path in _coverage/*.lcov; do + # Remove coverage from generated code in the build directory lcov --rc lcov_branch_coverage=1 -r "${path}" '*/_build/*' -o "$(pwd)/${path}" + # Remove any coverage from system files + lcov --rc lcov_branch_coverage=1 -e "${path}" "$(pwd)/*" -o "$(pwd)/${path}" done genhtml \ diff --git a/.gitlab-ci/cross_file_mingw64.txt b/.gitlab-ci/cross_file_mingw64.txt new file mode 100644 index 000000000..1897b686a --- /dev/null +++ b/.gitlab-ci/cross_file_mingw64.txt @@ -0,0 +1,17 @@ +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] +c_args = [] +c_link_args = [] + +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +strip = 'x86_64-w64-mingw32-strip' +pkgconfig = 'x86_64-w64-mingw32-pkg-config' +windres = 'x86_64-w64-mingw32-windres' diff --git a/.gitlab-ci/run-docker.sh b/.gitlab-ci/run-docker.sh index 4fc59a1d6..91d3042e7 100755 --- a/.gitlab-ci/run-docker.sh +++ b/.gitlab-ci/run-docker.sh @@ -2,10 +2,16 @@ set -e -TAG="registry.gitlab.gnome.org/gnome/glib/master:v1" +TAG="registry.gitlab.gnome.org/gnome/glib/master:v6" -sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \ +docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \ --file "Dockerfile" . -sudo docker run --rm \ - --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \ - --tty --interactive "${TAG}" bash + +if [ "$1" = "--push" ]; then + docker login registry.gitlab.gnome.org + docker push $TAG +else + docker run --rm \ + --volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \ + --tty --interactive "${TAG}" bash +fi diff --git a/.gitlab-ci/test-msvc.bat b/.gitlab-ci/test-msvc.bat new file mode 100644 index 000000000..9b674f76e --- /dev/null +++ b/.gitlab-ci/test-msvc.bat @@ -0,0 +1,19 @@ +@echo on +:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the +:: specified build architecture +call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 +@echo on + +:: FIXME: make warnings fatal +pip3 install --upgrade --user meson==0.47.0 || goto :error +meson _build || goto :error +ninja -C _build || goto :error + +:: FIXME: dont ignore test errors +meson test -C _build --timeout-multiplier %MESON_TEST_TIMEOUT_MULTIPLIER% + +:: FIXME: can we get code coverage support? + +goto :EOF +:error +exit /b 1 diff --git a/.gitlab-ci/test-msys2.sh b/.gitlab-ci/test-msys2.sh index a3b0ef906..d8891e35b 100755 --- a/.gitlab-ci/test-msys2.sh +++ b/.gitlab-ci/test-msys2.sh @@ -23,29 +23,38 @@ pacman --noconfirm -S --needed \ mingw-w64-$MSYS2_ARCH-toolchain \ mingw-w64-$MSYS2_ARCH-zlib +curl -O -J -L "https://github.com/linux-test-project/lcov/releases/download/v1.13/lcov-1.13.tar.gz" +echo "44972c878482cc06a05fe78eaa3645cbfcbad6634615c3309858b207965d8a23 lcov-1.13.tar.gz" | sha256sum -c +tar -xzf lcov-1.13.tar.gz +LCOV="$(pwd)/lcov-1.13/bin/lcov" + +mkdir -p _coverage mkdir -p _ccache export CCACHE_BASEDIR="$(pwd)" export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache" -pip3 install --upgrade --user meson +pip3 install --upgrade --user meson==0.47.0 export PATH="$HOME/.local/bin:$PATH" export CFLAGS="-coverage -ftest-coverage -fprofile-arcs" +DIR="$(pwd)" meson --werror --buildtype debug _build cd _build ninja -# FIXME: fix the test suite -meson test || true +"${LCOV}" \ + --quiet \ + --rc lcov_branch_coverage=1 \ + --directory "${DIR}/_build" \ + --capture \ + --initial \ + --output-file "${DIR}/_coverage/${CI_JOB_NAME}-baseline.lcov" -cd .. -curl -O -J -L "https://github.com/linux-test-project/lcov/releases/download/v1.13/lcov-1.13.tar.gz" -echo "44972c878482cc06a05fe78eaa3645cbfcbad6634615c3309858b207965d8a23 lcov-1.13.tar.gz" | sha256sum -c -tar -xvzf lcov-1.13.tar.gz +# FIXME: fix the test suite +meson test --timeout-multiplier ${MESON_TEST_TIMEOUT_MULTIPLIER} || true -mkdir -p _coverage -./lcov-1.13/bin/lcov \ +"${LCOV}" \ + --quiet \ --rc lcov_branch_coverage=1 \ - --directory . \ + --directory "${DIR}/_build" \ --capture \ - --no-external \ - --output-file "_coverage/${CI_JOB_NAME}.lcov" + --output-file "${DIR}/_coverage/${CI_JOB_NAME}.lcov" diff --git a/AUTHORS b/AUTHORS index 17814caa1..16884db81 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,7 +1,7 @@ Below are just a few of the people who have contributed to GLib. Please don't mail these people about problems you -have with GTK+; see the README file for information about -filing bugs and submitting patches. +have with GLib; see the README.md file for information about +filing bugs and submitting changes. GLib-2.0 Team ------------- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..5345964ee --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,72 @@ +GLib is part of the GNOME git repository. At the current time, any +person with write access to the GNOME repository, can make changes to +GLib. This is a good thing, in that it encourages many people to work +on GLib, and progress can be made quickly. However, GLib is a fairly +large and complicated package that many other things depend on, so to +avoid unnecessary breakage, and to take advantage of the knowledge +about GLib that has been built up over the years, we'd like to ask +people committing to GLib to follow a few rules: + +0) Ask first. If your changes are major, or could possibly break existing + code, you should always ask. If your change is minor and you've + been working on GLib for a while it probably isn't necessary + to ask. But when in doubt, ask. Even if your change is correct, + somebody may know a better way to do things. + + If you are making changes to GLib, you should be subscribed + to gtk-devel-list@gnome.org. (Subscription address: + gtk-devel-list-request@gnome.org.) This is a good place to ask + about intended changes. + + #gtk+ on GIMPNet (irc.gimp.org, irc.us.gimp.org, irc.eu.gimp.org, ...) + is also a good place to find GTK+ developers to discuss changes with, + however, email to gtk-devel-list is the most certain and preferred + method. + +1) Ask _first_. + +2) With git, we no longer maintain a ChangeLog file, but you are expected + to produce a meaningful commit message. Changes without a sufficient + commit message will be reverted. See below for the expected format + of commit messages. + +Notes: + +* When developing larger features or complicated bug fixes, it is + advisable to work in a branch in your own cloned GLib repository. + You may even consider making your repository publically available + so that others can easily test and review your changes. + +* The expected format for git commit messages is as follows: + +=== begin example commit === +Short explanation of the commit + +Longer explanation explaining exactly what's changed, whether any +external or private interfaces changed, what bugs were fixed (with bug +tracker reference if applicable) and so forth. Be concise but not too brief. +=== end example commit === + + - Always add a brief description of the commit to the _first_ line of + the commit and terminate by two newlines (it will work without the + second newline, but that is not nice for the interfaces). + + - First line (the brief description) must only be one sentence and + should start with a capital letter unless it starts with a lowercase + symbol or identifier. Don't use a trailing period either. Don't exceed + 72 characters. + + - The main description (the body) is normal prose and should use normal + punctuation and capital letters where appropriate. Normally, for patches + sent to a mailing list it's copied from there. + + - When committing code on behalf of others use the --author option, e.g. + git commit -a --author "Joe Coder " and --signoff. + + +Owen Taylor +13 Aug 1998 +17 Apr 2001 + +Matthias Clasen +31 Mar 2009 diff --git a/HACKING b/HACKING index e04e0dcdd..7c130ab40 100644 --- a/HACKING +++ b/HACKING @@ -33,5 +33,5 @@ Note that autogen.sh runs configure for you. If you wish to pass options like --prefix=/usr to configure you can give those options to autogen.sh and they will be passed on to configure. -For information about submitting patches see the README.commits file. For +For information about submitting patches see the CONTRIBUTING.md file. For information about major design decisions, see the README.rationale file. diff --git a/Makefile.am b/Makefile.am index 49b5e4e71..a888e6df3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,8 +6,8 @@ include $(top_srcdir)/glib.mk ACLOCAL_AMFLAGS = -I m4macros ${ACLOCAL_FLAGS} -SUBDIRS = . m4macros glib gmodule gthread gobject gio po docs tests -DIST_SUBDIRS = $(SUBDIRS) build win32 +SUBDIRS = . m4macros glib gmodule gthread gobject gio po docs tests subprojects +DIST_SUBDIRS = $(SUBDIRS) build bin_SCRIPTS = glib-gettextize @@ -34,12 +34,11 @@ EXTRA_DIST += \ ChangeLog.pre-2-2 \ ChangeLog.pre-2-0 \ ChangeLog.pre-1-2 \ - glib-zip.in \ NEWS.pre-1-3 \ acglib.m4 \ sanity_check \ - README.commits \ - README.in \ + CONTRIBUTING.md \ + README.md \ README.rationale \ INSTALL.in \ README.win32 \ @@ -50,7 +49,6 @@ EXTRA_DIST += \ tap-driver.sh \ tap-test \ msvc_recommended_pragmas.h \ - config.h.win32.in \ po/po2tbl.sed.in \ glib-2.0.pc.in \ gobject-2.0.pc.in \ @@ -66,7 +64,6 @@ EXTRA_DIST += \ $(NULL) meson_build_files = \ - config.h.meson \ meson_options.txt \ meson.build \ docs/reference/gio/meson.build \ @@ -79,7 +76,10 @@ meson_build_files = \ docs/reference/gobject/xml/gtkdocentities.ent.in \ docs/reference/gobject/xml/meson.build \ gio/data-to-c.py \ + gio/fam/gfamfilemonitor.map \ + gio/fam/meson.build \ gio/gdbus-2.0/codegen/meson.build \ + gio/gio-querymodules-wrapper.py \ gio/inotify/meson.build \ gio/kqueue/meson.build \ gio/meson.build \ @@ -110,10 +110,8 @@ EXTRA_DIST += $(meson_build_files) # These may be in the builddir too BUILT_EXTRA_DIST += \ - README \ INSTALL \ ChangeLog \ - config.h.win32 \ $(NULL) CONFIGURE_DEPENDENCIES = acglib.m4 diff --git a/NEWS b/NEWS index e9a88e435..9794c4497 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,32 @@ +Overview of changes in GLib 2.57.2 +================================== + +* Require pcre 8.31 +* Require meson 0.47.0 + +* Bugs fixed: + 742456 Add g_steal_pointer() convenience function to mark ownership... + 795569 MinGW CI: fix tests + 796341 gmem.h: Use typeof() in g_steal_pointer() macro + #1013 Support for per-session overrides + #1360 glib-mkenums breaks if option specified but no nick + #1175 Add names and tags to various GSources and GTasks constructed in GLib + #903 g_main_context_wait() not deprecated in API, but emits a g_critical()... + #786 Fix memory leaks in libgio tests + #927 gio/gresource.c:do_lookup check for terminating "/" + #976 Document difference between g_assert() and g_assert_*()... + #1447 glib 2.57.1: test_month_names: assertion failed... + #1407 Update to Unicode Character Database 11 + #1455 glib python tools have full python path in shebang, limits to 128 characters + #1459 Missing g_return_val_if_fail in g_async_queue_timeout_pop + +* Translation updates: + Friulian + German + Romanian + Spanish + + Overview of changes in GLib 2.57.1 ================================== diff --git a/README b/README new file mode 100644 index 000000000..96dc92fbd --- /dev/null +++ b/README @@ -0,0 +1 @@ +See README.md diff --git a/README.commits b/README.commits deleted file mode 100644 index 5345964ee..000000000 --- a/README.commits +++ /dev/null @@ -1,72 +0,0 @@ -GLib is part of the GNOME git repository. At the current time, any -person with write access to the GNOME repository, can make changes to -GLib. This is a good thing, in that it encourages many people to work -on GLib, and progress can be made quickly. However, GLib is a fairly -large and complicated package that many other things depend on, so to -avoid unnecessary breakage, and to take advantage of the knowledge -about GLib that has been built up over the years, we'd like to ask -people committing to GLib to follow a few rules: - -0) Ask first. If your changes are major, or could possibly break existing - code, you should always ask. If your change is minor and you've - been working on GLib for a while it probably isn't necessary - to ask. But when in doubt, ask. Even if your change is correct, - somebody may know a better way to do things. - - If you are making changes to GLib, you should be subscribed - to gtk-devel-list@gnome.org. (Subscription address: - gtk-devel-list-request@gnome.org.) This is a good place to ask - about intended changes. - - #gtk+ on GIMPNet (irc.gimp.org, irc.us.gimp.org, irc.eu.gimp.org, ...) - is also a good place to find GTK+ developers to discuss changes with, - however, email to gtk-devel-list is the most certain and preferred - method. - -1) Ask _first_. - -2) With git, we no longer maintain a ChangeLog file, but you are expected - to produce a meaningful commit message. Changes without a sufficient - commit message will be reverted. See below for the expected format - of commit messages. - -Notes: - -* When developing larger features or complicated bug fixes, it is - advisable to work in a branch in your own cloned GLib repository. - You may even consider making your repository publically available - so that others can easily test and review your changes. - -* The expected format for git commit messages is as follows: - -=== begin example commit === -Short explanation of the commit - -Longer explanation explaining exactly what's changed, whether any -external or private interfaces changed, what bugs were fixed (with bug -tracker reference if applicable) and so forth. Be concise but not too brief. -=== end example commit === - - - Always add a brief description of the commit to the _first_ line of - the commit and terminate by two newlines (it will work without the - second newline, but that is not nice for the interfaces). - - - First line (the brief description) must only be one sentence and - should start with a capital letter unless it starts with a lowercase - symbol or identifier. Don't use a trailing period either. Don't exceed - 72 characters. - - - The main description (the body) is normal prose and should use normal - punctuation and capital letters where appropriate. Normally, for patches - sent to a mailing list it's copied from there. - - - When committing code on behalf of others use the --author option, e.g. - git commit -a --author "Joe Coder " and --signoff. - - -Owen Taylor -13 Aug 1998 -17 Apr 2001 - -Matthias Clasen -31 Mar 2009 diff --git a/README.in b/README.in deleted file mode 100644 index 3e8b2e5fc..000000000 --- a/README.in +++ /dev/null @@ -1,366 +0,0 @@ -General Information -=================== - -This is GLib version @GLIB_VERSION@. GLib is the low-level core -library that forms the basis for projects such as GTK+ and GNOME. It -provides data structure handling for C, portability wrappers, and -interfaces for such runtime functionality as an event loop, threads, -dynamic loading, and an object system. - -The official download locations are: - ftp://ftp.gtk.org/pub/glib - http://download.gnome.org/sources/glib - -The official web site is: - http://www.gtk.org/ - -Information about mailing lists can be found at - http://www.gtk.org/mailing-lists.php - -To subscribe, send mail to gtk-list-request@gnome.org -with the subject "subscribe". - -Installation -============ - -See the file 'INSTALL' - -How to report bugs -================== - -Bugs should be reported to the GNOME bug tracking system. -(http://bugzilla.gnome.org, product glib.) You will need -to create an account for yourself. - -In the bug report please include: - -* Information about your system. For instance: - - - What operating system and version - - For Linux, what version of the C library - - And anything else you think is relevant. - -* How to reproduce the bug. - - If you can reproduce it with one of the test programs that are built - in the tests/ subdirectory, that will be most convenient. Otherwise, - please include a short test program that exhibits the behavior. - As a last resort, you can also provide a pointer to a larger piece - of software that can be downloaded. - -* If the bug was a crash, the exact text that was printed out - when the crash occured. - -* Further information such as stack traces may be useful, but - is not necessary. - -Patches -======= - -Patches should also be submitted to bugzilla.gnome.org. If the -patch fixes an existing bug, add the patch as an attachment -to that bug report. - -Otherwise, enter a new bug report that describes the patch, -and attach the patch to that bug report. - -Patches should be in unified diff form. (The -up option to GNU diff.) - -Notes about GLib 2.48 -===================== - -* The system copy of PCRE is now used by default to implement GRegex. - Configure with --with-pcre=internal if a system PCRE version - is unavailable or undesired. - -Notes about GLib 2.46 -===================== - -* GTask no longer imposes a fixed limit on the number of tasks that - can be run_in_thread() simultaneously, since doing this inevitably - results in deadlocks in some use cases. Instead, it now has a base - number of threads that can be used "for free", but will gradually - add more threads to the pool if too much time passes without any - tasks completing. - - The exact behavior may continue to change in the future, and it's - possible that some future version of GLib may not do any - rate-limiting at all. As a result, you should no longer assume that - GTask will rate-limit tasks itself (or, by extension, that calls to - certain async gio methods will automatically be rate-limited for - you). If you have a very large number of tasks to run, and don't - want them to all run at once, you should rate-limit them yourself. - -Notes about GLib 2.40 -===================== - -* g_test_run() no longer runs tests in exactly the order they are - registered; instead, it groups them according to test suites (ie, - path components) like the documentation always claimed it did. In - some cases, this can result in a sub-optimal ordering of tests, - relative to the old behavior. The fix is to change the test paths to - properly group together the tests that should run together. (eg, if - you want to run test_foo_simple(), test_bar_simple(), and - test_foo_using_bar() in that order, they should have test paths like - "/simple/foo", "/simple/bar", "/complex/foo-using-bar", not - "/foo/simple", "/bar/simple", "/foo/using-bar" (which would result - in test_foo_using_bar() running before test_bar_simple()). - - (The behavior actually changed in GLib 2.36, but it was not - documented at the time, since we didn't realize it mattered.) - -Notes about GLib 2.36 -===================== - -* It is no longer necessary to call g_type_init(). If you are - loading GLib as a dynamic module, you should be careful to avoid - unloading it, then subsequently loading it again. This never - really worked before, but it is now explicitly undefined behavior. - Note that if g_type_init() was the only explicit use of a GObject - API and you are using linker flags such as --no-add-needed, then - you may have to artificially use some GObject call to keep the - linker from optimizing away -lgobject. We recommend to use - g_type_ensure (G_TYPE_OBJECT) for this purpose. - -* This release contains an incompatible change to the g_get_home_dir() - function. Previously, this function would effectively ignore the HOME - environment variable and always return the value from /etc/password. - As of this version, the HOME variable is used if it is set and the - value from /etc/passwd is only used as a fallback. - -* The 'flowinfo' and 'scope_id' fields of GInetSocketAddress - (introduced in GLib 2.32) have been fixed to be in host byte order - rather than network byte order. This is an incompatible change, but - the previous behavior was clearly broken, so it seems unlikely that - anyone was using it. - -Notes about GLib 2.34 -===================== - -* GIO now looks for thumbnails in XDG_CACHE_HOME, following a - recent alignment of the thumbnail spec with the basedir spec. - -* The default values for GThreadPools max_unused_threads and - max_idle_time settings have been changed to 2 and 15*1000, - respectively. - -Notes about GLib 2.32 -===================== - -* It is no longer necessary to use g_thread_init() or to link against - libgthread. libglib is now always thread-enabled. Custom thread - system implementations are no longer supported (including errorcheck - mutexes). - -* The thread and synchronisation APIs have been updated. - GMutex and GCond can be statically allocated without explicit - initialisation, as can new types GRWLock and GRecMutex. The - GStatic_______ variants of these types have been deprecated. GPrivate - can also be statically allocated and has a nicer API (deprecating - GStaticPrivate). Finally, g_thread_create() has been replaced with a - substantially simplified g_thread_new(). - -* The g_once_init_enter()/_leave() functions have been replaced with - macros that allow for a pointer to any gsize-sized object, not just a - gsize*. The assertions to ensure that a pointer to a correctly-sized - object is being used will not work with generic pointers (ie: (void*) - and (gpointer) casts) which would have worked with the old version. - -* It is now mandatory to include glib.h instead of individual headers. - -* The -uninstalled variants of the pkg-config files have been dropped. - -* For a long time, gobject-2.0.pc mistakenly declared a public - dependency on gthread-2.0.pc (when the dependency should have been - private). This means that programs got away with calling - g_thread_init() without explicitly listing gthread-2.0.pc among their - dependencies. - - gthread has now been removed as a gobject dependency, which will cause - such programs to break. - - The fix for this problem is either to declare an explicit dependency - on gthread-2.0.pc (if you care about compatibility with older GLib - versions) or to stop calling g_thread_init(). - -* g_debug() output is no longer enabled by default. It can be enabled - on a per-domain basis with the G_MESSAGES_DEBUG environment variable - like - G_MESSAGES_DEBUG=domain1,domain2 - or - G_MESSAGES_DEBUG=all - -Notes about GLib 2.30 -===================== - -* GObject includes a generic marshaller, g_cclosure_marshal_generic. - To use it, simply specify NULL as the marshaller in g_signal_new(). - The generic marshaller is implemented with libffi, and consequently - GObject depends on libffi now. - -Notes about GLib 2.28 -===================== - -* The GApplication API has changed compared to the version that was - included in the 2.25 development snapshots. Existing users will need - adjustments. - -Notes about GLib 2.26 -===================== - -* Nothing noteworthy. - -Notes about GLib 2.24 -===================== - -* It is now allowed to call g_thread_init(NULL) multiple times, and - to call glib functions before g_thread_init(NULL) is called - (although the later is mainly a change in docs as this worked before - too). See the GThread reference documentation for the details. - -* GObject now links to GThread and threads are enabled automatically - when g_type_init() is called. - -* GObject no longer allows to call g_object_set() on construct-only properties - while an object is being initialized. If this behavior is needed, setting a - custom constructor that just chains up will re-enable this functionality. - -* GMappedFile on an empty file now returns NULL for the contents instead of - returning an empty string. The documentation specifically states that code - may not rely on nul-termination here so any breakage caused by this change - is a bug in application code. - -Notes about GLib 2.22 -===================== - -* Repeated calls to g_simple_async_result_set_op_res_gpointer used - to leak the data. This has been fixed to always call the provided - destroy notify. - -Notes about GLib 2.20 -===================== - -* The functions for launching applications (e.g. g_app_info_launch() + - friends) now passes a FUSE file:// URI if possible (requires gvfs - with the FUSE daemon to be running and operational). With gvfs 2.26, - FUSE file:// URIs will be mapped back to gio URIs in the GFile - constructors. The intent of this change is to better integrate - POSIX-only applications, see bug #528670 for the rationale. The - only user-visible change is when an application needs to examine an - URI passed to it (e.g. as a positional parameter). Instead of - looking at the given URI, the application will now need to look at - the result of g_file_get_uri() after having constructed a GFile - object with the given URI. - -Notes about GLib 2.18 -===================== - -* The recommended way of using GLib has always been to only include the - toplevel headers glib.h, glib-object.h and gio.h. GLib enforces this by - generating an error when individual headers are directly included. - To help with the transition, the enforcement is not turned on by - default for GLib headers (it is turned on for GObject and GIO). - To turn it on, define the preprocessor symbol G_DISABLE_SINGLE_INCLUDES. - -Notes about GLib 2.16 -===================== - -* GLib now includes GIO, which adds optional dependencies against libattr - and libselinux for extended attribute and SELinux support. Use - --disable-xattr and --disable-selinux to build without these. - -Notes about GLib 2.10 -===================== - -* The functions g_snprintf() and g_vsnprintf() have been removed from - the gprintf.h header, since they are already declared in glib.h. This - doesn't break documented use of gprintf.h, but people have been known - to include gprintf.h without including glib.h. - -* The Unicode support has been updated to Unicode 4.1. This adds several - new members to the GUnicodeBreakType enumeration. - -* The support for Solaris threads has been retired. Solaris has provided - POSIX threads for long enough now to have them available on every - Solaris platform. - -* 'make check' has been changed to validate translations by calling - msgfmt with the -c option. As a result, it may fail on systems with - older gettext implementations (GNU gettext < 0.14.1, or Solaris gettext). - 'make check' will also fail on systems where the C compiler does not - support ELF visibility attributes. - -* The GMemChunk API has been deprecated in favour of a new 'slice - allocator'. See the g_slice documentation for more details. - -* A new type, GInitiallyUnowned, has been introduced, which is - intended to serve as a common implementation of the 'floating reference' - concept that is e.g. used by GtkObject. Note that changing the - inheritance hierarchy of a type can cause problems for language - bindings and other code which needs to work closely with the type - system. Therefore, switching to GInitiallyUnowned should be done - carefully. g_object_compat_control() has been added to GLib 2.8.5 - to help with the transition. - -Notes about GLib 2.6.0 -====================== - -* GLib 2.6 introduces the concept of 'GLib filename encoding', which is the - on-disk encoding on Unix, but UTF-8 on Windows. All GLib functions - returning or accepting pathnames have been changed to expect - filenames in this encoding, and the common POSIX functions dealing - with pathnames have been wrapped. These wrappers are declared in the - header which must be included explicitly; it is not - included through . - - On current (NT-based) Windows versions, where the on-disk file names - are Unicode, these wrappers use the wide-character API in the C - library. Thus applications can handle file names containing any - Unicode characters through GLib's own API and its POSIX wrappers, - not just file names restricted to characters in the system codepage. - - To keep binary compatibility with applications compiled against - older versions of GLib, the Windows DLL still provides entry points - with the old semantics using the old names, and applications - compiled against GLib 2.6 will actually use new names for the - functions. This is transparent to the programmer. - - When compiling against GLib 2.6, applications intended to be - portable to Windows must take the UTF-8 file name encoding into - consideration, and use the gstdio wrappers to access files whose - names have been constructed from strings returned from GLib. - -* Likewise, g_get_user_name() and g_get_real_name() have been changed - to return UTF-8 on Windows, while keeping the old semantics for - applications compiled against older versions of GLib. - -* The GLib uses an '_' prefix to indicate private symbols that - must not be used by applications. On some platforms, symbols beginning - with prefixes such as _g will be exported from the library, on others not. - In no case can applications use these private symbols. In addition to that, - GLib+ 2.6 makes several symbols private which were not in any installed - header files and were never intended to be exported. - -* To reduce code size and improve efficiency, GLib, when compiled - with the GNU toolchain, has separate internal and external entry - points for exported functions. The internal names, which begin with - IA__, may be seen when debugging a GLib program. - -* On Windows, GLib no longer opens a console window when printing - warning messages if stdout or stderr are invalid, as they are in - "Windows subsystem" (GUI) applications. Simply redirect stdout or - stderr if you need to see them. - -* The child watch functionality tends to reveal a bug in many - thread implementations (in particular the older LinuxThreads - implementation on Linux) where it's not possible to call waitpid() - for a child created in a different thread. For this reason, for - maximum portability, you should structure your code to fork all - child processes that you want to wait for from the main thread. - -* A problem was recently discovered with g_signal_connect_object(); - it doesn't actually disconnect the signal handler once the object being - connected to dies, just disables it. See the API docs for the function - for further details and the correct workaround that will continue to - work with future versions of GLib. diff --git a/README.md b/README.md new file mode 100644 index 000000000..677f2dd86 --- /dev/null +++ b/README.md @@ -0,0 +1,365 @@ +General Information +=================== + +GLib is the low-level core +library that forms the basis for projects such as GTK+ and GNOME. It +provides data structure handling for C, portability wrappers, and +interfaces for such runtime functionality as an event loop, threads, +dynamic loading, and an object system. + +The official download locations are: + ftp://ftp.gtk.org/pub/glib + http://download.gnome.org/sources/glib + +The official web site is: + http://www.gtk.org/ + +Information about mailing lists can be found at + http://www.gtk.org/mailing-lists.php + +To subscribe, send mail to gtk-list-request@gnome.org +with the subject "subscribe". + +Installation +============ + +See the file 'INSTALL' + +How to report bugs +================== + +Bugs should be reported to the GNOME issue tracking system. +(https://gitlab.gnome.org/GNOME/glib/issues/new). You will need +to create an account for yourself. + +In the bug report please include: + +* Information about your system. For instance: + + - What operating system and version + - For Linux, what version of the C library + + And anything else you think is relevant. + +* How to reproduce the bug. + + If you can reproduce it with one of the test programs that are built + in the tests/ subdirectory, that will be most convenient. Otherwise, + please include a short test program that exhibits the behavior. + As a last resort, you can also provide a pointer to a larger piece + of software that can be downloaded. + +* If the bug was a crash, the exact text that was printed out + when the crash occured. + +* Further information such as stack traces may be useful, but + is not necessary. + +Patches +======= + +Patches should also be submitted as merge requests to gitlab.gnome.org. If the +patch fixes an existing issue, please refer to the issue in your commit message +with the following notation (for issue 123): +Closes: #123 + +Otherwise, create a new merge request that introduces the change, filing a +separate issue is not required. + +Notes about GLib 2.48 +===================== + +* The system copy of PCRE is now used by default to implement GRegex. + Configure with --with-pcre=internal if a system PCRE version + is unavailable or undesired. + +Notes about GLib 2.46 +===================== + +* GTask no longer imposes a fixed limit on the number of tasks that + can be run_in_thread() simultaneously, since doing this inevitably + results in deadlocks in some use cases. Instead, it now has a base + number of threads that can be used "for free", but will gradually + add more threads to the pool if too much time passes without any + tasks completing. + + The exact behavior may continue to change in the future, and it's + possible that some future version of GLib may not do any + rate-limiting at all. As a result, you should no longer assume that + GTask will rate-limit tasks itself (or, by extension, that calls to + certain async gio methods will automatically be rate-limited for + you). If you have a very large number of tasks to run, and don't + want them to all run at once, you should rate-limit them yourself. + +Notes about GLib 2.40 +===================== + +* g_test_run() no longer runs tests in exactly the order they are + registered; instead, it groups them according to test suites (ie, + path components) like the documentation always claimed it did. In + some cases, this can result in a sub-optimal ordering of tests, + relative to the old behavior. The fix is to change the test paths to + properly group together the tests that should run together. (eg, if + you want to run test_foo_simple(), test_bar_simple(), and + test_foo_using_bar() in that order, they should have test paths like + "/simple/foo", "/simple/bar", "/complex/foo-using-bar", not + "/foo/simple", "/bar/simple", "/foo/using-bar" (which would result + in test_foo_using_bar() running before test_bar_simple()). + + (The behavior actually changed in GLib 2.36, but it was not + documented at the time, since we didn't realize it mattered.) + +Notes about GLib 2.36 +===================== + +* It is no longer necessary to call g_type_init(). If you are + loading GLib as a dynamic module, you should be careful to avoid + unloading it, then subsequently loading it again. This never + really worked before, but it is now explicitly undefined behavior. + Note that if g_type_init() was the only explicit use of a GObject + API and you are using linker flags such as --no-add-needed, then + you may have to artificially use some GObject call to keep the + linker from optimizing away -lgobject. We recommend to use + g_type_ensure (G_TYPE_OBJECT) for this purpose. + +* This release contains an incompatible change to the g_get_home_dir() + function. Previously, this function would effectively ignore the HOME + environment variable and always return the value from /etc/password. + As of this version, the HOME variable is used if it is set and the + value from /etc/passwd is only used as a fallback. + +* The 'flowinfo' and 'scope_id' fields of GInetSocketAddress + (introduced in GLib 2.32) have been fixed to be in host byte order + rather than network byte order. This is an incompatible change, but + the previous behavior was clearly broken, so it seems unlikely that + anyone was using it. + +Notes about GLib 2.34 +===================== + +* GIO now looks for thumbnails in XDG_CACHE_HOME, following a + recent alignment of the thumbnail spec with the basedir spec. + +* The default values for GThreadPools max_unused_threads and + max_idle_time settings have been changed to 2 and 15*1000, + respectively. + +Notes about GLib 2.32 +===================== + +* It is no longer necessary to use g_thread_init() or to link against + libgthread. libglib is now always thread-enabled. Custom thread + system implementations are no longer supported (including errorcheck + mutexes). + +* The thread and synchronisation APIs have been updated. + GMutex and GCond can be statically allocated without explicit + initialisation, as can new types GRWLock and GRecMutex. The + GStatic_______ variants of these types have been deprecated. GPrivate + can also be statically allocated and has a nicer API (deprecating + GStaticPrivate). Finally, g_thread_create() has been replaced with a + substantially simplified g_thread_new(). + +* The g_once_init_enter()/_leave() functions have been replaced with + macros that allow for a pointer to any gsize-sized object, not just a + gsize*. The assertions to ensure that a pointer to a correctly-sized + object is being used will not work with generic pointers (ie: (void*) + and (gpointer) casts) which would have worked with the old version. + +* It is now mandatory to include glib.h instead of individual headers. + +* The -uninstalled variants of the pkg-config files have been dropped. + +* For a long time, gobject-2.0.pc mistakenly declared a public + dependency on gthread-2.0.pc (when the dependency should have been + private). This means that programs got away with calling + g_thread_init() without explicitly listing gthread-2.0.pc among their + dependencies. + + gthread has now been removed as a gobject dependency, which will cause + such programs to break. + + The fix for this problem is either to declare an explicit dependency + on gthread-2.0.pc (if you care about compatibility with older GLib + versions) or to stop calling g_thread_init(). + +* g_debug() output is no longer enabled by default. It can be enabled + on a per-domain basis with the G_MESSAGES_DEBUG environment variable + like + G_MESSAGES_DEBUG=domain1,domain2 + or + G_MESSAGES_DEBUG=all + +Notes about GLib 2.30 +===================== + +* GObject includes a generic marshaller, g_cclosure_marshal_generic. + To use it, simply specify NULL as the marshaller in g_signal_new(). + The generic marshaller is implemented with libffi, and consequently + GObject depends on libffi now. + +Notes about GLib 2.28 +===================== + +* The GApplication API has changed compared to the version that was + included in the 2.25 development snapshots. Existing users will need + adjustments. + +Notes about GLib 2.26 +===================== + +* Nothing noteworthy. + +Notes about GLib 2.24 +===================== + +* It is now allowed to call g_thread_init(NULL) multiple times, and + to call glib functions before g_thread_init(NULL) is called + (although the later is mainly a change in docs as this worked before + too). See the GThread reference documentation for the details. + +* GObject now links to GThread and threads are enabled automatically + when g_type_init() is called. + +* GObject no longer allows to call g_object_set() on construct-only properties + while an object is being initialized. If this behavior is needed, setting a + custom constructor that just chains up will re-enable this functionality. + +* GMappedFile on an empty file now returns NULL for the contents instead of + returning an empty string. The documentation specifically states that code + may not rely on nul-termination here so any breakage caused by this change + is a bug in application code. + +Notes about GLib 2.22 +===================== + +* Repeated calls to g_simple_async_result_set_op_res_gpointer used + to leak the data. This has been fixed to always call the provided + destroy notify. + +Notes about GLib 2.20 +===================== + +* The functions for launching applications (e.g. g_app_info_launch() + + friends) now passes a FUSE file:// URI if possible (requires gvfs + with the FUSE daemon to be running and operational). With gvfs 2.26, + FUSE file:// URIs will be mapped back to gio URIs in the GFile + constructors. The intent of this change is to better integrate + POSIX-only applications, see bug #528670 for the rationale. The + only user-visible change is when an application needs to examine an + URI passed to it (e.g. as a positional parameter). Instead of + looking at the given URI, the application will now need to look at + the result of g_file_get_uri() after having constructed a GFile + object with the given URI. + +Notes about GLib 2.18 +===================== + +* The recommended way of using GLib has always been to only include the + toplevel headers glib.h, glib-object.h and gio.h. GLib enforces this by + generating an error when individual headers are directly included. + To help with the transition, the enforcement is not turned on by + default for GLib headers (it is turned on for GObject and GIO). + To turn it on, define the preprocessor symbol G_DISABLE_SINGLE_INCLUDES. + +Notes about GLib 2.16 +===================== + +* GLib now includes GIO, which adds optional dependencies against libattr + and libselinux for extended attribute and SELinux support. Use + --disable-xattr and --disable-selinux to build without these. + +Notes about GLib 2.10 +===================== + +* The functions g_snprintf() and g_vsnprintf() have been removed from + the gprintf.h header, since they are already declared in glib.h. This + doesn't break documented use of gprintf.h, but people have been known + to include gprintf.h without including glib.h. + +* The Unicode support has been updated to Unicode 4.1. This adds several + new members to the GUnicodeBreakType enumeration. + +* The support for Solaris threads has been retired. Solaris has provided + POSIX threads for long enough now to have them available on every + Solaris platform. + +* 'make check' has been changed to validate translations by calling + msgfmt with the -c option. As a result, it may fail on systems with + older gettext implementations (GNU gettext < 0.14.1, or Solaris gettext). + 'make check' will also fail on systems where the C compiler does not + support ELF visibility attributes. + +* The GMemChunk API has been deprecated in favour of a new 'slice + allocator'. See the g_slice documentation for more details. + +* A new type, GInitiallyUnowned, has been introduced, which is + intended to serve as a common implementation of the 'floating reference' + concept that is e.g. used by GtkObject. Note that changing the + inheritance hierarchy of a type can cause problems for language + bindings and other code which needs to work closely with the type + system. Therefore, switching to GInitiallyUnowned should be done + carefully. g_object_compat_control() has been added to GLib 2.8.5 + to help with the transition. + +Notes about GLib 2.6.0 +====================== + +* GLib 2.6 introduces the concept of 'GLib filename encoding', which is the + on-disk encoding on Unix, but UTF-8 on Windows. All GLib functions + returning or accepting pathnames have been changed to expect + filenames in this encoding, and the common POSIX functions dealing + with pathnames have been wrapped. These wrappers are declared in the + header which must be included explicitly; it is not + included through . + + On current (NT-based) Windows versions, where the on-disk file names + are Unicode, these wrappers use the wide-character API in the C + library. Thus applications can handle file names containing any + Unicode characters through GLib's own API and its POSIX wrappers, + not just file names restricted to characters in the system codepage. + + To keep binary compatibility with applications compiled against + older versions of GLib, the Windows DLL still provides entry points + with the old semantics using the old names, and applications + compiled against GLib 2.6 will actually use new names for the + functions. This is transparent to the programmer. + + When compiling against GLib 2.6, applications intended to be + portable to Windows must take the UTF-8 file name encoding into + consideration, and use the gstdio wrappers to access files whose + names have been constructed from strings returned from GLib. + +* Likewise, g_get_user_name() and g_get_real_name() have been changed + to return UTF-8 on Windows, while keeping the old semantics for + applications compiled against older versions of GLib. + +* The GLib uses an '_' prefix to indicate private symbols that + must not be used by applications. On some platforms, symbols beginning + with prefixes such as _g will be exported from the library, on others not. + In no case can applications use these private symbols. In addition to that, + GLib+ 2.6 makes several symbols private which were not in any installed + header files and were never intended to be exported. + +* To reduce code size and improve efficiency, GLib, when compiled + with the GNU toolchain, has separate internal and external entry + points for exported functions. The internal names, which begin with + IA__, may be seen when debugging a GLib program. + +* On Windows, GLib no longer opens a console window when printing + warning messages if stdout or stderr are invalid, as they are in + "Windows subsystem" (GUI) applications. Simply redirect stdout or + stderr if you need to see them. + +* The child watch functionality tends to reveal a bug in many + thread implementations (in particular the older LinuxThreads + implementation on Linux) where it's not possible to call waitpid() + for a child created in a different thread. For this reason, for + maximum portability, you should structure your code to fork all + child processes that you want to wait for from the main thread. + +* A problem was recently discovered with g_signal_connect_object(); + it doesn't actually disconnect the signal handler once the object being + connected to dies, just disables it. See the API docs for the function + for further details and the correct workaround that will continue to + work with future versions of GLib. diff --git a/README.win32 b/README.win32 index 4fda64ae0..1683d54b9 100644 --- a/README.win32 +++ b/README.win32 @@ -80,6 +80,11 @@ To overcome this problem, please set your system's locale setting for non-Unicod English (United States), reboot, and restart the build, and the code should build normally. See also this GNOME Wiki page [1] that gives a bit further info on this. +In Visual Studio 2015 and later, the /utf-8 option is provided, which is set by the +latest Meson releases when building GLib, and can be used in other project files +that uses GLib to avoid the need of setting your system's locale setting for +non-Unicode and the subsequent requirement to restart the system. + Building software that use GLib or GTK+ ======================================= @@ -150,14 +155,11 @@ library. The DLL generated by either compiler is binary compatible with the other one. Thus one either has to manually edit glibconfig.h -afterwards, or use the supplied glibconfig.h.win32 which has been -produced by running configure twice, once using gcc and once using -MSVC, and merging the resulting files with diff -D. +afterwards. For MSVC7 and later (Visual C++ .NET 2003, Visual C++ 2005, Visual C++ 2008 etc) it is preferred to use specific builds of GLib DLLs that use -the same C runtime as the code that uses GLib. Such DLLs should be -named differently than the ones that use msvcrt.dll. +the same C runtime as the code that uses GLib. For GLib, the DLL that uses msvcrt.dll is called libglib-2.0-0.dll, and the import libraries libglib-2.0.dll.a and glib-2.0.lib. Note that @@ -172,32 +174,78 @@ and libtool documentation. Building with Visual Studio =========================== -A more detailed outline of building GLib with its dependencies can -now be found on the GNOME wiki: +Meson is now the supported method of building GLib using Visual Studio. + +Note that you will need a libintl implementation, zlib, and libFFI, and +optionally PCRE1, which should preferably be built with the same compiler +that is now being used to build GLib. Ensure that their headers, .lib's +and DLLs can be found in the paths specified by the INCLUDE, LIB and PATH +envvars. The Meson build process will pull in a copy of the ZLib and the +libFFI sources if they cannot be found, and will build an in-source copy +of PCRE1 if PCRE1 cannt be found. + +One can also refer to the following page for building the dependencies: https://wiki.gnome.org/Projects/GTK%2B/Win32/MSVCCompilationOfGTKStack -Please do not build GLib in paths that contain spaces in them, as -this may cause problems during compilation and during usage of the -library. +You will also need the following items: +-Python 3.6.x, you need the 32-bit version if you are building GLib + as a 32-bit/x86 build, or the amd64/x64 version for building 64-bit/x86-64 + builds. You will then need to install or update Meson by using pip. +-The Ninja build tool, required for Visual Studio 2008, 2012 and 2013 builds, + and optional for 2010, 2015 and 2017 builds, where Visual Studio projects + can be generated instead of the Ninja build files. +-GIT for Windows is highly recommended, in the case where some required + dependencies are not found, and Meson makes use of GIT to download + the sources to build in the build process. + +To do a build using Meson, do the following: + +-Open a Visual Studio (or SDK) command prompt that matches the Visual Studio + version and build platform (Win32/x86, x64, etc.) that will be used in all + the following steps. + +-Create an empty directory/folder for the build. It needs to be in the same + drive as where your GLib sources are located (i.e. $(GLIB_SRCDIR)). cd into + that directory/folder. + +-Setup your PATH envvar: + + set PATH=%PATH%;$(PYTHON_INSTALL_DIR);$(NINJA_DIR) + + where PYTHON_INSTALL_DIR is where Python 3.6.x+ is installed to, and NINJA_DIR + is where your ninja executable can be found. The NINJA_DIR can be omitted if one + passes --backend=vs to the Meson configuration line, for Visual Studio 2010, 2015 + and 2017 builds. + +-Configure the build using Meson: + + python $(PYTHON_INSTALL_DIR)\scripts\meson.py $(GLIB_SRCDIR) --buildtype=$(build_configuration) --prefix=$(INSTALL_PREFIX) [--backend=vs] + + Please see the Meson docs for an explanation for --buildtype, the path passed for + --prefix need not to be on the same drive as where the build is carried out, but + it is recommended to use forward slashes for this path. The --backend=vs can be + used if the Visual Studio project generator is preferred over using Ninja, for + Visual Studio 2010, 2015 and 2017 builds. -In an unpacked tarball, you will find in build\win32\vs9 (VS 2008) and -build\win32\vs10 (VS 2010) a solution file that can be used to build -the GLib DLLs and some auxiliary programs under VS 2008 and VS 2010 -(Express Edition will suffice with the needed dependencies) respectively. -Read the README.txt file in those folders for more -information. Note that you will need a libintl implementation, zlib, and -libFFI. +-Build, test and install the build: + Run ninja (and ninja test and ninja install) or open the generated Visual Studio + projects to compile, test and install the build. -If you are building from a GIT checkout, you will first need to use some -Unix-like environment or run win32/setup.py, -which will expand the VS 2008/2010 project files, the DLL resouce files and -other miscellanious files required for the build. Run win32/setup.py -as follows: +Note that if building the sources with Visual Studio 2008, note the following +additional items: -$python win32/setup.py --perl path_to_your_perl.exe +-You need to run the following lines from your build directory, to embed the manifests + that are generated during the build, assuming the built binaries are installed + to $(PREFIX), after a successful build/installation: -for more usage on this script, run -$python win32/setup.py -h/--help +for /r %f in (*.dll.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f $(PREFIX)\bin\%~nf;2 +for /r %f in (*.exe.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f $(PREFIX)\bin\%~nf;1 -[1]: https://wiki.gnome.org/Projects/GTK%2B/Win32/MSVCCompilationOfGTKStack under "Preparations" +-If building for amd64/x86_64/x64, sometimes the compilation of sources may seem to hang, which + is caused by an optimization issue in the 2008 x64 compiler. You need to use Task Manager to + remove all running instances of cl.exe, which will cause the build process to terminate. Update + the build flags of the sources that hang on compilation by changing its "/O2" flag to "/O1" + in build.ninja, and retry the build, where things should continue to build normally. At the + time of writing, this is needed for compiling glib/gtestutils.c, gio/gsettings.c and + gio/gsettingsschema.c diff --git a/autogen.sh b/autogen.sh index 4bbc00d98..9e4ba4c39 100755 --- a/autogen.sh +++ b/autogen.sh @@ -25,10 +25,10 @@ if test -z $AUTORECONF; then exit 1 fi -# README and INSTALL are required by automake, but may be deleted by clean -# up rules. to get automake to work, simply touch these here, they will be -# regenerated from their corresponding *.in files by ./configure anyway. -touch README INSTALL +# INSTALL is required by automake, but may be deleted by clean +# up rules. to get automake to work, simply touch it here. It will be +# regenerated from its corresponding *.in file by ./configure anyway. +touch INSTALL autoreconf --force --install --verbose || exit $? diff --git a/build/win32/vs8/Makefile.am b/build/win32/vs8/Makefile.am deleted file mode 100644 index 69cd83f42..000000000 --- a/build/win32/vs8/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -EXTRA_DIST = \ - README \ - gio.vcproj \ - glib-genmarshal.vcproj \ - glib.sln \ - glib.vcproj \ - gmodule.vcproj \ - gobject.vcproj \ - gspawn-win32-helper-console.vcproj \ - gspawn-win32-helper.vcproj \ - gthread.vcproj diff --git a/build/win32/vs8/README b/build/win32/vs8/README deleted file mode 100644 index 4576aaeb6..000000000 --- a/build/win32/vs8/README +++ /dev/null @@ -1,4 +0,0 @@ -Note that this is mostly experimental and not really maintained. It -seems that the OAH project at https://code.launchpad.net/oah might be -a better choice if you want to start building GLib (and more of the -GTK+ stack) with Visual Studio. diff --git a/build/win32/vs8/gio.vcproj b/build/win32/vs8/gio.vcproj deleted file mode 100644 index 13902acc4..000000000 --- a/build/win32/vs8/gio.vcproj +++ /dev/null @@ -1,486 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/glib-genmarshal.vcproj b/build/win32/vs8/glib-genmarshal.vcproj deleted file mode 100644 index 06cb39866..000000000 --- a/build/win32/vs8/glib-genmarshal.vcproj +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/glib.sln b/build/win32/vs8/glib.sln deleted file mode 100644 index 544560e10..000000000 --- a/build/win32/vs8/glib.sln +++ /dev/null @@ -1,84 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glib", "glib.vcproj", "{12BCA020-EABF-429E-876A-A476BC9C10C0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmodule", "gmodule.vcproj", "{4214047C-F5C1-40B3-8369-5DCED8C32770}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gobject", "gobject.vcproj", "{F172EFFC-E30F-4593-809E-DB2024B1E753}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gthread", "gthread.vcproj", "{C8AFB8C3-FFFD-460F-BC13-9AC25D7B117C}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glib-genmarshal", "glib-genmarshal.vcproj", "{BD12E835-5C52-4E5D-8234-1C579F33E27A}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gio", "gio.vcproj", "{F3D1583C-5613-4809-BD98-7CC1C1276F92}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - {F172EFFC-E30F-4593-809E-DB2024B1E753} = {F172EFFC-E30F-4593-809E-DB2024B1E753} - {4214047C-F5C1-40B3-8369-5DCED8C32770} = {4214047C-F5C1-40B3-8369-5DCED8C32770} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gspawn-win32-helper", "gspawn-win32-helper.vcproj", "{289240E7-E167-47CE-A20C-58D852E520BA}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gspawn-win32-helper-console", "gspawn-win32-helper-console.vcproj", "{E40E8A7E-7CAE-4659-9B8B-BC38898E3074}" - ProjectSection(ProjectDependencies) = postProject - {12BCA020-EABF-429E-876A-A476BC9C10C0} = {12BCA020-EABF-429E-876A-A476BC9C10C0} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {12BCA020-EABF-429E-876A-A476BC9C10C0}.Debug|Win32.ActiveCfg = Debug|Win32 - {12BCA020-EABF-429E-876A-A476BC9C10C0}.Debug|Win32.Build.0 = Debug|Win32 - {12BCA020-EABF-429E-876A-A476BC9C10C0}.Release|Win32.ActiveCfg = Release|Win32 - {12BCA020-EABF-429E-876A-A476BC9C10C0}.Release|Win32.Build.0 = Release|Win32 - {4214047C-F5C1-40B3-8369-5DCED8C32770}.Debug|Win32.ActiveCfg = Debug|Win32 - {4214047C-F5C1-40B3-8369-5DCED8C32770}.Debug|Win32.Build.0 = Debug|Win32 - {4214047C-F5C1-40B3-8369-5DCED8C32770}.Release|Win32.ActiveCfg = Release|Win32 - {4214047C-F5C1-40B3-8369-5DCED8C32770}.Release|Win32.Build.0 = Release|Win32 - {F172EFFC-E30F-4593-809E-DB2024B1E753}.Debug|Win32.ActiveCfg = Debug|Win32 - {F172EFFC-E30F-4593-809E-DB2024B1E753}.Debug|Win32.Build.0 = Debug|Win32 - {F172EFFC-E30F-4593-809E-DB2024B1E753}.Release|Win32.ActiveCfg = Release|Win32 - {F172EFFC-E30F-4593-809E-DB2024B1E753}.Release|Win32.Build.0 = Release|Win32 - {C8AFB8C3-FFFD-460F-BC13-9AC25D7B117C}.Debug|Win32.ActiveCfg = Debug|Win32 - {C8AFB8C3-FFFD-460F-BC13-9AC25D7B117C}.Debug|Win32.Build.0 = Debug|Win32 - {C8AFB8C3-FFFD-460F-BC13-9AC25D7B117C}.Release|Win32.ActiveCfg = Release|Win32 - {C8AFB8C3-FFFD-460F-BC13-9AC25D7B117C}.Release|Win32.Build.0 = Release|Win32 - {BD12E835-5C52-4E5D-8234-1C579F33E27A}.Debug|Win32.ActiveCfg = Debug|Win32 - {BD12E835-5C52-4E5D-8234-1C579F33E27A}.Debug|Win32.Build.0 = Debug|Win32 - {BD12E835-5C52-4E5D-8234-1C579F33E27A}.Release|Win32.ActiveCfg = Release|Win32 - {BD12E835-5C52-4E5D-8234-1C579F33E27A}.Release|Win32.Build.0 = Release|Win32 - {F3D1583C-5613-4809-BD98-7CC1C1276F92}.Debug|Win32.ActiveCfg = Debug|Win32 - {F3D1583C-5613-4809-BD98-7CC1C1276F92}.Debug|Win32.Build.0 = Debug|Win32 - {F3D1583C-5613-4809-BD98-7CC1C1276F92}.Release|Win32.ActiveCfg = Release|Win32 - {F3D1583C-5613-4809-BD98-7CC1C1276F92}.Release|Win32.Build.0 = Release|Win32 - {289240E7-E167-47CE-A20C-58D852E520BA}.Debug|Win32.ActiveCfg = Debug|Win32 - {289240E7-E167-47CE-A20C-58D852E520BA}.Debug|Win32.Build.0 = Debug|Win32 - {289240E7-E167-47CE-A20C-58D852E520BA}.Release|Win32.ActiveCfg = Release|Win32 - {289240E7-E167-47CE-A20C-58D852E520BA}.Release|Win32.Build.0 = Release|Win32 - {E40E8A7E-7CAE-4659-9B8B-BC38898E3074}.Debug|Win32.ActiveCfg = Debug|Win32 - {E40E8A7E-7CAE-4659-9B8B-BC38898E3074}.Debug|Win32.Build.0 = Debug|Win32 - {E40E8A7E-7CAE-4659-9B8B-BC38898E3074}.Release|Win32.ActiveCfg = Release|Win32 - {E40E8A7E-7CAE-4659-9B8B-BC38898E3074}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/build/win32/vs8/glib.vcproj b/build/win32/vs8/glib.vcproj deleted file mode 100644 index de358764f..000000000 --- a/build/win32/vs8/glib.vcproj +++ /dev/null @@ -1,605 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/gmodule.vcproj b/build/win32/vs8/gmodule.vcproj deleted file mode 100644 index bf519f70b..000000000 --- a/build/win32/vs8/gmodule.vcproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/gobject.vcproj b/build/win32/vs8/gobject.vcproj deleted file mode 100644 index dc1d542da..000000000 --- a/build/win32/vs8/gobject.vcproj +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/gspawn-win32-helper-console.vcproj b/build/win32/vs8/gspawn-win32-helper-console.vcproj deleted file mode 100644 index 5bf95af71..000000000 --- a/build/win32/vs8/gspawn-win32-helper-console.vcproj +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/gspawn-win32-helper.vcproj b/build/win32/vs8/gspawn-win32-helper.vcproj deleted file mode 100644 index 6e34dbcd7..000000000 --- a/build/win32/vs8/gspawn-win32-helper.vcproj +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/win32/vs8/gthread.vcproj b/build/win32/vs8/gthread.vcproj deleted file mode 100644 index 386838dbb..000000000 --- a/build/win32/vs8/gthread.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config.h.meson b/config.h.meson deleted file mode 100644 index fd0bfcaf9..000000000 --- a/config.h.meson +++ /dev/null @@ -1,840 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -#mesondefine AC_APPLE_UNIVERSAL_BUILD - -/* The normal alignment of `guint32', in bytes. */ -#mesondefine ALIGNOF_GUINT32 - -/* The normal alignment of `guint64', in bytes. */ -#mesondefine ALIGNOF_GUINT64 - -/* The normal alignment of `unsigned long', in bytes. */ -#mesondefine ALIGNOF_UNSIGNED_LONG - -/* poll doesn't work on devices */ -#mesondefine BROKEN_POLL - -/* struct ip_mreq_source definition is broken on Android NDK <= r16 */ -#mesondefine BROKEN_IP_MREQ_SOURCE_STRUCT - -/* Whether we're building a DLL and hence need symbols exported for a DLL */ -#mesondefine DLL_EXPORT - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -#mesondefine CRAY_STACKSEG_END - -/* Define to 1 if using `alloca.c'. */ -#mesondefine C_ALLOCA - -/* Whether to disable memory pools */ -#mesondefine DISABLE_MEM_POOLS - -/* Whether to enable GC friendliness by default */ -#mesondefine ENABLE_GC_FRIENDLY_DEFAULT - -/* always defined to indicate that i18n is enabled */ -#mesondefine ENABLE_NLS - -/* Define the gettext package to be used */ -#mesondefine GETTEXT_PACKAGE - -/* Define to the GLIB binary age */ -#mesondefine GLIB_BINARY_AGE - -/* Define to the GLIB interface age */ -#mesondefine GLIB_INTERFACE_AGE - -/* Define the location where the catalogs will be installed */ -#mesondefine GLIB_LOCALE_DIR - -/* Define to the GLIB major version */ -#mesondefine GLIB_MAJOR_VERSION - -/* Define to the GLIB micro version */ -#mesondefine GLIB_MICRO_VERSION - -/* Define to the GLIB minor version */ -#mesondefine GLIB_MINOR_VERSION - -/* A 'va_copy' style function */ -#mesondefine G_VA_COPY - -/* 'va_lists' cannot be copies as values */ -#mesondefine G_VA_COPY_AS_ARRAY - -/* Define to 1 if you have `alloca', as a function or macro. */ -#mesondefine HAVE_ALLOCA - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#mesondefine HAVE_ALLOCA_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_ATTR_XATTR_H - -/* Define to 1 if you have the `bind_textdomain_codeset' function. */ -#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET - -/* Define if you have a version of the snprintf function with semantics as - specified by the ISO C99 standard. */ -#mesondefine HAVE_C99_SNPRINTF - -/* Define if you have a version of the vsnprintf function with semantics as - specified by the ISO C99 standard. */ -#mesondefine HAVE_C99_VSNPRINTF - -/* define to 1 if Carbon is available */ -#mesondefine HAVE_CARBON - -/* Define to 1 if you have the `clock_gettime' function. */ -#mesondefine HAVE_CLOCK_GETTIME - -/* define to 1 if Cocoa is available */ -#mesondefine HAVE_COCOA - -/* Have nl_langinfo (CODESET) */ -#mesondefine HAVE_CODESET - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_CRT_EXTERNS_H - -/* Define if dbus-1 is available */ -#mesondefine HAVE_DBUS1 - -/* Define to 1 if you have the `dcgettext' function. */ -#mesondefine HAVE_DCGETTEXT - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#mesondefine HAVE_DIRENT_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_DLFCN_H - -/* Define to 1 if using dtrace probes. */ -#mesondefine HAVE_DTRACE - -/* Define to 1 if you have the `endmntent' function. */ -#mesondefine HAVE_ENDMNTENT - -/* Define to 1 if you have the `endservent' function. */ -#mesondefine HAVE_ENDSERVENT - -/* we have the eventfd(2) system call */ -#mesondefine HAVE_EVENTFD - -/* Define to 1 if you have the `fallocate' function. */ -#mesondefine HAVE_FALLOCATE - -/* Define if we have FAM */ -#mesondefine HAVE_FAM - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_FAM_H - -/* Define if we have FAMNoExists in fam */ -#mesondefine HAVE_FAM_NO_EXISTS - -/* Define to 1 if you have the `fchmod' function. */ -#mesondefine HAVE_FCHMOD - -/* Define to 1 if you have the `fchown' function. */ -#mesondefine HAVE_FCHOWN - -/* Define to 1 if you have the `fdwalk' function. */ -#mesondefine HAVE_FDWALK - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_FSTAB_H - -/* Define to 1 if you have the `fsync' function. */ -#mesondefine HAVE_FSYNC - -/* we have the futex(2) system call */ -#mesondefine HAVE_FUTEX - -/* Define to 1 if you have the `getc_unlocked' function. */ -#mesondefine HAVE_GETC_UNLOCKED - -/* Define to 1 if you have the `getfsstat' function. */ -#mesondefine HAVE_GETFSSTAT - -/* Define to 1 if you have the `getgrgid_r' function. */ -#mesondefine HAVE_GETGRGID_R - -/* Define to 1 if you have the `getmntent_r' function. */ -#mesondefine HAVE_GETMNTENT_R - -/* Define to 1 if you have the `getprotobyname_r' function. */ -#mesondefine HAVE_GETPROTOBYNAME_R - -/* Define to 1 if you have the `getpwuid_r' function. */ -#mesondefine HAVE_GETPWUID_R - -/* Define to 1 if you have the `getresuid' function. */ -#mesondefine HAVE_GETRESUID - -/* Define if the GNU gettext() function is already present or preinstalled. */ -#mesondefine HAVE_GETTEXT - -/* Define to 1 if you have the `getvfsstat' function. */ -#mesondefine HAVE_GETVFSSTAT - -/* Define to 1 if you have the `gmtime_r' function. */ -#mesondefine HAVE_GMTIME_R - -/* define to use system printf */ -#mesondefine HAVE_GOOD_PRINTF - -/* Define to 1 if you have the `hasmntopt' function. */ -#mesondefine HAVE_HASMNTOPT - -/* Define to 1 if you have the `if_indextoname' function. */ -#mesondefine HAVE_IF_INDEXTONAME - -/* Define to 1 if you have the `if_nametoindex' function. */ -#mesondefine HAVE_IF_NAMETOINDEX - -/* Define to 1 if you have the `inotify_init1' function. */ -#mesondefine HAVE_INOTIFY_INIT1 - -/* define to support printing 64-bit integers with format I64 */ -#mesondefine HAVE_INT64_AND_I64 - -/* Define if you have the 'intmax_t' type in or . */ -#mesondefine HAVE_INTMAX_T - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_INTTYPES_H - -/* Define if exists, doesn't clash with , and - declares uintmax_t. */ -#mesondefine HAVE_INTTYPES_H_WITH_UINTMAX - -/* Define if we have struct ip_mreqn */ -#mesondefine HAVE_IP_MREQN - -/* Define to 1 if you have the `issetugid' function. */ -#mesondefine HAVE_ISSETUGID - -/* Define to 1 if you have the `kevent' function. */ -#mesondefine HAVE_KEVENT - -/* Define to 1 if you have the `kqueue' function. */ -#mesondefine HAVE_KQUEUE - -/* Check for nl_langinfo and abbreviated alternative month names */ -#mesondefine HAVE_LANGINFO_ABALTMON - -/* Check for nl_langinfo and alternative month names */ -#mesondefine HAVE_LANGINFO_ALTMON - -/* Define if you have and nl_langinfo(CODESET). */ -#mesondefine HAVE_LANGINFO_CODESET - -/* Have nl_langinfo (_NL_CTYPE_OUTDIGITn_MB) */ -#mesondefine HAVE_LANGINFO_OUTDIGIT - -/* Have nl_langinfo (PM_STR) */ -#mesondefine HAVE_LANGINFO_TIME - -/* Define to 1 if you have the `lchmod' function. */ -#mesondefine HAVE_LCHMOD - -/* Define to 1 if you have the `lchown' function. */ -#mesondefine HAVE_LCHOWN - -/* Define if your file defines LC_MESSAGES. */ -#mesondefine HAVE_LC_MESSAGES - -/* Define if you have the __libc_enable_secure variable (GNU libc, eglibc) */ -#mesondefine HAVE_LIBC_ENABLE_SECURE - -/* Define if libelf is available */ -#mesondefine HAVE_LIBELF - -/* Define if libmount is available */ -#mesondefine HAVE_LIBMOUNT - -/* Define to 1 if you have the `link' function. */ -#mesondefine HAVE_LINK - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_LINUX_MAGIC_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_LOCALE_H - -/* Define to 1 if you have the `localtime_r' function. */ -#mesondefine HAVE_LOCALTIME_R - -/* Define if you have the 'long double' type. */ -#mesondefine HAVE_LONG_DOUBLE - -/* Define if you have the 'long long' type. */ -#mesondefine HAVE_LONG_LONG - -/* define if system printf can print long long */ -#mesondefine HAVE_LONG_LONG_FORMAT - -/* Define to 1 if you have the `lstat' function. */ -#mesondefine HAVE_LSTAT - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_MACH_MACH_TIME_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_MALLOC_H - -/* Define to 1 if you have the `mbrtowc' function. */ -#mesondefine HAVE_MBRTOWC - -/* Define to 1 if you have the `memalign' function. */ -#mesondefine HAVE_MEMALIGN - -/* Define to 1 if you have the `memmem' function. */ -#mesondefine HAVE_MEMMEM - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_MEMORY_H - -/* Define to 1 if you have the `mmap' function. */ -#mesondefine HAVE_MMAP - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_MNTENT_H - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#mesondefine HAVE_NDIR_H - -/* We have AF_NETLINK sockets */ -#mesondefine HAVE_NETLINK - -/* Define to 1 if you have the `newlocale' function. */ -#mesondefine HAVE_NEWLOCALE - -/* open option O_DIRECTORY */ -#mesondefine HAVE_OPEN_O_DIRECTORY - -/* Define to 1 if you have the `pipe2' function. */ -#mesondefine HAVE_PIPE2 - -/* Define to 1 if you have the `poll' function. */ -#mesondefine HAVE_POLL - -/* Define to 1 if you have the `posix_memalign' function. */ -#mesondefine HAVE_POSIX_MEMALIGN - -/* Define to 1 if you have the `prlimit' function. */ -#mesondefine HAVE_PRLIMIT - -/* Have function pthread_attr_setstacksize */ -#mesondefine HAVE_PTHREAD_ATTR_SETSTACKSIZE - -/* Have function pthread_cond_timedwait_relative_np */ -#mesondefine HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP - -/* Have function pthread_condattr_setclock */ -#mesondefine HAVE_PTHREAD_CONDATTR_SETCLOCK - -/* Have function pthread_setname_np without TID as argument */ -#mesondefine HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID - -/* Have function pthread_setname_np with TID as argument */ -#mesondefine HAVE_PTHREAD_SETNAME_NP_WITH_TID - -/* Have function pthread_getname_np */ -#mesondefine HAVE_PTHREAD_GETNAME_NP - -/* Define to 1 if the system has the type `ptrdiff_t'. */ -#mesondefine HAVE_PTRDIFF_T - -/* Define to 1 if you have the `readlink' function. */ -#mesondefine HAVE_READLINK - -/* Define to 1 if you have the `recvmmsg' function. */ -#mesondefine HAVE_RECVMMSG - -/* Define to 1 if you have the 'res_init' function. */ -#mesondefine HAVE_RES_INIT - -/* Define to 1 if you have the 'res_nclose' function. */ -#mesondefine HAVE_RES_NCLOSE - -/* Define to 1 if you have the 'res_ndestroy' function. */ -#mesondefine HAVE_RES_NDESTROY - -/* Define to 1 if you have the 'res_ninit' function. */ -#mesondefine HAVE_RES_NINIT - -/* Define to 1 if you have the 'res_nquery' function. */ -#mesondefine HAVE_RES_NQUERY - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SCHED_H - -/* Define to 1 if libselinux is available */ -#mesondefine HAVE_SELINUX - -/* Define to 1 if you have the `sendmmsg' function. */ -#mesondefine HAVE_SENDMMSG - -/* Define to 1 if you have the `setenv' function. */ -#mesondefine HAVE_SETENV - -/* Define to 1 if you have the `setmntent' function. */ -#mesondefine HAVE_SETMNTENT - -/* Define if you have the 'sig_atomic_t' type. */ -#mesondefine HAVE_SIG_ATOMIC_T - -/* Define if there is support for the ioctl request SIOCGIFADDR. */ -#mesondefine HAVE_SIOCGIFADDR - -/* Define to 1 if you have the `snprintf' function. */ -#mesondefine HAVE_SNPRINTF - -/* Define to 1 if you have the `splice' function. */ -#mesondefine HAVE_SPLICE - -/* Define to 1 if you have the `statfs' function. */ -#mesondefine HAVE_STATFS - -/* Define to 1 if you have the `statvfs' function. */ -#mesondefine HAVE_STATVFS - -/* Define to 1 if you have the `mkostemp' function. */ -#mesondefine HAVE_MKOSTEMP - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_STDDEF_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_STDINT_H - -/* Define if exists, doesn't clash with , and declares - uintmax_t. */ -#mesondefine HAVE_STDINT_H_WITH_UINTMAX - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_STDLIB_H - -/* Define to 1 if you have the `stpcpy' function. */ -#mesondefine HAVE_STPCPY - -/* Define to 1 if you have the `strcasecmp' function. */ -#mesondefine HAVE_STRCASECMP - -/* Define to 1 if you have the `strerror_r' function. */ -#mesondefine HAVE_STRERROR_R - -/* Define if strerror_r returns char * */ -#mesondefine STRERROR_R_CHAR_P - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_STRING_H - -/* Have functions strlcpy and strlcat */ -#mesondefine HAVE_STRLCPY - -/* Define to 1 if you have the `strncasecmp' function. */ -#mesondefine HAVE_STRNCASECMP - -/* Define to 1 if you have the `strnlen' function. */ -#mesondefine HAVE_STRNLEN - -/* Define to 1 if you have the `strsignal' function. */ -#mesondefine HAVE_STRSIGNAL - -/* Define to 1 if you have the `strtod_l' function. */ -#mesondefine HAVE_STRTOD_L - -/* Define to 1 if you have the `strtoll_l' function. */ -#mesondefine HAVE_STRTOLL_L - -/* Define to 1 if you have the `strtoull_l' function. */ -#mesondefine HAVE_STRTOULL_L - -/* Define to 1 if `d_type' is a member of `struct dirent'. */ -#mesondefine HAVE_STRUCT_DIRENT_D_TYPE - -/* Define to 1 if `f_bavail' is a member of `struct statfs'. */ -#mesondefine HAVE_STRUCT_STATFS_F_BAVAIL - -/* Define to 1 if `f_fstypename' is a member of `struct statfs'. */ -#mesondefine HAVE_STRUCT_STATFS_F_FSTYPENAME - -/* Define to 1 if `f_basetype' is a member of `struct statvfs'. */ -#mesondefine HAVE_STRUCT_STATVFS_F_BASETYPE - -/* Define to 1 if `f_fstypename' is a member of `struct statvfs'. */ -#mesondefine HAVE_STRUCT_STATVFS_F_FSTYPENAME - -/* Define to 1 if `st_atimensec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_ATIMENSEC - -/* Define to 1 if `st_atim.tv_nsec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC - -/* Define to 1 if `st_birthtim' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_BIRTHTIM - -/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_BIRTHTIME - -/* Define to 1 if `st_birthtimensec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC - -/* Define to 1 if `st_birthtim.tv_nsec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC - -/* Define to 1 if `st_blksize' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_BLKSIZE - -/* Define to 1 if `st_blocks' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_BLOCKS - -/* Define to 1 if `st_ctimensec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_CTIMENSEC - -/* Define to 1 if `st_ctim.tv_nsec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC - -/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_MTIMENSEC - -/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ -#mesondefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC - -/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ -#mesondefine HAVE_STRUCT_TM_TM_GMTOFF - -/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ -#mesondefine HAVE_STRUCT_TM___TM_GMTOFF - -/* Define to 1 if you have the `symlink' function. */ -#mesondefine HAVE_SYMLINK - -/* Define to 1 if you have the `sysctlbyname' function. */ -#mesondefine HAVE_SYSCTLBYNAME - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#mesondefine HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_EVENT_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_FILIO_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_INOTIFY_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_MKDEV_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_MNTCTL_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_MNTTAB_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_MOUNT_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#mesondefine HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_PARAM_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_POLL_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_RESOURCE_H - -/* found fd_set in sys/select.h */ -#mesondefine HAVE_SYS_SELECT_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_STATFS_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_STATVFS_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_SYSCTL_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_TIMES_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_TIME_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_UIO_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_VFSTAB_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_VFS_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_VMOUNT_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_SYS_XATTR_H - -/* Define to 1 if you have the `timegm' function. */ -#mesondefine HAVE_TIMEGM - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_UNISTD_H - -/* Define if your printf function family supports positional parameters as - specified by Unix98. */ -#mesondefine HAVE_UNIX98_PRINTF - -/* Define to 1 if you have the `unsetenv' function. */ -#mesondefine HAVE_UNSETENV - -/* Define to 1 if you have the `uselocale' function. */ -#mesondefine HAVE_USELOCALE - -/* Define to 1 if you have the `utimes' function. */ -#mesondefine HAVE_UTIMES - -/* Define to 1 if you have the `valloc' function. */ -#mesondefine HAVE_VALLOC - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_VALUES_H - -/* Define to 1 if you have the `vasprintf' function. */ -#mesondefine HAVE_VASPRINTF - -/* Define to 1 if you have the `vsnprintf' function. */ -#mesondefine HAVE_VSNPRINTF - -/* Define if you have the 'wchar_t' type. */ -#mesondefine HAVE_WCHAR_T - -/* Define if you Have wcrtomb() */ -#mesondefine HAVE_WCRTOMB - -/* Define to 1 if you have the `wcslen' function. */ -#mesondefine HAVE_WCSLEN - -/* Define if you have the 'wint_t' type. */ -#mesondefine HAVE_WINT_T - -/* Have a working bcopy */ -#mesondefine HAVE_WORKING_BCOPY - -/* Define to 1 if xattr is available */ -#mesondefine HAVE_XATTR - -/* Define to 1 if xattr API uses XATTR_NOFOLLOW */ -#mesondefine HAVE_XATTR_NOFOLLOW - -/* Define to 1 if you have the header file. */ -#mesondefine HAVE_XLOCALE_H - -/* Define to 1 if you have the `_NSGetEnviron' function. */ -#mesondefine HAVE__NSGETENVIRON - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR "" - -/* Do we cache iconv descriptors */ -#mesondefine NEED_ICONV_CACHE - -/* didn't find fd_set */ -#mesondefine NO_FD_SET - -/* Define to the address where bug reports for this package should be sent. */ -#mesondefine PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#mesondefine PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#mesondefine PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#mesondefine PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#mesondefine PACKAGE_URL - -/* Define to the version of this package. */ -#mesondefine PACKAGE_VERSION - -/* define if posix_memalign() can allocate any size */ -#mesondefine POSIX_MEMALIGN_WITH_COMPLIANT_ALLOCS - -/* The size of `char', as computed by sizeof. */ -#mesondefine SIZEOF_CHAR - -/* The size of `int', as computed by sizeof. */ -#mesondefine SIZEOF_INT - -/* The size of `long', as computed by sizeof. */ -#mesondefine SIZEOF_LONG - -/* The size of `long long', as computed by sizeof. */ -#mesondefine SIZEOF_LONG_LONG - -/* The size of `short', as computed by sizeof. */ -#mesondefine SIZEOF_SHORT - -/* The size of `size_t', as computed by sizeof. */ -#mesondefine SIZEOF_SIZE_T - -/* The size of `ssize_t', as computed by sizeof. */ -#mesondefine SIZEOF_SSIZE_T - -/* The size of `void *', as computed by sizeof. */ -#mesondefine SIZEOF_VOID_P - -/* The size of `__int64', as computed by sizeof. */ -#mesondefine SIZEOF___INT64 - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -#mesondefine STACK_DIRECTION - -/* Number of arguments to statfs() */ -#mesondefine STATFS_ARGS - -/* Define to 1 if you have the ANSI C header files. */ -#mesondefine STDC_HEADERS - -/* Use no threads */ -/* #undef THREADS_NONE */ - -/* Use pthreads */ -#mesondefine THREADS_POSIX - -/* Use w32 threads */ -#mesondefine THREADS_WIN32 - -/* Using GNU libiconv */ -#mesondefine USE_LIBICONV_GNU - -/* Using a native implementation of iconv in a separate library */ -#mesondefine USE_LIBICONV_NATIVE - -/* Define to use statfs() */ -#mesondefine USE_STATFS - -/* Define to use statvfs() */ -#mesondefine USE_STATVFS - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -#mesondefine _ALL_SOURCE -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -#mesondefine _GNU_SOURCE -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -#mesondefine _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -#mesondefine _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -#mesondefine __EXTENSIONS__ -#endif - -/* using the system-supplied PCRE library */ -#mesondefine USE_SYSTEM_PCRE - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#mesondefine _FILE_OFFSET_BITS - -/* defines how to decorate public symbols while building */ -#mesondefine _GLIB_EXTERN - -/* Define for large files, on AIX-style hosts. */ -#mesondefine _LARGE_FILES - -/* Target the Windows 7 API */ -#mesondefine _WIN32_WINNT - -/* Needed to get declarations for msg_control and msg_controllen on Solaris */ -#mesondefine _XOPEN_SOURCE - -/* Needed to get declarations for msg_control and msg_controllen on Solaris */ -#mesondefine _XOPEN_SOURCE_EXTENDED - -/* Needed to get declarations for msg_control and msg_controllen on Solaris */ -#mesondefine __EXTENSIONS__ - -/* compiler supports atomic operations */ -#mesondefine __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 - -/* Define to empty if `const' does not conform to ANSI C. */ -#mesondefine const - -/* Define to long or long long if and don't define. */ -#mesondefine intmax_t - -/* Define to empty if the C compiler doesn't support this keyword. */ -#mesondefine signed - -/* Define to `unsigned int' if does not define. */ -#mesondefine size_t - -#mesondefine EXEEXT - -#mesondefine MAJOR_IN_MKDEV -#mesondefine MAJOR_IN_SYSMACROS -#mesondefine HAVE_RTLD_LAZY -#mesondefine HAVE_RTLD_NOW -#mesondefine HAVE_RTLD_GLOBAL diff --git a/config.h.win32.in b/config.h.win32.in deleted file mode 100644 index 14ac11d39..000000000 --- a/config.h.win32.in +++ /dev/null @@ -1,872 +0,0 @@ -/* config.h.win32.in Merged from two versions generated by configure for gcc and MSVC. */ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* The normal alignment of `guint32', in bytes. */ -#define ALIGNOF_GUINT32 4 - -/* The normal alignment of `guint64', in bytes. */ -#define ALIGNOF_GUINT64 8 - -/* The normal alignment of `unsigned long', in bytes. */ -#define ALIGNOF_UNSIGNED_LONG 4 - -/* poll doesn't work on devices */ -#define BROKEN_POLL 1 - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Whether to disable memory pools */ -/* #undef DISABLE_MEM_POOLS */ - -/* Whether to enable GC friendliness by default */ -/* #undef ENABLE_GC_FRIENDLY_DEFAULT */ - -/* always defined to indicate that i18n is enabled */ -#define ENABLE_NLS 1 - -/* Define the gettext package to be used */ -#define GETTEXT_PACKAGE "@GETTEXT_PACKAGE@" - -/* Define to the GLIB binary age */ -#define GLIB_BINARY_AGE @GLIB_BINARY_AGE@ - -/* Define to the GLIB interface age */ -#define GLIB_INTERFACE_AGE @GLIB_INTERFACE_AGE@ - -/* Define the location where the catalogs will be installed */ -#define GLIB_LOCALE_DIR "NONE/share/locale" - -/* Define to the GLIB major version */ -#define GLIB_MAJOR_VERSION @GLIB_MAJOR_VERSION@ - -/* Define to the GLIB micro version */ -#define GLIB_MICRO_VERSION @GLIB_MICRO_VERSION@ - -/* Define to the GLIB minor version */ -#define GLIB_MINOR_VERSION @GLIB_MINOR_VERSION@ - -/* A 'va_copy' style function */ -#if !defined (_MSC_VER) || (_MSC_VER >= 1800) -# define G_VA_COPY va_copy -#else /* _MSC_VER && _MSC_VER < 1800 */ -/* #undef G_VA_COPY */ -#endif - -/* 'va_lists' cannot be copies as values */ -/* #undef G_VA_COPY_AS_ARRAY */ - -/* Define to 1 if you have `alloca', as a function or macro. */ -/* #undef HAVE_ALLOCA */ - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -/* #undef HAVE_ALLOCA_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ATTR_XATTR_H */ - -/* Define to 1 if you have the `bind_textdomain_codeset' function. */ -#define HAVE_BIND_TEXTDOMAIN_CODESET 1 - -/* Define if you have a version of the snprintf function with semantics as - specified by the ISO C99 standard. */ -#undef HAVE_C99_SNPRINTF - -/* Define if you have a version of the vsnprintf function with semantics as - specified by the ISO C99 standard. */ -#undef HAVE_C99_VSNPRINTF - -/* define to 1 if Carbon is available */ -/* #undef HAVE_CARBON */ - -/* Define to 1 if you have the `clock_gettime' function. */ -/* #undef HAVE_CLOCK_GETTIME */ - -/* define to 1 if Cocoa is available */ -/* #undef HAVE_COCOA */ - -/* Have nl_langinfo (CODESET) */ -/* #undef HAVE_CODESET */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CRT_EXTERNS_H */ - -/* Define if dbus-1 is available */ -/* #undef HAVE_DBUS1 */ - -/* Define to 1 if you have the `dcgettext' function. */ -#define HAVE_DCGETTEXT 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#ifndef _MSC_VER -# define HAVE_DIRENT_H 1 -#else -/* # undef HAVE_DIRENT_H */ -#endif - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define to 1 if using dtrace probes. */ -/* #undef HAVE_DTRACE */ - -/* Define to 1 if you have the `endmntent' function. */ -/* #undef HAVE_ENDMNTENT */ - -/* Define to 1 if you have the `endservent' function. */ -/* #undef HAVE_ENDSERVENT */ - -/* we have the eventfd(2) system call */ -/* #undef HAVE_EVENTFD */ - -/* Define to 1 if you have the `fallocate' function. */ -/* #undef HAVE_FALLOCATE */ - -/* Define if we have FAM */ -/* #undef HAVE_FAM */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FAM_H */ - -/* Define if we have FAMNoExists in fam */ -/* #undef HAVE_FAM_NO_EXISTS */ - -/* Define to 1 if you have the `fchmod' function. */ -/* #undef HAVE_FCHMOD */ - -/* Define to 1 if you have the `fchown' function. */ -/* #undef HAVE_FCHOWN */ - -/* Define to 1 if you have the `fdwalk' function. */ -/* #undef HAVE_FDWALK */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FSTAB_H */ - -/* Define to 1 if you have the `fsync' function. */ -/* #undef HAVE_FSYNC */ - -/* we have the futex(2) system call */ -/* #undef HAVE_FUTEX */ - -/* Define to 1 if you have the `getc_unlocked' function. */ -/* #undef HAVE_GETC_UNLOCKED */ - -/* Define to 1 if you have the `getfsstat' function. */ -/* #undef HAVE_GETFSSTAT */ - -/* Define to 1 if you have the `getgrgid_r' function. */ -/* #undef HAVE_GETGRGID_R */ - -/* Define to 1 if you have the `getmntent_r' function. */ -/* #undef HAVE_GETMNTENT_R */ - -/* Define to 1 if you have the `getprotobyname_r' function. */ -/* #undef HAVE_GETPROTOBYNAME_R */ - -/* Define to 1 if you have the `getpwuid_r' function. */ -/* #undef HAVE_GETPWUID_R */ - -/* Define to 1 if you have the `getresuid' function. */ -/* #undef HAVE_GETRESUID */ - -/* Define if the GNU gettext() function is already present or preinstalled. */ -#define HAVE_GETTEXT 1 - -/* Define to 1 if you have the `getvfsstat' function. */ -/* #undef HAVE_GETVFSSTAT */ - -/* Define to 1 if you have the `gmtime_r' function. */ -/* #undef HAVE_GMTIME_R */ - -/* define to use system printf */ -/* #undef HAVE_GOOD_PRINTF */ - -/* Define to 1 if you have the `hasmntopt' function. */ -/* #undef HAVE_HASMNTOPT */ - -/* Define to 1 if you have the `if_indextoname' function. */ -#define HAVE_IF_INDEXTONAME 1 - -/* Define to 1 if you have the `if_nametoindex' function. */ -#define HAVE_IF_NAMETOINDEX 1 - -/* Define to 1 if you have the `inotify_init1' function. */ -/* #undef HAVE_INOTIFY_INIT1 */ - -/* define to support printing 64-bit integers with format I64 */ -/* #undef HAVE_INT64_AND_I64 */ - -/* Define if you have the 'intmax_t' type in or . */ -#if !defined (_MSC_VER) || (_MSC_VER >= 1600) -# define HAVE_INTMAX_T 1 -#endif - -/* Define to 1 if you have the header file. */ -#if !defined (_MSC_VER) || (_MSC_VER >= 1800) -# define HAVE_INTTYPES_H 1 -#endif - -/* Define if exists, doesn't clash with , and - declares uintmax_t. */ -#if !defined (_MSC_VER) || (_MSC_VER >= 1800) -# define HAVE_INTTYPES_H_WITH_UINTMAX 1 -#endif - -/* Define if we have struct ip_mreqn */ -/* #undef HAVE_IP_MREQN */ - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kevent' function. */ -/* #undef HAVE_KEVENT */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define if you have and nl_langinfo(CODESET). */ -/* #undef HAVE_LANGINFO_CODESET */ - -/* Have nl_langinfo (_NL_CTYPE_OUTDIGITn_MB) */ -/* #undef HAVE_LANGINFO_OUTDIGIT */ - -/* Have nl_langinfo (PM_STR) */ -/* #undef HAVE_LANGINFO_TIME */ - -/* Define to 1 if you have the `lchmod' function. */ -/* #undef HAVE_LCHMOD */ - -/* Define to 1 if you have the `lchown' function. */ -/* #undef HAVE_LCHOWN */ - -/* Define if your file defines LC_MESSAGES. */ -/* #undef HAVE_LC_MESSAGES */ - -/* Define if you have the __libc_enable_secure variable (GNU libc, eglibc) */ -/* #undef HAVE_LIBC_ENABLE_SECURE */ - -/* Define if libelf is available */ -/* #undef HAVE_LIBELF */ - -/* Define to 1 if you have the `link' function. */ -/* #undef HAVE_LINK */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_MAGIC_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define to 1 if you have the `localtime_r' function. */ -/* #undef HAVE_LOCALTIME_R */ - -/* Define if you have the 'long double' type. */ -#define HAVE_LONG_DOUBLE 1 - -/* Define if you have the 'long long' type. */ -#define HAVE_LONG_LONG 1 - -/* define if system printf can print long long */ -/* #undef HAVE_LONG_LONG_FORMAT */ - -/* Define to 1 if you have the `lstat' function. */ -/* #undef HAVE_LSTAT */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACH_MACH_TIME_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the `mbrtowc' function. */ -#define HAVE_MBRTOWC 1 - -/* Define to 1 if you have the `memalign' function. */ -/* #undef HAVE_MEMALIGN */ - -/* Define to 1 if you have the `memmem' function. */ -/* #undef HAVE_MEMMEM */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mmap' function. */ -/* #undef HAVE_MMAP */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MNTENT_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* We have AF_NETLINK sockets */ -/* #undef HAVE_NETLINK */ - -/* Define to 1 if you have the `newlocale' function. */ -/* #undef HAVE_NEWLOCALE */ - -/* open option O_DIRECTORY */ -/* #undef HAVE_OPEN_O_DIRECTORY */ - -/* Define to 1 if you have the `pipe2' function. */ -/* #undef HAVE_PIPE2 */ - -/* Define to 1 if you have the `poll' function. */ -/* #undef HAVE_POLL */ - -/* Define to 1 if you have the `posix_memalign' function. */ -/* #undef HAVE_POSIX_MEMALIGN */ - -/* Define to 1 if you have the `prlimit' function. */ -/* #undef HAVE_PRLIMIT */ - -/* Have function pthread_attr_setstacksize */ -/* #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE */ - -/* Have function pthread_cond_timedwait_relative_np */ -/* #undef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP */ - -/* Have function pthread_condattr_setclock */ -/* #undef HAVE_PTHREAD_CONDATTR_SETCLOCK */ - -/* Have function pthread_setname_np without TID as argument */ -/* #undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID */ - -/* Have function pthread_setname_np with TID as argument */ -/* #undef HAVE_PTHREAD_SETNAME_NP_WITH_TID */ - -/* Define to 1 if the system has the type `ptrdiff_t'. */ -#define HAVE_PTRDIFF_T 1 - -/* Define to 1 if you have the `readlink' function. */ -/* #undef HAVE_READLINK */ - -/* Define to 1 if you have the `recvmmsg' function. */ -/* #undef HAVE_RECVMMSG */ - -/* Define to 1 if you have the 'res_init' function. */ -/* #undef HAVE_RES_INIT */ - -/* Define to 1 if you have the 'res_nclose' function. */ -/* #undef HAVE_RES_NCLOSE */ - -/* Define to 1 if you have the 'res_ndestroy' function. */ -/* #undef HAVE_RES_NDESTROY */ - -/* Define to 1 if you have the 'res_ninit' function. */ -/* #undef HAVE_RES_NINIT */ - -/* Define to 1 if you have the 'res_nquery' function. */ -/* #undef HAVE_RES_NQUERY */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SCHED_H */ - -/* Define to 1 if libselinux is available */ -/* #undef HAVE_SELINUX */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SELINUX_SELINUX_H */ - -/* Define to 1 if you have the `sendmmsg' function. */ -/* #undef HAVE_SENDMMSG */ - -/* Define to 1 if you have the `setenv' function. */ -/* #undef HAVE_SETENV */ - -/* Define to 1 if you have the `setmntent' function. */ -/* #undef HAVE_SETMNTENT */ - -/* Define if you have the 'sig_atomic_t' type. */ -#define HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 -#if defined (_MSC_VER) && (_MSC_VER < 1900) -# define snprintf _snprintf -#endif - -/* Define to 1 if you have the `splice' function. */ -/* #undef HAVE_SPLICE */ - -/* Define to 1 if you have the `statfs' function. */ -/* #undef HAVE_STATFS */ - -/* Define to 1 if you have the `statvfs' function. */ -/* #undef HAVE_STATVFS */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDDEF_H 1 - -/* Define to 1 if you have the header file. */ -#if !defined (_MSC_VER) || (_MSC_VER >= 1600) -# define HAVE_STDINT_H 1 -#endif - -/* Define if exists, doesn't clash with , and declares - uintmax_t. */ -#if !defined (_MSC_VER) || (_MSC_VER >= 1600) -# define HAVE_STDINT_H_WITH_UINTMAX 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `stpcpy' function. */ -/* #undef HAVE_STPCPY */ - -/* Define to 1 if you have the `strcasecmp' function. */ -#define HAVE_STRCASECMP 1 -#ifdef _MSC_VER -# define strcasecmp _stricmp -#endif - -/* Define to 1 if you have the `strerror_r' function. */ -/* #undef HAVE_STRERROR_R */ - -/* Define if strerror_r returns char * */ -/* #undef STRERROR_R_CHAR_P */ - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -# define HAVE_STRINGS_H 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Have functions strlcpy and strlcat */ -/* #undef HAVE_STRLCPY */ - -/* Define to 1 if you have the `strncasecmp' function. */ -#define HAVE_STRNCASECMP 1 -#ifdef _MSC_VER -# define strncasecmp _strnicmp -#endif - -/* Define to 1 if you have the `strnlen' function. */ -#define HAVE_STRNLEN 1 - -/* Define to 1 if you have the `strsignal' function. */ -/* #undef HAVE_STRSIGNAL */ - -/* Define to 1 if you have the `strtod_l' function. */ -/* #undef HAVE_STRTOD_L */ - -/* Define to 1 if you have the `strtoll_l' function. */ -/* #undef HAVE_STRTOLL_L */ - -/* Define to 1 if you have the `strtoull_l' function. */ -/* #undef HAVE_STRTOULL_L */ - -/* Define to 1 if `d_type' is a member of `struct dirent'. */ -/* #undef HAVE_STRUCT_DIRENT_D_TYPE */ - -/* Define to 1 if `f_bavail' is a member of `struct statfs'. */ -/* #undef HAVE_STRUCT_STATFS_F_BAVAIL */ - -/* Define to 1 if `f_fstypename' is a member of `struct statfs'. */ -/* #undef HAVE_STRUCT_STATFS_F_FSTYPENAME */ - -/* Define to 1 if `f_basetype' is a member of `struct statvfs'. */ -/* #undef HAVE_STRUCT_STATVFS_F_BASETYPE */ - -/* Define to 1 if `f_fstypename' is a member of `struct statvfs'. */ -/* #undef HAVE_STRUCT_STATVFS_F_FSTYPENAME */ - -/* Define to 1 if `st_atimensec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_ATIMENSEC */ - -/* Define to 1 if `st_atim.tv_nsec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC */ - -/* Define to 1 if `st_birthtim' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIM */ - -/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */ - -/* Define to 1 if `st_birthtimensec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC */ - -/* Define to 1 if `st_birthtim.tv_nsec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC */ - -/* Define to 1 if `st_blksize' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */ - -/* Define to 1 if `st_blocks' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BLOCKS */ - -/* Define to 1 if `st_ctimensec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_CTIMENSEC */ - -/* Define to 1 if `st_ctim.tv_nsec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC */ - -/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_MTIMENSEC */ - -/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */ - -/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ -/* #undef HAVE_STRUCT_TM_TM_GMTOFF */ - -/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ -/* #undef HAVE_STRUCT_TM___TM_GMTOFF */ - -/* Define to 1 if you have the `symlink' function. */ -/* #undef HAVE_SYMLINK */ - -/* Define to 1 if you have the `sysctlbyname' function. */ -/* #undef HAVE_SYSCTLBYNAME */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_FILIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_INOTIFY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MKDEV_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MNTCTL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MNTTAB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MOUNT_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -# define HAVE_SYS_PARAM_H 1 -#endif - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_POLL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_RESOURCE_H */ - -/* found fd_set in sys/select.h */ -/* #undef HAVE_SYS_SELECT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STATFS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STATVFS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SYSCTL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TIMES_H */ - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -# define HAVE_SYS_TIME_H 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_VFSTAB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_VFS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_VMOUNT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_XATTR_H */ - -/* Define to 1 if you have the `timegm' function. */ -/* #undef HAVE_TIMEGM */ - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -# define HAVE_UNISTD_H 1 -#endif - -/* Define if your printf function family supports positional parameters as - specified by Unix98. */ -/* #undef HAVE_UNIX98_PRINTF */ - -/* Define to 1 if you have the `unsetenv' function. */ -/* #undef HAVE_UNSETENV */ - -/* Define to 1 if you have the `uselocale' function. */ -/* #undef HAVE_USELOCALE */ - -/* Define to 1 if you have the `utimes' function. */ -/* #undef HAVE_UTIMES */ - -/* Define to 1 if you have the `valloc' function. */ -/* #undef HAVE_VALLOC */ - -/* Define to 1 if you have the header file. */ -#ifdef _MSC_VER -# define HAVE_VALUES_H 1 -#endif - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 - -/* Define if you have the 'wchar_t' type. */ -#define HAVE_WCHAR_T 1 - -/* Define to 1 if you have the `wcslen' function. */ -#define HAVE_WCSLEN 1 - -/* Define if you have the 'wint_t' type. */ -#define HAVE_WINT_T 1 - -/* Have a working bcopy */ -/* #undef HAVE_WORKING_BCOPY */ - -/* Define to 1 if xattr is available */ -/* #undef HAVE_XATTR */ - -/* Define to 1 if xattr API uses XATTR_NOFOLLOW */ -/* #undef HAVE_XATTR_NOFOLLOW */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_XLOCALE_H */ - -/* Define to 1 if you have the `_NSGetEnviron' function. */ -/* #undef HAVE__NSGETENVIRON */ - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR "" - -/* Do we cache iconv descriptors */ -/* #undef NEED_ICONV_CACHE */ - -/* didn't find fd_set */ -/* #undef NO_FD_SET */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=glib" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "glib" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "glib @GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@.@GLIB_MICRO_VERSION@" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "glib" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "@GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@.@GLIB_MICRO_VERSION@" - -/* define if posix_memalign() can allocate any size */ -/* #undef POSIX_MEMALIGN_WITH_COMPLIANT_ALLOCS */ - -/* The size of `char', as computed by sizeof. */ -#define SIZEOF_CHAR 1 - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* The size of `size_t', as computed by sizeof. */ -#ifdef _WIN64 -# define SIZEOF_SIZE_T 8 -#else -# define SIZEOF_SIZE_T 4 -#endif - -/* The size of `ssize_t', as computed by sizeof. */ -#ifdef _WIN64 -# define SIZEOF_SSIZE_T 8 -#else -# define SIZEOF_SSIZE_T 4 -#endif - -/* The size of `void *', as computed by sizeof. */ -#ifdef _WIN64 -# define SIZEOF_VOID_P 8 -#else -# define SIZEOF_VOID_P 4 -#endif - -/* The size of `__int64', as computed by sizeof. */ -#define SIZEOF___INT64 8 - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Number of arguments to statfs() */ -/* #undef STATFS_ARGS */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Use no threads */ -/* #undef THREADS_NONE */ - -/* Use pthreads */ -/* #undef THREADS_POSIX */ - -/* Use w32 threads */ -#define THREADS_WIN32 1 - -/* Using GNU libiconv */ -/* #undef USE_LIBICONV_GNU */ - -/* Using a native implementation of iconv in a separate library */ -#define USE_LIBICONV_NATIVE 1 - -/* Define to use statfs() */ -/* #undef USE_STATFS */ - -/* Define to use statvfs() */ -/* #undef USE_STATVFS */ - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -/* #undef _ALL_SOURCE */ -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -/* #undef _POSIX_PTHREAD_SEMANTICS */ -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -/* #undef _TANDEM_SOURCE */ -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -#define __EXTENSIONS__ 1 -#endif - -/* using the system-supplied PCRE library */ -/* This is determined in the MSVC projects */ -/* #undef USE_SYSTEM_PCRE */ - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* defines how to decorate public symbols while building */ -#ifdef _MSC_VER -# define _GLIB_EXTERN __declspec (dllexport) extern -#else -# define _GLIB_EXTERN __attribute__((visibility("default"))) __declspec (dllexport) extern -#endif - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Target the Windows 7 API */ -#define _WIN32_WINNT 0x0601 - -/* Needed to get declarations for msg_control and msg_controllen on Solaris */ -/* #undef _XOPEN_SOURCE */ - -/* Needed to get declarations for msg_control and msg_controllen on Solaris */ -/* #undef _XOPEN_SOURCE_EXTENDED */ - -/* Needed to get declarations for msg_control and msg_controllen on Solaris */ -#define __EXTENSIONS__ 1 - -/* compiler supports atomic operations */ -/* #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to long or long long if and don't define. */ -/* #undef intmax_t */ - -/* Define to empty if the C compiler doesn't support this keyword. */ -/* #undef signed */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -#define EXEEXT ".exe" - -/* #undef MAJOR_IN_MKDEV */ -/* #undef MAJOR_IN_SYSMACROS */ -/* #undef HAVE_RTLD_LAZY */ -/* #undef HAVE_RTLD_NOW */ -/* #undef HAVE_RTLD_GLOBAL */ diff --git a/configure.ac b/configure.ac index 7afeb87dc..11fde900f 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ m4_define(glib_configure_ac) m4_define([glib_major_version], [2]) m4_define([glib_minor_version], [57]) -m4_define([glib_micro_version], [1]) +m4_define([glib_micro_version], [2]) m4_define([glib_interface_age], [0]) m4_define([glib_binary_age], [m4_eval(100 * glib_minor_version + glib_micro_version)]) @@ -54,7 +54,7 @@ m4_define([glib_debug_default], AC_INIT(glib, [glib_version], - [http://bugzilla.gnome.org/enter_bug.cgi?product=glib]) + [https://gitlab.gnome.org/GNOME/glib/issues/new]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([glib/glib.h]) @@ -248,31 +248,8 @@ AC_ARG_ENABLE(debug, [turn on debugging @<:@default=glib_debug_default@:>@]),, enable_debug=glib_debug_default) -AC_ARG_ENABLE(gc_friendly, - [AS_HELP_STRING([--enable-gc-friendly], - [turn on garbage collector friendliness [default=no]])],, - [enable_gc_friendly=no]) -AC_ARG_ENABLE(mem_pools, - [AS_HELP_STRING([--disable-mem-pools], - [disable all glib memory pools])],, - [disable_mem_pools=no]) - GLIB_TESTS -AC_MSG_CHECKING([whether to enable garbage collector friendliness]) -AS_IF([test "x$enable_gc_friendly" = "xyes"], [ - AC_DEFINE(ENABLE_GC_FRIENDLY_DEFAULT, 1, [Whether to enable GC friendliness by default]) - AC_MSG_RESULT([yes]) -], [ AC_MSG_RESULT([no]) ]) - -AC_MSG_CHECKING([whether to disable memory pools]) -AS_IF([test "x$disable_mem_pools" = "xno"], [ - AC_MSG_RESULT([no]) -], [ - AC_DEFINE(DISABLE_MEM_POOLS, [1], [Whether to disable memory pools]) - AC_MSG_RESULT([yes]) -]) - dnl location to install runtime libraries, e.g. ../../lib to install dnl to /lib if libdir is /usr/lib AC_ARG_WITH(runtime-libdir, @@ -355,7 +332,6 @@ AC_SUBST(GLIB_EXTRA_CFLAGS) AC_EXEEXT AC_PROG_AWK -AC_CHECK_PROGS(PERL, [perl5 perl]) # option to specify python interpreter to use; this just sets $PYTHON, so that # we will fallback to reading $PYTHON if --with-python is not given, and @@ -503,20 +479,9 @@ AM_CONDITIONAL(OS_WIN32_AND_DLL_COMPILATION, [test x$glib_native_win32 = xyes -a # Checks for library functions. AC_FUNC_ALLOCA AC_CHECK_FUNCS(mmap posix_memalign memalign valloc fsync pipe2 issetugid) -AC_CHECK_FUNCS(timegm gmtime_r) +AC_CHECK_FUNCS(timegm gmtime_r posix_spawn) AC_FUNC_STRERROR_R() -AC_CACHE_CHECK([for __libc_enable_secure], glib_cv_have_libc_enable_secure, - [AC_TRY_LINK([#include - extern int __libc_enable_secure;], - [return __libc_enable_secure;], - glib_cv_have_libc_enable_secure=yes, - glib_cv_have_libc_enable_secure=no)]) -AS_IF([test x$glib_cv_have_libc_enable_secure = xyes], [ - AC_DEFINE(HAVE_LIBC_ENABLE_SECURE, 1, - [Define if you have the __libc_enable_secure variable (GNU libc, eglibc)]) -]) - AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(long) @@ -567,10 +532,6 @@ AS_IF([test x$glib_native_win32 != xyes && test x$ac_cv_sizeof_long_long = x8], done]) AS_IF([ test -n "$glib_cv_long_long_format"], [ AC_MSG_RESULT(%${glib_cv_long_long_format}u) - AC_DEFINE(HAVE_LONG_LONG_FORMAT,1,[define if system printf can print long long]) - if test x"$glib_cv_long_long_format" = xI64; then - AC_DEFINE(HAVE_INT64_AND_I64,1,[define to support printing 64-bit integers with format I64]) - fi ], [AC_MSG_RESULT(none)]) ],[ test x$ac_cv_sizeof___int64 = x8], [ # __int64 is a 64 bit integer. @@ -578,8 +539,6 @@ AS_IF([test x$glib_native_win32 != xyes && test x$ac_cv_sizeof_long_long = x8], # We know this is MSVCRT.DLL, and what the formats are glib_cv_long_long_format=I64 AC_MSG_RESULT(%${glib_cv_long_long_format}u) - AC_DEFINE(HAVE_LONG_LONG_FORMAT,1,[define if system printf can print long long]) - AC_DEFINE(HAVE_INT64_AND_I64,1,[define to support printing 64-bit integers with format I64]) ]) AC_C_CONST @@ -685,7 +644,7 @@ fi # check for header files AC_CHECK_HEADERS([sys/param.h sys/resource.h mach/mach_time.h]) AC_CHECK_HEADERS([sys/select.h stdint.h inttypes.h sched.h malloc.h]) -AC_CHECK_HEADERS([sys/vfs.h sys/vmount.h sys/statfs.h sys/statvfs.h sys/filio.h]) +AC_CHECK_HEADERS([sys/vfs.h sys/vmount.h sys/statfs.h sys/statvfs.h sys/filio.h sys/auxv.h]) AC_CHECK_HEADERS([mntent.h sys/mnttab.h sys/vfstab.h sys/mntctl.h fstab.h]) AC_CHECK_HEADERS([linux/magic.h]) AC_CHECK_HEADERS([termios.h]) @@ -705,6 +664,8 @@ AC_CHECK_HEADERS([sys/mount.h sys/sysctl.h], [], [], AC_CHECK_FUNCS(sysctlbyname) AC_HEADER_MAJOR +AS_IF([test "$ac_cv_header_sys_types_h_makedev" = "yes"], + [AC_DEFINE([MAJOR_IN_TYPES], [1], [Define to 1 if `major', `minor', and `makedev' are declared in .])]) AC_CHECK_HEADERS([xlocale.h]) # check for structure fields @@ -1221,24 +1182,6 @@ jm_AC_TYPE_INTMAX_T AC_CHECK_FUNCS([snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) AC_FUNC_SNPRINTF_C99 -# Check if needs to be included for fd_set -AC_MSG_CHECKING([for fd_set]) -AC_TRY_COMPILE([#include ], - [fd_set readMask, writeMask;], gtk_ok=yes, gtk_ok=no) -AS_IF([test "$gtk_ok" = "yes"], [ - AC_MSG_RESULT([yes, found in sys/types.h]) -], [ - AC_EGREP_HEADER(fd_set, sys/select.h, gtk_ok=yes) - if test "$gtk_ok" = "yes"; then - # *** FIXME: give it a different name - AC_DEFINE(HAVE_SYS_SELECT_H,1,[found fd_set in sys/select.h]) - AC_MSG_RESULT([yes, found in sys/select.h]) - else - AC_DEFINE(NO_FD_SET,1,[didn't find fd_set]) - AC_MSG_RESULT(no) - fi -]) - dnl Check for nl_langinfo and CODESET AC_LANG_SAVE AC_LANG_C @@ -1335,48 +1278,6 @@ if test x$glib_cv_langinfo_abaltmon = xyes; then fi AC_LANG_RESTORE -dnl **************************************** -dnl *** posix_memalign *** -dnl **************************************** -AC_MSG_CHECKING(for a compliant posix_memalign() implementation) -AC_CACHE_VAL(glib_cv_compliant_posix_memalign,[ - glib_cv_compliant_posix_memalign=0 - if test "$ac_cv_func_posix_memalign" = "yes" ; then - AC_TRY_RUN([ - #define _XOPEN_SOURCE 600 - #include /* posix_memalign() should be defined here */ - /* some systems break if #include used */ - static void test_memalign (size_t boundary, size_t size) { - void *mem = 0; - if (posix_memalign (&mem, boundary, size) != 0 || !mem) - exit (1); - else - free (mem); - } - int main() { - test_memalign ( 128, 128 - 2 * sizeof (void*)); - test_memalign ( 256, 256 - 2 * sizeof (void*)); - test_memalign ( 512, 512 - 2 * sizeof (void*)); - test_memalign ( 1024, 1024 - 2 * sizeof (void*)); - test_memalign ( 2048, 2048 - 2 * sizeof (void*)); - test_memalign ( 4096, 4096 - 2 * sizeof (void*)); - test_memalign ( 8192, 8192 - 2 * sizeof (void*)); - test_memalign (16384, 16384 - 2 * sizeof (void*)); - test_memalign (32768, 32768 - 2 * sizeof (void*)); - exit (0); /* success */ - } - ], - [glib_cv_compliant_posix_memalign=1], [], [:]) - : - fi - ]) -AS_IF([test "$glib_cv_compliant_posix_memalign" = "1"], [ - AC_MSG_RESULT(yes) - AC_DEFINE(POSIX_MEMALIGN_WITH_COMPLIANT_ALLOCS, 1, [define if posix_memalign() can allocate any size]) -], [ - AC_MSG_RESULT(no) -]) - dnl **************************************** dnl *** strlcpy/strlcat *** @@ -1651,14 +1552,14 @@ dnl ********************** AC_MSG_CHECKING(for gspawn implementation) case "$host" in *-*-mingw*) - GSPAWN=gspawn-win32.lo + g_spawn_impl=win32 ;; *) - GSPAWN=gspawn.lo + g_spawn_impl=unix ;; esac -AC_MSG_RESULT($GSPAWN) -AC_SUBST(GSPAWN) +AC_MSG_RESULT($g_spawn_impl) +AM_CONDITIONAL(G_SPAWN_WIN32, [test "$g_spawn_impl" = "win32"]) dnl ************************* dnl *** GIOChannel checks *** @@ -1667,14 +1568,14 @@ dnl ************************* AC_MSG_CHECKING(for GIOChannel implementation) case "$host" in *-*-mingw*) - GIO=giowin32.lo + g_io_channel_impl=win32 ;; *) - GIO=giounix.lo + g_io_channel_impl=unix ;; esac -AC_MSG_RESULT($GIO) -AC_SUBST(GIO) +AC_MSG_RESULT($g_io_channel_impl) +AM_CONDITIONAL(G_IO_CHANNEL_WIN32, [test "$g_io_channel_impl" = "win32"]) dnl ********************************* dnl *** Directory for GIO modules *** @@ -1751,8 +1652,7 @@ FAM_LIBS= if test "x$should_disable_fam" = "xno"; then AC_CHECK_LIB(fam, FAMOpen, [AC_CHECK_HEADERS(fam.h, - [AC_DEFINE(HAVE_FAM, [], [Define if we have FAM]) - AC_CHECK_LIB(fam, FAMNoExists, + [AC_CHECK_LIB(fam, FAMNoExists, AC_DEFINE(HAVE_FAM_NO_EXISTS, [], [Define if we have FAMNoExists in fam])) FAM_LIBS="-lfam"] fam_support=yes, @@ -1872,18 +1772,6 @@ dnl **************************************** dnl *** platform dependent source checks *** dnl **************************************** -AC_MSG_CHECKING(for platform-dependent source) -case "$host" in - *-*-cygwin*|*-*-mingw*) - PLATFORMDEP=gwin32.lo - ;; - *) - PLATFORMDEP= - ;; -esac -AC_MSG_RESULT($PLATFORMDEP) -AC_SUBST(PLATFORMDEP) - AC_MSG_CHECKING([whether to compile timeloop]) case "$host" in *-*-cygwin*|*-*-mingw*|*-*-minix) @@ -2168,13 +2056,11 @@ AS_IF([test x$have_threads = xposix], [ AC_DEFINE([THREADS_WIN32], [1], [Use w32 threads]) g_threads_impl="WIN32" ], [ - AC_DEFINE([THREADS_NONE], [1], [Use no threads]) g_threads_impl="NONE" G_THREAD_LIBS=error ]) AM_CONDITIONAL(THREADS_POSIX, [test "$g_threads_impl" = "POSIX"]) AM_CONDITIONAL(THREADS_WIN32, [test "$g_threads_impl" = "WIN32"]) -AM_CONDITIONAL(THREADS_NONE, [test "$g_threads_impl" = "NONE"]) if test "x$G_THREAD_LIBS" = xerror; then AC_MSG_ERROR($LIBS_NOT_FOUND_1$have_threads$LIBS_NOT_FOUND_2) @@ -2464,7 +2350,7 @@ dnl ********************* dnl *** GRegex checks *** dnl ********************* -PCRE_REQUIRED_VERSION=8.13 +PCRE_REQUIRED_VERSION=8.31 # Check if we should use the internal or the system-supplied pcre AC_ARG_WITH(pcre, @@ -3508,7 +3394,8 @@ AC_ARG_ENABLE(compile-warnings, enable_compile_warnings=yes) AS_IF([test "x$enable_compile_warnings" != xno], [ CC_CHECK_FLAGS_APPEND([GLIB_WARN_CFLAGS], [CFLAGS], [\ - -Wall -Wstrict-prototypes -Wduplicated-branches \ + -Wall -Wstrict-prototypes -Wduplicated-branches -Wmisleading-indentation \ + -Wno-bad-function-cast \ -Werror=declaration-after-statement \ -Werror=missing-prototypes -Werror=implicit-function-declaration \ -Werror=pointer-arith -Werror=init-self -Werror=format-security \ @@ -3560,21 +3447,11 @@ gobject-2.0.pc gio-2.0.pc gio-unix-2.0.pc gio-windows-2.0.pc -glib-zip glib-gettextize Makefile build/Makefile build/win32/Makefile build/win32/dirent/Makefile -win32/Makefile -win32/vs9/Makefile -win32/vs9/glib-version-paths.vsprops -win32/vs10/Makefile -win32/vs10/glib-version-paths.props -win32/vs11/Makefile -win32/vs12/Makefile -win32/vs14/Makefile -win32/vs15/Makefile glib/Makefile glib/libcharset/Makefile glib/gnulib/Makefile @@ -3615,13 +3492,13 @@ tests/Makefile tests/gobject/Makefile tests/refcount/Makefile m4macros/Makefile +subprojects/Makefile ]) # We need this command because the configure script will not preserve # the same attributes of the template files AC_CONFIG_COMMANDS([chmod-scripts], -[chmod 0755 glib-zip -chmod 0755 glib-gettextize +[chmod 0755 glib-gettextize chmod 0755 gobject/glib-genmarshal chmod 0755 gobject/glib-mkenums]) @@ -3631,9 +3508,6 @@ chmod 0755 gobject/glib-mkenums]) if false; then AC_CONFIG_FILES([ INSTALL - README - config.h.win32 - glib/glibconfig.h.win32 glib/glib.rc gmodule/gmodule.rc gobject/gobject.rc diff --git a/docs/macros.txt b/docs/macros.txt index 8b4202987..953616382 100644 --- a/docs/macros.txt +++ b/docs/macros.txt @@ -9,10 +9,6 @@ GLib's configure options and corresponding macros none --enable-debug=yes [default for development branches] -DG_ENABLE_DEBUG -g ---enable-gc-friendly=yes - #define ENABLE_GC_FRIENDLY_DEFAULT 1 ---disable-mem-pools=yes - #define DISABLE_MEM_POOLS 1 Besides these, there are some local feature specific options, but my main focus here is to concentrate on macros that affect overall GLib behaviour @@ -22,26 +18,6 @@ and/or third party code. Notes on GLib's internal and global macros ========================================== - -ENABLE_GC_FRIENDLY_DEFAULT - Newly allocated memory that isn't directly initialized, as well - as memory being freed should be reset to 0. The point here is to - allow memory checkers and similar programs that use bohem GC alike - algorithms to produce more accurate results. - This can also be accomplished by setting the environment variable - G_DEBUG=gc-friendly. -DISABLE_MEM_POOLS - Many small chunks of memory are often allocated via collective pools - in GLib and are cached after release to speed up reallocations. - For sparse memory systems this behaviour is often inferior, so - memory pools can be disabled to avoid excessive caching and force - atomic maintenance of chunks through the g_malloc/g_free. - Code currently affected by this macro: - - GList, GSList, GNode allocations - - GMemChunks become basically non-effective - - GSignal disables all caching (potentially very slow) - - GType doesn't honour the GTypeInfo n_preallocs field anymore - - the GBSearchArray flag G_BSEARCH_ALIGN_POWER2 becomes non-functional G_DISABLE_ASSERT The g_assert() and g_assert_not_reached() become non-functional with this define. The motivation is to speed up end-user apps by diff --git a/docs/reference/gio/Makefile.am b/docs/reference/gio/Makefile.am index e04ab6843..08093e8a0 100644 --- a/docs/reference/gio/Makefile.am +++ b/docs/reference/gio/Makefile.am @@ -8,6 +8,7 @@ DOC_MAIN_SGML_FILE=gio-docs.xml # Extra options to supply to gtkdoc-scan SCAN_OPTIONS = \ + --rebuild-types \ --deprecated-guards="G_DISABLE_DEPRECATED" \ --ignore-decorators="GLIB_VAR|G_GNUC_INTERNAL|G_GNUC_WARN_UNUSED_RESULT|GLIB_AVAILABLE_IN_ALL|GLIB_AVAILABLE_IN_2_26|GLIB_AVAILABLE_IN_2_28|GLIB_AVAILABLE_IN_2_30|GLIB_AVAILABLE_IN_2_32|GLIB_AVAILABLE_IN_2_34|GLIB_AVAILABLE_IN_2_36|GLIB_AVAILABLE_IN_2_38|GLIB_AVAILABLE_IN_2_40|GLIB_AVAILABLE_IN_2_42|GLIB_AVAILABLE_IN_2_44|GLIB_AVAILABLE_IN_2_46|GLIB_AVAILABLE_IN_2_48|GLIB_AVAILABLE_IN_2_50|GLIB_AVAILABLE_IN_2_52|GLIB_AVAILABLE_IN_2_54|GLIB_AVAILABLE_IN_2_56|GLIB_DEPRECATED_IN_2_26|GLIB_DEPRECATED_IN_2_26_FOR|GLIB_DEPRECATED_IN_2_28|GLIB_DEPRECATED_IN_2_28_FOR|GLIB_DEPRECATED_IN_2_30|GLIB_DEPRECATED_IN_2_30_FOR|GLIB_DEPRECATED_IN_2_32|GLIB_DEPRECATED_IN_2_32_FOR|GLIB_DEPRECATED_IN_2_34|GLIB_DEPRECATED_IN_2_34_FOR|GLIB_DEPRECATED_IN_2_36|GLIB_DEPRECATED_IN_2_36_FOR|GLIB_DEPRECATED_IN_2_38|GLIB_DEPRECATED_IN_2_38_FOR|GLIB_DEPRECATED_IN_2_40|GLIB_DEPRECATED_IN_2_40_FOR|GLIB_DEPRECATED_IN_2_42|GLIB_DEPRECATED_IN_2_42_FOR|GLIB_DEPRECATED_IN_2_44|GLIB_DEPRECATED_IN_2_44_FOR|GLIB_DEPRECATED_IN_2_46|GLIB_DEPRECATED_IN_2_46_FOR|GLIB_DEPRECATED_IN_2_48|GLIB_DEPRECATED_IN_2_48_FOR|GLIB_DEPRECATED_IN_2_50|GLIB_DEPRECATED_IN_2_50_FOR|GLIB_DEPRECATED_IN_2_52|GLIB_DEPRECATED_IN_2_52_FOR|GLIB_DEPRECATED_IN_2_54|GLIB_DEPRECATED_IN_2_54_FOR|GLIB_DEPRECATED_IN_2_56|GLIB_DEPRECATED_IN_2_56_FOR" @@ -20,82 +21,115 @@ HFILE_GLOB= \ CFILE_GLOB=$(top_srcdir)/gio/*.c IGNORE_HFILES = \ - fam \ - fen \ - gdbus-2.0 \ - gvdb \ - inotify \ - kqueue \ - libasyncns \ - tests \ - win32 \ - xdgmime \ - gappinfoprivate.h \ - gapplicationimpl.h \ - gasynchelper.h \ - gcontenttypeprivate.h \ - gcontextspecificgroup.h \ - gcredentialsprivate.h \ - gdbus-daemon-generated.h \ - gdbusactiongroup-private.h \ - gdbusauth.h \ - gdbusauthmechanismanon.h \ - gdbusauthmechanismexternal.h \ - gdbusauthmechanism.h \ - gdbusauthmechanismsha1.h \ - gdbusdaemon.h \ - gdbusprivate.h \ - gdelayedsettingsbackend.h \ - gdummyfile.h \ - gdummyproxyresolver.h \ - gdummytlsbackend.h \ - gfileattribute-priv.h \ - gfileinfo-priv.h \ - ghttpproxy.h \ - gio_trace.h \ - giomodule-priv.h \ - gioprivate.h \ - giowin32-priv.h \ - glocaldirectorymonitor.h \ - glocalfileenumerator.h \ - glocalfile.h \ - glocalfileinfo.h \ - glocalfileinputstream.h \ - glocalfileiostream.h \ - glocalfilemonitor.h \ - glocalfileoutputstream.h \ - glocalvfs.h \ - gmountprivate.h \ - gnativevolumemonitor.h \ - gnetworkingprivate.h \ - gnetworkmonitorbase.h \ - gnetworkmonitornetlink.h \ - gnetworkmonitornm.h \ - gnotificationbackend.h \ - gnotification-private.h \ - gpollfilemonitor.h \ - gregistrysettingsbackend.h \ - gresourcefile.h \ - gsettingsbackendinternal.h \ - gsettings-mapping.h \ - gsettingsschema-internal.h \ - gsocketinputstream.h \ - gsocketoutputstream.h \ - gsocks4aproxy.h \ - gsocks4proxy.h \ - gsocks5proxy.h \ - gsubprocesslauncher-private.h \ - gthreadedresolver.h \ - gunionvolumemonitor.h \ - gunixmount.h \ - gunixresolver.h \ - gunixvolume.h \ - gunixvolumemonitor.h \ - gwin32appinfo.h \ - gwin32mount.h \ - gwin32resolver.h \ - gwin32volumemonitor.h \ - thumbnail-verify.h + fam \ + fen \ + gdbus-2.0 \ + gvdb \ + inotify \ + kqueue \ + libasyncns \ + tests \ + win32 \ + xdgmime \ + gappinfoprivate.h \ + gapplicationimpl.h \ + gasynchelper.h \ + gcontenttypeprivate.h \ + gcontextspecificgroup.h \ + gcredentialsprivate.h \ + gdbus-daemon-generated.h \ + gdbusactiongroup-private.h \ + gdbusauth.h \ + gdbusauthmechanismanon.h \ + gdbusauthmechanismexternal.h \ + gdbusauthmechanism.h \ + gdbusauthmechanismsha1.h \ + gdbusdaemon.h \ + gdbusprivate.h \ + gdelayedsettingsbackend.h \ + gdummyfile.h \ + gdummyproxyresolver.h \ + gdummytlsbackend.h \ + gfileattribute-priv.h \ + gfileinfo-priv.h \ + ghttpproxy.h \ + giomodule-priv.h \ + gioprivate.h \ + giowin32-priv.h \ + glocaldirectorymonitor.h \ + glocalfileenumerator.h \ + glocalfile.h \ + glocalfileinfo.h \ + glocalfileinputstream.h \ + glocalfileiostream.h \ + glocalfilemonitor.h \ + glocalfileoutputstream.h \ + glocalvfs.h \ + gmountprivate.h \ + gnativevolumemonitor.h \ + gnetworkingprivate.h \ + gnetworkmonitorbase.h \ + gnetworkmonitornetlink.h \ + gnetworkmonitornm.h \ + gnetworkmonitorportal.h \ + gnotificationbackend.h \ + gnotification-private.h \ + gpollfilemonitor.h \ + gproxyresolverportal.h \ + gregistrysettingsbackend.h \ + gresourcefile.h \ + gsettingsbackendinternal.h \ + gsettings-mapping.h \ + gsettingsschema-internal.h \ + gsocketinputstream.h \ + gsocketoutputstream.h \ + gsocks4aproxy.h \ + gsocks4proxy.h \ + gsocks5proxy.h \ + gsubprocesslauncher-private.h \ + gthreadedresolver.h \ + gunionvolumemonitor.h \ + gunixmount.h \ + gunixresolver.h \ + gunixvolume.h \ + gunixvolumemonitor.h \ + gwin32appinfo.h \ + gwin32mount.h \ + gwin32registrykey.h \ + gwin32resolver.h \ + gwin32volumemonitor.h \ + thumbnail-verify.h \ + xdp-dbus.h \ + $(NULL) + +if OS_WIN32 +IGNORE_HFILES += \ + gfiledescriptorbased.h \ + gunixconnection.h \ + gunixcredentialsmessage.h \ + gunixmounts.h \ + gunixfdlist.h \ + gunixfdmessage.h \ + gunixinputstream.h \ + gunixoutputstream.h \ + gunixsocketaddress.h \ + gdesktopappinfo.h \ + gosxappinfo.h \ + $(NULL) +else + +if OS_COCOA +IGNORE_HFILES += gdesktopappinfo.h +else +IGNORE_HFILES += gosxappinfo.h +endif + +IGNORE_HFILES += \ + gwin32networkmonitor.h \ + gwin32inputstream.h \ + gwin32outputstream.h \ + $(NULL) +endif MKDB_IGNORE_FILES = \ gdbus-daemon-generated.c \ @@ -198,8 +232,6 @@ endif CLEANFILES ?= CLEANFILES += $(man_MANS) -EXTRA_DIST += $(man_MANS) - dist-hook-local: all-local gio-docs-clean: clean diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml index b1145e5ef..e4192084d 100644 --- a/docs/reference/gio/gdbus-codegen.xml +++ b/docs/reference/gio/gdbus-codegen.xml @@ -39,6 +39,8 @@ FILE + + OUTFILE @@ -69,7 +71,11 @@ arguments on the command line and generates output files. It currently supports generating C source code (via ) or header (via ) - and Docbook XML (via ). + and Docbook XML (via ). Alternatively, + more restricted C source code and headers can be generated, which just + contain the interface information (as GDBusInterfaceInfo + structures) using and + . @@ -90,8 +96,11 @@ For C code generation either that - generates source code, or that - generates headers, can be used. These options must be used along with + generates source code, that + generates headers, that generates + interface information source code, or + that generates interface information + headers, can be used. These options must be used along with , which is used to specify the file to output to. @@ -282,8 +291,10 @@ Directory to output generated source to. Equivalent to changing directory before generation. - This option cannot be used with neither nor - , and must be used. + This option cannot be used with , + , or + ; and + must be used. @@ -321,12 +332,52 @@ + + + + + If this option is passed, it will generate the header code for the + GDBusInterfaceInfo structures only and will write it to + the disk by using the path and file name provided by + . + + + Using , or + are not allowed to be used along with + the and + options, because these options + are used to generate only one file. + + + + + + + + + If this option is passed, it will generate the source code for the + GDBusInterfaceInfo structures only and will write it to + the disk by using the path and file name provided by + . + + + Using , or + are not allowed to be used along with + the and + options, because these options + are used to generate only one file. + + + + OUTFILE - The full path where the header () or the source code - () will be written, using the path and filename provided by + The full path where the header (, + ) or the source code + (, ) will + be written, using the path and filename provided by . The full path could be something like $($OUTFILE).{c,h}. @@ -987,7 +1038,7 @@ on_handle_hello_world (MyAppFrobber *interface, Please send bug reports to either the distribution bug tracker or the upstream bug tracker at - https://bugzilla.gnome.org/enter_bug.cgi?product=glib. + https://gitlab.gnome.org/GNOME/glib/issues/new. diff --git a/docs/reference/gio/gdbus.xml b/docs/reference/gio/gdbus.xml index efcec33fe..0e6c14db1 100644 --- a/docs/reference/gio/gdbus.xml +++ b/docs/reference/gio/gdbus.xml @@ -399,7 +399,7 @@ $ gdbus wait --session --timeout 30 org.bar.SomeName Please send bug reports to either the distribution bug tracker or the upstream bug tracker at - . + . diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index 0a35f9541..0eb560716 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -1248,6 +1248,7 @@ g_drive_stop_finish g_drive_enumerate_identifiers g_drive_get_identifier g_drive_get_sort_key +G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE G_DRIVE G_IS_DRIVE @@ -1496,6 +1497,12 @@ g_mount_operation_get_password_save g_mount_operation_set_password_save g_mount_operation_get_choice g_mount_operation_set_choice +g_mount_operation_get_is_tcrypt_hidden_volume +g_mount_operation_set_is_tcrypt_hidden_volume +g_mount_operation_get_is_tcrypt_system_volume +g_mount_operation_set_is_tcrypt_system_volume +g_mount_operation_get_pim +g_mount_operation_set_pim g_mount_operation_reply GMountOperationClass @@ -1571,6 +1578,7 @@ g_unix_mount_point_guess_can_eject g_unix_mount_points_get g_unix_mounts_get g_unix_mount_at +g_unix_mount_for g_unix_mounts_changed_since g_unix_mount_points_changed_since g_unix_mount_monitor_get @@ -1616,6 +1624,7 @@ g_desktop_app_info_get_boolean g_desktop_app_info_has_key GDesktopAppLaunchCallback g_desktop_app_info_launch_uris_as_manager +g_desktop_app_info_launch_uris_as_manager_with_fds g_desktop_app_info_list_actions g_desktop_app_info_get_action_name diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types deleted file mode 100644 index 8ab7d918f..000000000 --- a/docs/reference/gio/gio.types +++ /dev/null @@ -1,156 +0,0 @@ -g_action_get_type -g_action_group_get_type -g_action_map_get_type -g_app_info_get_type -g_app_info_monitor_get_type -g_app_launch_context_get_type -g_application_command_line_get_type -g_application_get_type -g_async_initable_get_type -g_async_result_get_type -g_buffered_input_stream_get_type -g_buffered_output_stream_get_type -g_bytes_icon_get_type -g_cancellable_get_type -g_charset_converter_get_type -g_converter_get_type -g_converter_input_stream_get_type -g_converter_output_stream_get_type -g_credentials_get_type -g_data_input_stream_get_type -g_data_output_stream_get_type -g_dbus_action_group_get_type -g_dbus_annotation_info_get_type -g_dbus_arg_info_get_type -g_dbus_auth_observer_get_type -g_dbus_connection_get_type -g_dbus_interface_get_type -g_dbus_interface_info_get_type -g_dbus_interface_skeleton_get_type -g_dbus_menu_model_get_type -g_dbus_message_get_type -g_dbus_method_info_get_type -g_dbus_method_invocation_get_type -g_dbus_node_info_get_type -g_dbus_object_get_type -g_dbus_object_manager_client_get_type -g_dbus_object_manager_get_type -g_dbus_object_manager_server_get_type -g_dbus_object_proxy_get_type -g_dbus_object_skeleton_get_type -g_dbus_property_info_get_type -g_dbus_proxy_get_type -g_dbus_server_get_type -g_dbus_signal_info_get_type -g_desktop_app_info_get_type -g_desktop_app_info_lookup_get_type -g_drive_get_type -g_dtls_client_connection_get_type -g_dtls_connection_get_type -g_dtls_server_connection_get_type -g_emblem_get_type -g_emblemed_icon_get_type -g_file_attribute_info_list_get_type -g_file_attribute_matcher_get_type -g_file_descriptor_based_get_type -g_file_enumerator_get_type -g_file_get_type -g_file_icon_get_type -g_file_info_get_type -g_file_input_stream_get_type -g_file_io_stream_get_type -g_file_monitor_get_type -g_file_output_stream_get_type -g_filename_completer_get_type -g_filter_input_stream_get_type -g_filter_output_stream_get_type -g_icon_get_type -g_inet_address_get_type -g_inet_address_mask_get_type -g_inet_socket_address_get_type -g_initable_get_type -g_input_stream_get_type -g_io_module_get_type -g_io_stream_get_type -g_list_model_get_type -g_list_store_get_type -g_loadable_icon_get_type -g_memory_input_stream_get_type -g_memory_output_stream_get_type -g_menu_attribute_iter_get_type -g_menu_get_type -g_menu_item_get_type -g_menu_link_iter_get_type -g_menu_model_get_type -g_mount_get_type -g_mount_operation_get_type -g_network_address_get_type -g_network_monitor_get_type -g_network_service_get_type -g_notification_get_type -g_output_stream_get_type -g_permission_get_type -g_pollable_input_stream_get_type -g_pollable_output_stream_get_type -g_property_action_get_type -g_proxy_address_enumerator_get_type -g_proxy_address_get_type -g_proxy_get_type -g_proxy_resolver_get_type -g_remote_action_group_get_type -g_resolver_get_type -g_resource_get_type -g_seekable_get_type -g_settings_backend_get_type -g_settings_get_type -g_settings_schema_get_type -g_settings_schema_key_get_type -g_settings_schema_source_get_type -g_simple_action_get_type -g_simple_action_group_get_type -g_simple_async_result_get_type -g_simple_io_stream_get_type -g_simple_permission_get_type -g_simple_proxy_resolver_get_type -g_socket_address_enumerator_get_type -g_socket_address_get_type -g_socket_client_get_type -g_socket_connectable_get_type -g_socket_connection_get_type -g_socket_control_message_get_type -g_socket_get_type -g_socket_listener_get_type -g_socket_service_get_type -g_srv_target_get_type -g_subprocess_get_type -g_subprocess_launcher_get_type -g_task_get_type -g_tcp_connection_get_type -g_tcp_wrapper_connection_get_type -g_test_dbus_get_type -g_themed_icon_get_type -g_threaded_socket_service_get_type -g_tls_backend_get_type -g_tls_certificate_get_type -g_tls_client_connection_get_type -g_tls_connection_get_type -g_tls_database_get_type -g_tls_file_database_get_type -g_tls_interaction_get_type -g_tls_password_get_type -g_tls_server_connection_get_type -g_unix_connection_get_type -g_unix_credentials_message_get_type -g_unix_fd_list_get_type -g_unix_fd_message_get_type -g_unix_input_stream_get_type -g_unix_mount_entry_get_type -g_unix_mount_monitor_get_type -g_unix_mount_point_get_type -g_unix_output_stream_get_type -g_unix_socket_address_get_type -g_vfs_get_type -g_volume_get_type -g_volume_monitor_get_type -g_zlib_compressor_get_type -g_zlib_decompressor_get_type diff --git a/docs/reference/gio/gio.xml b/docs/reference/gio/gio.xml index c3fd8f5b6..f2635d0b3 100644 --- a/docs/reference/gio/gio.xml +++ b/docs/reference/gio/gio.xml @@ -455,6 +455,21 @@ Show extra information. + + + The numeric PIM when unlocking a VeraCrypt volume. + + + + + Mount a TCRYPT hidden volume. + + + + + Mount a TCRYPT system volume. + + diff --git a/docs/reference/gio/meson.build b/docs/reference/gio/meson.build index 47046f250..c7ca62abb 100644 --- a/docs/reference/gio/meson.build +++ b/docs/reference/gio/meson.build @@ -182,7 +182,6 @@ if get_option('gtk_doc') gnome.gtkdoc('gio', main_xml : 'gio-docs.xml', namespace : 'g', - gobject_typesfile : 'gio.types', mode : 'none', dependencies : [libgio_dep, libgobject_dep, libglib_dep], src_dir : 'gio', diff --git a/docs/reference/gio/migrating-gnome-vfs.xml b/docs/reference/gio/migrating-gnome-vfs.xml index ba3987cad..27194aa9a 100644 --- a/docs/reference/gio/migrating-gnome-vfs.xml +++ b/docs/reference/gio/migrating-gnome-vfs.xml @@ -127,7 +127,7 @@ start_monitoring_trash (void) since we have not found a compelling use case where #GnomeVFSMIMEMonitor was used. If you think you have such a use case, please report it at - bugzilla.gnome.org. + https://gitlab.gnome.org/GNOME/glib/issues/new. diff --git a/docs/reference/gio/xml/meson.build b/docs/reference/gio/xml/meson.build index 6d1e295b8..6aeb74514 100644 --- a/docs/reference/gio/xml/meson.build +++ b/docs/reference/gio/xml/meson.build @@ -1,6 +1,6 @@ ent_conf = configuration_data() ent_conf.set('PACKAGE', 'glib') -ent_conf.set('PACKAGE_BUGREPORT', 'https://bugzilla.gnome.org/enter_bug.cgi?product=glib') +ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new') ent_conf.set('PACKAGE_NAME', 'glib') ent_conf.set('PACKAGE_STRING', 'glib') ent_conf.set('PACKAGE_TARNAME', 'glib') diff --git a/docs/reference/glib/Makefile.am b/docs/reference/glib/Makefile.am index 44536cf21..dfefa25ff 100644 --- a/docs/reference/glib/Makefile.am +++ b/docs/reference/glib/Makefile.am @@ -61,7 +61,9 @@ IGNORE_HFILES = \ gtranslit-data.h \ glib-init.h \ gconstructor.h \ - valgrind.h + valgrind.h \ + gvalgrind.h \ + $(NULL) # Images to copy into HTML directory HTML_IMAGES = \ @@ -138,8 +140,6 @@ endif CLEANFILES ?= CLEANFILES += $(man_MANS) -EXTRA_DIST += $(man_MANS) - dist-hook-local: all-local glib-docs-clean: clean diff --git a/docs/reference/glib/building.xml b/docs/reference/glib/building.xml index 57c3c8c7d..b131c7561 100644 --- a/docs/reference/glib/building.xml +++ b/docs/reference/glib/building.xml @@ -227,107 +227,6 @@ - - <option>--disable-gc-friendly</option> and - <option>--enable-gc-friendly</option> - - - By default, and with - as well, GLib does not clear the memory for certain objects before - they are freed. For example, GLib may decide to recycle GList nodes - by putting them in a free list. However, memory profiling and debugging - tools like Valgrind work - better if an application does not keep dangling pointers to freed - memory (even though these pointers are no longer dereferenced), or - invalid pointers inside uninitialized memory. - The option makes GLib - clear memory in these situations: - - - - - - When shrinking a GArray, GLib will clear the memory no longer - available in the array: shrink an array from 10 bytes to 7, and - the last 3 bytes will be cleared. This includes removals of single - and multiple elements. - - - - - When growing a GArray, GLib will clear the new chunk of memory. - Grow an array from 7 bytes to 10 bytes, and the last 3 bytes will - be cleared. - - - - - The above applies to GPtrArray as well. - - - - - When freeing a node from a GHashTable, GLib will first clear - the node, which used to have pointers to the key and the value - stored at that node. - - - - - When destroying or removing a GTree node, GLib will clear the node, - which used to have pointers to the node's value, and the left and - right subnodes. - - - - - - Since clearing the memory has a cost, - is the default. - - - - - <option>--disable-mem-pools</option> and - <option>--enable-mem-pools</option> - - - Many small chunks of memory are often allocated via collective pools - in GLib and are cached after release to speed up reallocations. - For sparse memory systems this behaviour is often inferior, so - memory pools can be disabled to avoid excessive caching and force - atomic maintenance of chunks through the g_malloc() - and g_free() functions. Code currently affected by - this: - - - - GMemChunks become basically non-effective - - - - - GSignal disables all caching - (potentially very slow) - - - - - GType doesn't honour the - GTypeInfo - n_preallocs field anymore - - - - - the GBSearchArray flag - G_BSEARCH_ALIGN_POWER2 becomes non-functional - - - - - - <option>--with-threads</option> diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml index a0716c172..afebbec8b 100644 --- a/docs/reference/glib/glib-docs.xml +++ b/docs/reference/glib/glib-docs.xml @@ -119,6 +119,10 @@ + + + + @@ -256,6 +260,10 @@ Index of new symbols in 2.56 + + Index of new symbols in 2.58 + + diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 32a7664e8..8c733e0aa 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -219,6 +219,7 @@ MAX ABS CLAMP +G_APPROX_VALUE G_STRUCT_MEMBER @@ -620,6 +621,7 @@ g_source_set_name_by_id g_source_get_context g_source_set_callback GSourceFunc +G_SOURCE_FUNC g_source_set_callback_indirect g_source_set_ready_time g_source_get_ready_time @@ -1231,6 +1233,7 @@ GSpawnError G_SPAWN_ERROR GSpawnFlags GSpawnChildSetupFunc +g_spawn_async_with_fds g_spawn_async_with_pipes g_spawn_async g_spawn_sync @@ -3146,6 +3149,7 @@ g_assert_cmpint g_assert_cmpuint g_assert_cmphex g_assert_cmpfloat +g_assert_cmpfloat_with_epsilon g_assert_cmpmem g_assert_no_error g_assert_error @@ -3447,3 +3451,54 @@ g_hostname_is_ip_address g_uuid_string_is_valid g_uuid_string_random + +
+refcount +grefcount +g_ref_count_init +g_ref_count_inc +g_ref_count_dec +g_ref_count_compare + +gatomicrefcount +g_atomic_ref_count_init +g_atomic_ref_count_inc +g_atomic_ref_count_dec +g_atomic_ref_count_compare +
+ +
+rcbox +g_rc_box_alloc +g_rc_box_alloc0 +g_rc_box_new +g_rc_box_new0 +g_rc_box_dup +g_rc_box_acquire +g_rc_box_release +g_rc_box_release_full +g_rc_box_get_size +
+ +
+arcbox +g_atomic_rc_box_alloc +g_atomic_rc_box_alloc0 +g_atomic_rc_box_new +g_atomic_rc_box_new0 +g_atomic_rc_box_dup +g_atomic_rc_box_acquire +g_atomic_rc_box_release +g_atomic_rc_box_release_full +g_atomic_rc_box_get_size +
+ +
+refstring +g_ref_string_new +g_ref_string_new_intern +g_ref_string_new_len +g_ref_string_acquire +g_ref_string_release +g_ref_string_length +
diff --git a/docs/reference/glib/glib.types b/docs/reference/glib/glib.types deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/reference/glib/gvariant-text.xml b/docs/reference/glib/gvariant-text.xml index da80d174e..d569f0c74 100644 --- a/docs/reference/glib/gvariant-text.xml +++ b/docs/reference/glib/gvariant-text.xml @@ -563,7 +563,10 @@ Bytestrings The bytestring syntax is a piece of syntactic sugar meant to complement the bytestring APIs in GVariant. It - constructs arrays of non-nul bytes (type 'ay') with a nul terminator at the end. + constructs arrays of non-nul bytes (type 'ay') with a nul terminator at the end. These are + normal C strings with no particular encoding enforced, so the bytes may not be valid UTF-8. + Bytestrings are a special case of byte arrays; byte arrays (also type 'ay'), in the general + case, can contain nul at any position, and need not end with nul. Bytestrings are specified with either b"" or b''. As with strings, @@ -576,7 +579,7 @@ forms \0nnn and \xnn. - b'abc' is equivalent to [byte 0x97, 0x98, 0x99, 0]. + b'abc' is equivalent to [byte 0x61, 0x62, 0x63, 0]. When formatting arrays of bytes, the printer will choose to display the array as a bytestring if it contains diff --git a/docs/reference/glib/gvariant-varargs.xml b/docs/reference/glib/gvariant-varargs.xml index fbbbfcbd3..b60ab2a34 100644 --- a/docs/reference/glib/gvariant-varargs.xml +++ b/docs/reference/glib/gvariant-varargs.xml @@ -984,7 +984,7 @@ data = g_variant_new_parsed ("(%o, {'brightness': {'value': <%i>, 'max': <%i>}}) The '^' character currently supports conversion to and from bytestrings or to and from arrays - of strings or bytestrings. It has a number of forms. + of strings or bytestrings. It does not support byte arrays. It has a number of forms. diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build index f0f915e96..fbe3422d0 100644 --- a/docs/reference/glib/meson.build +++ b/docs/reference/glib/meson.build @@ -34,6 +34,7 @@ if get_option('gtk_doc') 'glib-init.h', 'gconstructor.h', 'valgrind.h', + 'gvalgrind.h', ] ignore_decorators = [ @@ -107,7 +108,6 @@ if get_option('gtk_doc') src_dir : [ 'glib', 'gmodule' ], dependencies : libglib_dep, scan_args : [ - '--rebuild-types', '--deprecated-guards=G_DISABLE_DEPRECATED', '--ignore-decorators=' + '|'.join(ignore_decorators), '--ignore-headers=' + ' '.join(ignore_headers), diff --git a/docs/reference/glib/resources.xml b/docs/reference/glib/resources.xml index 186bbf744..80e6f4cd2 100644 --- a/docs/reference/glib/resources.xml +++ b/docs/reference/glib/resources.xml @@ -21,11 +21,10 @@ Getting help with GLib If you encounter a bug, misfeature, or missing feature in GLib, please -file a bug report on -http://bugzilla.gnome.org. +file a bug report on the issue tracker at +https://gitlab.gnome.org/GNOME/glib/issues/new. We'd also appreciate reports of incomplete or misleading information in -the GLib documentation; file those against the "docs" component of the "glib" -product in Bugzilla. +the GLib documentation; file those with the ‘Documentation’ label. @@ -36,30 +35,28 @@ discussed, we'll add a note to that effect in the report. -The bug tracker should definitely be used for feature requests, it's -not only for bugs. We track all GLib development in Bugzilla, so it's +The issue tracker should definitely be used for feature requests, it's +not only for bugs. We track all GLib development in GitLab, so it's the way to be sure the GLib developers won't forget about an issue. -Submitting Patches +Code Contributions -If you develop a bugfix or enhancement for GLib, please file that in -Bugzilla as well. Bugzilla allows you to attach files; please attach a -patch generated by the diff utility, using the - option to make the patch more readable. All patches -must be offered under the terms of the GNU LGPL license, so be sure you -are authorized to give us the patch under those terms. +If you develop a bugfix or enhancement for GLib, please open a merge request +for that in GitLab as well. All branches must be offered under the terms of +the GNU LGPL license, so be sure you are authorized to give us the branch +under those terms. -If you want to discuss your patch before or after developing it, mail +If you want to discuss your branch before or after developing it, mail gtk-devel-list@gnome.org. -But be sure to file the Bugzilla report as well; if the patch is only on the -list and not in Bugzilla, it's likely to slip through the cracks. +But be sure to create the GitLab merge request as well; if the branch is only +on the list and not in GitLab, it's likely to slip through the cracks. @@ -92,7 +89,7 @@ questions. gtk-devel-list is for discussion of work on GTK+ (and GLib) itself, it is not for asking questions about how to use GTK+ (or GLib) -in applications. gtk-devel-list is appropriate for discussion of patches, +in applications. gtk-devel-list is appropriate for discussion of branches, bugs, proposed features, and so on. diff --git a/docs/reference/glib/xml/meson.build b/docs/reference/glib/xml/meson.build index 6d1e295b8..6aeb74514 100644 --- a/docs/reference/glib/xml/meson.build +++ b/docs/reference/glib/xml/meson.build @@ -1,6 +1,6 @@ ent_conf = configuration_data() ent_conf.set('PACKAGE', 'glib') -ent_conf.set('PACKAGE_BUGREPORT', 'https://bugzilla.gnome.org/enter_bug.cgi?product=glib') +ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new') ent_conf.set('PACKAGE_NAME', 'glib') ent_conf.set('PACKAGE_STRING', 'glib') ent_conf.set('PACKAGE_TARNAME', 'glib') diff --git a/docs/reference/gobject/Makefile.am b/docs/reference/gobject/Makefile.am index 430ab6d5f..6efe781e1 100644 --- a/docs/reference/gobject/Makefile.am +++ b/docs/reference/gobject/Makefile.am @@ -13,6 +13,7 @@ DOC_SOURCE_DIR =$(top_srcdir)/gobject $(top_builddir)/gobject # Extra options to supply to gtkdoc-scan SCAN_OPTIONS = \ + --rebuild-types \ --deprecated-guards="G_DISABLE_DEPRECATED" \ --ignore-decorators="GLIB_VAR|G_GNUC_INTERNAL|G_GNUC_WARN_UNUSED_RESULT|GLIB_AVAILABLE_IN_ALL|GLIB_AVAILABLE_IN_2_26|GLIB_AVAILABLE_IN_2_28|GLIB_AVAILABLE_IN_2_30|GLIB_AVAILABLE_IN_2_32|GLIB_AVAILABLE_IN_2_34|GLIB_AVAILABLE_IN_2_36|GLIB_AVAILABLE_IN_2_38|GLIB_AVAILABLE_IN_2_40|GLIB_AVAILABLE_IN_2_42|GLIB_AVAILABLE_IN_2_44|GLIB_AVAILABLE_IN_2_46|GLIB_AVAILABLE_IN_2_48|GLIB_AVAILABLE_IN_2_50|GLIB_AVAILABLE_IN_2_52|GLIB_AVAILABLE_IN_2_54|GLIB_AVAILABLE_IN_2_56|GLIB_DEPRECATED_IN_2_26|GLIB_DEPRECATED_IN_2_26_FOR|GLIB_DEPRECATED_IN_2_28|GLIB_DEPRECATED_IN_2_28_FOR|GLIB_DEPRECATED_IN_2_30|GLIB_DEPRECATED_IN_2_30_FOR|GLIB_DEPRECATED_IN_2_32|GLIB_DEPRECATED_IN_2_32_FOR|GLIB_DEPRECATED_IN_2_34|GLIB_DEPRECATED_IN_2_34_FOR|GLIB_DEPRECATED_IN_2_36|GLIB_DEPRECATED_IN_2_36_FOR|GLIB_DEPRECATED_IN_2_38|GLIB_DEPRECATED_IN_2_38_FOR|GLIB_DEPRECATED_IN_2_40|GLIB_DEPRECATED_IN_2_40_FOR|GLIB_DEPRECATED_IN_2_42|GLIB_DEPRECATED_IN_2_42_FOR|GLIB_DEPRECATED_IN_2_44|GLIB_DEPRECATED_IN_2_44_FOR|GLIB_DEPRECATED_IN_2_46|GLIB_DEPRECATED_IN_2_46_FOR|GLIB_DEPRECATED_IN_2_48|GLIB_DEPRECATED_IN_2_48_FOR|GLIB_DEPRECATED_IN_2_50|GLIB_DEPRECATED_IN_2_50_FOR|GLIB_DEPRECATED_IN_2_52|GLIB_DEPRECATED_IN_2_52_FOR|GLIB_DEPRECATED_IN_2_54|GLIB_DEPRECATED_IN_2_54_FOR|GLIB_DEPRECATED_IN_2_56|GLIB_DEPRECATED_IN_2_56_FOR" @@ -64,7 +65,6 @@ include $(top_srcdir)/gtk-doc.make # Other files to distribute EXTRA_DIST += \ - gobject.cI \ version.xml.in ######################################################################## @@ -95,8 +95,6 @@ endif CLEANFILES ?= CLEANFILES += $(man_MANS) -EXTRA_DIST += $(man_MANS) - dist-hook-local: all-local gobject-docs-clean: clean diff --git a/docs/reference/gobject/gobject-docs.xml b/docs/reference/gobject/gobject-docs.xml index 646d91a91..f045df5b3 100644 --- a/docs/reference/gobject/gobject-docs.xml +++ b/docs/reference/gobject/gobject-docs.xml @@ -188,6 +188,14 @@ Index of new symbols in 2.46 + + Index of new symbols in 2.54 + + + + Index of new symbols in 2.56 + + diff --git a/docs/reference/gobject/gobject.cI b/docs/reference/gobject/gobject.cI deleted file mode 100644 index 2976940e3..000000000 --- a/docs/reference/gobject/gobject.cI +++ /dev/null @@ -1,11 +0,0 @@ -/* - * This is a hack to work around a limitation of gtkdoc-scan: it insists - * on putting () behind every symbol listed in gobject.types. Thus we - * can't put G_TYPE_OBJECT there, but have to sneak a g_object_get_type() - * function in the generated source via an #include. - */ -GType -g_object_get_type (void) -{ - return G_TYPE_OBJECT; -} diff --git a/docs/reference/gobject/gobject.types b/docs/reference/gobject/gobject.types deleted file mode 100644 index bb4e7b875..000000000 --- a/docs/reference/gobject/gobject.types +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include "gobject.cI" - -g_binding_get_type -g_object_get_type -g_type_module_get_type -g_type_plugin_get_type diff --git a/docs/reference/gobject/meson.build b/docs/reference/gobject/meson.build index de46cf96d..ac2da57d9 100644 --- a/docs/reference/gobject/meson.build +++ b/docs/reference/gobject/meson.build @@ -77,12 +77,12 @@ if get_option('gtk_doc') gnome.gtkdoc('gobject', main_xml : 'gobject-docs.xml', namespace : 'g', - gobject_typesfile : join_paths(meson.current_source_dir(), 'gobject.types'), mode : 'none', dependencies : [libgobject_dep, libglib_dep], include_directories : [gtkdocincl], src_dir : 'gobject', scan_args : [ + '--rebuild-types', '--deprecated-guards=G_DISABLE_DEPRECATED', '--ignore-decorators=' + '|'.join(ignore_decorators), '--ignore-headers=' + ' '.join(ignore_headers), diff --git a/docs/reference/gobject/tut_howto.xml b/docs/reference/gobject/tut_howto.xml index 0e119009b..daaad4697 100644 --- a/docs/reference/gobject/tut_howto.xml +++ b/docs/reference/gobject/tut_howto.xml @@ -1069,6 +1069,20 @@ viewer_file_init (ViewerFile *self) { /* Instance variable initialisation code. */ } + + + + If the object is not of final type, e.g. was declared using + G_DECLARE_DERIVABLE_TYPE + then + G_ADD_PRIVATE + macro should be added. The private structure should be declared exactly + as for a normal derivable object, see . + +G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, G_TYPE_OBJECT, + G_ADD_PRIVATE (ViewerFile) + G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE, + viewer_file_editable_interface_init)) diff --git a/docs/reference/gobject/xml/meson.build b/docs/reference/gobject/xml/meson.build index 6d1e295b8..6aeb74514 100644 --- a/docs/reference/gobject/xml/meson.build +++ b/docs/reference/gobject/xml/meson.build @@ -1,6 +1,6 @@ ent_conf = configuration_data() ent_conf.set('PACKAGE', 'glib') -ent_conf.set('PACKAGE_BUGREPORT', 'https://bugzilla.gnome.org/enter_bug.cgi?product=glib') +ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/glib/issues/new') ent_conf.set('PACKAGE_NAME', 'glib') ent_conf.set('PACKAGE_STRING', 'glib') ent_conf.set('PACKAGE_TARNAME', 'glib') diff --git a/gio/Makefile.am b/gio/Makefile.am index df4f24014..e14cad229 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -288,6 +288,9 @@ unix_sources = \ gportalsupport.h \ $(portal_sources) \ $(NULL) +nodist_unix_sources = \ + $(nodist_portal_sources) \ + $(NULL) giounixincludedir=$(includedir)/gio-unix-2.0/gio giounixinclude_HEADERS = \ @@ -316,6 +319,8 @@ endif gdbus_daemon_sources = \ gdbusdaemon.c \ gdbusdaemon.h \ + $(NULL) +nodist_gdbus_daemon_sources = \ gdbus-daemon-generated.c \ gdbus-daemon-generated.h \ $(NULL) @@ -336,6 +341,9 @@ win32_actual_sources = \ gwin32networkmonitor.h \ gwin32notificationbackend.c \ $(NULL) +nodist_win32_actual_sources = \ + $(nodist_gdbus_daemon_sources) \ + $(NULL) win32_more_sources_for_vcproj = \ gwin32appinfo.c \ @@ -353,6 +361,7 @@ appinfo_sources += gwin32appinfo.c gwin32appinfo.h contenttype_sources += gcontenttype-win32.c platform_libadd += -lshlwapi -lws2_32 -ldnsapi -liphlpapi win32_sources = $(win32_actual_sources) +nodist_win32_sources = $(nodist_win32_actual_sources) giowin32includedir=$(includedir)/gio-win32-2.0/gio giowin32include_HEADERS = \ @@ -369,7 +378,6 @@ CLEANFILES += $(xdp_dbus_built_sources) portal_interfaces = \ org.freedesktop.portal.Documents.xml \ org.freedesktop.portal.OpenURI.xml \ - org.freedesktop.portal.NetworkMonitor.xml \ org.freedesktop.portal.ProxyResolver.xml \ $(NULL) @@ -393,7 +401,9 @@ portal_sources = \ gnetworkmonitorportal.h \ gproxyresolverportal.c \ gproxyresolverportal.h \ - $(xdp_dbus_built_sources) \ + $(NULL) +nodist_portal_sources = \ + $(xdp_dbus_built_sources) \ $(NULL) if OS_UNIX @@ -547,14 +557,16 @@ gio_base_sources = \ gzlibcompressor.c \ gzlibdecompressor.c \ gmountprivate.h \ - gioenumtypes.h \ - gioenumtypes.c \ glistmodel.c \ gliststore.c \ $(application_sources) \ $(gdbus_sources) \ $(local_sources) \ $(NULL) +nodist_gio_base_sources = \ + gioenumtypes.h \ + gioenumtypes.c \ + $(NULL) libgio_2_0_la_SOURCES = \ $(gio_base_sources) \ @@ -564,6 +576,11 @@ libgio_2_0_la_SOURCES = \ $(win32_sources) \ $(settings_sources) \ $(NULL) +nodist_libgio_2_0_la_SOURCES = \ + $(nodist_gio_base_sources) \ + $(nodist_unix_sources) \ + $(nodist_win32_sources) \ + $(NULL) EXTRA_DIST += strinfo.c @@ -601,11 +618,28 @@ libgio_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -export-dynamic $(no_undefined) +# We cannot build .m files because it would require adding AC_PROG_OBJC in +# configure.ac, and it cannot be added conditionally. That means we would always +# depend on an objective-c compiler even when not needed. To work around that +# limitation we rename .m files to .c and compile them separately with +# -xobjective-c into an intermediary library. Note that we cannot rename those +# files to .c directly in the source tree because Meson needs the .m extension. +# This must be done outside of "if OS_COCOA" block otherwise distcheck fails. +# See https://bugzilla.gnome.org/show_bug.cgi?id=672777. +OBJC_FILES = \ + gnextstepsettingsbackend.m \ + gosxcontenttype.m \ + gosxappinfo.m \ + gcocoanotificationbackend.m \ + $(NULL) +OBJC_C_FILES = $(OBJC_FILES:.m=.c) +BUILT_SOURCES += $(OBJC_C_FILES) +CLEANFILES += $(OBJC_C_FILES) +EXTRA_DIST += $(OBJC_FILES) +$(OBJC_C_FILES): %.c: %.m Makefile + cp $< $@ + if OS_COCOA -# Let's avoid polluting the CFLAGS of libgio with -xobjective-c -# We cannot simply rename the ObjC files to .m because it plays -# tricks with Automake. For further reference, see: -# https://bugzilla.gnome.org/show_bug.cgi?id=672777 libgio_objc_2_0_la_CFLAGS = $(libgio_2_0_la_CFLAGS) -xobjective-c libgio_objc_2_0_la_CPPFLAGS = $(libgio_2_0_la_CPPFLAGS) libgio_objc_2_0_la_LDFLAGS = $(libgio_2_0_la_LDFLAGS) -Wl,-framework,Foundation -Wl,-framework,AppKit @@ -745,12 +779,12 @@ gio_headers = \ $(NULL) gioincludedir=$(includedir)/glib-2.0/gio/ -gioinclude_HEADERS = \ - $(gio_headers) \ - gioenumtypes.h - -nodist_gioinclude_HEADERS = \ - gnetworking.h \ +gioinclude_HEADERS = \ + $(gio_headers) \ + $(NULL) +nodist_gioinclude_HEADERS = \ + gioenumtypes.h \ + gnetworking.h \ $(NULL) # these sources (also mentioned above) are generated. @@ -769,8 +803,6 @@ EXTRA_DIST += \ gioenumtypes.c.template \ gio.rc.in \ gschema.dtd \ - gconstructor_as_data.h \ - gnetworking.h.win32 \ $(NULL) BUILT_EXTRA_DIST += \ @@ -803,7 +835,7 @@ gio.def: libgio-2.0.la gio-2.0.lib: libgio-2.0.la gio.def $(AM_V_GEN) lib.exe -machine:@LIB_EXE_MACHINE_FLAG@ -name:libgio-2.0-$(LT_CURRENT_MINUS_AGE).dll -def:$(builddir)/gio.def -out:$@ -bin_PROGRAMS = gio-querymodules glib-compile-schemas glib-compile-resources gsettings +bin_PROGRAMS = gio-querymodules glib-compile-schemas glib-compile-resources gsettings gio-launch-desktop glib_compile_resources_LDADD = libgio-2.0.la \ $(top_builddir)/gobject/libgobject-2.0.la \ @@ -824,16 +856,20 @@ gio_querymodules_LDADD = libgio-2.0.la \ $(top_builddir)/glib/libglib-2.0.la \ $(NULL) +gio_launch_desktop_SOURCES = gio-launch-desktop.c + gconstructor_as_data.h: $(top_srcdir)/glib/gconstructor.h data-to-c.py - $(AM_V_GEN) $(srcdir)/data-to-c.py $(top_srcdir)/glib/gconstructor.h gconstructor_code $@ + $(AM_V_GEN) $(PYTHON) $(srcdir)/data-to-c.py $(top_srcdir)/glib/gconstructor.h gconstructor_code $@ glib_compile_schemas_LDADD = $(top_builddir)/glib/libglib-2.0.la glib_compile_schemas_SOURCES = \ - gconstructor_as_data.h \ gvdb/gvdb-format.h \ gvdb/gvdb-builder.h \ gvdb/gvdb-builder.c \ glib-compile-schemas.c +nodist_glib_compile_schemas_SOURCES = \ + gconstructor_as_data.h \ + $(NULL) gsettings_LDADD = libgio-2.0.la \ $(top_builddir)/gobject/libgobject-2.0.la \ @@ -911,6 +947,7 @@ completiondir = $(datadir)/bash-completion/completions completion_DATA = \ completion/gapplication \ completion/gdbus \ + completion/gio \ completion/gsettings \ completion/gresource EXTRA_DIST += $(completion_DATA) @@ -956,43 +993,7 @@ gio_LDADD = libgio-2.0.la \ $(top_builddir)/glib/libglib-2.0.la \ $(NULL) -# ------------------------------------------------------------------------ -# ------ MSVC Project File Generation ------ -# ------------------------------------------------------------------------ -# -MSVCPROJS = gio glib-compile-resources glib-compile-schemas gio-tool - -gio_FILES = \ - $(gio_base_sources) \ - $(win32_actual_sources) \ - $(win32_more_sources_for_vcproj) \ - $(settings_base_sources) \ - $(win32_settings_sources) - -gio_EXCLUDES = dummy - -gio_HEADERS_DIR = $(includedir)/glib-2.0/gio -gio_HEADERS_INST = $(gioinclude_HEADERS) $(nodist_gioinclude_HEADERS) -gio_HEADERS_EXCLUDES = dummy - -glib_compile_resources_FILES = $(glib_compile_resources_SOURCES) -glib_compile_resources_EXCLUDES = dummy - -glib_compile_schemas_FILES = $(glib_compile_schemas_SOURCES) -glib_compile_schemas_EXCLUDES = dummy - -gio_tool_FILES = $(gio_SOURCES) -gio_tool_EXCLUDES = dummy - -include $(top_srcdir)/win32/Makefile.msvcproj - -dist-hook: \ - $(BUILT_EXTRA_DIST) \ - $(top_builddir)/win32/vs9/gio.vcproj \ - $(top_builddir)/win32/vs9/gio.headers \ - $(top_builddir)/win32/vs9/glib-compile-schemas.vcproj \ - $(top_builddir)/win32/vs9/glib-compile-resources.vcproj \ - $(top_builddir)/win32/vs9/gio-tool.vcproj +dist-hook: $(BUILT_EXTRA_DIST) files='$(BUILT_EXTRA_DIST)'; \ for f in $$files; do \ if test -f $$f; then d=.; else d=$(srcdir); fi; \ diff --git a/gio/completion/.gitignore b/gio/completion/.gitignore new file mode 100644 index 000000000..6930af958 --- /dev/null +++ b/gio/completion/.gitignore @@ -0,0 +1 @@ +!gio diff --git a/gio/completion/gio b/gio/completion/gio new file mode 100755 index 000000000..c1db98561 --- /dev/null +++ b/gio/completion/gio @@ -0,0 +1,120 @@ +# +# Copyright (C) 2018 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 +# licence, or (at your option) any later version. +# +# This 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 . +# + +# Check for bash +[ -z "$BASH_VERSION" ] && return + +#################################################################################################### + +# Check whether the suggestions have common prefix (i.e. suggestions won't be +# shown and prefix will be completed first) +__has_common_prefix() { + for (( i = 1; i < ${#COMPREPLY[@]}; i++ )); do + if [[ "${COMPREPLY[i-1]:${#cur}:1}" != "${COMPREPLY[i]:${#cur}:1}" ]]; then + return 1 # False + fi + done + + return 0 # True +} + +# Complete file location +__gio_location() { + # Prevent breaking on colons, we have to work with uris + local cur + _get_comp_words_by_ref -n : cur + + # Resolve dirname for dir listing + local dir="" + if [[ $cur =~ "/"$ ]]; then + dir="$cur" + elif [[ $cur =~ "/" ]]; then + dir="$(dirname "$cur")/" + fi + + # List daemon mounts, just if dir is not specified, or looks like scheme + local mounts=() + if [[ $dir == "" ]] || [[ $dir =~ ":"$ && ! $dir =~ "/" ]]; then + while IFS=$'\n' read mount; do + # Do not care about local mounts + [[ "$mount" =~ ^"file:" ]] && continue + + # Use only matching mounts + [[ "$mount" =~ ^"$cur" && "$mount" != "$cur" ]] && mounts+=("$mount") + done < <(gio mount -l | sed -n -r 's/^ *Mount\([0-9]+\): .* -> (.*)$/\1/p') + fi + + # Workaround to unescape dir name (e.g. "\ " -> " ") + declare -a tmp="( ${dir} )" + unescaped_dir="${tmp[0]}" + + # List files + local files=() + local names=() + while IFS=$'\t' read name size type; do + # Escape name properly + local escaped_name="$(printf "%q" "$name")" + + # Append slash for directories and space for files + if [[ "$type" == "(directory)" ]]; then + escaped_name="$escaped_name/" + else + escaped_name="$escaped_name " + fi + + path="$dir$escaped_name" + + # Use only matching paths + if [[ "$path" =~ ^"$cur" ]]; then + files+=("$path") + names+=("$escaped_name") + fi + done < <(gio list -hl "$unescaped_dir" 2> /dev/null) + + COMPREPLY=("${files[@]}" "${mounts[@]}") + + # Workaround to show suggestions as basenames only + if ! __has_common_prefix; then + COMPREPLY=("${mounts[@]} ${names[@]}") + + # Workaround to prevent overwritting suggestions, it adds empty + # suggestion, otherwise names with colons will be corrupted + COMPREPLY+=(" ") + + return 0 + fi + + # Workaround to complete names with colons, it removes colon prefix from + # COMPREPLY + __ltrim_colon_completions "$cur" +} + +__gio() { + # Complete subcommands + if (( ${COMP_CWORD} == 1 )); then + COMPREPLY=($(compgen -W "help version cat copy info list mime mkdir monitor mount move open rename save set trash tree" -- "${COMP_WORDS[1]}")) + compopt +o nospace + return 0 + fi + + # Complete file locations + __gio_location +} + +#################################################################################################### + +complete -o nospace -F __gio gio diff --git a/gio/fam/gfamfilemonitor.map b/gio/fam/gfamfilemonitor.map new file mode 100644 index 000000000..43ed5a77c --- /dev/null +++ b/gio/fam/gfamfilemonitor.map @@ -0,0 +1,8 @@ +{ +global: + g_io_module_load; + g_io_module_unload; + g_io_module_query; +local: + *; +}; diff --git a/gio/fam/meson.build b/gio/fam/meson.build new file mode 100644 index 000000000..d24670a63 --- /dev/null +++ b/gio/fam/meson.build @@ -0,0 +1,36 @@ +if not get_option('fam') + subdir_done() +endif + +fam_dep = cc.find_library('fam') +fam_c_args = ['-DG_DISABLE_DEPRECATED'] + gio_c_args +if cc.has_function('FAMNoExists', dependencies : fam_dep) + fam_c_args += '-DHAVE_FAM_NO_EXISTS=1' +endif + +deps = [ + fam_dep, + libglib_dep, + libgobject_dep, + libgio_dep, +] + +symbol_map = join_paths(meson.current_source_dir(), 'gfamfilemonitor.map') +fam_ldflags = cc.get_supported_link_arguments([ + '-Wl,--version-script,' + symbol_map, + '-Wl,-no-undefined', +]) + +module = shared_module('giofam', 'gfamfilemonitor.c', + include_directories : [gmoduleinc], + dependencies : deps, + c_args : fam_c_args, + link_args : fam_ldflags, + link_depends : symbol_map, + install_dir : glib_giomodulesdir, + install : true, +) + +if not meson.is_cross_build() + meson.add_install_script('../gio-querymodules-wrapper.py', gio_querymodules.full_path(), glib_giomodulesdir) +endif diff --git a/gio/gbufferedoutputstream.c b/gio/gbufferedoutputstream.c index 8b2bcdc04..98bda501d 100644 --- a/gio/gbufferedoutputstream.c +++ b/gio/gbufferedoutputstream.c @@ -699,7 +699,7 @@ g_buffered_output_stream_flush_async (GOutputStream *stream, GTask *task; FlushData *fdata; - fdata = g_slice_new (FlushData); + fdata = g_slice_new0 (FlushData); fdata->flush_stream = TRUE; fdata->close_stream = FALSE; @@ -732,7 +732,7 @@ g_buffered_output_stream_close_async (GOutputStream *stream, GTask *task; FlushData *fdata; - fdata = g_slice_new (FlushData); + fdata = g_slice_new0 (FlushData); fdata->close_stream = TRUE; task = g_task_new (stream, cancellable, callback, data); diff --git a/gio/gcocoanotificationbackend.c b/gio/gcocoanotificationbackend.c deleted file mode 100644 index ae4ad8833..000000000 --- a/gio/gcocoanotificationbackend.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright © 2015 Patrick Griffis - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Patrick Griffis - */ - -#include "config.h" - -#import -#include "gnotificationbackend.h" -#include "gapplication.h" -#include "gaction.h" -#include "gactiongroup.h" -#include "giomodule-priv.h" -#include "gnotification-private.h" -#include "gthemedicon.h" -#include "gfileicon.h" -#include "gfile.h" - -#define G_TYPE_COCOA_NOTIFICATION_BACKEND (g_cocoa_notification_backend_get_type ()) -#define G_COCOA_NOTIFICATION_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_COCOA_NOTIFICATION_BACKEND, GCocoaNotificationBackend)) - -typedef struct _GCocoaNotificationBackend GCocoaNotificationBackend; -typedef GNotificationBackendClass GCocoaNotificationBackendClass; -struct _GCocoaNotificationBackend -{ - GNotificationBackend parent; -}; - -GType g_cocoa_notification_backend_get_type (void); - -G_DEFINE_TYPE_WITH_CODE (GCocoaNotificationBackend, g_cocoa_notification_backend, G_TYPE_NOTIFICATION_BACKEND, - _g_io_modules_ensure_extension_points_registered (); - g_io_extension_point_implement (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "cocoa", 0)); - -static NSString * -nsstring_from_cstr (const char *cstr) -{ - if (!cstr) - return nil; - - return [[NSString alloc] initWithUTF8String:cstr]; -} - -static NSImage* -nsimage_from_gicon (GIcon *icon) -{ - if (G_IS_FILE_ICON (icon)) - { - NSImage *image = nil; - GFile *file; - char *path; - - file = g_file_icon_get_file (G_FILE_ICON (icon)); - path = g_file_get_path (file); - if (path) - { - NSString *str_path = nsstring_from_cstr (path); - image = [[NSImage alloc] initByReferencingFile:str_path]; - - [str_path release]; - g_free (path); - } - return image; - } - else - { - g_warning ("This icon type is not handled by this NotificationBackend"); - return nil; - } -} - -static void -activate_detailed_action (const char * action) -{ - char *name; - GVariant *target; - - if (!g_str_has_prefix (action, "app.")) - { - g_warning ("Notification action does not have \"app.\" prefix"); - return; - } - - if (g_action_parse_detailed_name (action, &name, &target, NULL)) - { - g_action_group_activate_action (G_ACTION_GROUP (g_application_get_default()), name + 4, target); - g_free (name); - if (target) - g_variant_unref (target); - } -} - -@interface GNotificationCenterDelegate : NSObject @end -@implementation GNotificationCenterDelegate - --(void) userNotificationCenter:(NSUserNotificationCenter*) center - didActivateNotification:(NSUserNotification*) notification -{ - if ([notification activationType] == NSUserNotificationActivationTypeContentsClicked) - { - const char *action = [[notification userInfo][@"default"] UTF8String]; - if (action) - activate_detailed_action (action); - /* OSX Always activates the front window */ - } - else if ([notification activationType] == NSUserNotificationActivationTypeActionButtonClicked) - { - const char *action = [[notification userInfo][@"button0"] UTF8String]; - if (action) - activate_detailed_action (action); - } - - [center removeDeliveredNotification:notification]; -} - -@end - -static GNotificationCenterDelegate *cocoa_notification_delegate; - -static gboolean -g_cocoa_notification_backend_is_supported (void) -{ - NSBundle *bundle = [NSBundle mainBundle]; - - /* This is always actually supported, but without a bundle it does nothing */ - if (![bundle bundleIdentifier]) - return FALSE; - - return TRUE; -} - -static void -add_actions_to_notification (NSUserNotification *userNotification, - GNotification *notification) -{ - guint n_buttons = g_notification_get_n_buttons (notification); - char *action = NULL, *label = NULL; - GVariant *target = NULL; - NSMutableDictionary *user_info = nil; - - if (g_notification_get_default_action (notification, &action, &target)) - { - char *detailed_name = g_action_print_detailed_name (action, target); - NSString *action_name = nsstring_from_cstr (detailed_name); - user_info = [[NSMutableDictionary alloc] init]; - - user_info[@"default"] = action_name; - - [action_name release]; - g_free (detailed_name); - g_clear_pointer (&action, g_free); - g_clear_pointer (&target, g_variant_unref); - } - - if (n_buttons) - { - g_notification_get_button (notification, 0, &label, &action, &target); - if (label) - { - NSString *str_label = nsstring_from_cstr (label); - char *detailed_name = g_action_print_detailed_name (action, target); - NSString *action_name = nsstring_from_cstr (detailed_name); - - if (!user_info) - user_info = [[NSMutableDictionary alloc] init]; - - user_info[@"button0"] = action_name; - userNotification.actionButtonTitle = str_label; - - [str_label release]; - [action_name release]; - g_free (label); - g_free (action); - g_free (detailed_name); - g_clear_pointer (&target, g_variant_unref); - } - - if (n_buttons > 1) - g_warning ("Only a single button is currently supported by this NotificationBackend"); - } - - userNotification.userInfo = user_info; - [user_info release]; -} - -static void -g_cocoa_notification_backend_send_notification (GNotificationBackend *backend, - const gchar *cstr_id, - GNotification *notification) -{ - NSString *str_title = nil, *str_text = nil, *str_id = nil; - NSImage *content = nil; - const char *cstr; - GIcon *icon; - NSUserNotification *userNotification; - NSUserNotificationCenter *center; - - if ((cstr = g_notification_get_title (notification))) - str_title = nsstring_from_cstr (cstr); - if ((cstr = g_notification_get_body (notification))) - str_text = nsstring_from_cstr (cstr); - if (cstr_id != NULL) - str_id = nsstring_from_cstr (cstr_id); - if ((icon = g_notification_get_icon (notification))) - content = nsimage_from_gicon (icon); - /* NOTE: There is no priority */ - - userNotification = [NSUserNotification new]; - userNotification.title = str_title; - userNotification.informativeText = str_text; - userNotification.identifier = str_id; - userNotification.contentImage = content; - /* NOTE: Buttons only show up if your bundle has NSUserNotificationAlertStyle set to "alerts" */ - add_actions_to_notification (userNotification, notification); - - if (!cocoa_notification_delegate) - cocoa_notification_delegate = [[GNotificationCenterDelegate alloc] init]; - - center = [NSUserNotificationCenter defaultUserNotificationCenter]; - center.delegate = cocoa_notification_delegate; - [center deliverNotification:userNotification]; - - [str_title release]; - [str_text release]; - [str_id release]; - [content release]; - [userNotification release]; -} - -static void -g_cocoa_notification_backend_withdraw_notification (GNotificationBackend *backend, - const gchar *cstr_id) -{ - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - NSArray *notifications = [center deliveredNotifications]; - NSString *str_id = nsstring_from_cstr (cstr_id); - - for (NSUserNotification *notification in notifications) - { - if ([notification.identifier compare:str_id] == NSOrderedSame) - { - [center removeDeliveredNotification:notification]; - break; - } - } - - [notifications release]; - [str_id release]; -} - -static void -g_cocoa_notification_backend_init (GCocoaNotificationBackend *backend) -{ -} - -static void -g_cocoa_notification_backend_class_init (GCocoaNotificationBackendClass *klass) -{ - GNotificationBackendClass *backend_class = G_NOTIFICATION_BACKEND_CLASS (klass); - - backend_class->is_supported = g_cocoa_notification_backend_is_supported; - backend_class->send_notification = g_cocoa_notification_backend_send_notification; - backend_class->withdraw_notification = g_cocoa_notification_backend_withdraw_notification; -} diff --git a/gio/gcocoanotificationbackend.m b/gio/gcocoanotificationbackend.m new file mode 100644 index 000000000..ae4ad8833 --- /dev/null +++ b/gio/gcocoanotificationbackend.m @@ -0,0 +1,278 @@ +/* + * Copyright © 2015 Patrick Griffis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Authors: Patrick Griffis + */ + +#include "config.h" + +#import +#include "gnotificationbackend.h" +#include "gapplication.h" +#include "gaction.h" +#include "gactiongroup.h" +#include "giomodule-priv.h" +#include "gnotification-private.h" +#include "gthemedicon.h" +#include "gfileicon.h" +#include "gfile.h" + +#define G_TYPE_COCOA_NOTIFICATION_BACKEND (g_cocoa_notification_backend_get_type ()) +#define G_COCOA_NOTIFICATION_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_COCOA_NOTIFICATION_BACKEND, GCocoaNotificationBackend)) + +typedef struct _GCocoaNotificationBackend GCocoaNotificationBackend; +typedef GNotificationBackendClass GCocoaNotificationBackendClass; +struct _GCocoaNotificationBackend +{ + GNotificationBackend parent; +}; + +GType g_cocoa_notification_backend_get_type (void); + +G_DEFINE_TYPE_WITH_CODE (GCocoaNotificationBackend, g_cocoa_notification_backend, G_TYPE_NOTIFICATION_BACKEND, + _g_io_modules_ensure_extension_points_registered (); + g_io_extension_point_implement (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "cocoa", 0)); + +static NSString * +nsstring_from_cstr (const char *cstr) +{ + if (!cstr) + return nil; + + return [[NSString alloc] initWithUTF8String:cstr]; +} + +static NSImage* +nsimage_from_gicon (GIcon *icon) +{ + if (G_IS_FILE_ICON (icon)) + { + NSImage *image = nil; + GFile *file; + char *path; + + file = g_file_icon_get_file (G_FILE_ICON (icon)); + path = g_file_get_path (file); + if (path) + { + NSString *str_path = nsstring_from_cstr (path); + image = [[NSImage alloc] initByReferencingFile:str_path]; + + [str_path release]; + g_free (path); + } + return image; + } + else + { + g_warning ("This icon type is not handled by this NotificationBackend"); + return nil; + } +} + +static void +activate_detailed_action (const char * action) +{ + char *name; + GVariant *target; + + if (!g_str_has_prefix (action, "app.")) + { + g_warning ("Notification action does not have \"app.\" prefix"); + return; + } + + if (g_action_parse_detailed_name (action, &name, &target, NULL)) + { + g_action_group_activate_action (G_ACTION_GROUP (g_application_get_default()), name + 4, target); + g_free (name); + if (target) + g_variant_unref (target); + } +} + +@interface GNotificationCenterDelegate : NSObject @end +@implementation GNotificationCenterDelegate + +-(void) userNotificationCenter:(NSUserNotificationCenter*) center + didActivateNotification:(NSUserNotification*) notification +{ + if ([notification activationType] == NSUserNotificationActivationTypeContentsClicked) + { + const char *action = [[notification userInfo][@"default"] UTF8String]; + if (action) + activate_detailed_action (action); + /* OSX Always activates the front window */ + } + else if ([notification activationType] == NSUserNotificationActivationTypeActionButtonClicked) + { + const char *action = [[notification userInfo][@"button0"] UTF8String]; + if (action) + activate_detailed_action (action); + } + + [center removeDeliveredNotification:notification]; +} + +@end + +static GNotificationCenterDelegate *cocoa_notification_delegate; + +static gboolean +g_cocoa_notification_backend_is_supported (void) +{ + NSBundle *bundle = [NSBundle mainBundle]; + + /* This is always actually supported, but without a bundle it does nothing */ + if (![bundle bundleIdentifier]) + return FALSE; + + return TRUE; +} + +static void +add_actions_to_notification (NSUserNotification *userNotification, + GNotification *notification) +{ + guint n_buttons = g_notification_get_n_buttons (notification); + char *action = NULL, *label = NULL; + GVariant *target = NULL; + NSMutableDictionary *user_info = nil; + + if (g_notification_get_default_action (notification, &action, &target)) + { + char *detailed_name = g_action_print_detailed_name (action, target); + NSString *action_name = nsstring_from_cstr (detailed_name); + user_info = [[NSMutableDictionary alloc] init]; + + user_info[@"default"] = action_name; + + [action_name release]; + g_free (detailed_name); + g_clear_pointer (&action, g_free); + g_clear_pointer (&target, g_variant_unref); + } + + if (n_buttons) + { + g_notification_get_button (notification, 0, &label, &action, &target); + if (label) + { + NSString *str_label = nsstring_from_cstr (label); + char *detailed_name = g_action_print_detailed_name (action, target); + NSString *action_name = nsstring_from_cstr (detailed_name); + + if (!user_info) + user_info = [[NSMutableDictionary alloc] init]; + + user_info[@"button0"] = action_name; + userNotification.actionButtonTitle = str_label; + + [str_label release]; + [action_name release]; + g_free (label); + g_free (action); + g_free (detailed_name); + g_clear_pointer (&target, g_variant_unref); + } + + if (n_buttons > 1) + g_warning ("Only a single button is currently supported by this NotificationBackend"); + } + + userNotification.userInfo = user_info; + [user_info release]; +} + +static void +g_cocoa_notification_backend_send_notification (GNotificationBackend *backend, + const gchar *cstr_id, + GNotification *notification) +{ + NSString *str_title = nil, *str_text = nil, *str_id = nil; + NSImage *content = nil; + const char *cstr; + GIcon *icon; + NSUserNotification *userNotification; + NSUserNotificationCenter *center; + + if ((cstr = g_notification_get_title (notification))) + str_title = nsstring_from_cstr (cstr); + if ((cstr = g_notification_get_body (notification))) + str_text = nsstring_from_cstr (cstr); + if (cstr_id != NULL) + str_id = nsstring_from_cstr (cstr_id); + if ((icon = g_notification_get_icon (notification))) + content = nsimage_from_gicon (icon); + /* NOTE: There is no priority */ + + userNotification = [NSUserNotification new]; + userNotification.title = str_title; + userNotification.informativeText = str_text; + userNotification.identifier = str_id; + userNotification.contentImage = content; + /* NOTE: Buttons only show up if your bundle has NSUserNotificationAlertStyle set to "alerts" */ + add_actions_to_notification (userNotification, notification); + + if (!cocoa_notification_delegate) + cocoa_notification_delegate = [[GNotificationCenterDelegate alloc] init]; + + center = [NSUserNotificationCenter defaultUserNotificationCenter]; + center.delegate = cocoa_notification_delegate; + [center deliverNotification:userNotification]; + + [str_title release]; + [str_text release]; + [str_id release]; + [content release]; + [userNotification release]; +} + +static void +g_cocoa_notification_backend_withdraw_notification (GNotificationBackend *backend, + const gchar *cstr_id) +{ + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + NSArray *notifications = [center deliveredNotifications]; + NSString *str_id = nsstring_from_cstr (cstr_id); + + for (NSUserNotification *notification in notifications) + { + if ([notification.identifier compare:str_id] == NSOrderedSame) + { + [center removeDeliveredNotification:notification]; + break; + } + } + + [notifications release]; + [str_id release]; +} + +static void +g_cocoa_notification_backend_init (GCocoaNotificationBackend *backend) +{ +} + +static void +g_cocoa_notification_backend_class_init (GCocoaNotificationBackendClass *klass) +{ + GNotificationBackendClass *backend_class = G_NOTIFICATION_BACKEND_CLASS (klass); + + backend_class->is_supported = g_cocoa_notification_backend_is_supported; + backend_class->send_notification = g_cocoa_notification_backend_send_notification; + backend_class->withdraw_notification = g_cocoa_notification_backend_withdraw_notification; +} diff --git a/gio/gcontenttype.c b/gio/gcontenttype.c index af8ef44c6..57249d94e 100644 --- a/gio/gcontenttype.c +++ b/gio/gcontenttype.c @@ -405,8 +405,8 @@ g_content_type_get_description (const gchar *type) * * Gets the mime type for the content type, if one is registered. * - * Returns: (nullable): the registered mime type for the given @type, - * or %NULL if unknown. + * Returns: (nullable) (transfer full): the registered mime type for the + * given @type, or %NULL if unknown; free with g_free(). */ char * g_content_type_get_mime_type (const char *type) diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py index 032a29ed5..e74131cdb 100644 --- a/gio/gdbus-2.0/codegen/codegen.py +++ b/gio/gdbus-2.0/codegen/codegen.py @@ -613,6 +613,286 @@ class HeaderCodeGenerator: # ---------------------------------------------------------------------------------------------------- +class InterfaceInfoHeaderCodeGenerator: + def __init__(self, ifaces, namespace, header_name, use_pragma, outfile): + self.ifaces = ifaces + self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) + self.header_guard = header_name.upper().replace('.', '_').replace('-', '_').replace('/', '_').replace(':', '_') + self.use_pragma = use_pragma + self.outfile = outfile + + # ---------------------------------------------------------------------------------------------------- + + def generate_header_preamble(self): + self.outfile.write(LICENSE_STR.format(config.VERSION)) + self.outfile.write('\n') + + if self.use_pragma: + self.outfile.write('#pragma once\n') + else: + self.outfile.write('#ifndef __{!s}__\n'.format(self.header_guard)) + self.outfile.write('#define __{!s}__\n'.format(self.header_guard)) + + self.outfile.write('\n') + self.outfile.write('#include \n') + self.outfile.write('\n') + self.outfile.write('G_BEGIN_DECLS\n') + self.outfile.write('\n') + + # ---------------------------------------------------------------------------------------------------- + + def declare_infos(self): + for i in self.ifaces: + self.outfile.write('extern const GDBusInterfaceInfo %s_interface;\n' % i.name_lower) + + # ---------------------------------------------------------------------------------------------------- + + def generate_header_postamble(self): + self.outfile.write('\n') + self.outfile.write('G_END_DECLS\n') + + if not self.use_pragma: + self.outfile.write('\n') + self.outfile.write('#endif /* __{!s}__ */\n'.format(self.header_guard)) + + # ---------------------------------------------------------------------------------------------------- + + def generate(self): + self.generate_header_preamble() + self.declare_infos() + self.generate_header_postamble() + +# ---------------------------------------------------------------------------------------------------- + +class InterfaceInfoBodyCodeGenerator: + def __init__(self, ifaces, namespace, header_name, outfile): + self.ifaces = ifaces + self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) + self.header_name = header_name + self.outfile = outfile + + # ---------------------------------------------------------------------------------------------------- + + def generate_body_preamble(self): + self.outfile.write(LICENSE_STR.format(config.VERSION)) + self.outfile.write('\n') + self.outfile.write('#ifdef HAVE_CONFIG_H\n' + '# include "config.h"\n' + '#endif\n' + '\n' + '#include "%s"\n' + '\n' + '#include \n' + % (self.header_name)) + self.outfile.write('\n') + + # ---------------------------------------------------------------------------------------------------- + + def generate_array(self, array_name_lower, element_type, elements): + self.outfile.write('const %s * const %s[] =\n' % (element_type, array_name_lower)) + self.outfile.write('{\n') + for (_, name) in sorted(elements, key=utils.version_cmp_key): + self.outfile.write(' &%s,\n' % name) + self.outfile.write(' NULL,\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + def define_annotations(self, array_name_lower, annotations): + if len(annotations) == 0: + return + + annotation_pointers = [] + + for a in annotations: + # Skip internal annotations. + if a.key.startswith('org.gtk.GDBus'): + continue + + self.define_annotations('%s__%s_annotations' % (array_name_lower, a.key_lower), a.annotations) + + self.outfile.write('const GDBusAnnotationInfo %s__%s_annotation =\n' % (array_name_lower, a.key_lower)) + self.outfile.write('{\n') + self.outfile.write(' -1, /* ref count */\n') + self.outfile.write(' (gchar *) "%s",\n' % a.key) + self.outfile.write(' (gchar *) "%s",\n' % a.value) + if len(a.annotations) > 0: + self.outfile.write(' (GDBusAnnotationInfo **) %s__%s_annotations,\n' % (array_name_lower, a.key_lower)) + else: + self.outfile.write(' NULL, /* no annotations */\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + key = (a.since, '%s__%s_annotation' % (array_name_lower, a.key_lower)) + annotation_pointers.append(key) + + self.generate_array(array_name_lower, 'GDBusAnnotationInfo', + annotation_pointers) + + def define_args(self, array_name_lower, args): + if len(args) == 0: + return + + arg_pointers = [] + + for a in args: + self.define_annotations('%s__%s_arg_annotations' % (array_name_lower, a.name), a.annotations) + + self.outfile.write('const GDBusArgInfo %s__%s_arg =\n' % (array_name_lower, a.name)) + self.outfile.write('{\n') + self.outfile.write(' -1, /* ref count */\n') + self.outfile.write(' (gchar *) "%s",\n' % a.name) + self.outfile.write(' (gchar *) "%s",\n' % a.signature) + if len(a.annotations) > 0: + self.outfile.write(' (GDBusAnnotationInfo **) %s__%s_arg_annotations,\n' % (array_name_lower, a.name)) + else: + self.outfile.write(' NULL, /* no annotations */\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + key = (a.since, '%s__%s_arg' % (array_name_lower, a.name)) + arg_pointers.append(key) + + self.generate_array(array_name_lower, 'GDBusArgInfo', arg_pointers) + + def define_infos(self): + for i in self.ifaces: + self.outfile.write('/* ------------------------------------------------------------------------ */\n') + self.outfile.write('/* Definitions for %s */\n' % i.name) + self.outfile.write('\n') + + # GDBusMethodInfos. + if len(i.methods) > 0: + method_pointers = [] + + for m in i.methods: + self.define_args('%s_interface__%s_method_in_args' % (i.name_lower, m.name_lower), m.in_args) + self.define_args('%s_interface__%s_method_out_args' % (i.name_lower, m.name_lower), m.out_args) + self.define_annotations('%s_interface__%s_method_annotations' % (i.name_lower, m.name_lower), m.annotations) + + self.outfile.write('const GDBusMethodInfo %s_interface__%s_method =\n' % (i.name_lower, m.name_lower)) + self.outfile.write('{\n') + self.outfile.write(' -1, /* ref count */\n') + self.outfile.write(' (gchar *) "%s",\n' % m.name) + if len(m.in_args) > 0: + self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_method_in_args,\n' % (i.name_lower, m.name_lower)) + else: + self.outfile.write(' NULL, /* no in args */\n') + if len(m.out_args) > 0: + self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_method_out_args,\n' % (i.name_lower, m.name_lower)) + else: + self.outfile.write(' NULL, /* no out args */\n') + if len(m.annotations) > 0: + self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_method_annotations,\n' % (i.name_lower, m.name_lower)) + else: + self.outfile.write(' NULL, /* no annotations */\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + key = (m.since, '%s_interface__%s_method' % (i.name_lower, m.name_lower)) + method_pointers.append(key) + + self.generate_array('%s_interface_methods' % i.name_lower, + 'GDBusMethodInfo', method_pointers) + + # GDBusSignalInfos. + if len(i.signals) > 0: + signal_pointers = [] + + for s in i.signals: + self.define_args('%s_interface__%s_signal_args' % (i.name_lower, s.name_lower), s.args) + self.define_annotations('%s_interface__%s_signal_annotations' % (i.name_lower, s.name_lower), s.annotations) + + self.outfile.write('const GDBusSignalInfo %s_interface__%s_signal =\n' % (i.name_lower, s.name_lower)) + self.outfile.write('{\n') + self.outfile.write(' -1, /* ref count */\n') + self.outfile.write(' (gchar *) "%s",\n' % s.name) + if len(s.args) > 0: + self.outfile.write(' (GDBusArgInfo **) %s_interface__%s_signal_args,\n' % (i.name_lower, s.name_lower)) + else: + self.outfile.write(' NULL, /* no args */\n') + if len(s.annotations) > 0: + self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_signal_annotations,\n' % (i.name_lower, s.name_lower)) + else: + self.outfile.write(' NULL, /* no annotations */\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + key = (m.since, '%s_interface__%s_signal' % (i.name_lower, s.name_lower)) + signal_pointers.append(key) + + self.generate_array('%s_interface_signals' % i.name_lower, + 'GDBusSignalInfo', signal_pointers) + + # GDBusPropertyInfos. + if len(i.properties) > 0: + property_pointers = [] + + for p in i.properties: + if p.readable and p.writable: + flags = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' + elif p.readable: + flags = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE' + elif p.writable: + flags = 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE' + else: + flags = 'G_DBUS_PROPERTY_INFO_FLAGS_NONE' + + self.define_annotations('%s_interface__%s_property_annotations' % (i.name_lower, p.name_lower), p.annotations) + + self.outfile.write('const GDBusPropertyInfo %s_interface__%s_property =\n' % (i.name_lower, p.name_lower)) + self.outfile.write('{\n') + self.outfile.write(' -1, /* ref count */\n') + self.outfile.write(' (gchar *) "%s",\n' % p.name) + self.outfile.write(' (gchar *) "%s",\n' % p.signature) + self.outfile.write(' %s,\n' % flags) + if len(p.annotations) > 0: + self.outfile.write(' (GDBusAnnotationInfo **) %s_interface__%s_property_annotations,\n' % (i.name_lower, p.name_lower)) + else: + self.outfile.write(' NULL, /* no annotations */\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + key = (m.since, '%s_interface__%s_property' % (i.name_lower, p.name_lower)) + property_pointers.append(key) + + self.generate_array('%s_interface_properties' % i.name_lower, + 'GDBusPropertyInfo', property_pointers) + + # Finally the GDBusInterfaceInfo. + self.define_annotations('%s_interface_annotations' % i.name_lower, + i.annotations) + + self.outfile.write('const GDBusInterfaceInfo %s_interface =\n' % i.name_lower) + self.outfile.write('{\n') + self.outfile.write(' -1, /* ref count */\n') + self.outfile.write(' (gchar *) "%s",\n' % i.name) + if len(i.methods) > 0: + self.outfile.write(' (GDBusMethodInfo **) %s_interface_methods,\n' % i.name_lower) + else: + self.outfile.write(' NULL, /* no methods */\n') + if len(i.signals) > 0: + self.outfile.write(' (GDBusSignalInfo **) %s_interface_signals,\n' % i.name_lower) + else: + self.outfile.write(' NULL, /* no signals */\n') + if len(i.properties) > 0: + self.outfile.write(' (GDBusPropertyInfo **) %s_interface_properties,\n' % i.name_lower) + else: + self.outfile.write( 'NULL, /* no properties */\n') + if len(i.annotations) > 0: + self.outfile.write(' (GDBusAnnotationInfo **) %s_interface_annotations,\n' % i.name_lower) + else: + self.outfile.write(' NULL, /* no annotations */\n') + self.outfile.write('};\n') + self.outfile.write('\n') + + # ---------------------------------------------------------------------------------------------------- + + def generate(self): + self.generate_body_preamble() + self.define_infos() + +# ---------------------------------------------------------------------------------------------------- + class CodeGenerator: def __init__(self, ifaces, namespace, generate_objmanager, header_name, input_files_basenames, docbook_gen, outfile): @@ -788,7 +1068,7 @@ class CodeGenerator: '\n') def generate_annotations(self, prefix, annotations): - if annotations == None: + if annotations is None: return n = 0 diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py index 65876a2e8..03de1d107 100755 --- a/gio/gdbus-2.0/codegen/codegen_main.py +++ b/gio/gdbus-2.0/codegen/codegen_main.py @@ -63,38 +63,38 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value): iface_obj = i break - if iface_obj == None: + if iface_obj is None: print_error('No interface "{}"'.format(iface)) target_obj = None if method: method_obj = find_method(iface_obj, method) - if method_obj == None: + if method_obj is None: print_error('No method "{}" on interface "{}"'.format(method, iface)) if arg: arg_obj = find_arg(method_obj.in_args, arg) - if (arg_obj == None): + if (arg_obj is None): arg_obj = find_arg(method_obj.out_args, arg) - if (arg_obj == None): + if (arg_obj is None): print_error('No arg "{}" on method "{}" on interface "{}"'.format(arg, method, iface)) target_obj = arg_obj else: target_obj = method_obj elif signal: signal_obj = find_signal(iface_obj, signal) - if signal_obj == None: + if signal_obj is None: print_error('No signal "{}" on interface "{}"'.format(signal, iface)) if arg: arg_obj = find_arg(signal_obj.args, arg) - if (arg_obj == None): + if (arg_obj is None): print_error('No arg "{}" on signal "{}" on interface "{}"'.format(arg, signal, iface)) target_obj = arg_obj else: target_obj = signal_obj elif prop: prop_obj = find_prop(iface_obj, prop) - if prop_obj == None: + if prop_obj is None: print_error('No property "{}" on interface "{}"'.format(prop, iface)) target_obj = prop_obj else: @@ -152,7 +152,7 @@ def codegen_main(): arg_parser.add_argument('files', metavar='FILE', nargs='*', help='D-Bus introspection XML file') arg_parser.add_argument('--xml-files', metavar='FILE', action='append', default=[], - help='D-Bus introspection XML file') + help=argparse.SUPPRESS) arg_parser.add_argument('--interface-prefix', metavar='PREFIX', default='', help='String to strip from D-Bus interface names for code and docs') arg_parser.add_argument('--c-namespace', metavar='NAMESPACE', default='', @@ -175,6 +175,10 @@ def codegen_main(): help='Generate C headers') group.add_argument('--body', action='store_true', help='Generate C code') + group.add_argument('--interface-info-header', action='store_true', + help='Generate GDBusInterfaceInfo C header') + group.add_argument('--interface-info-body', action='store_true', + help='Generate GDBusInterfaceInfo C code') group = arg_parser.add_mutually_exclusive_group() group.add_argument('--output', metavar='FILE', @@ -210,6 +214,24 @@ def codegen_main(): c_file = args.output header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' + elif args.interface_info_header: + if args.output is None: + print_error('Using --interface-info-header requires --output') + if args.c_generate_object_manager: + print_error('--c-generate-object-manager is incompatible with ' + '--interface-info-header') + + h_file = args.output + header_name = os.path.basename(h_file) + elif args.interface_info_body: + if args.output is None: + print_error('Using --interface-info-body requires --output') + if args.c_generate_object_manager: + print_error('--c-generate-object-manager is incompatible with ' + '--interface-info-body') + + c_file = args.output + header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' all_ifaces = [] input_files_basenames = [] @@ -220,7 +242,7 @@ def codegen_main(): all_ifaces.extend(parsed_ifaces) input_files_basenames.append(os.path.basename(fname)) - if args.annotate != None: + if args.annotate is not None: apply_annotations(all_ifaces, args.annotate) for i in all_ifaces: @@ -254,6 +276,23 @@ def codegen_main(): outfile) gen.generate() + if args.interface_info_header: + with open(h_file, 'w') as outfile: + gen = codegen.InterfaceInfoHeaderCodeGenerator(all_ifaces, + args.c_namespace, + header_name, + args.pragma_once, + outfile) + gen.generate() + + if args.interface_info_body: + with open(c_file, 'w') as outfile: + gen = codegen.InterfaceInfoBodyCodeGenerator(all_ifaces, + args.c_namespace, + header_name, + outfile) + gen.generate() + sys.exit(0) if __name__ == "__main__": diff --git a/gio/gdbus-2.0/codegen/dbustypes.py b/gio/gdbus-2.0/codegen/dbustypes.py index bfc69f596..2ff736a5e 100644 --- a/gio/gdbus-2.0/codegen/dbustypes.py +++ b/gio/gdbus-2.0/codegen/dbustypes.py @@ -27,6 +27,25 @@ class Annotation: self.key = key self.value = value self.annotations = [] + self.since = '' + + def post_process(self, interface_prefix, cns, cns_upper, cns_lower, container): + key = self.key + overridden_key = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name') + if utils.is_ugly_case(overridden_key): + self.key_lower = overridden_key.lower() + else: + if overridden_key: + key = overridden_key + self.key_lower = utils.camel_case_to_uscore(key).lower().replace('-', '_').replace('.', '_') + + if len(self.since) == 0: + self.since = utils.lookup_since(self.annotations) + if len(self.since) == 0: + self.since = container.since + + for a in self.annotations: + a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) class Arg: def __init__(self, name, signature): @@ -42,7 +61,7 @@ class Arg: if len(self.since) == 0: self.since = utils.lookup_since(self.annotations) - if self.name == None: + if self.name is None: self.name = 'unnamed_arg%d'%arg_number # default to GVariant self.ctype_in_g = 'GVariant *' @@ -229,6 +248,8 @@ class Arg: self.gvalue_get = 'g_value_get_boxed' self.array_annotation = '(array zero-terminated=1)' + for a in self.annotations: + a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) class Method: def __init__(self, name): @@ -270,6 +291,9 @@ class Method: if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': self.deprecated = True + for a in self.annotations: + a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Signal: def __init__(self, name): self.name = name @@ -305,6 +329,9 @@ class Signal: if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': self.deprecated = True + for a in self.annotations: + a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Property: def __init__(self, name, signature, access): self.name = name @@ -356,6 +383,9 @@ class Property: if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true': self.deprecated = True + for a in self.annotations: + a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + class Interface: def __init__(self, name): self.name = name @@ -429,3 +459,6 @@ class Interface: for p in self.properties: p.post_process(interface_prefix, cns, cns_upper, cns_lower, self) + + for a in self.annotations: + a.post_process(interface_prefix, cns, cns_upper, cns_lower, self) diff --git a/gio/gdbus-2.0/codegen/meson.build b/gio/gdbus-2.0/codegen/meson.build index 54a86b0d6..24d2527bc 100644 --- a/gio/gdbus-2.0/codegen/meson.build +++ b/gio/gdbus-2.0/codegen/meson.build @@ -10,7 +10,7 @@ gdbus_codegen_files = [ gdbus_codegen_conf = configuration_data() gdbus_codegen_conf.set('VERSION', glib_version) -gdbus_codegen_conf.set('PYTHON', python.path()) +gdbus_codegen_conf.set('PYTHON', python_name) gdbus_codegen_conf.set('DATADIR', glib_datadir) # Install gdbus-codegen executable @@ -20,6 +20,8 @@ gdbus_codegen = configure_file(input : 'gdbus-codegen.in', install_dir : get_option('bindir'), configuration : gdbus_codegen_conf ) + # Provide tools for others when we're a subproject and they use the Meson GNOME module +meson.override_find_program('gdbus-codegen', gdbus_codegen) codegen_dir = join_paths(get_option('datadir'), 'glib-2.0/codegen') @@ -30,12 +32,11 @@ gdbus_codegen_built_files += configure_file(input : 'config.py.in', install_dir : codegen_dir, configuration : gdbus_codegen_conf) -blank_conf = configuration_data() foreach f : gdbus_codegen_files # Copy these into the builddir so that gdbus-codegen can be used uninstalled # and then install it too so that it can be used after installation gdbus_codegen_built_files += configure_file(input : f, output : f, install : true, install_dir : codegen_dir, - configuration : blank_conf) + copy : true) endforeach diff --git a/gio/gdbus-2.0/codegen/utils.py b/gio/gdbus-2.0/codegen/utils.py index bdfa703ac..95ba107d3 100644 --- a/gio/gdbus-2.0/codegen/utils.py +++ b/gio/gdbus-2.0/codegen/utils.py @@ -116,21 +116,21 @@ def lookup_annotation(annotations, key): def lookup_docs(annotations): s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString') - if s == None: + if s is None: return '' else: return s def lookup_since(annotations): s = lookup_annotation(annotations, 'org.gtk.GDBus.Since') - if s == None: + if s is None: return '' else: return s def lookup_brief_docs(annotations): s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString.Short') - if s == None: + if s is None: return '' else: return s diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index 2191c115a..f377378ec 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -418,6 +418,10 @@ g_dbus_is_supported_address (const gchar *string, supported = is_valid_nonce_tcp (a[n], key_value_pairs, error); else if (g_strcmp0 (a[n], "autolaunch:") == 0) supported = TRUE; + else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Unknown or unsupported transport “%s†for address “%sâ€"), + transport_name, a[n]); g_free (transport_name); g_hash_table_unref (key_value_pairs); diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c index aba9cea59..553bcdc32 100644 --- a/gio/gdbusauthmechanismsha1.c +++ b/gio/gdbusauthmechanismsha1.c @@ -603,7 +603,7 @@ keyring_generate_entry (const gchar *cookie_context, gchar **lines; gint max_line_id; GString *new_contents; - guint64 now; + gint64 now; gboolean have_id; gint use_id; gchar *use_cookie; @@ -658,7 +658,7 @@ keyring_generate_entry (const gchar *cookie_context, } new_contents = g_string_new (NULL); - now = time (NULL); + now = g_get_real_time () / G_USEC_PER_SEC; changed_file = FALSE; max_line_id = 0; @@ -672,7 +672,7 @@ keyring_generate_entry (const gchar *cookie_context, gchar **tokens; gchar *endp; gint line_id; - guint64 line_when; + gint64 line_when; gboolean keep_entry; if (line[0] == '\0') @@ -807,9 +807,9 @@ keyring_generate_entry (const gchar *cookie_context, g_free (raw_cookie); g_string_append_printf (new_contents, - "%d %" G_GUINT64_FORMAT " %s\n", + "%d %" G_GINT64_FORMAT " %s\n", *out_id, - (guint64) time (NULL), + g_get_real_time () / G_USEC_PER_SEC, *out_cookie); changed_file = TRUE; } diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index ae463e430..543ca0b2d 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -88,15 +88,6 @@ * kind of pitfalls it avoids * - Export objects before claiming names * - Talk about auto-starting services (cf. GBusNameWatcherFlags) - * - * - use abstract sockets in test code - * - right now it doesn't work, dbus-daemon(1) fails with - * - * /gdbus/connection/filter: Failed to start message bus: Failed to bind - * socket "/tmp/g-dbus-tests-pid-28531": Address already in use - * ** WARNING **: Error reading address from dbus daemon, 0 bytes read - * - * or similar. */ #include "config.h" @@ -4121,7 +4112,7 @@ invoke_get_property_in_idle_cb (gpointer _data) { reply = g_dbus_message_new_method_error (data->message, "org.freedesktop.DBus.Error.UnknownMethod", - _("No such interface 'org.freedesktop.DBus.Properties' on object at path %s"), + _("No such interface “org.freedesktop.DBus.Properties†on object at path %s"), g_dbus_message_get_path (data->message)); g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4263,7 +4254,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection *connect { reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("No such property '%s'"), + _("No such property “%sâ€"), property_name); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4275,7 +4266,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection *connect { reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("Property '%s' is not readable"), + _("Property “%s†is not readable"), property_name); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4286,7 +4277,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection *connect { reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("Property '%s' is not writable"), + _("Property “%s†is not writable"), property_name); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4306,7 +4297,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection *connect { reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("Error setting property '%s': Expected type '%s' but got '%s'"), + _("Error setting property “%sâ€: Expected type “%s†but got “%sâ€"), property_name, property_info->signature, g_variant_get_type_string (value)); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); @@ -4411,7 +4402,7 @@ handle_getset_property (GDBusConnection *connection, GDBusMessage *reply; reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("No such interface '%s'"), + _("No such interface “%sâ€"), interface_name); g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4468,7 +4459,7 @@ invoke_get_all_properties_in_idle_cb (gpointer _data) { reply = g_dbus_message_new_method_error (data->message, "org.freedesktop.DBus.Error.UnknownMethod", - _("No such interface 'org.freedesktop.DBus.Properties' on object at path %s"), + _("No such interface “org.freedesktop.DBus.Properties†on object at path %s"), g_dbus_message_get_path (data->message)); g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4619,7 +4610,7 @@ handle_get_all_properties (GDBusConnection *connection, GDBusMessage *reply; reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("No such interface '%s'"), + _("No such interface “%sâ€"), interface_name); g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4837,7 +4828,7 @@ call_in_idle_cb (gpointer user_data) GDBusMessage *reply; reply = g_dbus_message_new_method_error (g_dbus_method_invocation_get_message (invocation), "org.freedesktop.DBus.Error.UnknownMethod", - _("No such interface '%s' on object at path %s"), + _("No such interface “%s†on object at path %s"), g_dbus_method_invocation_get_interface_name (invocation), g_dbus_method_invocation_get_object_path (invocation)); g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); @@ -4935,7 +4926,7 @@ validate_and_maybe_schedule_method_call (GDBusConnection *connection, { reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.UnknownMethod", - _("No such method '%s'"), + _("No such method “%sâ€"), g_dbus_message_get_member (message)); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -4966,7 +4957,7 @@ validate_and_maybe_schedule_method_call (GDBusConnection *connection, reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("Type of message, '%s', does not match expected type '%s'"), + _("Type of message, “%sâ€, does not match expected type “%sâ€"), g_variant_get_type_string (parameters), type_string); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); @@ -5624,7 +5615,7 @@ decode_method_reply (GDBusMessage *reply, g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Method '%s' returned type '%s', but expected '%s'"), + _("Method “%s†returned type “%sâ€, but expected “%sâ€"), method_name, g_variant_get_type_string (result), type_string); g_variant_unref (result); @@ -6588,7 +6579,7 @@ handle_subtree_method_invocation (GDBusConnection *connection, GDBusMessage *reply; reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.InvalidArgs", - _("No such interface '%s'"), + _("No such interface “%sâ€"), interface_name); g_dbus_connection_send_message (es->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); @@ -6699,7 +6690,7 @@ process_subtree_vtable_message_in_idle_cb (gpointer _data) GDBusMessage *reply; reply = g_dbus_message_new_method_error (data->message, "org.freedesktop.DBus.Error.UnknownMethod", - _("Method '%s' on interface '%s' with signature '%s' does not exist"), + _("Method “%s†on interface “%s†with signature “%s†does not exist"), g_dbus_message_get_member (data->message), g_dbus_message_get_interface (data->message), g_dbus_message_get_signature (data->message)); @@ -7097,7 +7088,7 @@ distribute_method_call (GDBusConnection *connection, /* if we end up here, the message has not been not handled - so return an error saying this */ reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.UnknownMethod", - _("No such interface '%s' on object at path %s"), + _("No such interface “%s†on object at path %s"), interface_name, object_path); g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); @@ -7149,7 +7140,7 @@ message_bus_get_singleton (GBusType bus_type, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable" - " - unknown value '%s'"), + " — unknown value “%sâ€"), starter_bus); } else diff --git a/gio/gdbusdaemon.c b/gio/gdbusdaemon.c index 3516183f9..e6b3c1af0 100644 --- a/gio/gdbusdaemon.c +++ b/gio/gdbusdaemon.c @@ -1247,8 +1247,8 @@ handle_remove_match (_GFreedesktopDBus *object, else _g_freedesktop_dbus_complete_remove_match (object, invocation); } - - match_free (match); + if (match) + match_free (match); return TRUE; } diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c index be001ae55..68122387b 100644 --- a/gio/gdbusmessage.c +++ b/gio/gdbusmessage.c @@ -32,6 +32,8 @@ #include #elif MAJOR_IN_SYSMACROS #include +#elif MAJOR_IN_TYPES +#include #else #define MAJOR_MINOR_NOT_FOUND 1 #endif diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index a2aa760c7..d0ffbace3 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -155,6 +155,7 @@ static guint n_desktop_file_dirs; static const guint desktop_file_dir_user_config_index = 0; static guint desktop_file_dir_user_data_index; static GMutex desktop_file_dir_lock; +static const gchar *gio_launch_desktop_path = NULL; /* Monitor 'changed' signal handler {{{2 */ static void desktop_file_dir_reset (DesktopFileDir *dir); @@ -2562,41 +2563,6 @@ create_files_for_uris (GList *uris) return g_list_reverse (res); } -typedef struct -{ - GSpawnChildSetupFunc user_setup; - gpointer user_setup_data; - - char *pid_envvar; -} ChildSetupData; - -static void -child_setup (gpointer user_data) -{ - ChildSetupData *data = user_data; - - if (data->pid_envvar) - { - pid_t pid = getpid (); - char buf[20]; - int i; - - /* Write the pid into the space already reserved for it in the - * environment array. We can't use sprintf because it might - * malloc, so we do it by hand. It's simplest to write the pid - * out backwards first, then copy it over. - */ - for (i = 0; pid; i++, pid /= 10) - buf[i] = (pid % 10) + '0'; - for (i--; i >= 0; i--) - *(data->pid_envvar++) = buf[i]; - *data->pid_envvar = '\0'; - } - - if (data->user_setup) - data->user_setup (data->user_setup_data); -} - static void notify_desktop_launch (GDBusConnection *session_bus, GDesktopAppInfo *info, @@ -2675,6 +2641,9 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, gpointer user_setup_data, GDesktopAppLaunchCallback pid_callback, gpointer pid_callback_data, + gint stdin_fd, + gint stdout_fd, + gint stderr_fd, GError **error) { gboolean completed = FALSE; @@ -2683,7 +2652,6 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, char **argv, **envp; int argc; - ChildSetupData data; g_return_val_if_fail (info != NULL, FALSE); @@ -2705,6 +2673,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, GList *launched_uris; GList *iter; char *sn_id = NULL; + char **wrapped_argv; + int i; old_uris = dup_uris; if (!expand_application_parameters (info, exec_line, &dup_uris, &argc, &argv, error)) @@ -2723,25 +2693,11 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, goto out; } - data.user_setup = user_setup; - data.user_setup_data = user_setup_data; - if (info->filename) - { - envp = g_environ_setenv (envp, - "GIO_LAUNCHED_DESKTOP_FILE", - info->filename, - TRUE); - envp = g_environ_setenv (envp, - "GIO_LAUNCHED_DESKTOP_FILE_PID", - "XXXXXXXXXXXXXXXXXXXX", /* filled in child_setup */ - TRUE); - data.pid_envvar = (char *)g_environ_getenv (envp, "GIO_LAUNCHED_DESKTOP_FILE_PID"); - } - else - { - data.pid_envvar = NULL; - } + envp = g_environ_setenv (envp, + "GIO_LAUNCHED_DESKTOP_FILE", + info->filename, + TRUE); sn_id = NULL; if (launch_context) @@ -2760,14 +2716,40 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, g_list_free_full (launched_files, g_object_unref); } - if (!g_spawn_async (info->path, - argv, - envp, - spawn_flags, - child_setup, - &data, - &pid, - error)) + if (g_once_init_enter (&gio_launch_desktop_path)) + { + const gchar *tmp; + + /* Allow test suite to specify path to gio-launch-desktop */ + tmp = g_getenv ("GIO_LAUNCH_DESKTOP"); + + /* Fall back on usual searching in $PATH */ + if (tmp == NULL) + tmp = "gio-launch-desktop"; + g_once_init_leave (&gio_launch_desktop_path, tmp); + } + + wrapped_argv = g_new (char *, argc + 2); + wrapped_argv[0] = g_strdup (gio_launch_desktop_path); + + for (i = 0; i < argc; i++) + wrapped_argv[i + 1] = g_steal_pointer (&argv[i]); + + wrapped_argv[i + 1] = NULL; + g_free (argv); + argv = NULL; + + if (!g_spawn_async_with_fds (info->path, + wrapped_argv, + envp, + spawn_flags, + user_setup, + user_setup_data, + &pid, + stdin_fd, + stdout_fd, + stderr_fd, + error)) { if (sn_id) g_app_launch_context_launch_failed (launch_context, sn_id); @@ -2805,8 +2787,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info, g_free (sn_id); g_list_free (launched_uris); - g_strfreev (argv); - argv = NULL; + g_strfreev (wrapped_argv); + wrapped_argv = NULL; } while (dup_uris != NULL); @@ -2940,6 +2922,9 @@ g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo, gpointer user_setup_data, GDesktopAppLaunchCallback pid_callback, gpointer pid_callback_data, + gint stdin_fd, + gint stdout_fd, + gint stderr_fd, GError **error) { GDesktopAppInfo *info = G_DESKTOP_APP_INFO (appinfo); @@ -2953,7 +2938,8 @@ g_desktop_app_info_launch_uris_internal (GAppInfo *appinfo, else success = g_desktop_app_info_launch_uris_with_spawn (info, session_bus, info->exec, uris, launch_context, spawn_flags, user_setup, user_setup_data, - pid_callback, pid_callback_data, error); + pid_callback, pid_callback_data, + stdin_fd, stdout_fd, stderr_fd, error); if (session_bus != NULL) { @@ -2978,6 +2964,7 @@ g_desktop_app_info_launch_uris (GAppInfo *appinfo, launch_context, _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL, + -1, -1, -1, error); } @@ -3028,6 +3015,61 @@ g_desktop_app_info_launch (GAppInfo *appinfo, return res; } +/** + * g_desktop_app_info_launch_uris_as_manager_with_fds: + * @appinfo: a #GDesktopAppInfo + * @uris: (element-type utf8): List of URIs + * @launch_context: (nullable): a #GAppLaunchContext + * @spawn_flags: #GSpawnFlags, used for each process + * @user_setup: (scope async) (nullable): a #GSpawnChildSetupFunc, used once + * for each process. + * @user_setup_data: (closure user_setup) (nullable): User data for @user_setup + * @pid_callback: (scope call) (nullable): Callback for child processes + * @pid_callback_data: (closure pid_callback) (nullable): User data for @callback + * @stdin_fd: file descriptor to use for child's stdin, or -1 + * @stdout_fd: file descriptor to use for child's stdout, or -1 + * @stderr_fd: file descriptor to use for child's stderr, or -1 + * @error: return location for a #GError, or %NULL + * + * Equivalent to g_desktop_app_info_launch_uris_as_manager() but allows + * you to pass in file descriptors for the stdin, stdout and stderr streams + * of the launched process. + * + * If application launching occurs via some non-spawn mechanism (e.g. D-Bus + * activation) then @stdin_fd, @stdout_fd and @stderr_fd are ignored. + * + * Returns: %TRUE on successful launch, %FALSE otherwise. + * + * Since: 2.58 + */ +gboolean +g_desktop_app_info_launch_uris_as_manager_with_fds (GDesktopAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GSpawnFlags spawn_flags, + GSpawnChildSetupFunc user_setup, + gpointer user_setup_data, + GDesktopAppLaunchCallback pid_callback, + gpointer pid_callback_data, + gint stdin_fd, + gint stdout_fd, + gint stderr_fd, + GError **error) +{ + return g_desktop_app_info_launch_uris_internal ((GAppInfo*)appinfo, + uris, + launch_context, + spawn_flags, + user_setup, + user_setup_data, + pid_callback, + pid_callback_data, + stdin_fd, + stdout_fd, + stderr_fd, + error); +} + /** * g_desktop_app_info_launch_uris_as_manager: * @appinfo: a #GDesktopAppInfo @@ -3046,11 +3088,12 @@ g_desktop_app_info_launch (GAppInfo *appinfo, * launch applications. Ordinary applications should use * g_app_info_launch_uris(). * - * If the application is launched via traditional UNIX fork()/exec() - * then @spawn_flags, @user_setup and @user_setup_data are used for the - * call to g_spawn_async(). Additionally, @pid_callback (with - * @pid_callback_data) will be called to inform about the PID of the - * created process. + * If the application is launched via GSpawn, then @spawn_flags, @user_setup + * and @user_setup_data are used for the call to g_spawn_async(). + * Additionally, @pid_callback (with @pid_callback_data) will be called to + * inform about the PID of the created process. See g_spawn_async_with_pipes() + * for information on certain parameter conditions that can enable an + * optimized posix_spawn() codepath to be used. * * If application launching occurs via some other mechanism (eg: D-Bus * activation) then @spawn_flags, @user_setup, @user_setup_data, @@ -3069,15 +3112,16 @@ g_desktop_app_info_launch_uris_as_manager (GDesktopAppInfo *appinfo, gpointer pid_callback_data, GError **error) { - return g_desktop_app_info_launch_uris_internal ((GAppInfo*)appinfo, - uris, - launch_context, - spawn_flags, - user_setup, - user_setup_data, - pid_callback, - pid_callback_data, - error); + return g_desktop_app_info_launch_uris_as_manager_with_fds (appinfo, + uris, + launch_context, + spawn_flags, + user_setup, + user_setup_data, + pid_callback, + pid_callback_data, + -1, -1, -1, + error); } /* OnlyShowIn API support {{{2 */ @@ -4652,7 +4696,10 @@ g_desktop_app_info_launch_action (GDesktopAppInfo *info, if (exec_line) g_desktop_app_info_launch_uris_with_spawn (info, session_bus, exec_line, NULL, launch_context, - _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL, NULL); + _SPAWN_FLAGS_DEFAULT, NULL, NULL, NULL, NULL, + -1, -1, -1, NULL); + + g_free (exec_line); } if (session_bus != NULL) diff --git a/gio/gdesktopappinfo.h b/gio/gdesktopappinfo.h index a2df3dd51..86a3caa30 100644 --- a/gio/gdesktopappinfo.h +++ b/gio/gdesktopappinfo.h @@ -169,6 +169,20 @@ gboolean g_desktop_app_info_launch_uris_as_manager (GDesktopAppInfo gpointer pid_callback_data, GError **error); +GLIB_AVAILABLE_IN_2_58 +gboolean g_desktop_app_info_launch_uris_as_manager_with_fds (GDesktopAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GSpawnFlags spawn_flags, + GSpawnChildSetupFunc user_setup, + gpointer user_setup_data, + GDesktopAppLaunchCallback pid_callback, + gpointer pid_callback_data, + gint stdin_fd, + gint stdout_fd, + gint stderr_fd, + GError **error); + GLIB_AVAILABLE_IN_2_40 gchar *** g_desktop_app_info_search (const gchar *search_string); diff --git a/gio/gdrive.c b/gio/gdrive.c index bd42691d9..24784f3df 100644 --- a/gio/gdrive.c +++ b/gio/gdrive.c @@ -611,10 +611,12 @@ g_drive_poll_for_media_finish (GDrive *drive, * @drive: a #GDrive * @kind: the kind of identifier to return * - * Gets the identifier of the given kind for @drive. + * Gets the identifier of the given kind for @drive. The only + * identifier currently available is + * #G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE. * - * Returns: a newly allocated string containing the - * requested identfier, or %NULL if the #GDrive + * Returns: (nullable) (transfer full): a newly allocated string containing the + * requested identifier, or %NULL if the #GDrive * doesn't have this kind of identifier. */ char * @@ -921,7 +923,7 @@ g_drive_stop_finish (GDrive *drive, * * Gets the sort key for @drive, if any. * - * Returns: Sorting key for @drive or %NULL if no such key is available. + * Returns: (nullable): Sorting key for @drive or %NULL if no such key is available. * * Since: 2.32 */ diff --git a/gio/gdrive.h b/gio/gdrive.h index a33704219..ec92071c7 100644 --- a/gio/gdrive.h +++ b/gio/gdrive.h @@ -30,6 +30,15 @@ G_BEGIN_DECLS +/** + * G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE: + * + * The string used to obtain a Unix device path with g_drive_get_identifier(). + * + * Since: 2.58 + */ +#define G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE "unix-device" + #define G_TYPE_DRIVE (g_drive_get_type ()) #define G_DRIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_DRIVE, GDrive)) #define G_IS_DRIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_DRIVE)) diff --git a/gio/gfdonotificationbackend.c b/gio/gfdonotificationbackend.c index a0d481433..c4fa0dc1d 100644 --- a/gio/gfdonotificationbackend.c +++ b/gio/gfdonotificationbackend.c @@ -62,12 +62,12 @@ typedef struct GVariant *default_action_target; } FreedesktopNotification; - static void freedesktop_notification_free (gpointer data) { FreedesktopNotification *n = data; + g_object_unref (n->backend); g_free (n->id); g_free (n->default_action); if (n->default_action_target) @@ -76,6 +76,24 @@ freedesktop_notification_free (gpointer data) g_slice_free (FreedesktopNotification, n); } +static FreedesktopNotification * +freedesktop_notification_new (GFdoNotificationBackend *backend, + const gchar *id, + GNotification *notification) +{ + FreedesktopNotification *n; + + n = g_slice_new0 (FreedesktopNotification); + n->backend = g_object_ref (backend); + n->id = g_strdup (id); + n->notify_id = 0; + g_notification_get_default_action (notification, + &n->default_action, + &n->default_action_target); + + return n; +} + static FreedesktopNotification * g_fdo_notification_backend_find_notification (GFdoNotificationBackend *backend, const gchar *id) @@ -319,8 +337,19 @@ notification_sent (GObject *source_object, val = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), result, &error); if (val) { + GFdoNotificationBackend *backend = n->backend; + FreedesktopNotification *match; + g_variant_get (val, "(u)", &n->notify_id); g_variant_unref (val); + + match = g_fdo_notification_backend_find_notification_by_notify_id (backend, n->notify_id); + if (match != NULL) + { + backend->notifications = g_slist_remove (backend->notifications, match); + freedesktop_notification_free (match); + } + backend->notifications = g_slist_prepend (backend->notifications, n); } else { @@ -331,9 +360,7 @@ notification_sent (GObject *source_object, warning_printed = TRUE; } - n->backend->notifications = g_slist_remove (n->backend->notifications, n); freedesktop_notification_free (n); - g_error_free (error); } } @@ -378,7 +405,7 @@ g_fdo_notification_backend_send_notification (GNotificationBackend *backend, GNotification *notification) { GFdoNotificationBackend *self = G_FDO_NOTIFICATION_BACKEND (backend); - FreedesktopNotification *n; + FreedesktopNotification *n, *tmp; if (self->notify_subscription == 0) { @@ -391,24 +418,11 @@ g_fdo_notification_backend_send_notification (GNotificationBackend *backend, notify_signal, backend, NULL); } - n = g_fdo_notification_backend_find_notification (self, id); - if (n == NULL) - { - n = g_slice_new0 (FreedesktopNotification); - n->backend = self; - n->id = g_strdup (id); - n->notify_id = 0; - - n->backend->notifications = g_slist_prepend (n->backend->notifications, n); - } - else - { - /* Only clear default action. All other fields are still valid */ - g_clear_pointer (&n->default_action, g_free); - g_clear_pointer (&n->default_action_target, g_variant_unref); - } + n = freedesktop_notification_new (self, id, notification); - g_notification_get_default_action (notification, &n->default_action, &n->default_action_target); + tmp = g_fdo_notification_backend_find_notification (self, id); + if (tmp) + n->notify_id = tmp->notify_id; call_notify (backend->dbus_connection, backend->application, n->notify_id, notification, notification_sent, n); } diff --git a/gio/gfile.c b/gio/gfile.c index c17aeb040..a5709a4cc 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -702,6 +702,11 @@ g_file_get_parse_name (GFile *file) * the actual file or directory represented by the #GFile; see * g_file_copy() if attempting to copy a file. * + * g_file_dup() is useful when a second handle is needed to the same underlying + * file, for use in a separate thread (#GFile is not thread-safe). For use + * within the same thread, use g_object_ref() to increment the existing object’s + * reference count. + * * This call does no blocking I/O. * * Returns: (transfer full): a new #GFile that is a duplicate @@ -2974,7 +2979,7 @@ retry: if (errsv == EINTR) goto retry; - else if (errsv == ENOSYS || errsv == EINVAL) + else if (errsv == ENOSYS || errsv == EINVAL || errsv == EOPNOTSUPP) g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Splice not supported")); else diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h index 4decee346..8416b4fad 100644 --- a/gio/gfileinfo.h +++ b/gio/gfileinfo.h @@ -644,7 +644,8 @@ typedef struct _GFileInfoClass GFileInfoClass; * * A key in the "unix" namespace for checking if the file represents a * UNIX mount point. This attribute is %TRUE if the file is a UNIX mount - * point. This attribute is only available for UNIX file systems. + * point. Since 2.58, `/` is considered to be a mount point. + * This attribute is only available for UNIX file systems. * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. **/ #define G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT "unix::is-mountpoint" /* boolean */ diff --git a/gio/ginetaddress.c b/gio/ginetaddress.c index 0a0a85a48..787c757da 100644 --- a/gio/ginetaddress.c +++ b/gio/ginetaddress.c @@ -376,98 +376,6 @@ g_inet_address_init (GInetAddress *address) address->priv = g_inet_address_get_instance_private (address); } -/* These are provided so that we can use inet_pton() and inet_ntop() on Windows - * if they are available (i.e. Vista and later), and use the existing code path - * on Windows XP/Server 2003. We can drop this portion when we drop support for - * XP/Server 2003. - */ -#if defined(G_OS_WIN32) && _WIN32_WINNT < 0x0600 -static gint -inet_pton (gint family, - const gchar *addr_string, - gpointer addr) -{ - /* For Vista/Server 2008 and later, there is native inet_pton() in Winsock2 */ - if (ws2funcs.pInetPton != NULL) - return ws2funcs.pInetPton (family, addr_string, addr); - else - { - /* Fallback codepath for XP/Server 2003 */ - struct sockaddr_storage sa; - struct sockaddr_in *sin = (struct sockaddr_in *)&sa; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa; - gint len = sizeof (sa); - - if (family != AF_INET && family != AF_INET6) - { - WSASetLastError (WSAEAFNOSUPPORT); - return -1; - } - - /* WSAStringToAddress() will accept various not-an-IP-address - * strings like "127.0.0.1:80", "[1234::5678]:80", "127.1", etc. - */ - if (!g_hostname_is_ip_address (addr_string)) - return 0; - - if (WSAStringToAddress ((LPTSTR) addr_string, family, NULL, (LPSOCKADDR) &sa, &len) != 0) - return 0; - - if (family == AF_INET) - *(IN_ADDR *)addr = sin->sin_addr; - else - *(IN6_ADDR *)addr = sin6->sin6_addr; - - return 1; - } -} - -static const gchar * -inet_ntop (gint family, - const gpointer addr, - gchar *addr_str, - socklen_t size) -{ - /* On Vista/Server 2008 and later, there is native inet_ntop() in Winsock2 */ - if (ws2funcs.pInetNtop != NULL) - return ws2funcs.pInetNtop (family, addr, addr_str, size); - else - { - /* Fallback codepath for XP/Server 2003 */ - DWORD buflen = size, addrlen; - struct sockaddr_storage sa; - struct sockaddr_in *sin = (struct sockaddr_in *)&sa; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa; - - memset (&sa, 0, sizeof (sa)); - sa.ss_family = family; - if (sa.ss_family == AF_INET) - { - struct in_addr *addrv4 = (struct in_addr *) addr; - - addrlen = sizeof (*sin); - memcpy (&sin->sin_addr, addrv4, sizeof (sin->sin_addr)); - } - else if (sa.ss_family == AF_INET6) - { - struct in6_addr *addrv6 = (struct in6_addr *) addr; - - addrlen = sizeof (*sin6); - memcpy (&sin6->sin6_addr, addrv6, sizeof (sin6->sin6_addr)); - } - else - { - WSASetLastError (WSAEAFNOSUPPORT); - return NULL; - } - if (WSAAddressToString ((LPSOCKADDR) &sa, addrlen, NULL, addr_str, &buflen) == 0) - return addr_str; - else - return NULL; - } -} -#endif - /** * g_inet_address_new_from_string: * @string: a string representation of an IP address diff --git a/gio/gio-autocleanups.h b/gio/gio-autocleanups.h index 624702289..dcba4d976 100644 --- a/gio/gio-autocleanups.h +++ b/gio/gio-autocleanups.h @@ -108,6 +108,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GProxy, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GProxyResolver, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GRemoteActionGroup, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GResolver, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GResource, g_resource_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSeekable, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSettingsBackend, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSettingsSchema, g_settings_schema_unref) diff --git a/gio/gio-launch-desktop.c b/gio/gio-launch-desktop.c new file mode 100644 index 000000000..03845df28 --- /dev/null +++ b/gio/gio-launch-desktop.c @@ -0,0 +1,52 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2018 Endless Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Author: Daniel Drake + */ + +/* + * gio-launch-desktop: GDesktopAppInfo helper + * Executable wrapper to set GIO_LAUNCHED_DESKTOP_FILE_PID + * There are complications when doing this in a fork()/exec() codepath, + * and it cannot otherwise be done with posix_spawn(). + * This wrapper is designed to be minimal and lightweight. + * It does not even link against glib. + */ + +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + pid_t pid = getpid (); + char buf[50]; + int r; + + if (argc < 2) + return -1; + + r = snprintf (buf, sizeof (buf), "GIO_LAUNCHED_DESKTOP_FILE_PID=%ld", (long) pid); + if (r >= sizeof (buf)) + return -1; + + putenv (buf); + + return execvp (argv[1], argv + 1); +} diff --git a/gio/gio-querymodules-wrapper.py b/gio/gio-querymodules-wrapper.py new file mode 100644 index 000000000..8960540b4 --- /dev/null +++ b/gio/gio-querymodules-wrapper.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import sys + +if not os.environ.get('DESTDIR'): + print('GIO module cache creation...') + subprocess.call([sys.argv[1], sys.argv[2]]) diff --git a/gio/gio-tool-cat.c b/gio/gio-tool-cat.c index 394748815..66841dd3e 100644 --- a/gio/gio-tool-cat.c +++ b/gio/gio-tool-cat.c @@ -130,7 +130,7 @@ handle_cat (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio cat"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s...", _("LOCATION")); + param = g_strdup_printf ("%s…", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-copy.c b/gio/gio-tool-copy.c index c6a9b6b2d..4cc4a9d96 100644 --- a/gio/gio-tool-copy.c +++ b/gio/gio-tool-copy.c @@ -95,7 +95,7 @@ handle_copy (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio copy"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s... %s", _("SOURCE"), _("DESTINATION")); + param = g_strdup_printf ("%s… %s", _("SOURCE"), _("DESTINATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-info.c b/gio/gio-tool-info.c index c446d60e8..d6fc6b46c 100644 --- a/gio/gio-tool-info.c +++ b/gio/gio-tool-info.c @@ -279,7 +279,7 @@ handle_info (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio info"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s...", _("LOCATION")); + param = g_strdup_printf ("%s…", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-list.c b/gio/gio-tool-list.c index 202d79978..d1501b8e0 100644 --- a/gio/gio-tool-list.c +++ b/gio/gio-tool-list.c @@ -162,7 +162,7 @@ handle_list (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio list"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("[%s...]", _("LOCATION")); + param = g_strdup_printf ("[%s…]", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-mkdir.c b/gio/gio-tool-mkdir.c index 3d7b50a02..7900704c9 100644 --- a/gio/gio-tool-mkdir.c +++ b/gio/gio-tool-mkdir.c @@ -45,7 +45,7 @@ handle_mkdir (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio mkdir"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s...", _("LOCATION")); + param = g_strdup_printf ("%s…", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-monitor.c b/gio/gio-tool-monitor.c index d6de7a2b0..f2ffb3387 100644 --- a/gio/gio-tool-monitor.c +++ b/gio/gio-tool-monitor.c @@ -200,7 +200,7 @@ handle_monitor (int argc, gchar *argv[], gboolean do_help) g_set_prgname ("gio monitor"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("[%s...]", _("LOCATION")); + param = g_strdup_printf ("%s…", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-mount.c b/gio/gio-tool-mount.c index 9522713e9..b5aaa1af2 100644 --- a/gio/gio-tool-mount.c +++ b/gio/gio-tool-mount.c @@ -48,8 +48,12 @@ static gboolean anonymous = FALSE; static gboolean mount_list = FALSE; static gboolean extra_detail = FALSE; static gboolean mount_monitor = FALSE; +static gboolean tcrypt_hidden = FALSE; +static gboolean tcrypt_system = FALSE; +static guint tcrypt_pim = 0; static const char *unmount_scheme = NULL; static const char *mount_device_file = NULL; +static const char *stop_device_file = NULL; static gboolean success = TRUE; @@ -59,6 +63,7 @@ static const GOptionEntry entries[] = { "device", 'd', 0, G_OPTION_ARG_STRING, &mount_device_file, N_("Mount volume with device file"), N_("DEVICE") }, { "unmount", 'u', 0, G_OPTION_ARG_NONE, &mount_unmount, N_("Unmount"), NULL}, { "eject", 'e', 0, G_OPTION_ARG_NONE, &mount_eject, N_("Eject"), NULL}, + { "stop", 't', 0, G_OPTION_ARG_STRING, &stop_device_file, N_("Stop drive with device file"), N_("DEVICE") }, { "unmount-scheme", 's', 0, G_OPTION_ARG_STRING, &unmount_scheme, N_("Unmount all mounts with the given scheme"), N_("SCHEME") }, { "force", 'f', 0, G_OPTION_ARG_NONE, &force, N_("Ignore outstanding file operations when unmounting or ejecting"), NULL }, { "anonymous", 'a', 0, G_OPTION_ARG_NONE, &anonymous, N_("Use an anonymous user when authenticating"), NULL }, @@ -66,6 +71,9 @@ static const GOptionEntry entries[] = { "list", 'l', 0, G_OPTION_ARG_NONE, &mount_list, N_("List"), NULL}, { "monitor", 'o', 0, G_OPTION_ARG_NONE, &mount_monitor, N_("Monitor events"), NULL}, { "detail", 'i', 0, G_OPTION_ARG_NONE, &extra_detail, N_("Show extra information"), NULL}, + { "tcrypt-pim", 0, 0, G_OPTION_ARG_INT, &tcrypt_pim, N_("The numeric PIM when unlocking a VeraCrypt volume"), N_("PIM")}, + { "tcrypt-hidden", 0, 0, G_OPTION_ARG_NONE, &tcrypt_hidden, N_("Mount a TCRYPT hidden volume"), NULL}, + { "tcrypt-system", 0, 0, G_OPTION_ARG_NONE, &tcrypt_system, N_("Mount a TCRYPT system volume"), NULL}, { NULL } }; @@ -172,6 +180,16 @@ ask_password_cb (GMountOperation *op, } } + if (flags & G_ASK_PASSWORD_TCRYPT) + { + if (tcrypt_pim) + g_mount_operation_set_pim (op, tcrypt_pim); + if (tcrypt_hidden) + g_mount_operation_set_is_tcrypt_hidden_volume (op, TRUE); + if (tcrypt_system) + g_mount_operation_set_is_tcrypt_system_volume (op, TRUE); + } + /* Only try anonymous access once. */ if (anonymous && GPOINTER_TO_INT (g_object_get_data (G_OBJECT (op), "state")) == MOUNT_OP_ASKED) @@ -252,6 +270,8 @@ mount_mountable_done_cb (GObject *object, else g_object_unref (target); + g_object_unref (op); + outstanding_mounts--; if (outstanding_mounts == 0) @@ -280,6 +300,8 @@ mount_done_cb (GObject *object, g_error_free (error); } + g_object_unref (op); + outstanding_mounts--; if (outstanding_mounts == 0) @@ -436,6 +458,76 @@ eject (GFile *file) outstanding_mounts++; } +static void +stop_with_device_file_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + gchar *device_path = user_data; + + if (!g_drive_stop_finish (G_DRIVE (object), res, &error)) + { + print_error ("%s: %s", device_path, error->message); + g_error_free (error); + success = FALSE; + } + + g_free (device_path); + + outstanding_mounts--; + + if (outstanding_mounts == 0) + g_main_loop_quit (main_loop); +} + +static void +stop_with_device_file (const char *device_file) +{ + GVolumeMonitor *volume_monitor; + GList *drives; + GList *l; + + volume_monitor = g_volume_monitor_get (); + + drives = g_volume_monitor_get_connected_drives (volume_monitor); + for (l = drives; l != NULL; l = l->next) + { + GDrive *drive = G_DRIVE (l->data); + gchar *id; + + id = g_drive_get_identifier (drive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + if (g_strcmp0 (id, device_file) == 0) + { + GMountOperation *op; + GMountUnmountFlags flags; + + op = new_mount_op (); + flags = force ? G_MOUNT_UNMOUNT_FORCE : G_MOUNT_UNMOUNT_NONE; + g_drive_stop (drive, + flags, + op, + NULL, + stop_with_device_file_cb, + g_steal_pointer (&id)); + g_object_unref (op); + + outstanding_mounts++; + } + + g_free (id); + } + g_list_free_full (drives, g_object_unref); + + if (outstanding_mounts == 0) + { + print_error ("%s: %s", device_file, _("No drive for device file")); + success = FALSE; + } + + g_object_unref (volume_monitor); +} + static gboolean iterate_gmain_timeout_function (gpointer data) { @@ -938,6 +1030,8 @@ mount_with_device_file (const char *device_file) mount_with_device_file_cb, id); + g_object_unref (op); + outstanding_mounts++; } else @@ -1138,7 +1232,7 @@ handle_mount (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio mount"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("[%s...]", _("LOCATION")); + param = g_strdup_printf ("[%s…]", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); @@ -1160,14 +1254,14 @@ handle_mount (int argc, char *argv[], gboolean do_help) return 1; } - g_option_context_free (context); - main_loop = g_main_loop_new (NULL, FALSE); if (mount_list) list_monitor_items (); else if (mount_device_file != NULL) mount_with_device_file (mount_device_file); + else if (stop_device_file) + stop_with_device_file (stop_device_file); else if (unmount_scheme != NULL) unmount_all_with_scheme (unmount_scheme); else if (mount_monitor) @@ -1186,6 +1280,14 @@ handle_mount (int argc, char *argv[], gboolean do_help) g_object_unref (file); } } + else + { + show_help (context, _("No locations given")); + g_option_context_free (context); + return 1; + } + + g_option_context_free (context); if (outstanding_mounts > 0) g_main_loop_run (main_loop); diff --git a/gio/gio-tool-move.c b/gio/gio-tool-move.c index 97e11d26e..5755f59d4 100644 --- a/gio/gio-tool-move.c +++ b/gio/gio-tool-move.c @@ -91,7 +91,7 @@ handle_move (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio move"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s... %s", _("SOURCE"), _("DESTINATION")); + param = g_strdup_printf ("%s… %s", _("SOURCE"), _("DESTINATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); @@ -106,6 +106,7 @@ handle_move (int argc, char *argv[], gboolean do_help) if (do_help) { show_help (context, NULL); + g_option_context_free (context); return 0; } diff --git a/gio/gio-tool-open.c b/gio/gio-tool-open.c index f4a164227..73863c7c5 100644 --- a/gio/gio-tool-open.c +++ b/gio/gio-tool-open.c @@ -110,7 +110,7 @@ handle_open (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio open"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s...", _("LOCATION")); + param = g_strdup_printf ("%s…", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-remove.c b/gio/gio-tool-remove.c index bf3a0fac6..8748b4629 100644 --- a/gio/gio-tool-remove.c +++ b/gio/gio-tool-remove.c @@ -45,7 +45,7 @@ handle_remove (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio remove"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s...", _("LOCATION")); + param = g_strdup_printf ("%s…", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-set.c b/gio/gio-tool-set.c index acb471aca..ab3ac1544 100644 --- a/gio/gio-tool-set.c +++ b/gio/gio-tool-set.c @@ -86,7 +86,7 @@ handle_set (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio set"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("%s %s %s...", _("LOCATION"), _("ATTRIBUTE"), _("VALUE")); + param = g_strdup_printf ("%s %s %s…", _("LOCATION"), _("ATTRIBUTE"), _("VALUE")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool-trash.c b/gio/gio-tool-trash.c index 7f30f2dd4..4f9e3668a 100644 --- a/gio/gio-tool-trash.c +++ b/gio/gio-tool-trash.c @@ -78,7 +78,7 @@ handle_trash (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio trash"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("[%s...]", _("LOCATION")); + param = g_strdup_printf ("[%s…]", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); @@ -101,8 +101,6 @@ handle_trash (int argc, char *argv[], gboolean do_help) return 1; } - g_option_context_free (context); - if (argc > 1) { int i; @@ -133,5 +131,14 @@ handle_trash (int argc, char *argv[], gboolean do_help) g_object_unref (file); } + if (argc == 1 && !empty) + { + show_help (context, _("No locations given")); + g_option_context_free (context); + return 1; + } + + g_option_context_free (context); + return retval; } diff --git a/gio/gio-tool-tree.c b/gio/gio-tool-tree.c index 8a68c3d18..e63752edb 100644 --- a/gio/gio-tool-tree.c +++ b/gio/gio-tool-tree.c @@ -236,7 +236,7 @@ handle_tree (int argc, char *argv[], gboolean do_help) g_set_prgname ("gio tree"); /* Translators: commandline placeholder */ - param = g_strdup_printf ("[%s...]", _("LOCATION")); + param = g_strdup_printf ("[%s…]", _("LOCATION")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); diff --git a/gio/gio-tool.c b/gio/gio-tool.c index b4a863b45..18200014c 100644 --- a/gio/gio-tool.c +++ b/gio/gio-tool.c @@ -221,7 +221,7 @@ static void usage (void) { g_printerr ("%s\n", _("Usage:")); - g_printerr (" gio %s %s\n", _("COMMAND"), _("[ARGS...]")); + g_printerr (" gio %s %s\n", _("COMMAND"), _("[ARGS…]")); g_printerr ("\n"); g_printerr ("%s\n", _("Commands:")); g_printerr (" help %s\n", _("Print help")); diff --git a/gio/gioenums.h b/gio/gioenums.h index bc844b9b9..99b1c7937 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -572,17 +572,19 @@ typedef enum { * @G_ASK_PASSWORD_NEED_DOMAIN: operation requires a domain. * @G_ASK_PASSWORD_SAVING_SUPPORTED: operation supports saving settings. * @G_ASK_PASSWORD_ANONYMOUS_SUPPORTED: operation supports anonymous users. + * @G_ASK_PASSWORD_TCRYPT: operation takes TCRYPT parameters (Since: 2.58) * * #GAskPasswordFlags are used to request specific information from the * user, or to notify the user of their choices in an authentication * situation. **/ typedef enum { - G_ASK_PASSWORD_NEED_PASSWORD = (1 << 0), - G_ASK_PASSWORD_NEED_USERNAME = (1 << 1), - G_ASK_PASSWORD_NEED_DOMAIN = (1 << 2), - G_ASK_PASSWORD_SAVING_SUPPORTED = (1 << 3), - G_ASK_PASSWORD_ANONYMOUS_SUPPORTED = (1 << 4) + G_ASK_PASSWORD_NEED_PASSWORD = (1 << 0), + G_ASK_PASSWORD_NEED_USERNAME = (1 << 1), + G_ASK_PASSWORD_NEED_DOMAIN = (1 << 2), + G_ASK_PASSWORD_SAVING_SUPPORTED = (1 << 3), + G_ASK_PASSWORD_ANONYMOUS_SUPPORTED = (1 << 4), + G_ASK_PASSWORD_TCRYPT = (1 << 5), } GAskPasswordFlags; diff --git a/gio/giomodule.c b/gio/giomodule.c index 30731f7c2..36c0cefed 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -802,14 +802,29 @@ _g_io_module_get_default_type (const gchar *extension_point, } static gpointer -try_implementation (GIOExtension *extension, +try_implementation (const char *extension_point, + GIOExtension *extension, GIOModuleVerifyFunc verify_func) { GType type = g_io_extension_get_type (extension); gpointer impl; if (g_type_is_a (type, G_TYPE_INITABLE)) - return g_initable_new (type, NULL, NULL, NULL); + { + GError *error = NULL; + + impl = g_initable_new (type, NULL, &error, NULL); + if (impl) + return impl; + + g_debug ("Failed to initialize %s (%s) for %s: %s", + g_io_extension_get_name (extension), + g_type_name (type), + extension_point, + error ? error->message : ""); + g_clear_error (&error); + return NULL; + } else { impl = g_object_new (type, NULL); @@ -895,7 +910,7 @@ _g_io_module_get_default (const gchar *extension_point, preferred = g_io_extension_point_get_extension_by_name (ep, use_this); if (preferred) { - impl = try_implementation (preferred, verify_func); + impl = try_implementation (extension_point, preferred, verify_func); if (impl) goto done; } @@ -911,7 +926,7 @@ _g_io_module_get_default (const gchar *extension_point, if (extension == preferred) continue; - impl = try_implementation (extension, verify_func); + impl = try_implementation (extension_point, extension, verify_func); if (impl) goto done; } diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c index 99bcc58ba..bf88334b1 100644 --- a/gio/glib-compile-resources.c +++ b/gio/glib-compile-resources.c @@ -734,13 +734,13 @@ main (int argc, char **argv) GOptionContext *context; GOptionEntry entries[] = { { "version", 0, 0, G_OPTION_ARG_NONE, &show_version_and_exit, N_("Show program version and exit"), NULL }, - { "target", 0, 0, G_OPTION_ARG_FILENAME, &target, N_("name of the output file"), N_("FILE") }, - { "sourcedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &sourcedirs, N_("The directories where files are to be read from (default to current directory)"), N_("DIRECTORY") }, + { "target", 0, 0, G_OPTION_ARG_FILENAME, &target, N_("Name of the output file"), N_("FILE") }, + { "sourcedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &sourcedirs, N_("The directories to load files referenced in FILE from (default: current directory)"), N_("DIRECTORY") }, { "generate", 0, 0, G_OPTION_ARG_NONE, &generate_automatic, N_("Generate output in the format selected for by the target filename extension"), NULL }, { "generate-header", 0, 0, G_OPTION_ARG_NONE, &generate_header, N_("Generate source header"), NULL }, - { "generate-source", 0, 0, G_OPTION_ARG_NONE, &generate_source, N_("Generate sourcecode used to link in the resource file into your code"), NULL }, + { "generate-source", 0, 0, G_OPTION_ARG_NONE, &generate_source, N_("Generate source code used to link in the resource file into your code"), NULL }, { "generate-dependencies", 0, 0, G_OPTION_ARG_NONE, &generate_dependencies, N_("Generate dependency list"), NULL }, - { "dependency-file", 0, 0, G_OPTION_ARG_FILENAME, &dependency_file, N_("name of the dependency file to generate"), N_("FILE") }, + { "dependency-file", 0, 0, G_OPTION_ARG_FILENAME, &dependency_file, N_("Name of the dependency file to generate"), N_("FILE") }, { "generate-phony-targets", 0, 0, G_OPTION_ARG_NONE, &generate_phony_targets, N_("Include phony targets in the generated dependency file"), NULL }, { "manual-register", 0, 0, G_OPTION_ARG_NONE, &manual_register, N_("Don’t automatically create and register resource"), NULL }, { "internal", 0, 0, G_OPTION_ARG_NONE, &internal, N_("Don’t export functions; declare them G_GNUC_INTERNAL"), NULL }, @@ -1030,7 +1030,7 @@ main (int argc, char **argv) return 1; } - fprintf (file, + g_fprintf (file, "#ifndef __RESOURCE_%s_H__\n" "#define __RESOURCE_%s_H__\n" "\n" @@ -1040,14 +1040,14 @@ main (int argc, char **argv) c_name, c_name, linkage, c_name); if (manual_register) - fprintf (file, + g_fprintf (file, "\n" "%s void %s_register_resource (void);\n" "%s void %s_unregister_resource (void);\n" "\n", linkage, c_name, linkage, c_name); - fprintf (file, + g_fprintf (file, "#endif\n"); fclose (file); @@ -1078,7 +1078,7 @@ main (int argc, char **argv) return 1; } - fprintf (file, + g_fprintf (file, "#include \n" "\n" "#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))\n" @@ -1092,17 +1092,17 @@ main (int argc, char **argv) for (i = 0; i < data_size; i++) { if (i % 8 == 0) - fprintf (file, " "); - fprintf (file, "0x%2.2x", (int)data[i]); + g_fprintf (file, " "); + g_fprintf (file, "0x%2.2x", (int)data[i]); if (i != data_size - 1) - fprintf (file, ", "); + g_fprintf (file, ", "); if ((i % 8 == 7) || (i == data_size - 1)) - fprintf (file, "\n"); + g_fprintf (file, "\n"); } - fprintf (file, "} };\n"); + g_fprintf (file, "} };\n"); - fprintf (file, + g_fprintf (file, "\n" "static GStaticResource static_resource = { %s_resource_data.data, sizeof (%s_resource_data.data), NULL, NULL, NULL };\n" "%s GResource *%s_get_resource (void);\n" @@ -1115,7 +1115,7 @@ main (int argc, char **argv) if (manual_register) { - fprintf (file, + g_fprintf (file, "\n" "%s void %s_unregister_resource (void);\n" "void %s_unregister_resource (void)\n" @@ -1132,8 +1132,8 @@ main (int argc, char **argv) } else { - fprintf (file, "%s", gconstructor_code); - fprintf (file, + g_fprintf (file, "%s", gconstructor_code); + g_fprintf (file, "\n" "#ifdef G_HAS_CONSTRUCTORS\n" "\n" diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c index f6e1b4036..d4340d463 100644 --- a/gio/glib-compile-schemas.c +++ b/gio/glib-compile-schemas.c @@ -179,6 +179,8 @@ typedef struct GString *unparsed_default_value; GVariant *default_value; + GVariantDict *desktop_overrides; + GString *strinfo; gboolean is_enum; gboolean is_flags; @@ -731,6 +733,11 @@ key_state_serialise (KeyState *state) g_variant_builder_add (&builder, "(y(**))", 'r', state->minimum, state->maximum); + /* per-desktop overrides */ + if (state->desktop_overrides) + g_variant_builder_add (&builder, "(y@a{sv})", 'd', + g_variant_dict_end (state->desktop_overrides)); + state->serialised = g_variant_builder_end (&builder); } @@ -770,6 +777,9 @@ key_state_free (gpointer data) if (state->serialised) g_variant_unref (state->serialised); + if (state->desktop_overrides) + g_variant_dict_unref (state->desktop_overrides); + g_slice_free (KeyState, state); } @@ -1882,6 +1892,8 @@ set_overrides (GHashTable *schema_table, gchar **groups; gint i; + g_debug ("Processing override file '%s'", filename); + key_file = g_key_file_new (); if (!g_key_file_load_from_file (key_file, filename, 0, &error)) { @@ -1904,18 +1916,31 @@ set_overrides (GHashTable *schema_table, for (i = 0; groups[i]; i++) { const gchar *group = groups[i]; + const gchar *schema_name; + const gchar *desktop_id; SchemaState *schema; + gchar **pieces; gchar **keys; gint j; - schema = g_hash_table_lookup (schema_table, group); + pieces = g_strsplit (group, ":", 2); + schema_name = pieces[0]; + desktop_id = pieces[1]; + + g_debug ("Processing group '%s' (schema '%s', %s)", + group, schema_name, desktop_id ? desktop_id : "all desktops"); + + schema = g_hash_table_lookup (schema_table, schema_name); if (schema == NULL) - /* Having the schema not be installed is expected to be a - * common case. Don't even emit an error message about - * that. - */ - continue; + { + /* Having the schema not be installed is expected to be a + * common case. Don't even emit an error message about + * that. + */ + g_strfreev (pieces); + continue; + } keys = g_key_file_get_keys (key_file, group, NULL, NULL); g_assert (keys != NULL); @@ -1931,8 +1956,8 @@ set_overrides (GHashTable *schema_table, if (state == NULL) { - fprintf (stderr, _("No such key '%s' in schema '%s' as " - "specified in override file '%s'"), + fprintf (stderr, _("No such key “%s†in schema “%s†as " + "specified in override file “%sâ€"), key, group, filename); if (!strict) @@ -1943,6 +1968,32 @@ set_overrides (GHashTable *schema_table, fprintf (stderr, _(" and --strict was specified; exiting.\n")); g_key_file_free (key_file); + g_strfreev (pieces); + g_strfreev (groups); + g_strfreev (keys); + + return FALSE; + } + + if (desktop_id != NULL && state->l10n) + { + /* Let's avoid the n*m case of per-desktop localised + * default values, and just forbid it. + */ + fprintf (stderr, + _("cannot provide per-desktop overrides for localised " + "key “%s†in schema “%s†(override file “%sâ€)"), + key, group, filename); + + if (!strict) + { + fprintf (stderr, _("; ignoring override for this key.\n")); + continue; + } + + fprintf (stderr, _(" and --strict was specified; exiting.\n")); + g_key_file_free (key_file); + g_strfreev (pieces); g_strfreev (groups); g_strfreev (keys); @@ -1957,8 +2008,8 @@ set_overrides (GHashTable *schema_table, if (value == NULL) { - fprintf (stderr, _("error parsing key '%s' in schema '%s' " - "as specified in override file '%s': " + fprintf (stderr, _("error parsing key “%s†in schema “%s†" + "as specified in override file “%sâ€: " "%s."), key, group, filename, error->message); @@ -1973,6 +2024,7 @@ set_overrides (GHashTable *schema_table, fprintf (stderr, _("--strict was specified; exiting.\n")); g_key_file_free (key_file); + g_strfreev (pieces); g_strfreev (groups); g_strfreev (keys); @@ -1985,8 +2037,8 @@ set_overrides (GHashTable *schema_table, g_variant_compare (value, state->maximum) > 0) { fprintf (stderr, - _("override for key '%s' in schema '%s' in " - "override file '%s' is outside the range " + _("override for key “%s†in schema “%s†in " + "override file “%s†is outside the range " "given in the schema"), key, group, filename); @@ -2001,6 +2053,7 @@ set_overrides (GHashTable *schema_table, fprintf (stderr, _(" and --strict was specified; exiting.\n")); g_key_file_free (key_file); + g_strfreev (pieces); g_strfreev (groups); g_strfreev (keys); @@ -2013,8 +2066,8 @@ set_overrides (GHashTable *schema_table, if (!is_valid_choices (value, state->strinfo)) { fprintf (stderr, - _("override for key '%s' in schema '%s' in " - "override file '%s' is not in the list " + _("override for key “%s†in schema “%s†in " + "override file “%s†is not in the list " "of valid choices"), key, group, filename); @@ -2029,6 +2082,7 @@ set_overrides (GHashTable *schema_table, fprintf (stderr, _(" and --strict was specified; exiting.\n")); g_key_file_free (key_file); + g_strfreev (pieces); g_strfreev (groups); g_strfreev (keys); @@ -2036,11 +2090,24 @@ set_overrides (GHashTable *schema_table, } } - g_variant_unref (state->default_value); - state->default_value = value; + if (desktop_id != NULL) + { + if (state->desktop_overrides == NULL) + state->desktop_overrides = g_variant_dict_new (NULL); + + g_variant_dict_insert_value (state->desktop_overrides, desktop_id, value); + g_variant_unref (value); + } + else + { + g_variant_unref (state->default_value); + state->default_value = value; + } + g_free (string); } + g_strfreev (pieces); g_strfreev (keys); } @@ -2076,6 +2143,7 @@ main (int argc, char **argv) /* These options are only for use in the gschema-compile tests */ { "schema-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &schema_files, NULL, NULL }, + { "override-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &override_files, NULL, NULL }, { NULL } }; diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 3cd0137d6..354ac7c8c 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -1677,16 +1677,20 @@ find_mountpoint_for (const char *file, } } -char * -_g_local_file_find_topdir_for (const char *file) +static char * +_g_local_file_find_topdir_for_internal (const char *file, dev_t file_dev) { char *dir; char *mountpoint = NULL; dev_t dir_dev; dir = get_parent (file, &dir_dev); - if (dir == NULL) - return NULL; + if (dir == NULL || dir_dev != file_dev) + { + g_free (dir); + + return NULL; + } mountpoint = find_mountpoint_for (dir, dir_dev); g_free (dir); @@ -1694,6 +1698,17 @@ _g_local_file_find_topdir_for (const char *file) return mountpoint; } +char * +_g_local_file_find_topdir_for (const char *file) +{ + GStatBuf file_stat; + + if (g_lstat (file, &file_stat) != 0) + return NULL; + + return _g_local_file_find_topdir_for_internal (file, file_stat.st_dev); +} + static char * get_unique_filename (const char *basename, int id) @@ -1769,6 +1784,7 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) char uid_str[32]; GStatBuf global_stat, trash_stat; gboolean res; + GUnixMountEntry *mount; if (g_once_init_enter (&home_dev_set)) { @@ -1787,6 +1803,17 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) if (topdir == NULL) return FALSE; + mount = g_unix_mount_at (topdir, NULL); + if (mount == NULL || g_unix_mount_is_system_internal (mount)) + { + g_clear_pointer (&mount, g_unix_mount_free); + g_free (topdir); + + return FALSE; + } + + g_clear_pointer (&mount, g_unix_mount_free); + globaldir = g_build_filename (topdir, ".Trash", NULL); if (g_lstat (globaldir, &global_stat) == 0 && S_ISDIR (global_stat.st_mode) && @@ -1882,7 +1909,7 @@ g_local_file_trash (GFile *file, int i; char *data; gboolean is_homedir_trash; - char delete_time[32]; + char *delete_time = NULL; int fd; GStatBuf trash_stat, global_stat; char *dirname, *globaldir; @@ -1930,19 +1957,35 @@ g_local_file_trash (GFile *file, { uid_t uid; char uid_str[32]; + GUnixMountEntry *mount; uid = geteuid (); g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long)uid); - topdir = _g_local_file_find_topdir_for (local->filename); + topdir = _g_local_file_find_topdir_for_internal (local->filename, + file_stat.st_dev); if (topdir == NULL) { g_set_io_error (error, _("Unable to find toplevel directory to trash %s"), - file, G_IO_ERROR_NOT_SUPPORTED); + file, ENOTSUP); return FALSE; } - + + mount = g_unix_mount_at (topdir, NULL); + if (mount == NULL || g_unix_mount_is_system_internal (mount)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Trashing on system internal mounts is not supported")); + + g_clear_pointer (&mount, g_unix_mount_free); + g_free (topdir); + + return FALSE; + } + + g_clear_pointer (&mount, g_unix_mount_free); + /* Try looking for global trash dir $topdir/.Trash/$uid */ globaldir = g_build_filename (topdir, ".Trash", NULL); if (g_lstat (globaldir, &global_stat) == 0 && @@ -2094,16 +2137,17 @@ g_local_file_trash (GFile *file, g_free (topdir); { - time_t t; - struct tm now; - t = time (NULL); - localtime_r (&t, &now); - delete_time[0] = 0; - strftime(delete_time, sizeof (delete_time), "%Y-%m-%dT%H:%M:%S", &now); + GDateTime *now = g_date_time_new_now_local (); + if (now != NULL) + delete_time = g_date_time_format (now, "%Y-%m-%dT%H:%M:%S"); + else + delete_time = g_strdup ("9999-12-31T23:59:59"); + g_date_time_unref (now); } data = g_strdup_printf ("[Trash Info]\nPath=%s\nDeletionDate=%s\n", original_name_escaped, delete_time); + g_free (delete_time); g_file_set_contents (infofile, data, -1, NULL); diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index 801695ad0..b3e29374a 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -821,6 +821,7 @@ _g_local_file_info_get_parent_info (const char *dir, parent_info->is_sticky = FALSE; parent_info->has_trash_dir = FALSE; parent_info->device = 0; + parent_info->inode = 0; if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME) || _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE) || @@ -850,6 +851,7 @@ _g_local_file_info_get_parent_info (const char *dir, #endif parent_info->owner = statbuf.st_uid; parent_info->device = statbuf.st_dev; + parent_info->inode = statbuf.st_ino; /* No need to find trash dir if it's not writable anyway */ if (parent_info->writable && _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH)) @@ -922,9 +924,13 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher, _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, writable); + /* Trashing is supported only if the parent device is the same */ if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH)) - _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, - writable && parent_info->has_trash_dir); + _g_file_info_set_attribute_boolean_by_id (info, + G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, + writable && + parent_info->has_trash_dir && + parent_info->device == statbuf->st_dev); } } @@ -1117,8 +1123,10 @@ lookup_uid_data (uid_t uid) char buffer[4096]; struct passwd pwbuf; struct passwd *pwbufp; +#ifndef __BIONIC__ char *gecos, *comma; - +#endif + if (uid_cache == NULL) uid_cache = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)uid_data_free); @@ -1203,10 +1211,12 @@ static char * lookup_gid_name (gid_t gid) { char *name; +#if defined (HAVE_GETGRGID_R) char buffer[4096]; struct group gbuf; +#endif struct group *gbufp; - + if (gid_cache == NULL) gid_cache = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_free); @@ -1634,7 +1644,6 @@ _g_local_file_info_get_nostat (GFileInfo *info, static const char * get_icon_name (const char *path, - const char *content_type, gboolean use_symbolic, gboolean *with_fallbacks_out) { @@ -1679,10 +1688,6 @@ get_icon_name (const char *path, { name = use_symbolic ? "folder-videos-symbolic" : "folder-videos"; } - else if (g_content_type_is_mime_type (content_type,"inode/directory")) - { - name = use_symbolic ? "folder-symbolic" : "folder"; - } else { name = NULL; @@ -1703,7 +1708,7 @@ get_icon (const char *path, const char *icon_name; gboolean with_fallbacks; - icon_name = get_icon_name (path, content_type, use_symbolic, &with_fallbacks); + icon_name = get_icon_name (path, use_symbolic, &with_fallbacks); if (icon_name != NULL) { if (with_fallbacks) @@ -1970,7 +1975,7 @@ _g_local_file_info_get (const char *basename, if (stat_ok && parent_info && parent_info->device != 0 && _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT) && - statbuf.st_dev != parent_info->device) + (statbuf.st_dev != parent_info->device || statbuf.st_ino == parent_info->inode)) _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT, TRUE); if (stat_ok) diff --git a/gio/glocalfileinfo.h b/gio/glocalfileinfo.h index a231c24ca..7a6566163 100644 --- a/gio/glocalfileinfo.h +++ b/gio/glocalfileinfo.h @@ -36,6 +36,7 @@ typedef struct gboolean has_trash_dir; int owner; dev_t device; + ino_t inode; gpointer extra_data; GDestroyNotify free_extra_data; } GLocalParentFileInfo; diff --git a/gio/glocalfilemonitor.c b/gio/glocalfilemonitor.c index c19da3ba8..7b0a82439 100644 --- a/gio/glocalfilemonitor.c +++ b/gio/glocalfilemonitor.c @@ -648,6 +648,8 @@ g_file_monitor_source_new (gpointer instance, source = g_source_new (&source_funcs, sizeof (GFileMonitorSource)); fms = (GFileMonitorSource *) source; + g_source_set_name (source, "GFileMonitorSource"); + g_mutex_init (&fms->lock); fms->instance = instance; fms->pending_changes = g_sequence_new (pending_change_free); diff --git a/gio/gmount.c b/gio/gmount.c index 0169ea54b..dad4b8513 100644 --- a/gio/gmount.c +++ b/gio/gmount.c @@ -255,7 +255,8 @@ g_mount_get_symbolic_icon (GMount *mount) * considered an opaque string. Returns %NULL if there is no UUID * available. * - * Returns: the UUID for @mount or %NULL if no UUID can be computed. + * Returns: (nullable) (transfer full): the UUID for @mount or %NULL if no UUID + * can be computed. * The returned string should be freed with g_free() * when no longer needed. **/ @@ -276,8 +277,9 @@ g_mount_get_uuid (GMount *mount) * @mount: a #GMount. * * Gets the volume for the @mount. - * - * Returns: (transfer full): a #GVolume or %NULL if @mount is not associated with a volume. + * + * Returns: (transfer full) (nullable): a #GVolume or %NULL if @mount is not + * associated with a volume. * The returned object should be unreffed with * g_object_unref() when no longer needed. **/ @@ -302,7 +304,8 @@ g_mount_get_volume (GMount *mount) * This is a convenience method for getting the #GVolume and then * using that object to get the #GDrive. * - * Returns: (transfer full): a #GDrive or %NULL if @mount is not associated with a volume or a drive. + * Returns: (transfer full) (nullable): a #GDrive or %NULL if @mount is not + * associated with a volume or a drive. * The returned object should be unreffed with * g_object_unref() when no longer needed. **/ @@ -1037,7 +1040,7 @@ g_mount_unshadow (GMount *mount) * * Gets the sort key for @mount, if any. * - * Returns: Sorting key for @mount or %NULL if no such key is available. + * Returns: (nullable): Sorting key for @mount or %NULL if no such key is available. * * Since: 2.32 */ diff --git a/gio/gmountoperation.c b/gio/gmountoperation.c index 2a2b4ce5b..d59acb3b5 100644 --- a/gio/gmountoperation.c +++ b/gio/gmountoperation.c @@ -47,6 +47,12 @@ * #GtkMountOperation. If no user interaction is desired (for example * when automounting filesystems at login time), usually %NULL can be * passed, see each method taking a #GMountOperation for details. + * + * The term ‘TCRYPT’ is used to mean ‘compatible with TrueCrypt and VeraCrypt’. + * [TrueCrypt](https://en.wikipedia.org/wiki/TrueCrypt) is a discontinued system for + * encrypting file containers, partitions or whole disks, typically used with Windows. + * [VeraCrypt](https://www.veracrypt.fr/) is a maintained fork of TrueCrypt with various + * improvements and auditing fixes. */ enum { @@ -68,6 +74,9 @@ struct _GMountOperationPrivate { gboolean anonymous; GPasswordSave password_save; int choice; + gboolean hidden_volume; + gboolean system_volume; + guint pim; }; enum { @@ -77,7 +86,10 @@ enum { PROP_ANONYMOUS, PROP_DOMAIN, PROP_PASSWORD_SAVE, - PROP_CHOICE + PROP_CHOICE, + PROP_IS_TCRYPT_HIDDEN_VOLUME, + PROP_IS_TCRYPT_SYSTEM_VOLUME, + PROP_PIM }; G_DEFINE_TYPE_WITH_PRIVATE (GMountOperation, g_mount_operation, G_TYPE_OBJECT) @@ -124,6 +136,21 @@ g_mount_operation_set_property (GObject *object, g_value_get_int (value)); break; + case PROP_IS_TCRYPT_HIDDEN_VOLUME: + g_mount_operation_set_is_tcrypt_hidden_volume (operation, + g_value_get_boolean (value)); + break; + + case PROP_IS_TCRYPT_SYSTEM_VOLUME: + g_mount_operation_set_is_tcrypt_system_volume (operation, + g_value_get_boolean (value)); + break; + + case PROP_PIM: + g_mount_operation_set_pim (operation, + g_value_get_uint (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -169,6 +196,18 @@ g_mount_operation_get_property (GObject *object, g_value_set_int (value, priv->choice); break; + case PROP_IS_TCRYPT_HIDDEN_VOLUME: + g_value_set_boolean (value, priv->hidden_volume); + break; + + case PROP_IS_TCRYPT_SYSTEM_VOLUME: + g_value_set_boolean (value, priv->system_volume); + break; + + case PROP_PIM: + g_value_set_uint (value, priv->pim); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -504,6 +543,60 @@ g_mount_operation_class_init (GMountOperationClass *klass) 0, G_MAXINT, 0, G_PARAM_READWRITE| G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + + /** + * GMountOperation:is-tcrypt-hidden-volume: + * + * Whether the device to be unlocked is a TCRYPT hidden volume. + * See https://www.veracrypt.fr/en/Hidden%20Volume.html. + * + * Since: 2.58 + */ + g_object_class_install_property (object_class, + PROP_IS_TCRYPT_HIDDEN_VOLUME, + g_param_spec_boolean ("is-tcrypt-hidden-volume", + P_("TCRYPT Hidden Volume"), + P_("Whether to unlock a TCRYPT hidden volume. See https://www.veracrypt.fr/en/Hidden%20Volume.html."), + FALSE, + G_PARAM_READWRITE| + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + + /** + * GMountOperation:is-tcrypt-system-volume: + * + * Whether the device to be unlocked is a TCRYPT system volume. + * In this context, a system volume is a volume with a bootloader + * and operating system installed. This is only supported for Windows + * operating systems. For further documentation, see + * https://www.veracrypt.fr/en/System%20Encryption.html. + * + * Since: 2.58 + */ + g_object_class_install_property (object_class, + PROP_IS_TCRYPT_SYSTEM_VOLUME, + g_param_spec_boolean ("is-tcrypt-system-volume", + P_("TCRYPT System Volume"), + P_("Whether to unlock a TCRYPT system volume. Only supported for unlocking Windows system volumes. See https://www.veracrypt.fr/en/System%20Encryption.html."), + FALSE, + G_PARAM_READWRITE| + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + + /** + * GMountOperation:pim: + * + * The VeraCrypt PIM value, when unlocking a VeraCrypt volume. See + * https://www.veracrypt.fr/en/Personal%20Iterations%20Multiplier%20(PIM).html. + * + * Since: 2.58 + */ + g_object_class_install_property (object_class, + PROP_PIM, + g_param_spec_uint ("pim", + P_("PIM"), + P_("The VeraCrypt PIM value"), + 0, G_MAXUINT, 0, + G_PARAM_READWRITE| + G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); } static void @@ -736,6 +829,130 @@ g_mount_operation_set_choice (GMountOperation *op, } } +/** + * g_mount_operation_get_is_tcrypt_hidden_volume: + * @op: a #GMountOperation. + * + * Check to see whether the mount operation is being used + * for a TCRYPT hidden volume. + * + * Returns: %TRUE if mount operation is for hidden volume. + * + * Since: 2.58 + **/ +gboolean +g_mount_operation_get_is_tcrypt_hidden_volume (GMountOperation *op) +{ + g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), FALSE); + return op->priv->hidden_volume; +} + +/** + * g_mount_operation_set_is_tcrypt_hidden_volume: + * @op: a #GMountOperation. + * @hidden_volume: boolean value. + * + * Sets the mount operation to use a hidden volume if @hidden_volume is %TRUE. + * + * Since: 2.58 + **/ +void +g_mount_operation_set_is_tcrypt_hidden_volume (GMountOperation *op, + gboolean hidden_volume) +{ + GMountOperationPrivate *priv; + g_return_if_fail (G_IS_MOUNT_OPERATION (op)); + priv = op->priv; + + if (priv->hidden_volume != hidden_volume) + { + priv->hidden_volume = hidden_volume; + g_object_notify (G_OBJECT (op), "is-tcrypt-hidden-volume"); + } +} + +/** + * g_mount_operation_get_is_tcrypt_system_volume: + * @op: a #GMountOperation. + * + * Check to see whether the mount operation is being used + * for a TCRYPT system volume. + * + * Returns: %TRUE if mount operation is for system volume. + * + * Since: 2.58 + **/ +gboolean +g_mount_operation_get_is_tcrypt_system_volume (GMountOperation *op) +{ + g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), FALSE); + return op->priv->system_volume; +} + +/** + * g_mount_operation_set_is_tcrypt_system_volume: + * @op: a #GMountOperation. + * @system_volume: boolean value. + * + * Sets the mount operation to use a system volume if @system_volume is %TRUE. + * + * Since: 2.58 + **/ +void +g_mount_operation_set_is_tcrypt_system_volume (GMountOperation *op, + gboolean system_volume) +{ + GMountOperationPrivate *priv; + g_return_if_fail (G_IS_MOUNT_OPERATION (op)); + priv = op->priv; + + if (priv->system_volume != system_volume) + { + priv->system_volume = system_volume; + g_object_notify (G_OBJECT (op), "is-tcrypt-system-volume"); + } +} + +/** + * g_mount_operation_get_pim: + * @op: a #GMountOperation. + * + * Gets a PIM from the mount operation. + * + * Returns: The VeraCrypt PIM within @op. + * + * Since: 2.58 + **/ +guint +g_mount_operation_get_pim (GMountOperation *op) +{ + g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), 0); + return op->priv->pim; +} + +/** + * g_mount_operation_set_pim: + * @op: a #GMountOperation. + * @pim: an unsigned integer. + * + * Sets the mount operation's PIM to @pim. + * + * Since: 2.58 + **/ +void +g_mount_operation_set_pim (GMountOperation *op, + guint pim) +{ + GMountOperationPrivate *priv; + g_return_if_fail (G_IS_MOUNT_OPERATION (op)); + priv = op->priv; + if (priv->pim != pim) + { + priv->pim = pim; + g_object_notify (G_OBJECT (op), "pim"); + } +} + /** * g_mount_operation_reply: * @op: a #GMountOperation diff --git a/gio/gmountoperation.h b/gio/gmountoperation.h index 24b96e002..1361fb86f 100644 --- a/gio/gmountoperation.h +++ b/gio/gmountoperation.h @@ -149,6 +149,21 @@ void g_mount_operation_set_choice (GMountOperation *op, GLIB_AVAILABLE_IN_ALL void g_mount_operation_reply (GMountOperation *op, GMountOperationResult result); +GLIB_AVAILABLE_IN_2_58 +gboolean g_mount_operation_get_is_tcrypt_hidden_volume (GMountOperation *op); +GLIB_AVAILABLE_IN_2_58 +void g_mount_operation_set_is_tcrypt_hidden_volume (GMountOperation *op, + gboolean hidden_volume); +GLIB_AVAILABLE_IN_2_58 +gboolean g_mount_operation_get_is_tcrypt_system_volume (GMountOperation *op); +GLIB_AVAILABLE_IN_2_58 +void g_mount_operation_set_is_tcrypt_system_volume (GMountOperation *op, + gboolean system_volume); +GLIB_AVAILABLE_IN_2_58 +guint g_mount_operation_get_pim (GMountOperation *op); +GLIB_AVAILABLE_IN_2_58 +void g_mount_operation_set_pim (GMountOperation *op, + guint pim); G_END_DECLS diff --git a/gio/gnetworking.h.win32 b/gio/gnetworking.h.win32 deleted file mode 100644 index 1f45dba32..000000000 --- a/gio/gnetworking.h.win32 +++ /dev/null @@ -1,81 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2008-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#ifndef __G_NETWORKING_H__ -#define __G_NETWORKING_H__ - -#include - -#ifdef G_OS_WIN32 - -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#include -#include -#include -#include -#include -#include -#undef interface - -#else /* !G_OS_WIN32 */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef T_SRV -#define T_SRV 33 -#endif - -#ifndef _PATH_RESCONF -#define _PATH_RESCONF "/etc/resolv.conf" -#endif - -#ifndef CMSG_LEN -/* CMSG_LEN and CMSG_SPACE are defined by RFC 2292, but missing on - * some older platforms. - */ -#define CMSG_LEN(len) ((size_t)CMSG_DATA((struct cmsghdr *)NULL) + (len)) - -/* CMSG_SPACE must add at least as much padding as CMSG_NXTHDR() - * adds. We overestimate here. - */ -#define GLIB_ALIGN_TO_SIZEOF(len, obj) (((len) + sizeof (obj) - 1) & ~(sizeof (obj) - 1)) -#define CMSG_SPACE(len) GLIB_ALIGN_TO_SIZEOF (CMSG_LEN (len), struct cmsghdr) -#endif -#endif - -G_BEGIN_DECLS - -GLIB_AVAILABLE_IN_2_36 -void g_networking_init (void); - -G_END_DECLS - -#endif /* __G_NETWORKING_H__ */ diff --git a/gio/gnetworkmonitorportal.c b/gio/gnetworkmonitorportal.c index 856f8aa5b..16249ac55 100644 --- a/gio/gnetworkmonitorportal.c +++ b/gio/gnetworkmonitorportal.c @@ -21,7 +21,6 @@ #include "gnetworkmonitorportal.h" #include "ginitable.h" #include "giomodule-priv.h" -#include "gnetworkmonitor.h" #include "xdp-dbus.h" #include "gportalsupport.h" @@ -39,8 +38,13 @@ enum struct _GNetworkMonitorPortalPrivate { - GXdpNetworkMonitor *proxy; - gboolean network_available; + GDBusProxy *proxy; + gboolean has_network; + int version; + + gboolean available; + gboolean metered; + GNetworkConnectivity connectivity; }; G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorPortal, g_network_monitor_portal, G_TYPE_NETWORK_MONITOR_BASE, @@ -72,22 +76,15 @@ g_network_monitor_portal_get_property (GObject *object, switch (prop_id) { case PROP_NETWORK_AVAILABLE: - g_value_set_boolean (value, - nm->priv->network_available && - gxdp_network_monitor_get_available (nm->priv->proxy)); + g_value_set_boolean (value, nm->priv->available); break; case PROP_NETWORK_METERED: - g_value_set_boolean (value, - nm->priv->network_available && - gxdp_network_monitor_get_metered (nm->priv->proxy)); + g_value_set_boolean (value, nm->priv->metered); break; case PROP_CONNECTIVITY: - g_value_set_enum (value, - nm->priv->network_available - ? gxdp_network_monitor_get_connectivity (nm->priv->proxy) - : G_NETWORK_CONNECTIVITY_LOCAL); + g_value_set_enum (value, nm->priv->connectivity); break; default: @@ -97,22 +94,184 @@ g_network_monitor_portal_get_property (GObject *object, } static void -proxy_changed (GXdpNetworkMonitor *proxy, - gboolean available, - GNetworkMonitorPortal *nm) +got_available (GObject *source, + GAsyncResult *res, + gpointer data) { - if (nm->priv->network_available) - g_signal_emit_by_name (nm, "network-changed", available); + GDBusProxy *proxy = G_DBUS_PROXY (source); + GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data); + GError *error = NULL; + GVariant *ret; + gboolean available; + + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (ret == NULL) + { + g_warning ("%s", error->message); + g_clear_error (&error); + return; + } + + g_variant_get (ret, "(b)", &available); + g_variant_unref (ret); + + if (nm->priv->available != available) + { + nm->priv->available = available; + g_object_notify (G_OBJECT (nm), "network-available"); + g_signal_emit_by_name (nm, "network-changed", available); + } } +static void +got_metered (GObject *source, + GAsyncResult *res, + gpointer data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (source); + GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data); + GError *error = NULL; + GVariant *ret; + gboolean metered; + + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (ret == NULL) + { + g_warning ("%s", error->message); + g_clear_error (&error); + return; + } + + g_variant_get (ret, "(b)", &metered); + g_variant_unref (ret); + + if (nm->priv->metered != metered) + { + nm->priv->metered = metered; + g_object_notify (G_OBJECT (nm), "network-metered"); + } +} + +static void +got_connectivity (GObject *source, + GAsyncResult *res, + gpointer data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (source); + GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data); + GError *error = NULL; + GVariant *ret; + GNetworkConnectivity connectivity; + + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (ret == NULL) + { + g_warning ("%s", error->message); + g_clear_error (&error); + return; + } + + g_variant_get (ret, "(u)", &connectivity); + g_variant_unref (ret); + + if (nm->priv->connectivity != connectivity) + { + nm->priv->connectivity = connectivity; + g_object_notify (G_OBJECT (nm), "connectivity"); + } +} + +static void +proxy_signal (GDBusProxy *proxy, + const char *sender, + const char *signal, + GVariant *parameters, + GNetworkMonitorPortal *nm) +{ + if (!nm->priv->has_network) + return; + + if (nm->priv->version == 1) + { + gboolean available; + + g_variant_get (parameters, "(b)", &available); + g_signal_emit_by_name (nm, "network-changed", available); + } + else if (nm->priv->version == 2) + { + g_dbus_proxy_call (proxy, "GetConnectivity", NULL, 0, -1, NULL, got_connectivity, nm); + g_dbus_proxy_call (proxy, "GetMetered", NULL, 0, -1, NULL, got_metered, nm); + g_dbus_proxy_call (proxy, "GetAvailable", NULL, 0, -1, NULL, got_available, nm); + } +} + +static void +proxy_properties_changed (GDBusProxy *proxy, + GVariant *changed, + GVariant *invalidated, + GNetworkMonitorPortal *nm) +{ + if (!nm->priv->has_network) + return; + + if (nm->priv->version == 1) + { + GVariant *ret; + + ret = g_dbus_proxy_get_cached_property (proxy, "connectivity"); + if (ret) + { + GNetworkConnectivity connectivity = g_variant_get_uint32 (ret); + if (nm->priv->connectivity != connectivity) + { + nm->priv->connectivity = connectivity; + g_object_notify (G_OBJECT (nm), "connectivity"); + } + g_variant_unref (ret); + } + + ret = g_dbus_proxy_get_cached_property (proxy, "metered"); + if (ret) + { + gboolean metered = g_variant_get_boolean (ret); + if (nm->priv->metered != metered) + { + nm->priv->metered = metered; + g_object_notify (G_OBJECT (nm), "network-metered"); + } + g_variant_unref (ret); + } + + ret = g_dbus_proxy_get_cached_property (proxy, "available"); + if (ret) + { + gboolean available = g_variant_get_boolean (ret); + if (nm->priv->available != available) + { + nm->priv->available = available; + g_object_notify (G_OBJECT (nm), "network-available"); + g_signal_emit_by_name (nm, "network-changed", available); + } + g_variant_unref (ret); + } + } +} + static gboolean g_network_monitor_portal_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (initable); - GXdpNetworkMonitor *proxy; + GDBusProxy *proxy; gchar *name_owner = NULL; + int version; + GVariant *ret; + + nm->priv->available = FALSE; + nm->priv->metered = FALSE; + nm->priv->connectivity = G_NETWORK_CONNECTIVITY_LOCAL; if (!glib_should_use_portal ()) { @@ -120,17 +279,19 @@ g_network_monitor_portal_initable_init (GInitable *initable, return FALSE; } - proxy = gxdp_network_monitor_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START - | G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop", - cancellable, - error); + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START + | G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, + NULL, + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.NetworkMonitor", + cancellable, + error); if (!proxy) return FALSE; - name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy)); + name_owner = g_dbus_proxy_get_name_owner (proxy); if (!name_owner) { @@ -144,9 +305,26 @@ g_network_monitor_portal_initable_init (GInitable *initable, g_free (name_owner); - g_signal_connect (proxy, "changed", G_CALLBACK (proxy_changed), nm); + ret = g_dbus_proxy_get_cached_property (proxy, "version"); + g_variant_get (ret, "u", &version); + g_variant_unref (ret); + + if (version != 1 && version != 2) + { + g_object_unref (proxy); + g_set_error (error, + G_DBUS_ERROR, + G_DBUS_ERROR_NAME_HAS_NO_OWNER, + "NetworkMonitor portal unsupported version: %d", version); + return FALSE; + } + + g_signal_connect (proxy, "g-signal", G_CALLBACK (proxy_signal), nm); + g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (proxy_properties_changed), nm); + nm->priv->proxy = proxy; - nm->priv->network_available = glib_network_available_in_sandbox (); + nm->priv->has_network = glib_network_available_in_sandbox (); + nm->priv->version = version; return initable_parent_iface->init (initable, cancellable, error); } diff --git a/gio/gnextstepsettingsbackend.c b/gio/gnextstepsettingsbackend.c deleted file mode 100644 index 44ea845d8..000000000 --- a/gio/gnextstepsettingsbackend.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright © 2011 William Hua - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - * - * Author: William Hua - */ - -#include "config.h" - -#include "gsettingsbackendinternal.h" -#include "gsimplepermission.h" -#include "giomodule.h" - -#import - -GType g_nextstep_settings_backend_get_type (void); - -#define G_NEXTSTEP_SETTINGS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), g_nextstep_settings_backend_get_type (), GNextstepSettingsBackend)) - -typedef struct _GNextstepSettingsBackend GNextstepSettingsBackend; -typedef GSettingsBackendClass GNextstepSettingsBackendClass; - -struct _GNextstepSettingsBackend -{ - GSettingsBackend parent_instance; - - /*< private >*/ - NSUserDefaults *user_defaults; - GMutex mutex; -}; - -G_DEFINE_TYPE_WITH_CODE (GNextstepSettingsBackend, - g_nextstep_settings_backend, - G_TYPE_SETTINGS_BACKEND, - g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, - g_define_type_id, "nextstep", 90)); - -static void g_nextstep_settings_backend_finalize (GObject *backend); - -static GVariant * g_nextstep_settings_backend_read (GSettingsBackend *backend, - const gchar *key, - const GVariantType *expected_type, - gboolean default_value); - -static gboolean g_nextstep_settings_backend_get_writable (GSettingsBackend *backend, - const gchar *key); - -static gboolean g_nextstep_settings_backend_write (GSettingsBackend *backend, - const gchar *key, - GVariant *value, - gpointer origin_tag); - -static gboolean g_nextstep_settings_backend_write_tree (GSettingsBackend *backend, - GTree *tree, - gpointer origin_tag); - -static void g_nextstep_settings_backend_reset (GSettingsBackend *backend, - const gchar *key, - gpointer origin_tag); - -static void g_nextstep_settings_backend_subscribe (GSettingsBackend *backend, - const gchar *name); - -static void g_nextstep_settings_backend_unsubscribe (GSettingsBackend *backend, - const gchar *name); - -static void g_nextstep_settings_backend_sync (GSettingsBackend *backend); - -static GPermission * g_nextstep_settings_backend_get_permission (GSettingsBackend *backend, - const gchar *path); - -static gboolean g_nextstep_settings_backend_write_pair (gpointer name, - gpointer value, - gpointer data); - -static GVariant * g_nextstep_settings_backend_get_g_variant (id object, - const GVariantType *type); - -static id g_nextstep_settings_backend_get_ns_object (GVariant *variant); - -static void -g_nextstep_settings_backend_class_init (GNextstepSettingsBackendClass *class) -{ - G_OBJECT_CLASS (class)->finalize = g_nextstep_settings_backend_finalize; - class->read = g_nextstep_settings_backend_read; - class->get_writable = g_nextstep_settings_backend_get_writable; - class->write = g_nextstep_settings_backend_write; - class->write_tree = g_nextstep_settings_backend_write_tree; - class->reset = g_nextstep_settings_backend_reset; - class->subscribe = g_nextstep_settings_backend_subscribe; - class->unsubscribe = g_nextstep_settings_backend_unsubscribe; - class->sync = g_nextstep_settings_backend_sync; - class->get_permission = g_nextstep_settings_backend_get_permission; -} - -static void -g_nextstep_settings_backend_init (GNextstepSettingsBackend *self) -{ - NSAutoreleasePool *pool; - - pool = [[NSAutoreleasePool alloc] init]; - - self->user_defaults = [[NSUserDefaults standardUserDefaults] retain]; - - g_mutex_init (&self->mutex); - - [pool drain]; -} - -static void -g_nextstep_settings_backend_finalize (GObject *self) -{ - GNextstepSettingsBackend *backend = G_NEXTSTEP_SETTINGS_BACKEND (self); - NSAutoreleasePool *pool; - - pool = [[NSAutoreleasePool alloc] init]; - - g_mutex_clear (&backend->mutex); - - [backend->user_defaults release]; - - [pool drain]; - - G_OBJECT_CLASS (g_nextstep_settings_backend_parent_class)->finalize (self); -} - -static GVariant * -g_nextstep_settings_backend_read (GSettingsBackend *backend, - const gchar *key, - const GVariantType *expected_type, - gboolean default_value) -{ - GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); - NSAutoreleasePool *pool; - NSString *name; - id value; - GVariant *variant; - - if (default_value) - return NULL; - - pool = [[NSAutoreleasePool alloc] init]; - name = [NSString stringWithUTF8String:key]; - - g_mutex_lock (&self->mutex); - value = [self->user_defaults objectForKey:name]; - g_mutex_unlock (&self->mutex); - - variant = g_nextstep_settings_backend_get_g_variant (value, expected_type); - - [pool drain]; - - return variant; -} - -static gboolean -g_nextstep_settings_backend_get_writable (GSettingsBackend *backend, - const gchar *key) -{ - return TRUE; -} - -static gboolean -g_nextstep_settings_backend_write (GSettingsBackend *backend, - const gchar *key, - GVariant *value, - gpointer origin_tag) -{ - GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); - NSAutoreleasePool *pool; - - pool = [[NSAutoreleasePool alloc] init]; - - g_mutex_lock (&self->mutex); - g_nextstep_settings_backend_write_pair ((gpointer) key, value, self); - g_mutex_unlock (&self->mutex); - - g_settings_backend_changed (backend, key, origin_tag); - - [pool drain]; - - return TRUE; -} - -static gboolean -g_nextstep_settings_backend_write_tree (GSettingsBackend *backend, - GTree *tree, - gpointer origin_tag) -{ - GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); - NSAutoreleasePool *pool; - - pool = [[NSAutoreleasePool alloc] init]; - - g_mutex_lock (&self->mutex); - g_tree_foreach (tree, g_nextstep_settings_backend_write_pair, self); - g_mutex_unlock (&self->mutex); - g_settings_backend_changed_tree (backend, tree, origin_tag); - - [pool drain]; - - return TRUE; -} - -static void -g_nextstep_settings_backend_reset (GSettingsBackend *backend, - const gchar *key, - gpointer origin_tag) -{ - GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); - NSAutoreleasePool *pool; - NSString *name; - - pool = [[NSAutoreleasePool alloc] init]; - name = [NSString stringWithUTF8String:key]; - - g_mutex_lock (&self->mutex); - [self->user_defaults removeObjectForKey:name]; - g_mutex_unlock (&self->mutex); - - g_settings_backend_changed (backend, key, origin_tag); - - [pool drain]; -} - -static void -g_nextstep_settings_backend_subscribe (GSettingsBackend *backend, - const gchar *name) -{ -} - -static void -g_nextstep_settings_backend_unsubscribe (GSettingsBackend *backend, - const gchar *name) -{ -} - -static void -g_nextstep_settings_backend_sync (GSettingsBackend *backend) -{ - GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); - NSAutoreleasePool *pool; - - pool = [[NSAutoreleasePool alloc] init]; - - g_mutex_lock (&self->mutex); - [self->user_defaults synchronize]; - g_mutex_unlock (&self->mutex); - - [pool drain]; -} - -static GPermission * -g_nextstep_settings_backend_get_permission (GSettingsBackend *backend, - const gchar *path) -{ - return g_simple_permission_new (TRUE); -} - -static gboolean -g_nextstep_settings_backend_write_pair (gpointer name, - gpointer value, - gpointer data) -{ - GNextstepSettingsBackend *backend = G_NEXTSTEP_SETTINGS_BACKEND (data); - NSString *key; - id object; - - key = [NSString stringWithUTF8String:name]; - object = g_nextstep_settings_backend_get_ns_object (value); - - [backend->user_defaults setObject:object forKey:key]; - - return FALSE; -} - -static GVariant * -g_nextstep_settings_backend_get_g_variant (id object, - const GVariantType *type) -{ - if ([object isKindOfClass:[NSData class]]) - return g_variant_parse (type, [[[[NSString alloc] initWithData:object encoding:NSUTF8StringEncoding] autorelease] UTF8String], NULL, NULL, NULL); - else if ([object isKindOfClass:[NSNumber class]]) - { - if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) - return g_variant_new_boolean ([object boolValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE)) - return g_variant_new_byte ([object unsignedCharValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16)) - return g_variant_new_int16 ([object shortValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16)) - return g_variant_new_uint16 ([object unsignedShortValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32)) - return g_variant_new_int32 ([object longValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32)) - return g_variant_new_uint32 ([object unsignedLongValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64)) - return g_variant_new_int64 ([object longLongValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64)) - return g_variant_new_uint64 ([object unsignedLongLongValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE)) - return g_variant_new_handle ([object longValue]); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE)) - return g_variant_new_double ([object doubleValue]); - } - else if ([object isKindOfClass:[NSString class]]) - { - const char *string; - - string = [object UTF8String]; - - if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) - return g_variant_new_string (string); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH)) - return g_variant_is_object_path (string) ? - g_variant_new_object_path (string) : NULL; - else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE)) - return g_variant_is_signature (string) ? - g_variant_new_signature (string) : NULL; - } - else if ([object isKindOfClass:[NSDictionary class]]) - { - if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE ("a{s*}"))) - { - const GVariantType *value_type; - GVariantBuilder builder; - NSString *key; - - value_type = g_variant_type_value (g_variant_type_element (type)); - - g_variant_builder_init (&builder, type); - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - for(key in object) -#else - NSEnumerator *enumerator = [object objectEnumerator]; - while((key = [enumerator nextObject])) -#endif - { - GVariant *name; - id value; - GVariant *variant; - GVariant *entry; - - name = g_variant_new_string ([key UTF8String]); - value = [object objectForKey:key]; - variant = g_nextstep_settings_backend_get_g_variant (value, value_type); - - if (variant == NULL) - { - g_variant_builder_clear (&builder); - - return NULL; - } - - entry = g_variant_new_dict_entry (name, variant); - g_variant_builder_add_value (&builder, entry); - } - - return g_variant_builder_end (&builder); - } - } - else if ([object isKindOfClass:[NSArray class]]) - { - if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_ARRAY)) - { - const GVariantType *value_type; - GVariantBuilder builder; - id value; - - value_type = g_variant_type_element (type); - g_variant_builder_init (&builder, type); - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - for(value in object) -#else - NSEnumerator *enumerator = [object objectEnumerator]; - while((value = [enumerator nextObject])) -#endif - { - GVariant *variant = g_nextstep_settings_backend_get_g_variant (value, value_type); - - if (variant == NULL) - { - g_variant_builder_clear (&builder); - - return NULL; - } - - g_variant_builder_add_value (&builder, variant); - } - - return g_variant_builder_end (&builder); - } - } - - return NULL; -} - -static id -g_nextstep_settings_backend_get_ns_object (GVariant *variant) -{ - if (variant == NULL) - return nil; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) - return [NSNumber numberWithBool:g_variant_get_boolean (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE)) - return [NSNumber numberWithUnsignedChar:g_variant_get_byte (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)) - return [NSNumber numberWithShort:g_variant_get_int16 (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16)) - return [NSNumber numberWithUnsignedShort:g_variant_get_uint16 (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)) - return [NSNumber numberWithLong:g_variant_get_int32 (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) - return [NSNumber numberWithUnsignedLong:g_variant_get_uint32 (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)) - return [NSNumber numberWithLongLong:g_variant_get_int64 (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64)) - return [NSNumber numberWithUnsignedLongLong:g_variant_get_uint64 (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE)) - return [NSNumber numberWithLong:g_variant_get_handle (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE)) - return [NSNumber numberWithDouble:g_variant_get_double (variant)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) - return [NSString stringWithUTF8String:g_variant_get_string (variant, NULL)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH)) - return [NSString stringWithUTF8String:g_variant_get_string (variant, NULL)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE)) - return [NSString stringWithUTF8String:g_variant_get_string (variant, NULL)]; - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{s*}"))) - { - NSMutableDictionary *dictionary; - GVariantIter iter; - GVariant *name; - GVariant *value; - - dictionary = [NSMutableDictionary dictionaryWithCapacity:g_variant_iter_init (&iter, variant)]; - - while (g_variant_iter_loop (&iter, "{s*}", &name, &value)) - { - NSString *key; - id object; - - key = [NSString stringWithUTF8String:g_variant_get_string (name, NULL)]; - object = g_nextstep_settings_backend_get_ns_object (value); - - [dictionary setObject:object forKey:key]; - } - - return dictionary; - } - else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_ARRAY)) - { - NSMutableArray *array; - GVariantIter iter; - GVariant *value; - - array = [NSMutableArray arrayWithCapacity:g_variant_iter_init (&iter, variant)]; - - while ((value = g_variant_iter_next_value (&iter)) != NULL) - [array addObject:g_nextstep_settings_backend_get_ns_object (value)]; - - return array; - } - else - return [[NSString stringWithUTF8String:g_variant_print (variant, TRUE)] dataUsingEncoding:NSUTF8StringEncoding]; -} diff --git a/gio/gnextstepsettingsbackend.m b/gio/gnextstepsettingsbackend.m new file mode 100644 index 000000000..44ea845d8 --- /dev/null +++ b/gio/gnextstepsettingsbackend.m @@ -0,0 +1,480 @@ +/* + * Copyright © 2011 William Hua + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: William Hua + */ + +#include "config.h" + +#include "gsettingsbackendinternal.h" +#include "gsimplepermission.h" +#include "giomodule.h" + +#import + +GType g_nextstep_settings_backend_get_type (void); + +#define G_NEXTSTEP_SETTINGS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), g_nextstep_settings_backend_get_type (), GNextstepSettingsBackend)) + +typedef struct _GNextstepSettingsBackend GNextstepSettingsBackend; +typedef GSettingsBackendClass GNextstepSettingsBackendClass; + +struct _GNextstepSettingsBackend +{ + GSettingsBackend parent_instance; + + /*< private >*/ + NSUserDefaults *user_defaults; + GMutex mutex; +}; + +G_DEFINE_TYPE_WITH_CODE (GNextstepSettingsBackend, + g_nextstep_settings_backend, + G_TYPE_SETTINGS_BACKEND, + g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, + g_define_type_id, "nextstep", 90)); + +static void g_nextstep_settings_backend_finalize (GObject *backend); + +static GVariant * g_nextstep_settings_backend_read (GSettingsBackend *backend, + const gchar *key, + const GVariantType *expected_type, + gboolean default_value); + +static gboolean g_nextstep_settings_backend_get_writable (GSettingsBackend *backend, + const gchar *key); + +static gboolean g_nextstep_settings_backend_write (GSettingsBackend *backend, + const gchar *key, + GVariant *value, + gpointer origin_tag); + +static gboolean g_nextstep_settings_backend_write_tree (GSettingsBackend *backend, + GTree *tree, + gpointer origin_tag); + +static void g_nextstep_settings_backend_reset (GSettingsBackend *backend, + const gchar *key, + gpointer origin_tag); + +static void g_nextstep_settings_backend_subscribe (GSettingsBackend *backend, + const gchar *name); + +static void g_nextstep_settings_backend_unsubscribe (GSettingsBackend *backend, + const gchar *name); + +static void g_nextstep_settings_backend_sync (GSettingsBackend *backend); + +static GPermission * g_nextstep_settings_backend_get_permission (GSettingsBackend *backend, + const gchar *path); + +static gboolean g_nextstep_settings_backend_write_pair (gpointer name, + gpointer value, + gpointer data); + +static GVariant * g_nextstep_settings_backend_get_g_variant (id object, + const GVariantType *type); + +static id g_nextstep_settings_backend_get_ns_object (GVariant *variant); + +static void +g_nextstep_settings_backend_class_init (GNextstepSettingsBackendClass *class) +{ + G_OBJECT_CLASS (class)->finalize = g_nextstep_settings_backend_finalize; + class->read = g_nextstep_settings_backend_read; + class->get_writable = g_nextstep_settings_backend_get_writable; + class->write = g_nextstep_settings_backend_write; + class->write_tree = g_nextstep_settings_backend_write_tree; + class->reset = g_nextstep_settings_backend_reset; + class->subscribe = g_nextstep_settings_backend_subscribe; + class->unsubscribe = g_nextstep_settings_backend_unsubscribe; + class->sync = g_nextstep_settings_backend_sync; + class->get_permission = g_nextstep_settings_backend_get_permission; +} + +static void +g_nextstep_settings_backend_init (GNextstepSettingsBackend *self) +{ + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + self->user_defaults = [[NSUserDefaults standardUserDefaults] retain]; + + g_mutex_init (&self->mutex); + + [pool drain]; +} + +static void +g_nextstep_settings_backend_finalize (GObject *self) +{ + GNextstepSettingsBackend *backend = G_NEXTSTEP_SETTINGS_BACKEND (self); + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + g_mutex_clear (&backend->mutex); + + [backend->user_defaults release]; + + [pool drain]; + + G_OBJECT_CLASS (g_nextstep_settings_backend_parent_class)->finalize (self); +} + +static GVariant * +g_nextstep_settings_backend_read (GSettingsBackend *backend, + const gchar *key, + const GVariantType *expected_type, + gboolean default_value) +{ + GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); + NSAutoreleasePool *pool; + NSString *name; + id value; + GVariant *variant; + + if (default_value) + return NULL; + + pool = [[NSAutoreleasePool alloc] init]; + name = [NSString stringWithUTF8String:key]; + + g_mutex_lock (&self->mutex); + value = [self->user_defaults objectForKey:name]; + g_mutex_unlock (&self->mutex); + + variant = g_nextstep_settings_backend_get_g_variant (value, expected_type); + + [pool drain]; + + return variant; +} + +static gboolean +g_nextstep_settings_backend_get_writable (GSettingsBackend *backend, + const gchar *key) +{ + return TRUE; +} + +static gboolean +g_nextstep_settings_backend_write (GSettingsBackend *backend, + const gchar *key, + GVariant *value, + gpointer origin_tag) +{ + GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + g_mutex_lock (&self->mutex); + g_nextstep_settings_backend_write_pair ((gpointer) key, value, self); + g_mutex_unlock (&self->mutex); + + g_settings_backend_changed (backend, key, origin_tag); + + [pool drain]; + + return TRUE; +} + +static gboolean +g_nextstep_settings_backend_write_tree (GSettingsBackend *backend, + GTree *tree, + gpointer origin_tag) +{ + GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + g_mutex_lock (&self->mutex); + g_tree_foreach (tree, g_nextstep_settings_backend_write_pair, self); + g_mutex_unlock (&self->mutex); + g_settings_backend_changed_tree (backend, tree, origin_tag); + + [pool drain]; + + return TRUE; +} + +static void +g_nextstep_settings_backend_reset (GSettingsBackend *backend, + const gchar *key, + gpointer origin_tag) +{ + GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); + NSAutoreleasePool *pool; + NSString *name; + + pool = [[NSAutoreleasePool alloc] init]; + name = [NSString stringWithUTF8String:key]; + + g_mutex_lock (&self->mutex); + [self->user_defaults removeObjectForKey:name]; + g_mutex_unlock (&self->mutex); + + g_settings_backend_changed (backend, key, origin_tag); + + [pool drain]; +} + +static void +g_nextstep_settings_backend_subscribe (GSettingsBackend *backend, + const gchar *name) +{ +} + +static void +g_nextstep_settings_backend_unsubscribe (GSettingsBackend *backend, + const gchar *name) +{ +} + +static void +g_nextstep_settings_backend_sync (GSettingsBackend *backend) +{ + GNextstepSettingsBackend *self = G_NEXTSTEP_SETTINGS_BACKEND (backend); + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + g_mutex_lock (&self->mutex); + [self->user_defaults synchronize]; + g_mutex_unlock (&self->mutex); + + [pool drain]; +} + +static GPermission * +g_nextstep_settings_backend_get_permission (GSettingsBackend *backend, + const gchar *path) +{ + return g_simple_permission_new (TRUE); +} + +static gboolean +g_nextstep_settings_backend_write_pair (gpointer name, + gpointer value, + gpointer data) +{ + GNextstepSettingsBackend *backend = G_NEXTSTEP_SETTINGS_BACKEND (data); + NSString *key; + id object; + + key = [NSString stringWithUTF8String:name]; + object = g_nextstep_settings_backend_get_ns_object (value); + + [backend->user_defaults setObject:object forKey:key]; + + return FALSE; +} + +static GVariant * +g_nextstep_settings_backend_get_g_variant (id object, + const GVariantType *type) +{ + if ([object isKindOfClass:[NSData class]]) + return g_variant_parse (type, [[[[NSString alloc] initWithData:object encoding:NSUTF8StringEncoding] autorelease] UTF8String], NULL, NULL, NULL); + else if ([object isKindOfClass:[NSNumber class]]) + { + if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) + return g_variant_new_boolean ([object boolValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE)) + return g_variant_new_byte ([object unsignedCharValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16)) + return g_variant_new_int16 ([object shortValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16)) + return g_variant_new_uint16 ([object unsignedShortValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32)) + return g_variant_new_int32 ([object longValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32)) + return g_variant_new_uint32 ([object unsignedLongValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64)) + return g_variant_new_int64 ([object longLongValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64)) + return g_variant_new_uint64 ([object unsignedLongLongValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE)) + return g_variant_new_handle ([object longValue]); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE)) + return g_variant_new_double ([object doubleValue]); + } + else if ([object isKindOfClass:[NSString class]]) + { + const char *string; + + string = [object UTF8String]; + + if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) + return g_variant_new_string (string); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH)) + return g_variant_is_object_path (string) ? + g_variant_new_object_path (string) : NULL; + else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE)) + return g_variant_is_signature (string) ? + g_variant_new_signature (string) : NULL; + } + else if ([object isKindOfClass:[NSDictionary class]]) + { + if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE ("a{s*}"))) + { + const GVariantType *value_type; + GVariantBuilder builder; + NSString *key; + + value_type = g_variant_type_value (g_variant_type_element (type)); + + g_variant_builder_init (&builder, type); + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + for(key in object) +#else + NSEnumerator *enumerator = [object objectEnumerator]; + while((key = [enumerator nextObject])) +#endif + { + GVariant *name; + id value; + GVariant *variant; + GVariant *entry; + + name = g_variant_new_string ([key UTF8String]); + value = [object objectForKey:key]; + variant = g_nextstep_settings_backend_get_g_variant (value, value_type); + + if (variant == NULL) + { + g_variant_builder_clear (&builder); + + return NULL; + } + + entry = g_variant_new_dict_entry (name, variant); + g_variant_builder_add_value (&builder, entry); + } + + return g_variant_builder_end (&builder); + } + } + else if ([object isKindOfClass:[NSArray class]]) + { + if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_ARRAY)) + { + const GVariantType *value_type; + GVariantBuilder builder; + id value; + + value_type = g_variant_type_element (type); + g_variant_builder_init (&builder, type); + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + for(value in object) +#else + NSEnumerator *enumerator = [object objectEnumerator]; + while((value = [enumerator nextObject])) +#endif + { + GVariant *variant = g_nextstep_settings_backend_get_g_variant (value, value_type); + + if (variant == NULL) + { + g_variant_builder_clear (&builder); + + return NULL; + } + + g_variant_builder_add_value (&builder, variant); + } + + return g_variant_builder_end (&builder); + } + } + + return NULL; +} + +static id +g_nextstep_settings_backend_get_ns_object (GVariant *variant) +{ + if (variant == NULL) + return nil; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) + return [NSNumber numberWithBool:g_variant_get_boolean (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE)) + return [NSNumber numberWithUnsignedChar:g_variant_get_byte (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)) + return [NSNumber numberWithShort:g_variant_get_int16 (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16)) + return [NSNumber numberWithUnsignedShort:g_variant_get_uint16 (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)) + return [NSNumber numberWithLong:g_variant_get_int32 (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) + return [NSNumber numberWithUnsignedLong:g_variant_get_uint32 (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)) + return [NSNumber numberWithLongLong:g_variant_get_int64 (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64)) + return [NSNumber numberWithUnsignedLongLong:g_variant_get_uint64 (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE)) + return [NSNumber numberWithLong:g_variant_get_handle (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE)) + return [NSNumber numberWithDouble:g_variant_get_double (variant)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) + return [NSString stringWithUTF8String:g_variant_get_string (variant, NULL)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH)) + return [NSString stringWithUTF8String:g_variant_get_string (variant, NULL)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE)) + return [NSString stringWithUTF8String:g_variant_get_string (variant, NULL)]; + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{s*}"))) + { + NSMutableDictionary *dictionary; + GVariantIter iter; + GVariant *name; + GVariant *value; + + dictionary = [NSMutableDictionary dictionaryWithCapacity:g_variant_iter_init (&iter, variant)]; + + while (g_variant_iter_loop (&iter, "{s*}", &name, &value)) + { + NSString *key; + id object; + + key = [NSString stringWithUTF8String:g_variant_get_string (name, NULL)]; + object = g_nextstep_settings_backend_get_ns_object (value); + + [dictionary setObject:object forKey:key]; + } + + return dictionary; + } + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_ARRAY)) + { + NSMutableArray *array; + GVariantIter iter; + GVariant *value; + + array = [NSMutableArray arrayWithCapacity:g_variant_iter_init (&iter, variant)]; + + while ((value = g_variant_iter_next_value (&iter)) != NULL) + [array addObject:g_nextstep_settings_backend_get_ns_object (value)]; + + return array; + } + else + return [[NSString stringWithUTF8String:g_variant_print (variant, TRUE)] dataUsingEncoding:NSUTF8StringEncoding]; +} diff --git a/gio/gosxappinfo.c b/gio/gosxappinfo.c deleted file mode 100644 index 463b2da3c..000000000 --- a/gio/gosxappinfo.c +++ /dev/null @@ -1,759 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2014 Patrick Griffis - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - */ - -#include "config.h" - -#include "gappinfo.h" -#include "gosxappinfo.h" -#include "gcontenttype.h" -#include "gfile.h" -#include "gfileicon.h" -#include "gioerror.h" - -#import -#import -#import - -/** - * SECTION:gosxappinfo - * @title: GOsxAppInfo - * @short_description: Application information from NSBundles - * @include: gio/gosxappinfo.h - * - * #GOsxAppInfo is an implementation of #GAppInfo based on NSBundle information. - * - * Note that `` is unique to OSX. - */ - -static void g_osx_app_info_iface_init (GAppInfoIface *iface); -static const char *g_osx_app_info_get_id (GAppInfo *appinfo); - -/** - * GOsxAppInfo: - * - * Information about an installed application from a NSBundle. - */ -struct _GOsxAppInfo -{ - GObject parent_instance; - - NSBundle *bundle; - - /* Note that these are all NULL until first call - * to getter at which point they are cached here - */ - gchar *id; - gchar *name; - gchar *executable; - gchar *filename; - GIcon *icon; -}; - -G_DEFINE_TYPE_WITH_CODE (GOsxAppInfo, g_osx_app_info, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_APP_INFO, g_osx_app_info_iface_init)) - -static GOsxAppInfo * -g_osx_app_info_new (NSBundle *bundle) -{ - GOsxAppInfo *info = g_object_new (G_TYPE_OSX_APP_INFO, NULL); - - info->bundle = [bundle retain]; - - return info; -} - -static void -g_osx_app_info_init (GOsxAppInfo *info) -{ -} - -static void -g_osx_app_info_finalize (GObject *object) -{ - GOsxAppInfo *info = G_OSX_APP_INFO (object); - - g_free (info->id); - g_free (info->name); - g_free (info->executable); - g_free (info->filename); - g_clear_object (&info->icon); - - [info->bundle release]; - - G_OBJECT_CLASS (g_osx_app_info_parent_class)->finalize (object); -} - -static void -g_osx_app_info_class_init (GOsxAppInfoClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = g_osx_app_info_finalize; -} - -static GAppInfo * -g_osx_app_info_dup (GAppInfo *appinfo) -{ - GOsxAppInfo *info; - GOsxAppInfo *new_info; - - g_return_val_if_fail (appinfo != NULL, NULL); - - info = G_OSX_APP_INFO (appinfo); - new_info = g_osx_app_info_new ([info->bundle retain]); - - return G_APP_INFO (new_info); -} - -static gboolean -g_osx_app_info_equal (GAppInfo *appinfo1, - GAppInfo *appinfo2) -{ - const gchar *str1, *str2; - - g_return_val_if_fail (appinfo1 != NULL, FALSE); - g_return_val_if_fail (appinfo2 != NULL, FALSE); - - str1 = g_osx_app_info_get_id (appinfo1); - str2 = g_osx_app_info_get_id (appinfo2); - - return (g_strcmp0 (str1, str2) == 0); -} - -/*< internal > - * get_bundle_string_value: - * @bundle: a #NSBundle - * @key: an #NSString key - * - * Returns a value from a bundles info.plist file. - * It will be utf8 encoded and it must be g_free()'d. - * - */ -static gchar * -get_bundle_string_value (NSBundle *bundle, - NSString *key) -{ - NSString *value; - const gchar *cvalue; - gchar *ret; - - g_return_val_if_fail (bundle != NULL, NULL); - - value = (NSString *)[bundle objectForInfoDictionaryKey: key]; - if (!value) - return NULL; - - cvalue = [value cStringUsingEncoding: NSUTF8StringEncoding]; - ret = g_strdup (cvalue); - - return ret; -} - -static CFStringRef -create_cfstring_from_cstr (const gchar *cstr) -{ - return CFStringCreateWithCString (NULL, cstr, kCFStringEncodingUTF8); -} - -#ifdef G_ENABLE_DEBUG -static gchar * -create_cstr_from_cfstring (CFStringRef str) -{ - g_return_val_if_fail (str != NULL, NULL); - - CFIndex length = CFStringGetLength (str); - CFIndex maxlen = CFStringGetMaximumSizeForEncoding (length, kCFStringEncodingUTF8); - gchar *buffer = g_malloc (maxlen + 1); - Boolean success = CFStringGetCString (str, (char *) buffer, maxlen, - kCFStringEncodingUTF8); - if (success) - return buffer; - else - { - g_free (buffer); - return NULL; - } -} -#endif - -static char * -url_escape_hostname (const char *url) -{ - char *host_start, *ret; - - host_start = strstr (url, "://"); - if (host_start != NULL) - { - char *host_end, *scheme, *host, *hostname; - - scheme = g_strndup (url, host_start - url); - host_start += 3; - host_end = strchr (host_start, '/'); - - if (host_end != NULL) - host = g_strndup (host_start, host_end - host_start); - else - host = g_strdup (host_start); - - hostname = g_hostname_to_ascii (host); - - ret = g_strconcat (scheme, "://", hostname, host_end, NULL); - - g_free (scheme); - g_free (host); - g_free (hostname); - - return ret; - } - - return g_strdup (url); -} - -static CFURLRef -create_url_from_cstr (gchar *cstr, - gboolean is_file) -{ - gchar *puny_cstr; - CFStringRef str; - CFURLRef url; - - puny_cstr = url_escape_hostname (cstr); - str = CFStringCreateWithCString (NULL, puny_cstr ? puny_cstr : cstr, kCFStringEncodingUTF8); - - if (is_file) - url = CFURLCreateWithFileSystemPath (NULL, str, kCFURLPOSIXPathStyle, FALSE); - else - url = CFURLCreateWithString (NULL, str, NULL); - - if (!url) - g_debug ("Creating CFURL from %s %s failed!", cstr, is_file ? "file" : "uri"); - - g_free (puny_cstr); - CFRelease(str); - return url; -} - -static CFArrayRef -create_url_list_from_glist (GList *uris, - gboolean are_files) -{ - GList *lst; - int len = g_list_length (uris); - CFMutableArrayRef array; - - if (!len) - return NULL; - - array = CFArrayCreateMutable (NULL, len, &kCFTypeArrayCallBacks); - if (!array) - return NULL; - - for (lst = uris; lst != NULL && lst->data; lst = lst->next) - { - CFURLRef url = create_url_from_cstr ((char*)lst->data, are_files); - if (url) - CFArrayAppendValue (array, url); - } - - return (CFArrayRef)array; -} - -static LSLaunchURLSpec * -create_urlspec_for_appinfo (GOsxAppInfo *info, - GList *uris, - gboolean are_files) -{ - LSLaunchURLSpec *urlspec = g_new0 (LSLaunchURLSpec, 1); - gchar *app_cstr = g_osx_app_info_get_filename (info); - - /* Strip file:// from app url but ensure filesystem url */ - urlspec->appURL = create_url_from_cstr (app_cstr + 7, TRUE); - urlspec->launchFlags = kLSLaunchDefaults; - urlspec->itemURLs = create_url_list_from_glist (uris, are_files); - - return urlspec; -} - -static void -free_urlspec (LSLaunchURLSpec *urlspec) -{ - if (urlspec->itemURLs) - { - CFArrayRemoveAllValues ((CFMutableArrayRef)urlspec->itemURLs); - CFRelease (urlspec->itemURLs); - } - CFRelease (urlspec->appURL); - g_free (urlspec); -} - -static NSBundle * -get_bundle_for_url (CFURLRef app_url) -{ - NSBundle *bundle = [NSBundle bundleWithURL: (NSURL*)app_url]; - - if (!bundle) - { - g_debug ("Bundle not found for url."); - return NULL; - } - - return bundle; -} - -static NSBundle * -get_bundle_for_id (CFStringRef bundle_id) -{ - CFURLRef app_url; - NSBundle *bundle; - -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER - CFArrayRef urls = LSCopyApplicationURLsForBundleIdentifier (bundle_id, NULL); - if (urls) - { - /* TODO: if there's multiple, we should perhaps prefer one thats in $HOME, - * instead of just always picking the first. - */ - app_url = CFArrayGetValueAtIndex (urls, 0); - CFRetain (app_url); - CFRelease (urls); - } - else -#else - if (LSFindApplicationForInfo (kLSUnknownCreator, bundle_id, NULL, NULL, &app_url) == kLSApplicationNotFoundErr) -#endif - { -#ifdef G_ENABLE_DEBUG /* This can fail often, no reason to alloc strings */ - gchar *id_str = create_cstr_from_cfstring (bundle_id); - if (id_str) - { - g_debug ("Application not found for id \"%s\".", id_str); - g_free (id_str); - } - else - g_debug ("Application not found for unconvertable bundle id."); -#endif - return NULL; - } - - bundle = get_bundle_for_url (app_url); - CFRelease (app_url); - return bundle; -} - -static const char * -g_osx_app_info_get_id (GAppInfo *appinfo) -{ - GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); - - if (!info->id) - info->id = get_bundle_string_value (info->bundle, @"CFBundleIdentifier"); - - return info->id; -} - -static const char * -g_osx_app_info_get_name (GAppInfo *appinfo) -{ - GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); - - if (!info->name) - info->name = get_bundle_string_value (info->bundle, @"CFBundleName"); - - return info->name; -} - -static const char * -g_osx_app_info_get_display_name (GAppInfo *appinfo) -{ - return g_osx_app_info_get_name (appinfo); -} - -static const char * -g_osx_app_info_get_description (GAppInfo *appinfo) -{ - /* Bundles do not contain descriptions */ - return NULL; -} - -static const char * -g_osx_app_info_get_executable (GAppInfo *appinfo) -{ - GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); - - if (!info->executable) - info->executable = get_bundle_string_value (info->bundle, @"CFBundleExecutable"); - - return info->executable; -} - -char * -g_osx_app_info_get_filename (GOsxAppInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - if (!info->filename) - { - info->filename = g_strconcat ("file://", [[info->bundle bundlePath] - cStringUsingEncoding: NSUTF8StringEncoding], - NULL); - } - - return info->filename; -} - -static const char * -g_osx_app_info_get_commandline (GAppInfo *appinfo) -{ - /* There isn't really a command line value */ - return NULL; -} - -static GIcon * -g_osx_app_info_get_icon (GAppInfo *appinfo) -{ - GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); - - if (!info->icon) - { - gchar *icon_name, *app_uri, *icon_uri; - GFile *file; - - icon_name = get_bundle_string_value (info->bundle, @"CFBundleIconFile"); - if (!icon_name) - return NULL; - - app_uri = g_osx_app_info_get_filename (info); - icon_uri = g_strconcat (app_uri + 7, "/Contents/Resources/", icon_name, - g_str_has_suffix (icon_name, ".icns") ? NULL : ".icns", NULL); - g_free (icon_name); - - file = g_file_new_for_path (icon_uri); - info->icon = g_file_icon_new (file); - g_object_unref (file); - g_free (icon_uri); - } - - return info->icon; -} - -static gboolean -g_osx_app_info_launch_internal (GAppInfo *appinfo, - GList *uris, - gboolean are_files, - GError **error) -{ - GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); - LSLaunchURLSpec *urlspec = create_urlspec_for_appinfo (info, uris, are_files); - gint ret, success = TRUE; - - if ((ret = LSOpenFromURLSpec (urlspec, NULL))) - { - /* TODO: Better error codes */ - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Opening application failed with code %d", ret); - success = FALSE; - } - - free_urlspec (urlspec); - return success; -} - -static gboolean -g_osx_app_info_supports_uris (GAppInfo *appinfo) -{ - return TRUE; -} - -static gboolean -g_osx_app_info_supports_files (GAppInfo *appinfo) -{ - return TRUE; -} - -static gboolean -g_osx_app_info_launch (GAppInfo *appinfo, - GList *files, - GAppLaunchContext *launch_context, - GError **error) -{ - return g_osx_app_info_launch_internal (appinfo, files, TRUE, error); -} - -static gboolean -g_osx_app_info_launch_uris (GAppInfo *appinfo, - GList *uris, - GAppLaunchContext *launch_context, - GError **error) -{ - return g_osx_app_info_launch_internal (appinfo, uris, FALSE, error); -} - -static gboolean -g_osx_app_info_should_show (GAppInfo *appinfo) -{ - /* Bundles don't have hidden attribute */ - return TRUE; -} - -static gboolean -g_osx_app_info_set_as_default_for_type (GAppInfo *appinfo, - const char *content_type, - GError **error) -{ - return FALSE; -} - -static const char ** -g_osx_app_info_get_supported_types (GAppInfo *appinfo) -{ - /* TODO: get CFBundleDocumentTypes */ - return NULL; -} - -static gboolean -g_osx_app_info_set_as_last_used_for_type (GAppInfo *appinfo, - const char *content_type, - GError **error) -{ - /* Not supported. */ - return FALSE; -} - -static gboolean -g_osx_app_info_can_delete (GAppInfo *appinfo) -{ - return FALSE; -} - -static void -g_osx_app_info_iface_init (GAppInfoIface *iface) -{ - iface->dup = g_osx_app_info_dup; - iface->equal = g_osx_app_info_equal; - - iface->get_id = g_osx_app_info_get_id; - iface->get_name = g_osx_app_info_get_name; - iface->get_display_name = g_osx_app_info_get_display_name; - iface->get_description = g_osx_app_info_get_description; - iface->get_executable = g_osx_app_info_get_executable; - iface->get_commandline = g_osx_app_info_get_commandline; - iface->get_icon = g_osx_app_info_get_icon; - iface->get_supported_types = g_osx_app_info_get_supported_types; - - iface->set_as_last_used_for_type = g_osx_app_info_set_as_last_used_for_type; - iface->set_as_default_for_type = g_osx_app_info_set_as_default_for_type; - - iface->launch = g_osx_app_info_launch; - iface->launch_uris = g_osx_app_info_launch_uris; - - iface->supports_uris = g_osx_app_info_supports_uris; - iface->supports_files = g_osx_app_info_supports_files; - iface->should_show = g_osx_app_info_should_show; - iface->can_delete = g_osx_app_info_can_delete; -} - -GAppInfo * -g_app_info_create_from_commandline (const char *commandline, - const char *application_name, - GAppInfoCreateFlags flags, - GError **error) -{ - return NULL; -} - -GList * -g_osx_app_info_get_all_for_scheme (const char *cscheme) -{ - CFArrayRef bundle_list; - CFStringRef scheme; - NSBundle *bundle; - GList *info_list = NULL; - gint i; - - scheme = create_cfstring_from_cstr (cscheme); - bundle_list = LSCopyAllHandlersForURLScheme (scheme); - CFRelease (scheme); - - if (!bundle_list) - return NULL; - - for (i = 0; i < CFArrayGetCount (bundle_list); i++) - { - CFStringRef bundle_id = CFArrayGetValueAtIndex (bundle_list, i); - GAppInfo *info; - - bundle = get_bundle_for_id (bundle_id); - - if (!bundle) - continue; - - info = G_APP_INFO (g_osx_app_info_new (bundle)); - info_list = g_list_append (info_list, info); - } - CFRelease (bundle_list); - return info_list; -} - -GList * -g_app_info_get_all_for_type (const char *content_type) -{ - gchar *mime_type; - CFArrayRef bundle_list; - CFStringRef type; - NSBundle *bundle; - GList *info_list = NULL; - gint i; - - mime_type = g_content_type_get_mime_type (content_type); - if (g_str_has_prefix (mime_type, "x-scheme-handler/")) - { - gchar *scheme = strchr (mime_type, '/') + 1; - GList *ret = g_osx_app_info_get_all_for_scheme (scheme); - - g_free (mime_type); - return ret; - } - g_free (mime_type); - - type = create_cfstring_from_cstr (content_type); - bundle_list = LSCopyAllRoleHandlersForContentType (type, kLSRolesAll); - CFRelease (type); - - if (!bundle_list) - return NULL; - - for (i = 0; i < CFArrayGetCount (bundle_list); i++) - { - CFStringRef bundle_id = CFArrayGetValueAtIndex (bundle_list, i); - GAppInfo *info; - - bundle = get_bundle_for_id (bundle_id); - - if (!bundle) - continue; - - info = G_APP_INFO (g_osx_app_info_new (bundle)); - info_list = g_list_append (info_list, info); - } - CFRelease (bundle_list); - return info_list; -} - -GList * -g_app_info_get_recommended_for_type (const char *content_type) -{ - return g_app_info_get_all_for_type (content_type); -} - -GList * -g_app_info_get_fallback_for_type (const char *content_type) -{ - return g_app_info_get_all_for_type (content_type); -} - -GAppInfo * -g_app_info_get_default_for_type (const char *content_type, - gboolean must_support_uris) -{ - gchar *mime_type; - CFStringRef type; - NSBundle *bundle; -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER - CFURLRef bundle_id; -#else - CFStringRef bundle_id; -#endif - - mime_type = g_content_type_get_mime_type (content_type); - if (g_str_has_prefix (mime_type, "x-scheme-handler/")) - { - gchar *scheme = strchr (mime_type, '/') + 1; - GAppInfo *ret = g_app_info_get_default_for_uri_scheme (scheme); - - g_free (mime_type); - return ret; - } - g_free (mime_type); - - type = create_cfstring_from_cstr (content_type); - -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER - bundle_id = LSCopyDefaultApplicationURLForContentType (type, kLSRolesAll, NULL); -#else - bundle_id = LSCopyDefaultRoleHandlerForContentType (type, kLSRolesAll); -#endif - CFRelease (type); - - if (!bundle_id) - { - g_warning ("No default handler found for content type '%s'.", content_type); - return NULL; - } - -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER - bundle = get_bundle_for_url (bundle_id); -#else - bundle = get_bundle_for_id (bundle_id); -#endif - CFRelease (bundle_id); - - if (!bundle) - return NULL; - - return G_APP_INFO (g_osx_app_info_new (bundle)); -} - -GAppInfo * -g_app_info_get_default_for_uri_scheme (const char *uri_scheme) -{ - CFStringRef scheme, bundle_id; - NSBundle *bundle; - - scheme = create_cfstring_from_cstr (uri_scheme); - bundle_id = LSCopyDefaultHandlerForURLScheme (scheme); - CFRelease (scheme); - - if (!bundle_id) - { - g_warning ("No default handler found for url scheme '%s'.", uri_scheme); - return NULL; - } - - bundle = get_bundle_for_id (bundle_id); - CFRelease (bundle_id); - - if (!bundle) - return NULL; - - return G_APP_INFO (g_osx_app_info_new (bundle)); -} - -GList * -g_app_info_get_all (void) -{ - /* There is no API for this afaict - * could manually do it... - */ - return NULL; -} - -void -g_app_info_reset_type_associations (const char *content_type) -{ -} diff --git a/gio/gosxappinfo.m b/gio/gosxappinfo.m new file mode 100644 index 000000000..463b2da3c --- /dev/null +++ b/gio/gosxappinfo.m @@ -0,0 +1,759 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2014 Patrick Griffis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + */ + +#include "config.h" + +#include "gappinfo.h" +#include "gosxappinfo.h" +#include "gcontenttype.h" +#include "gfile.h" +#include "gfileicon.h" +#include "gioerror.h" + +#import +#import +#import + +/** + * SECTION:gosxappinfo + * @title: GOsxAppInfo + * @short_description: Application information from NSBundles + * @include: gio/gosxappinfo.h + * + * #GOsxAppInfo is an implementation of #GAppInfo based on NSBundle information. + * + * Note that `` is unique to OSX. + */ + +static void g_osx_app_info_iface_init (GAppInfoIface *iface); +static const char *g_osx_app_info_get_id (GAppInfo *appinfo); + +/** + * GOsxAppInfo: + * + * Information about an installed application from a NSBundle. + */ +struct _GOsxAppInfo +{ + GObject parent_instance; + + NSBundle *bundle; + + /* Note that these are all NULL until first call + * to getter at which point they are cached here + */ + gchar *id; + gchar *name; + gchar *executable; + gchar *filename; + GIcon *icon; +}; + +G_DEFINE_TYPE_WITH_CODE (GOsxAppInfo, g_osx_app_info, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_APP_INFO, g_osx_app_info_iface_init)) + +static GOsxAppInfo * +g_osx_app_info_new (NSBundle *bundle) +{ + GOsxAppInfo *info = g_object_new (G_TYPE_OSX_APP_INFO, NULL); + + info->bundle = [bundle retain]; + + return info; +} + +static void +g_osx_app_info_init (GOsxAppInfo *info) +{ +} + +static void +g_osx_app_info_finalize (GObject *object) +{ + GOsxAppInfo *info = G_OSX_APP_INFO (object); + + g_free (info->id); + g_free (info->name); + g_free (info->executable); + g_free (info->filename); + g_clear_object (&info->icon); + + [info->bundle release]; + + G_OBJECT_CLASS (g_osx_app_info_parent_class)->finalize (object); +} + +static void +g_osx_app_info_class_init (GOsxAppInfoClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = g_osx_app_info_finalize; +} + +static GAppInfo * +g_osx_app_info_dup (GAppInfo *appinfo) +{ + GOsxAppInfo *info; + GOsxAppInfo *new_info; + + g_return_val_if_fail (appinfo != NULL, NULL); + + info = G_OSX_APP_INFO (appinfo); + new_info = g_osx_app_info_new ([info->bundle retain]); + + return G_APP_INFO (new_info); +} + +static gboolean +g_osx_app_info_equal (GAppInfo *appinfo1, + GAppInfo *appinfo2) +{ + const gchar *str1, *str2; + + g_return_val_if_fail (appinfo1 != NULL, FALSE); + g_return_val_if_fail (appinfo2 != NULL, FALSE); + + str1 = g_osx_app_info_get_id (appinfo1); + str2 = g_osx_app_info_get_id (appinfo2); + + return (g_strcmp0 (str1, str2) == 0); +} + +/*< internal > + * get_bundle_string_value: + * @bundle: a #NSBundle + * @key: an #NSString key + * + * Returns a value from a bundles info.plist file. + * It will be utf8 encoded and it must be g_free()'d. + * + */ +static gchar * +get_bundle_string_value (NSBundle *bundle, + NSString *key) +{ + NSString *value; + const gchar *cvalue; + gchar *ret; + + g_return_val_if_fail (bundle != NULL, NULL); + + value = (NSString *)[bundle objectForInfoDictionaryKey: key]; + if (!value) + return NULL; + + cvalue = [value cStringUsingEncoding: NSUTF8StringEncoding]; + ret = g_strdup (cvalue); + + return ret; +} + +static CFStringRef +create_cfstring_from_cstr (const gchar *cstr) +{ + return CFStringCreateWithCString (NULL, cstr, kCFStringEncodingUTF8); +} + +#ifdef G_ENABLE_DEBUG +static gchar * +create_cstr_from_cfstring (CFStringRef str) +{ + g_return_val_if_fail (str != NULL, NULL); + + CFIndex length = CFStringGetLength (str); + CFIndex maxlen = CFStringGetMaximumSizeForEncoding (length, kCFStringEncodingUTF8); + gchar *buffer = g_malloc (maxlen + 1); + Boolean success = CFStringGetCString (str, (char *) buffer, maxlen, + kCFStringEncodingUTF8); + if (success) + return buffer; + else + { + g_free (buffer); + return NULL; + } +} +#endif + +static char * +url_escape_hostname (const char *url) +{ + char *host_start, *ret; + + host_start = strstr (url, "://"); + if (host_start != NULL) + { + char *host_end, *scheme, *host, *hostname; + + scheme = g_strndup (url, host_start - url); + host_start += 3; + host_end = strchr (host_start, '/'); + + if (host_end != NULL) + host = g_strndup (host_start, host_end - host_start); + else + host = g_strdup (host_start); + + hostname = g_hostname_to_ascii (host); + + ret = g_strconcat (scheme, "://", hostname, host_end, NULL); + + g_free (scheme); + g_free (host); + g_free (hostname); + + return ret; + } + + return g_strdup (url); +} + +static CFURLRef +create_url_from_cstr (gchar *cstr, + gboolean is_file) +{ + gchar *puny_cstr; + CFStringRef str; + CFURLRef url; + + puny_cstr = url_escape_hostname (cstr); + str = CFStringCreateWithCString (NULL, puny_cstr ? puny_cstr : cstr, kCFStringEncodingUTF8); + + if (is_file) + url = CFURLCreateWithFileSystemPath (NULL, str, kCFURLPOSIXPathStyle, FALSE); + else + url = CFURLCreateWithString (NULL, str, NULL); + + if (!url) + g_debug ("Creating CFURL from %s %s failed!", cstr, is_file ? "file" : "uri"); + + g_free (puny_cstr); + CFRelease(str); + return url; +} + +static CFArrayRef +create_url_list_from_glist (GList *uris, + gboolean are_files) +{ + GList *lst; + int len = g_list_length (uris); + CFMutableArrayRef array; + + if (!len) + return NULL; + + array = CFArrayCreateMutable (NULL, len, &kCFTypeArrayCallBacks); + if (!array) + return NULL; + + for (lst = uris; lst != NULL && lst->data; lst = lst->next) + { + CFURLRef url = create_url_from_cstr ((char*)lst->data, are_files); + if (url) + CFArrayAppendValue (array, url); + } + + return (CFArrayRef)array; +} + +static LSLaunchURLSpec * +create_urlspec_for_appinfo (GOsxAppInfo *info, + GList *uris, + gboolean are_files) +{ + LSLaunchURLSpec *urlspec = g_new0 (LSLaunchURLSpec, 1); + gchar *app_cstr = g_osx_app_info_get_filename (info); + + /* Strip file:// from app url but ensure filesystem url */ + urlspec->appURL = create_url_from_cstr (app_cstr + 7, TRUE); + urlspec->launchFlags = kLSLaunchDefaults; + urlspec->itemURLs = create_url_list_from_glist (uris, are_files); + + return urlspec; +} + +static void +free_urlspec (LSLaunchURLSpec *urlspec) +{ + if (urlspec->itemURLs) + { + CFArrayRemoveAllValues ((CFMutableArrayRef)urlspec->itemURLs); + CFRelease (urlspec->itemURLs); + } + CFRelease (urlspec->appURL); + g_free (urlspec); +} + +static NSBundle * +get_bundle_for_url (CFURLRef app_url) +{ + NSBundle *bundle = [NSBundle bundleWithURL: (NSURL*)app_url]; + + if (!bundle) + { + g_debug ("Bundle not found for url."); + return NULL; + } + + return bundle; +} + +static NSBundle * +get_bundle_for_id (CFStringRef bundle_id) +{ + CFURLRef app_url; + NSBundle *bundle; + +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER + CFArrayRef urls = LSCopyApplicationURLsForBundleIdentifier (bundle_id, NULL); + if (urls) + { + /* TODO: if there's multiple, we should perhaps prefer one thats in $HOME, + * instead of just always picking the first. + */ + app_url = CFArrayGetValueAtIndex (urls, 0); + CFRetain (app_url); + CFRelease (urls); + } + else +#else + if (LSFindApplicationForInfo (kLSUnknownCreator, bundle_id, NULL, NULL, &app_url) == kLSApplicationNotFoundErr) +#endif + { +#ifdef G_ENABLE_DEBUG /* This can fail often, no reason to alloc strings */ + gchar *id_str = create_cstr_from_cfstring (bundle_id); + if (id_str) + { + g_debug ("Application not found for id \"%s\".", id_str); + g_free (id_str); + } + else + g_debug ("Application not found for unconvertable bundle id."); +#endif + return NULL; + } + + bundle = get_bundle_for_url (app_url); + CFRelease (app_url); + return bundle; +} + +static const char * +g_osx_app_info_get_id (GAppInfo *appinfo) +{ + GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); + + if (!info->id) + info->id = get_bundle_string_value (info->bundle, @"CFBundleIdentifier"); + + return info->id; +} + +static const char * +g_osx_app_info_get_name (GAppInfo *appinfo) +{ + GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); + + if (!info->name) + info->name = get_bundle_string_value (info->bundle, @"CFBundleName"); + + return info->name; +} + +static const char * +g_osx_app_info_get_display_name (GAppInfo *appinfo) +{ + return g_osx_app_info_get_name (appinfo); +} + +static const char * +g_osx_app_info_get_description (GAppInfo *appinfo) +{ + /* Bundles do not contain descriptions */ + return NULL; +} + +static const char * +g_osx_app_info_get_executable (GAppInfo *appinfo) +{ + GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); + + if (!info->executable) + info->executable = get_bundle_string_value (info->bundle, @"CFBundleExecutable"); + + return info->executable; +} + +char * +g_osx_app_info_get_filename (GOsxAppInfo *info) +{ + g_return_val_if_fail (info != NULL, NULL); + + if (!info->filename) + { + info->filename = g_strconcat ("file://", [[info->bundle bundlePath] + cStringUsingEncoding: NSUTF8StringEncoding], + NULL); + } + + return info->filename; +} + +static const char * +g_osx_app_info_get_commandline (GAppInfo *appinfo) +{ + /* There isn't really a command line value */ + return NULL; +} + +static GIcon * +g_osx_app_info_get_icon (GAppInfo *appinfo) +{ + GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); + + if (!info->icon) + { + gchar *icon_name, *app_uri, *icon_uri; + GFile *file; + + icon_name = get_bundle_string_value (info->bundle, @"CFBundleIconFile"); + if (!icon_name) + return NULL; + + app_uri = g_osx_app_info_get_filename (info); + icon_uri = g_strconcat (app_uri + 7, "/Contents/Resources/", icon_name, + g_str_has_suffix (icon_name, ".icns") ? NULL : ".icns", NULL); + g_free (icon_name); + + file = g_file_new_for_path (icon_uri); + info->icon = g_file_icon_new (file); + g_object_unref (file); + g_free (icon_uri); + } + + return info->icon; +} + +static gboolean +g_osx_app_info_launch_internal (GAppInfo *appinfo, + GList *uris, + gboolean are_files, + GError **error) +{ + GOsxAppInfo *info = G_OSX_APP_INFO (appinfo); + LSLaunchURLSpec *urlspec = create_urlspec_for_appinfo (info, uris, are_files); + gint ret, success = TRUE; + + if ((ret = LSOpenFromURLSpec (urlspec, NULL))) + { + /* TODO: Better error codes */ + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Opening application failed with code %d", ret); + success = FALSE; + } + + free_urlspec (urlspec); + return success; +} + +static gboolean +g_osx_app_info_supports_uris (GAppInfo *appinfo) +{ + return TRUE; +} + +static gboolean +g_osx_app_info_supports_files (GAppInfo *appinfo) +{ + return TRUE; +} + +static gboolean +g_osx_app_info_launch (GAppInfo *appinfo, + GList *files, + GAppLaunchContext *launch_context, + GError **error) +{ + return g_osx_app_info_launch_internal (appinfo, files, TRUE, error); +} + +static gboolean +g_osx_app_info_launch_uris (GAppInfo *appinfo, + GList *uris, + GAppLaunchContext *launch_context, + GError **error) +{ + return g_osx_app_info_launch_internal (appinfo, uris, FALSE, error); +} + +static gboolean +g_osx_app_info_should_show (GAppInfo *appinfo) +{ + /* Bundles don't have hidden attribute */ + return TRUE; +} + +static gboolean +g_osx_app_info_set_as_default_for_type (GAppInfo *appinfo, + const char *content_type, + GError **error) +{ + return FALSE; +} + +static const char ** +g_osx_app_info_get_supported_types (GAppInfo *appinfo) +{ + /* TODO: get CFBundleDocumentTypes */ + return NULL; +} + +static gboolean +g_osx_app_info_set_as_last_used_for_type (GAppInfo *appinfo, + const char *content_type, + GError **error) +{ + /* Not supported. */ + return FALSE; +} + +static gboolean +g_osx_app_info_can_delete (GAppInfo *appinfo) +{ + return FALSE; +} + +static void +g_osx_app_info_iface_init (GAppInfoIface *iface) +{ + iface->dup = g_osx_app_info_dup; + iface->equal = g_osx_app_info_equal; + + iface->get_id = g_osx_app_info_get_id; + iface->get_name = g_osx_app_info_get_name; + iface->get_display_name = g_osx_app_info_get_display_name; + iface->get_description = g_osx_app_info_get_description; + iface->get_executable = g_osx_app_info_get_executable; + iface->get_commandline = g_osx_app_info_get_commandline; + iface->get_icon = g_osx_app_info_get_icon; + iface->get_supported_types = g_osx_app_info_get_supported_types; + + iface->set_as_last_used_for_type = g_osx_app_info_set_as_last_used_for_type; + iface->set_as_default_for_type = g_osx_app_info_set_as_default_for_type; + + iface->launch = g_osx_app_info_launch; + iface->launch_uris = g_osx_app_info_launch_uris; + + iface->supports_uris = g_osx_app_info_supports_uris; + iface->supports_files = g_osx_app_info_supports_files; + iface->should_show = g_osx_app_info_should_show; + iface->can_delete = g_osx_app_info_can_delete; +} + +GAppInfo * +g_app_info_create_from_commandline (const char *commandline, + const char *application_name, + GAppInfoCreateFlags flags, + GError **error) +{ + return NULL; +} + +GList * +g_osx_app_info_get_all_for_scheme (const char *cscheme) +{ + CFArrayRef bundle_list; + CFStringRef scheme; + NSBundle *bundle; + GList *info_list = NULL; + gint i; + + scheme = create_cfstring_from_cstr (cscheme); + bundle_list = LSCopyAllHandlersForURLScheme (scheme); + CFRelease (scheme); + + if (!bundle_list) + return NULL; + + for (i = 0; i < CFArrayGetCount (bundle_list); i++) + { + CFStringRef bundle_id = CFArrayGetValueAtIndex (bundle_list, i); + GAppInfo *info; + + bundle = get_bundle_for_id (bundle_id); + + if (!bundle) + continue; + + info = G_APP_INFO (g_osx_app_info_new (bundle)); + info_list = g_list_append (info_list, info); + } + CFRelease (bundle_list); + return info_list; +} + +GList * +g_app_info_get_all_for_type (const char *content_type) +{ + gchar *mime_type; + CFArrayRef bundle_list; + CFStringRef type; + NSBundle *bundle; + GList *info_list = NULL; + gint i; + + mime_type = g_content_type_get_mime_type (content_type); + if (g_str_has_prefix (mime_type, "x-scheme-handler/")) + { + gchar *scheme = strchr (mime_type, '/') + 1; + GList *ret = g_osx_app_info_get_all_for_scheme (scheme); + + g_free (mime_type); + return ret; + } + g_free (mime_type); + + type = create_cfstring_from_cstr (content_type); + bundle_list = LSCopyAllRoleHandlersForContentType (type, kLSRolesAll); + CFRelease (type); + + if (!bundle_list) + return NULL; + + for (i = 0; i < CFArrayGetCount (bundle_list); i++) + { + CFStringRef bundle_id = CFArrayGetValueAtIndex (bundle_list, i); + GAppInfo *info; + + bundle = get_bundle_for_id (bundle_id); + + if (!bundle) + continue; + + info = G_APP_INFO (g_osx_app_info_new (bundle)); + info_list = g_list_append (info_list, info); + } + CFRelease (bundle_list); + return info_list; +} + +GList * +g_app_info_get_recommended_for_type (const char *content_type) +{ + return g_app_info_get_all_for_type (content_type); +} + +GList * +g_app_info_get_fallback_for_type (const char *content_type) +{ + return g_app_info_get_all_for_type (content_type); +} + +GAppInfo * +g_app_info_get_default_for_type (const char *content_type, + gboolean must_support_uris) +{ + gchar *mime_type; + CFStringRef type; + NSBundle *bundle; +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER + CFURLRef bundle_id; +#else + CFStringRef bundle_id; +#endif + + mime_type = g_content_type_get_mime_type (content_type); + if (g_str_has_prefix (mime_type, "x-scheme-handler/")) + { + gchar *scheme = strchr (mime_type, '/') + 1; + GAppInfo *ret = g_app_info_get_default_for_uri_scheme (scheme); + + g_free (mime_type); + return ret; + } + g_free (mime_type); + + type = create_cfstring_from_cstr (content_type); + +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER + bundle_id = LSCopyDefaultApplicationURLForContentType (type, kLSRolesAll, NULL); +#else + bundle_id = LSCopyDefaultRoleHandlerForContentType (type, kLSRolesAll); +#endif + CFRelease (type); + + if (!bundle_id) + { + g_warning ("No default handler found for content type '%s'.", content_type); + return NULL; + } + +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER + bundle = get_bundle_for_url (bundle_id); +#else + bundle = get_bundle_for_id (bundle_id); +#endif + CFRelease (bundle_id); + + if (!bundle) + return NULL; + + return G_APP_INFO (g_osx_app_info_new (bundle)); +} + +GAppInfo * +g_app_info_get_default_for_uri_scheme (const char *uri_scheme) +{ + CFStringRef scheme, bundle_id; + NSBundle *bundle; + + scheme = create_cfstring_from_cstr (uri_scheme); + bundle_id = LSCopyDefaultHandlerForURLScheme (scheme); + CFRelease (scheme); + + if (!bundle_id) + { + g_warning ("No default handler found for url scheme '%s'.", uri_scheme); + return NULL; + } + + bundle = get_bundle_for_id (bundle_id); + CFRelease (bundle_id); + + if (!bundle) + return NULL; + + return G_APP_INFO (g_osx_app_info_new (bundle)); +} + +GList * +g_app_info_get_all (void) +{ + /* There is no API for this afaict + * could manually do it... + */ + return NULL; +} + +void +g_app_info_reset_type_associations (const char *content_type) +{ +} diff --git a/gio/gosxcontenttype.c b/gio/gosxcontenttype.c deleted file mode 100644 index 52ba5763a..000000000 --- a/gio/gosxcontenttype.c +++ /dev/null @@ -1,582 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2014 Patrick Griffis - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - */ - -#include "config.h" - -#include "gcontenttype.h" -#include "gicon.h" -#include "gthemedicon.h" - -#include - -#define XDG_PREFIX _gio_xdg -#include "xdgmime/xdgmime.h" - -/* We lock this mutex whenever we modify global state in this module. */ -G_LOCK_DEFINE_STATIC (gio_xdgmime); - - -/*< internal > - * create_cfstring_from_cstr: - * @cstr: a #gchar - * - * Converts a cstr to a utf8 cfstring - * It must be CFReleased()'d. - * - */ -static CFStringRef -create_cfstring_from_cstr (const gchar *cstr) -{ - return CFStringCreateWithCString (NULL, cstr, kCFStringEncodingUTF8); -} - -/*< internal > - * create_cstr_from_cfstring: - * @str: a #CFStringRef - * - * Converts a cfstring to a utf8 cstring. - * The incoming cfstring is released for you. - * The returned string must be g_free()'d. - * - */ -static gchar * -create_cstr_from_cfstring (CFStringRef str) -{ - g_return_val_if_fail (str != NULL, NULL); - - CFIndex length = CFStringGetLength (str); - CFIndex maxlen = CFStringGetMaximumSizeForEncoding (length, kCFStringEncodingUTF8); - gchar *buffer = g_malloc (maxlen + 1); - Boolean success = CFStringGetCString (str, (char *) buffer, maxlen, - kCFStringEncodingUTF8); - CFRelease (str); - if (success) - return buffer; - else - { - g_free (buffer); - return NULL; - } -} - -/*< internal > - * create_cstr_from_cfstring_with_fallback: - * @str: a #CFStringRef - * @fallback: a #gchar - * - * Tries to convert a cfstring to a utf8 cstring. - * If @str is NULL or conversion fails @fallback is returned. - * The incoming cfstring is released for you. - * The returned string must be g_free()'d. - * - */ -static gchar * -create_cstr_from_cfstring_with_fallback (CFStringRef str, - const gchar *fallback) -{ - gchar *cstr = NULL; - - if (str) - cstr = create_cstr_from_cfstring (str); - if (!cstr) - return g_strdup (fallback); - - return cstr; -} - -gboolean -g_content_type_equals (const gchar *type1, - const gchar *type2) -{ - CFStringRef str1, str2; - gboolean ret; - - g_return_val_if_fail (type1 != NULL, FALSE); - g_return_val_if_fail (type2 != NULL, FALSE); - - if (g_ascii_strcasecmp (type1, type2) == 0) - return TRUE; - - str1 = create_cfstring_from_cstr (type1); - str2 = create_cfstring_from_cstr (type2); - - ret = UTTypeEqual (str1, str2); - - CFRelease (str1); - CFRelease (str2); - - return ret; -} - -gboolean -g_content_type_is_a (const gchar *ctype, - const gchar *csupertype) -{ - CFStringRef type, supertype; - gboolean ret; - - g_return_val_if_fail (ctype != NULL, FALSE); - g_return_val_if_fail (csupertype != NULL, FALSE); - - type = create_cfstring_from_cstr (ctype); - supertype = create_cfstring_from_cstr (csupertype); - - ret = UTTypeConformsTo (type, supertype); - - CFRelease (type); - CFRelease (supertype); - - return ret; -} - -gboolean -g_content_type_is_mime_type (const gchar *type, - const gchar *mime_type) -{ - gchar *content_type; - gboolean ret; - - g_return_val_if_fail (type != NULL, FALSE); - g_return_val_if_fail (mime_type != NULL, FALSE); - - content_type = g_content_type_from_mime_type (mime_type); - ret = g_content_type_is_a (type, content_type); - g_free (content_type); - - return ret; -} - -gboolean -g_content_type_is_unknown (const gchar *type) -{ - g_return_val_if_fail (type != NULL, FALSE); - - /* Should dynamic types be considered "unknown"? */ - if (g_str_has_prefix (type, "dyn.")) - return TRUE; - /* application/octet-stream */ - else if (g_strcmp0 (type, "public.data") == 0) - return TRUE; - - return FALSE; -} - -gchar * -g_content_type_get_description (const gchar *type) -{ - CFStringRef str; - CFStringRef desc_str; - - g_return_val_if_fail (type != NULL, NULL); - - str = create_cfstring_from_cstr (type); - desc_str = UTTypeCopyDescription (str); - - CFRelease (str); - return create_cstr_from_cfstring_with_fallback (desc_str, "unknown"); -} - -/* - * _get_generic_icon_name_from_mime_type - * - * This function produces a generic icon name from a @mime_type. - * If no generic icon name is found in the xdg mime database, the - * generic icon name is constructed. - * - * Background: - * generic-icon elements specify the icon to use as a generic icon for this - * particular mime-type, given by the name attribute. This is used if there - * is no specific icon (see icon for how these are found). These are used - * for categories of similar types (like spreadsheets or archives) that can - * use a common icon. The Icon Naming Specification lists a set of such - * icon names. If this element is not specified then the mimetype is used - * to generate the generic icon by using the top-level media type - * (e.g. "video" in "video/ogg") and appending "-x-generic" - * (i.e. "video-x-generic" in the previous example). - * - * From: https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.18.html - */ - -static gchar * -_get_generic_icon_name_from_mime_type (const gchar *mime_type) -{ - const gchar *xdg_icon_name; - gchar *icon_name; - - G_LOCK (gio_xdgmime); - xdg_icon_name = xdg_mime_get_generic_icon (mime_type); - G_UNLOCK (gio_xdgmime); - - if (xdg_icon_name == NULL) - { - const char *p; - const char *suffix = "-x-generic"; - gsize prefix_len; - - p = strchr (mime_type, '/'); - if (p == NULL) - prefix_len = strlen (mime_type); - else - prefix_len = p - mime_type; - - icon_name = g_malloc (prefix_len + strlen (suffix) + 1); - memcpy (icon_name, mime_type, prefix_len); - memcpy (icon_name + prefix_len, suffix, strlen (suffix)); - icon_name[prefix_len + strlen (suffix)] = 0; - } - else - { - icon_name = g_strdup (xdg_icon_name); - } - - return icon_name; -} - - -static GIcon * -g_content_type_get_icon_internal (const gchar *uti, - gboolean symbolic) -{ - char *mimetype_icon; - char *mime_type; - char *generic_mimetype_icon = NULL; - char *q; - char *icon_names[6]; - int n = 0; - GIcon *themed_icon; - const char *xdg_icon; - int i; - - g_return_val_if_fail (uti != NULL, NULL); - - mime_type = g_content_type_get_mime_type (uti); - - G_LOCK (gio_xdgmime); - xdg_icon = xdg_mime_get_icon (mime_type); - G_UNLOCK (gio_xdgmime); - - if (xdg_icon) - icon_names[n++] = g_strdup (xdg_icon); - - mimetype_icon = g_strdup (mime_type); - while ((q = strchr (mimetype_icon, '/')) != NULL) - *q = '-'; - - icon_names[n++] = mimetype_icon; - - generic_mimetype_icon = _get_generic_icon_name_from_mime_type (mime_type); - - if (generic_mimetype_icon) - icon_names[n++] = generic_mimetype_icon; - - if (symbolic) - { - for (i = 0; i < n; i++) - { - icon_names[n + i] = icon_names[i]; - icon_names[i] = g_strconcat (icon_names[i], "-symbolic", NULL); - } - - n += n; - } - - themed_icon = g_themed_icon_new_from_names (icon_names, n); - - for (i = 0; i < n; i++) - g_free (icon_names[i]); - - g_free(mime_type); - - return themed_icon; -} - -GIcon * -g_content_type_get_icon (const gchar *type) -{ - return g_content_type_get_icon_internal (type, FALSE); -} - -GIcon * -g_content_type_get_symbolic_icon (const gchar *type) -{ - return g_content_type_get_icon_internal (type, TRUE); -} - -gchar * -g_content_type_get_generic_icon_name (const gchar *type) -{ - return NULL; -} - -gboolean -g_content_type_can_be_executable (const gchar *type) -{ - CFStringRef uti; - gboolean ret = FALSE; - - g_return_val_if_fail (type != NULL, FALSE); - - uti = create_cfstring_from_cstr (type); - - if (UTTypeConformsTo (uti, kUTTypeApplication)) - ret = TRUE; - else if (UTTypeConformsTo (uti, CFSTR("public.executable"))) - ret = TRUE; - else if (UTTypeConformsTo (uti, CFSTR("public.script"))) - ret = TRUE; - /* Our tests assert that all text can be executable... */ - else if (UTTypeConformsTo (uti, CFSTR("public.text"))) - ret = TRUE; - - CFRelease (uti); - return ret; -} - -gchar * -g_content_type_from_mime_type (const gchar *mime_type) -{ - CFStringRef mime_str; - CFStringRef uti_str; - - g_return_val_if_fail (mime_type != NULL, NULL); - - /* Their api does not handle globs but they are common. */ - if (g_str_has_suffix (mime_type, "*")) - { - if (g_str_has_prefix (mime_type, "audio")) - return g_strdup ("public.audio"); - if (g_str_has_prefix (mime_type, "image")) - return g_strdup ("public.image"); - if (g_str_has_prefix (mime_type, "text")) - return g_strdup ("public.text"); - if (g_str_has_prefix (mime_type, "video")) - return g_strdup ("public.movie"); - } - - /* Some exceptions are needed for gdk-pixbuf. - * This list is not exhaustive. - */ - if (g_str_has_prefix (mime_type, "image")) - { - if (g_str_has_suffix (mime_type, "x-icns")) - return g_strdup ("com.apple.icns"); - if (g_str_has_suffix (mime_type, "x-tga")) - return g_strdup ("com.truevision.tga-image"); - if (g_str_has_suffix (mime_type, "x-ico")) - return g_strdup ("com.microsoft.ico "); - } - - /* These are also not supported... - * Used in glocalfileinfo.c - */ - if (g_str_has_prefix (mime_type, "inode")) - { - if (g_str_has_suffix (mime_type, "directory")) - return g_strdup ("public.folder"); - if (g_str_has_suffix (mime_type, "symlink")) - return g_strdup ("public.symlink"); - } - - /* This is correct according to the Apple docs: - https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html - */ - if (strcmp (mime_type, "text/plain") == 0) - return g_strdup ("public.text"); - - /* Non standard type */ - if (strcmp (mime_type, "application/x-executable") == 0) - return g_strdup ("public.executable"); - - mime_str = create_cfstring_from_cstr (mime_type); - uti_str = UTTypeCreatePreferredIdentifierForTag (kUTTagClassMIMEType, mime_str, NULL); - - CFRelease (mime_str); - return create_cstr_from_cfstring_with_fallback (uti_str, "public.data"); -} - -gchar * -g_content_type_get_mime_type (const gchar *type) -{ - CFStringRef uti_str; - CFStringRef mime_str; - - g_return_val_if_fail (type != NULL, NULL); - - /* We must match the additions above - * so conversions back and forth work. - */ - if (g_str_has_prefix (type, "public")) - { - if (g_str_has_suffix (type, ".image")) - return g_strdup ("image/*"); - if (g_str_has_suffix (type, ".movie")) - return g_strdup ("video/*"); - if (g_str_has_suffix (type, ".text")) - return g_strdup ("text/*"); - if (g_str_has_suffix (type, ".audio")) - return g_strdup ("audio/*"); - if (g_str_has_suffix (type, ".folder")) - return g_strdup ("inode/directory"); - if (g_str_has_suffix (type, ".symlink")) - return g_strdup ("inode/symlink"); - if (g_str_has_suffix (type, ".executable")) - return g_strdup ("application/x-executable"); - } - - uti_str = create_cfstring_from_cstr (type); - mime_str = UTTypeCopyPreferredTagWithClass(uti_str, kUTTagClassMIMEType); - - CFRelease (uti_str); - return create_cstr_from_cfstring_with_fallback (mime_str, "application/octet-stream"); -} - -static gboolean -looks_like_text (const guchar *data, - gsize data_size) -{ - gsize i; - guchar c; - - for (i = 0; i < data_size; i++) - { - c = data[i]; - if (g_ascii_iscntrl (c) && !g_ascii_isspace (c) && c != '\b') - return FALSE; - } - return TRUE; -} - -gchar * -g_content_type_guess (const gchar *filename, - const guchar *data, - gsize data_size, - gboolean *result_uncertain) -{ - CFStringRef uti = NULL; - gchar *cextension; - CFStringRef extension; - int uncertain = -1; - - g_return_val_if_fail (data_size != (gsize) -1, NULL); - - if (filename && *filename) - { - gchar *basename = g_path_get_basename (filename); - gchar *dirname = g_path_get_dirname (filename); - gsize i = strlen (filename); - - if (filename[i - 1] == '/') - { - if (g_strcmp0 (dirname, "/Volumes") == 0) - { - uti = CFStringCreateCopy (NULL, kUTTypeVolume); - } - else if ((cextension = strrchr (basename, '.')) != NULL) - { - cextension++; - extension = create_cfstring_from_cstr (cextension); - uti = UTTypeCreatePreferredIdentifierForTag (kUTTagClassFilenameExtension, - extension, NULL); - CFRelease (extension); - - if (CFStringHasPrefix (uti, CFSTR ("dyn."))) - { - CFRelease (uti); - uti = CFStringCreateCopy (NULL, kUTTypeFolder); - uncertain = TRUE; - } - } - else - { - uti = CFStringCreateCopy (NULL, kUTTypeFolder); - uncertain = TRUE; /* Matches Unix backend */ - } - } - else - { - /* GTK needs this... */ - if (g_str_has_suffix (basename, ".ui")) - { - uti = CFStringCreateCopy (NULL, kUTTypeXML); - } - else if (g_str_has_suffix (basename, ".txt")) - { - uti = CFStringCreateCopy (NULL, CFSTR ("public.text")); - } - else if ((cextension = strrchr (basename, '.')) != NULL) - { - cextension++; - extension = create_cfstring_from_cstr (cextension); - uti = UTTypeCreatePreferredIdentifierForTag (kUTTagClassFilenameExtension, - extension, NULL); - CFRelease (extension); - } - g_free (basename); - g_free (dirname); - } - } - if (data && (!filename || !uti || - CFStringCompare (uti, CFSTR ("public.data"), 0) == kCFCompareEqualTo)) - { - const char *sniffed_mimetype; - G_LOCK (gio_xdgmime); - sniffed_mimetype = xdg_mime_get_mime_type_for_data (data, data_size, NULL); - G_UNLOCK (gio_xdgmime); - if (sniffed_mimetype != XDG_MIME_TYPE_UNKNOWN) - { - gchar *uti_str = g_content_type_from_mime_type (sniffed_mimetype); - uti = create_cfstring_from_cstr (uti_str); - g_free (uti_str); - } - if (!uti && looks_like_text (data, data_size)) - { - if (g_str_has_prefix ((const gchar*)data, "#!/")) - uti = CFStringCreateCopy (NULL, CFSTR ("public.script")); - else - uti = CFStringCreateCopy (NULL, CFSTR ("public.text")); - } - } - - if (!uti) - { - /* Generic data type */ - uti = CFStringCreateCopy (NULL, CFSTR ("public.data")); - if (result_uncertain) - *result_uncertain = TRUE; - } - else if (result_uncertain) - { - *result_uncertain = uncertain == -1 ? FALSE : uncertain; - } - - return create_cstr_from_cfstring (uti); -} - -GList * -g_content_types_get_registered (void) -{ - /* TODO: UTTypeCreateAllIdentifiersForTag? */ - return NULL; -} - -gchar ** -g_content_type_guess_for_tree (GFile *root) -{ - return NULL; -} diff --git a/gio/gosxcontenttype.m b/gio/gosxcontenttype.m new file mode 100644 index 000000000..52ba5763a --- /dev/null +++ b/gio/gosxcontenttype.m @@ -0,0 +1,582 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2014 Patrick Griffis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + */ + +#include "config.h" + +#include "gcontenttype.h" +#include "gicon.h" +#include "gthemedicon.h" + +#include + +#define XDG_PREFIX _gio_xdg +#include "xdgmime/xdgmime.h" + +/* We lock this mutex whenever we modify global state in this module. */ +G_LOCK_DEFINE_STATIC (gio_xdgmime); + + +/*< internal > + * create_cfstring_from_cstr: + * @cstr: a #gchar + * + * Converts a cstr to a utf8 cfstring + * It must be CFReleased()'d. + * + */ +static CFStringRef +create_cfstring_from_cstr (const gchar *cstr) +{ + return CFStringCreateWithCString (NULL, cstr, kCFStringEncodingUTF8); +} + +/*< internal > + * create_cstr_from_cfstring: + * @str: a #CFStringRef + * + * Converts a cfstring to a utf8 cstring. + * The incoming cfstring is released for you. + * The returned string must be g_free()'d. + * + */ +static gchar * +create_cstr_from_cfstring (CFStringRef str) +{ + g_return_val_if_fail (str != NULL, NULL); + + CFIndex length = CFStringGetLength (str); + CFIndex maxlen = CFStringGetMaximumSizeForEncoding (length, kCFStringEncodingUTF8); + gchar *buffer = g_malloc (maxlen + 1); + Boolean success = CFStringGetCString (str, (char *) buffer, maxlen, + kCFStringEncodingUTF8); + CFRelease (str); + if (success) + return buffer; + else + { + g_free (buffer); + return NULL; + } +} + +/*< internal > + * create_cstr_from_cfstring_with_fallback: + * @str: a #CFStringRef + * @fallback: a #gchar + * + * Tries to convert a cfstring to a utf8 cstring. + * If @str is NULL or conversion fails @fallback is returned. + * The incoming cfstring is released for you. + * The returned string must be g_free()'d. + * + */ +static gchar * +create_cstr_from_cfstring_with_fallback (CFStringRef str, + const gchar *fallback) +{ + gchar *cstr = NULL; + + if (str) + cstr = create_cstr_from_cfstring (str); + if (!cstr) + return g_strdup (fallback); + + return cstr; +} + +gboolean +g_content_type_equals (const gchar *type1, + const gchar *type2) +{ + CFStringRef str1, str2; + gboolean ret; + + g_return_val_if_fail (type1 != NULL, FALSE); + g_return_val_if_fail (type2 != NULL, FALSE); + + if (g_ascii_strcasecmp (type1, type2) == 0) + return TRUE; + + str1 = create_cfstring_from_cstr (type1); + str2 = create_cfstring_from_cstr (type2); + + ret = UTTypeEqual (str1, str2); + + CFRelease (str1); + CFRelease (str2); + + return ret; +} + +gboolean +g_content_type_is_a (const gchar *ctype, + const gchar *csupertype) +{ + CFStringRef type, supertype; + gboolean ret; + + g_return_val_if_fail (ctype != NULL, FALSE); + g_return_val_if_fail (csupertype != NULL, FALSE); + + type = create_cfstring_from_cstr (ctype); + supertype = create_cfstring_from_cstr (csupertype); + + ret = UTTypeConformsTo (type, supertype); + + CFRelease (type); + CFRelease (supertype); + + return ret; +} + +gboolean +g_content_type_is_mime_type (const gchar *type, + const gchar *mime_type) +{ + gchar *content_type; + gboolean ret; + + g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (mime_type != NULL, FALSE); + + content_type = g_content_type_from_mime_type (mime_type); + ret = g_content_type_is_a (type, content_type); + g_free (content_type); + + return ret; +} + +gboolean +g_content_type_is_unknown (const gchar *type) +{ + g_return_val_if_fail (type != NULL, FALSE); + + /* Should dynamic types be considered "unknown"? */ + if (g_str_has_prefix (type, "dyn.")) + return TRUE; + /* application/octet-stream */ + else if (g_strcmp0 (type, "public.data") == 0) + return TRUE; + + return FALSE; +} + +gchar * +g_content_type_get_description (const gchar *type) +{ + CFStringRef str; + CFStringRef desc_str; + + g_return_val_if_fail (type != NULL, NULL); + + str = create_cfstring_from_cstr (type); + desc_str = UTTypeCopyDescription (str); + + CFRelease (str); + return create_cstr_from_cfstring_with_fallback (desc_str, "unknown"); +} + +/* + * _get_generic_icon_name_from_mime_type + * + * This function produces a generic icon name from a @mime_type. + * If no generic icon name is found in the xdg mime database, the + * generic icon name is constructed. + * + * Background: + * generic-icon elements specify the icon to use as a generic icon for this + * particular mime-type, given by the name attribute. This is used if there + * is no specific icon (see icon for how these are found). These are used + * for categories of similar types (like spreadsheets or archives) that can + * use a common icon. The Icon Naming Specification lists a set of such + * icon names. If this element is not specified then the mimetype is used + * to generate the generic icon by using the top-level media type + * (e.g. "video" in "video/ogg") and appending "-x-generic" + * (i.e. "video-x-generic" in the previous example). + * + * From: https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.18.html + */ + +static gchar * +_get_generic_icon_name_from_mime_type (const gchar *mime_type) +{ + const gchar *xdg_icon_name; + gchar *icon_name; + + G_LOCK (gio_xdgmime); + xdg_icon_name = xdg_mime_get_generic_icon (mime_type); + G_UNLOCK (gio_xdgmime); + + if (xdg_icon_name == NULL) + { + const char *p; + const char *suffix = "-x-generic"; + gsize prefix_len; + + p = strchr (mime_type, '/'); + if (p == NULL) + prefix_len = strlen (mime_type); + else + prefix_len = p - mime_type; + + icon_name = g_malloc (prefix_len + strlen (suffix) + 1); + memcpy (icon_name, mime_type, prefix_len); + memcpy (icon_name + prefix_len, suffix, strlen (suffix)); + icon_name[prefix_len + strlen (suffix)] = 0; + } + else + { + icon_name = g_strdup (xdg_icon_name); + } + + return icon_name; +} + + +static GIcon * +g_content_type_get_icon_internal (const gchar *uti, + gboolean symbolic) +{ + char *mimetype_icon; + char *mime_type; + char *generic_mimetype_icon = NULL; + char *q; + char *icon_names[6]; + int n = 0; + GIcon *themed_icon; + const char *xdg_icon; + int i; + + g_return_val_if_fail (uti != NULL, NULL); + + mime_type = g_content_type_get_mime_type (uti); + + G_LOCK (gio_xdgmime); + xdg_icon = xdg_mime_get_icon (mime_type); + G_UNLOCK (gio_xdgmime); + + if (xdg_icon) + icon_names[n++] = g_strdup (xdg_icon); + + mimetype_icon = g_strdup (mime_type); + while ((q = strchr (mimetype_icon, '/')) != NULL) + *q = '-'; + + icon_names[n++] = mimetype_icon; + + generic_mimetype_icon = _get_generic_icon_name_from_mime_type (mime_type); + + if (generic_mimetype_icon) + icon_names[n++] = generic_mimetype_icon; + + if (symbolic) + { + for (i = 0; i < n; i++) + { + icon_names[n + i] = icon_names[i]; + icon_names[i] = g_strconcat (icon_names[i], "-symbolic", NULL); + } + + n += n; + } + + themed_icon = g_themed_icon_new_from_names (icon_names, n); + + for (i = 0; i < n; i++) + g_free (icon_names[i]); + + g_free(mime_type); + + return themed_icon; +} + +GIcon * +g_content_type_get_icon (const gchar *type) +{ + return g_content_type_get_icon_internal (type, FALSE); +} + +GIcon * +g_content_type_get_symbolic_icon (const gchar *type) +{ + return g_content_type_get_icon_internal (type, TRUE); +} + +gchar * +g_content_type_get_generic_icon_name (const gchar *type) +{ + return NULL; +} + +gboolean +g_content_type_can_be_executable (const gchar *type) +{ + CFStringRef uti; + gboolean ret = FALSE; + + g_return_val_if_fail (type != NULL, FALSE); + + uti = create_cfstring_from_cstr (type); + + if (UTTypeConformsTo (uti, kUTTypeApplication)) + ret = TRUE; + else if (UTTypeConformsTo (uti, CFSTR("public.executable"))) + ret = TRUE; + else if (UTTypeConformsTo (uti, CFSTR("public.script"))) + ret = TRUE; + /* Our tests assert that all text can be executable... */ + else if (UTTypeConformsTo (uti, CFSTR("public.text"))) + ret = TRUE; + + CFRelease (uti); + return ret; +} + +gchar * +g_content_type_from_mime_type (const gchar *mime_type) +{ + CFStringRef mime_str; + CFStringRef uti_str; + + g_return_val_if_fail (mime_type != NULL, NULL); + + /* Their api does not handle globs but they are common. */ + if (g_str_has_suffix (mime_type, "*")) + { + if (g_str_has_prefix (mime_type, "audio")) + return g_strdup ("public.audio"); + if (g_str_has_prefix (mime_type, "image")) + return g_strdup ("public.image"); + if (g_str_has_prefix (mime_type, "text")) + return g_strdup ("public.text"); + if (g_str_has_prefix (mime_type, "video")) + return g_strdup ("public.movie"); + } + + /* Some exceptions are needed for gdk-pixbuf. + * This list is not exhaustive. + */ + if (g_str_has_prefix (mime_type, "image")) + { + if (g_str_has_suffix (mime_type, "x-icns")) + return g_strdup ("com.apple.icns"); + if (g_str_has_suffix (mime_type, "x-tga")) + return g_strdup ("com.truevision.tga-image"); + if (g_str_has_suffix (mime_type, "x-ico")) + return g_strdup ("com.microsoft.ico "); + } + + /* These are also not supported... + * Used in glocalfileinfo.c + */ + if (g_str_has_prefix (mime_type, "inode")) + { + if (g_str_has_suffix (mime_type, "directory")) + return g_strdup ("public.folder"); + if (g_str_has_suffix (mime_type, "symlink")) + return g_strdup ("public.symlink"); + } + + /* This is correct according to the Apple docs: + https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html + */ + if (strcmp (mime_type, "text/plain") == 0) + return g_strdup ("public.text"); + + /* Non standard type */ + if (strcmp (mime_type, "application/x-executable") == 0) + return g_strdup ("public.executable"); + + mime_str = create_cfstring_from_cstr (mime_type); + uti_str = UTTypeCreatePreferredIdentifierForTag (kUTTagClassMIMEType, mime_str, NULL); + + CFRelease (mime_str); + return create_cstr_from_cfstring_with_fallback (uti_str, "public.data"); +} + +gchar * +g_content_type_get_mime_type (const gchar *type) +{ + CFStringRef uti_str; + CFStringRef mime_str; + + g_return_val_if_fail (type != NULL, NULL); + + /* We must match the additions above + * so conversions back and forth work. + */ + if (g_str_has_prefix (type, "public")) + { + if (g_str_has_suffix (type, ".image")) + return g_strdup ("image/*"); + if (g_str_has_suffix (type, ".movie")) + return g_strdup ("video/*"); + if (g_str_has_suffix (type, ".text")) + return g_strdup ("text/*"); + if (g_str_has_suffix (type, ".audio")) + return g_strdup ("audio/*"); + if (g_str_has_suffix (type, ".folder")) + return g_strdup ("inode/directory"); + if (g_str_has_suffix (type, ".symlink")) + return g_strdup ("inode/symlink"); + if (g_str_has_suffix (type, ".executable")) + return g_strdup ("application/x-executable"); + } + + uti_str = create_cfstring_from_cstr (type); + mime_str = UTTypeCopyPreferredTagWithClass(uti_str, kUTTagClassMIMEType); + + CFRelease (uti_str); + return create_cstr_from_cfstring_with_fallback (mime_str, "application/octet-stream"); +} + +static gboolean +looks_like_text (const guchar *data, + gsize data_size) +{ + gsize i; + guchar c; + + for (i = 0; i < data_size; i++) + { + c = data[i]; + if (g_ascii_iscntrl (c) && !g_ascii_isspace (c) && c != '\b') + return FALSE; + } + return TRUE; +} + +gchar * +g_content_type_guess (const gchar *filename, + const guchar *data, + gsize data_size, + gboolean *result_uncertain) +{ + CFStringRef uti = NULL; + gchar *cextension; + CFStringRef extension; + int uncertain = -1; + + g_return_val_if_fail (data_size != (gsize) -1, NULL); + + if (filename && *filename) + { + gchar *basename = g_path_get_basename (filename); + gchar *dirname = g_path_get_dirname (filename); + gsize i = strlen (filename); + + if (filename[i - 1] == '/') + { + if (g_strcmp0 (dirname, "/Volumes") == 0) + { + uti = CFStringCreateCopy (NULL, kUTTypeVolume); + } + else if ((cextension = strrchr (basename, '.')) != NULL) + { + cextension++; + extension = create_cfstring_from_cstr (cextension); + uti = UTTypeCreatePreferredIdentifierForTag (kUTTagClassFilenameExtension, + extension, NULL); + CFRelease (extension); + + if (CFStringHasPrefix (uti, CFSTR ("dyn."))) + { + CFRelease (uti); + uti = CFStringCreateCopy (NULL, kUTTypeFolder); + uncertain = TRUE; + } + } + else + { + uti = CFStringCreateCopy (NULL, kUTTypeFolder); + uncertain = TRUE; /* Matches Unix backend */ + } + } + else + { + /* GTK needs this... */ + if (g_str_has_suffix (basename, ".ui")) + { + uti = CFStringCreateCopy (NULL, kUTTypeXML); + } + else if (g_str_has_suffix (basename, ".txt")) + { + uti = CFStringCreateCopy (NULL, CFSTR ("public.text")); + } + else if ((cextension = strrchr (basename, '.')) != NULL) + { + cextension++; + extension = create_cfstring_from_cstr (cextension); + uti = UTTypeCreatePreferredIdentifierForTag (kUTTagClassFilenameExtension, + extension, NULL); + CFRelease (extension); + } + g_free (basename); + g_free (dirname); + } + } + if (data && (!filename || !uti || + CFStringCompare (uti, CFSTR ("public.data"), 0) == kCFCompareEqualTo)) + { + const char *sniffed_mimetype; + G_LOCK (gio_xdgmime); + sniffed_mimetype = xdg_mime_get_mime_type_for_data (data, data_size, NULL); + G_UNLOCK (gio_xdgmime); + if (sniffed_mimetype != XDG_MIME_TYPE_UNKNOWN) + { + gchar *uti_str = g_content_type_from_mime_type (sniffed_mimetype); + uti = create_cfstring_from_cstr (uti_str); + g_free (uti_str); + } + if (!uti && looks_like_text (data, data_size)) + { + if (g_str_has_prefix ((const gchar*)data, "#!/")) + uti = CFStringCreateCopy (NULL, CFSTR ("public.script")); + else + uti = CFStringCreateCopy (NULL, CFSTR ("public.text")); + } + } + + if (!uti) + { + /* Generic data type */ + uti = CFStringCreateCopy (NULL, CFSTR ("public.data")); + if (result_uncertain) + *result_uncertain = TRUE; + } + else if (result_uncertain) + { + *result_uncertain = uncertain == -1 ? FALSE : uncertain; + } + + return create_cstr_from_cfstring (uti); +} + +GList * +g_content_types_get_registered (void) +{ + /* TODO: UTTypeCreateAllIdentifiersForTag? */ + return NULL; +} + +gchar ** +g_content_type_guess_for_tree (GFile *root) +{ + return NULL; +} diff --git a/gio/gresource.c b/gio/gresource.c index 8ead26bc6..bf54f1d78 100644 --- a/gio/gresource.c +++ b/gio/gresource.c @@ -591,23 +591,24 @@ g_resource_load (const gchar *filename, return g_resource_new_from_table (table); } -static -gboolean do_lookup (GResource *resource, - const gchar *path, - GResourceLookupFlags lookup_flags, - gsize *size, - guint32 *flags, - const void **data, - gsize *data_size, - GError **error) +static gboolean +do_lookup (GResource *resource, + const gchar *path, + GResourceLookupFlags lookup_flags, + gsize *size, + guint32 *flags, + const void **data, + gsize *data_size, + GError **error) { char *free_path = NULL; gsize path_len; gboolean res = FALSE; GVariant *value; + /* Drop any trailing slash. */ path_len = strlen (path); - if (path[path_len-1] == '/') + if (path_len >= 1 && path[path_len-1] == '/') { path = free_path = g_strdup (path); free_path[path_len-1] = 0; diff --git a/gio/gsettings.c b/gio/gsettings.c index e5ed54a46..ab7f43835 100644 --- a/gio/gsettings.c +++ b/gio/gsettings.c @@ -1204,10 +1204,7 @@ g_settings_get_value (GSettings *settings, value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); if (value == NULL) - value = g_settings_schema_key_get_translated_default (&skey); - - if (value == NULL) - value = g_variant_ref (skey.default_value); + value = g_settings_schema_key_get_default_value (&skey); g_settings_schema_key_clear (&skey); @@ -1304,10 +1301,7 @@ g_settings_get_default_value (GSettings *settings, value = g_settings_read_from_backend (settings, &skey, FALSE, TRUE); if (value == NULL) - value = g_settings_schema_key_get_translated_default (&skey); - - if (value == NULL) - value = g_variant_ref (skey.default_value); + value = g_settings_schema_key_get_default_value (&skey); g_settings_schema_key_clear (&skey); @@ -1360,10 +1354,7 @@ g_settings_get_enum (GSettings *settings, value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); if (value == NULL) - value = g_settings_schema_key_get_translated_default (&skey); - - if (value == NULL) - value = g_variant_ref (skey.default_value); + value = g_settings_schema_key_get_default_value (&skey); result = g_settings_schema_key_to_enum (&skey, value); g_settings_schema_key_clear (&skey); @@ -1473,10 +1464,7 @@ g_settings_get_flags (GSettings *settings, value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); if (value == NULL) - value = g_settings_schema_key_get_translated_default (&skey); - - if (value == NULL) - value = g_variant_ref (skey.default_value); + value = g_settings_schema_key_get_default_value (&skey); result = g_settings_schema_key_to_flags (&skey, value); g_settings_schema_key_clear (&skey); @@ -1751,6 +1739,13 @@ g_settings_get_mapped (GSettings *settings, if (okay) goto okay; } + if ((value = g_settings_schema_key_get_per_desktop_default (&skey))) + { + okay = mapping (value, &result, user_data); + g_variant_unref (value); + if (okay) goto okay; + } + if (mapping (skey.default_value, &result, user_data)) goto okay; @@ -2658,6 +2653,20 @@ g_settings_binding_key_changed (GSettings *settings, } } + if (variant == NULL) + { + variant = g_settings_schema_key_get_per_desktop_default (&binding->key); + if (variant && + !binding->get_mapping (&value, variant, binding->user_data)) + { + g_error ("Per-desktop default value for key '%s' in schema '%s' " + "was rejected by the binding mapping function.", + binding->key.name, g_settings_schema_get_id (binding->key.schema)); + g_variant_unref (variant); + variant = NULL; + } + } + if (variant == NULL) { variant = g_variant_ref (binding->key.default_value); @@ -2912,10 +2921,12 @@ g_settings_bind_with_mapping (GSettings *settings, if (!g_variant_type_equal (binding->key.type, G_VARIANT_TYPE_BOOLEAN)) { + gchar *type_string = g_variant_type_dup_string (binding->key.type); g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN " "was specified, but key '%s' on schema '%s' has " "type '%s'", key, g_settings_schema_get_id (settings->priv->schema), - g_variant_type_dup_string (binding->key.type)); + type_string); + g_free (type_string); return; } @@ -2926,12 +2937,14 @@ g_settings_bind_with_mapping (GSettings *settings, !g_settings_mapping_is_compatible (binding->property->value_type, binding->key.type)) { + gchar *type_string = g_variant_type_dup_string (binding->key.type); g_critical ("g_settings_bind: property '%s' on class '%s' has type " "'%s' which is not compatible with type '%s' of key '%s' " "on schema '%s'", binding->property->name, G_OBJECT_TYPE_NAME (object), g_type_name (binding->property->value_type), - g_variant_type_dup_string (binding->key.type), key, + type_string, key, g_settings_schema_get_id (settings->priv->schema)); + g_free (type_string); return; } diff --git a/gio/gsettingsschema-internal.h b/gio/gsettingsschema-internal.h index f54de3b34..5f996b4bc 100644 --- a/gio/gsettingsschema-internal.h +++ b/gio/gsettingsschema-internal.h @@ -37,6 +37,7 @@ struct _GSettingsSchemaKey const GVariantType *type; GVariant *minimum, *maximum; GVariant *default_value; + GVariant *desktop_overrides; gint ref_count; }; @@ -58,6 +59,7 @@ gboolean g_settings_schema_key_type_check (GSettin GVariant * g_settings_schema_key_range_fixup (GSettingsSchemaKey *key, GVariant *value); GVariant * g_settings_schema_key_get_translated_default (GSettingsSchemaKey *key); +GVariant * g_settings_schema_key_get_per_desktop_default (GSettingsSchemaKey *key); gint g_settings_schema_key_to_enum (GSettingsSchemaKey *key, GVariant *value); diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c index f1274a369..17b7e3b01 100644 --- a/gio/gsettingsschema.c +++ b/gio/gsettingsschema.c @@ -27,6 +27,7 @@ #include #include #include +#include /** * SECTION:gsettingsschema @@ -1283,6 +1284,11 @@ g_settings_schema_key_init (GSettingsSchemaKey *key, endian_fixup (&key->maximum); break; + case 'd': + g_variant_get (data, "@a{sv}", &key->desktop_overrides); + endian_fixup (&key->desktop_overrides); + break; + default: g_warning ("unknown schema extension '%c'", code); break; @@ -1303,6 +1309,9 @@ g_settings_schema_key_clear (GSettingsSchemaKey *key) if (key->maximum) g_variant_unref (key->maximum); + if (key->desktop_overrides) + g_variant_unref (key->desktop_overrides); + g_variant_unref (key->default_value); g_settings_schema_unref (key->schema); @@ -1410,6 +1419,35 @@ g_settings_schema_key_get_translated_default (GSettingsSchemaKey *key) return value; } +GVariant * +g_settings_schema_key_get_per_desktop_default (GSettingsSchemaKey *key) +{ + static const gchar * const *current_desktops; + GVariant *value = NULL; + gint i; + + if (!key->desktop_overrides) + return NULL; + + if (g_once_init_enter (¤t_desktops)) + { + const gchar *xdg_current_desktop = g_getenv ("XDG_CURRENT_DESKTOP"); + gchar **tmp; + + if (xdg_current_desktop != NULL && xdg_current_desktop[0] != '\0') + tmp = g_strsplit (xdg_current_desktop, G_SEARCHPATH_SEPARATOR_S, -1); + else + tmp = g_new0 (gchar *, 0 + 1); + + g_once_init_leave (¤t_desktops, (const gchar **) tmp); + } + + for (i = 0; value == NULL && current_desktops[i] != NULL; i++) + value = g_variant_lookup_value (key->desktop_overrides, current_desktops[i], NULL); + + return value; +} + gint g_settings_schema_key_to_enum (GSettingsSchemaKey *key, GVariant *value) @@ -1698,6 +1736,9 @@ g_settings_schema_key_get_default_value (GSettingsSchemaKey *key) value = g_settings_schema_key_get_translated_default (key); + if (!value) + value = g_settings_schema_key_get_per_desktop_default (key); + if (!value) value = g_variant_ref (key->default_value); diff --git a/gio/gsocket.c b/gio/gsocket.c index 11be2e738..859e807cb 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -2957,9 +2957,11 @@ g_socket_check_connect_result (GSocket *socket, gssize g_socket_get_available_bytes (GSocket *socket) { -#ifdef G_OS_WIN32 +#ifndef SO_NREAD const gint bufsize = 64 * 1024; static guchar *buf = NULL; +#endif +#ifdef G_OS_WIN32 u_long avail; #else gint avail; @@ -2967,25 +2969,37 @@ g_socket_get_available_bytes (GSocket *socket) g_return_val_if_fail (G_IS_SOCKET (socket), -1); -#if defined (SO_NREAD) +#ifdef SO_NREAD if (!g_socket_get_option (socket, SOL_SOCKET, SO_NREAD, &avail, NULL)) return -1; -#elif !defined (G_OS_WIN32) - if (ioctl (socket->priv->fd, FIONREAD, &avail) < 0) - avail = -1; #else if (socket->priv->type == G_SOCKET_TYPE_DATAGRAM) { if (G_UNLIKELY (g_once_init_enter (&buf))) g_once_init_leave (&buf, g_malloc (bufsize)); + /* On datagram sockets, FIONREAD ioctl is not reliable because many + * systems add internal header size to the reported size, making it + * unusable for this function. */ avail = recv (socket->priv->fd, buf, bufsize, MSG_PEEK); - if (avail == -1 && get_socket_errno () == WSAEWOULDBLOCK) - avail = 0; + if (avail == -1) + { + int errsv = get_socket_errno (); +#ifdef G_OS_WIN32 + if (errsv == WSAEWOULDBLOCK) +#else + if (errsv == EWOULDBLOCK || errsv == EAGAIN) +#endif + avail = 0; + } } else { +#ifdef G_OS_WIN32 if (ioctlsocket (socket->priv->fd, FIONREAD, &avail) < 0) +#else + if (ioctl (socket->priv->fd, FIONREAD, &avail) < 0) +#endif avail = -1; } #endif diff --git a/gio/gtask.c b/gio/gtask.c index 814ba9433..df40357dd 100644 --- a/gio/gtask.c +++ b/gio/gtask.c @@ -1975,6 +1975,7 @@ g_task_thread_pool_init (void) g_thread_pool_set_sort_function (task_pool, g_task_compare_priority, NULL); task_pool_manager = g_source_new (&trivial_source_funcs, sizeof (GSource)); + g_source_set_name (task_pool_manager, "GTask thread pool manager"); g_source_set_callback (task_pool_manager, task_pool_manager_timeout, NULL, NULL); g_source_set_ready_time (task_pool_manager, -1); g_source_attach (task_pool_manager, diff --git a/gio/gthreadedresolver.c b/gio/gthreadedresolver.c index e89dc156c..9e110cd0b 100644 --- a/gio/gthreadedresolver.c +++ b/gio/gthreadedresolver.c @@ -803,7 +803,9 @@ free_records (GList *records) #if defined(G_OS_UNIX) #ifdef __BIONIC__ +#ifndef C_IN #define C_IN 1 +#endif int res_query(const char *, int, int, u_char *, int); #endif #endif @@ -876,7 +878,7 @@ do_lookup_records (GTask *task, #elif defined(HAVE_RES_NCLOSE) res_nclose (&res); #elif defined(HAVE_RES_NINIT) -#error "Your platform has res_ninit() but not res_nclose() or res_ndestroy(). Please file a bug at https://bugzilla.gnome.org/enter_bug.cgi?product=glib" +#error "Your platform has res_ninit() but not res_nclose() or res_ndestroy(). Please file a bug at https://gitlab.gnome.org/GNOME/glib/issues/new" #endif #endif /* HAVE_RES_NQUERY */ diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index f2db27e66..355329c19 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -307,7 +307,6 @@ g_unix_is_system_fs_type (const char *fs_type) "autofs", "autofs4", "cgroup", - "cifs", "configfs", "cxfs", "debugfs", @@ -329,8 +328,6 @@ g_unix_is_system_fs_type (const char *fs_type) "mfs", "mqueue", "ncpfs", - "nfs", - "nfs4", "nfsd", "nullfs", "ocfs2", @@ -343,7 +340,6 @@ g_unix_is_system_fs_type (const char *fs_type) "rpc_pipefs", "securityfs", "selinuxfs", - "smbfs", "sysfs", "tmpfs", "usbfs", diff --git a/gio/gunixsocketaddress.c b/gio/gunixsocketaddress.c index b0d3c8fe4..27e195e47 100644 --- a/gio/gunixsocketaddress.c +++ b/gio/gunixsocketaddress.c @@ -66,7 +66,9 @@ enum PROP_ADDRESS_TYPE }; +#ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX sizeof (((struct sockaddr_un *) 0)->sun_path) +#endif struct _GUnixSocketAddressPrivate { diff --git a/gio/gvolume.c b/gio/gvolume.c index f97ce4c12..d3bd3b288 100644 --- a/gio/gvolume.c +++ b/gio/gvolume.c @@ -66,7 +66,7 @@ * different kinds of identifiers, such as Hal UDIs, filesystem labels, * traditional Unix devices (e.g. `/dev/sda2`), UUIDs. GIO uses predefined * strings as names for the different kinds of identifiers: - * #G_VOLUME_IDENTIFIER_KIND_HAL_UDI, #G_VOLUME_IDENTIFIER_KIND_LABEL, etc. + * #G_VOLUME_IDENTIFIER_KIND_UUID, #G_VOLUME_IDENTIFIER_KIND_LABEL, etc. * Use g_volume_get_identifier() to obtain an identifier for a volume. * * @@ -195,7 +195,8 @@ g_volume_get_symbolic_icon (GVolume *volume) * considered an opaque string. Returns %NULL if there is no UUID * available. * - * Returns: the UUID for @volume or %NULL if no UUID can be computed. + * Returns: (nullable) (transfer full): the UUID for @volume or %NULL if no UUID + * can be computed. * The returned string should be freed with g_free() * when no longer needed. */ @@ -216,8 +217,8 @@ g_volume_get_uuid (GVolume *volume) * @volume: a #GVolume * * Gets the drive for the @volume. - * - * Returns: (transfer full): a #GDrive or %NULL if @volume is not + * + * Returns: (transfer full) (nullable): a #GDrive or %NULL if @volume is not * associated with a drive. The returned object should be unreffed * with g_object_unref() when no longer needed. */ @@ -238,8 +239,8 @@ g_volume_get_drive (GVolume *volume) * @volume: a #GVolume * * Gets the mount for the @volume. - * - * Returns: (transfer full): a #GMount or %NULL if @volume isn't mounted. + * + * Returns: (transfer full) (nullable): a #GMount or %NULL if @volume isn't mounted. * The returned object should be unreffed with g_object_unref() * when no longer needed. */ @@ -565,8 +566,8 @@ g_volume_eject_with_operation_finish (GVolume *volume, * See the [introduction][volume-identifier] for more * information about volume identifiers. * - * Returns: a newly allocated string containing the - * requested identfier, or %NULL if the #GVolume + * Returns: (nullable) (transfer full): a newly allocated string containing the + * requested identifier, or %NULL if the #GVolume * doesn't have this kind of identifier */ char * @@ -666,7 +667,7 @@ g_volume_get_activation_root (GVolume *volume) * * Gets the sort key for @volume, if any. * - * Returns: Sorting key for @volume or %NULL if no such key is available + * Returns: (nullable): Sorting key for @volume or %NULL if no such key is available * * Since: 2.32 */ diff --git a/gio/gvolume.h b/gio/gvolume.h index c4a506e84..1bb47e5cf 100644 --- a/gio/gvolume.h +++ b/gio/gvolume.h @@ -30,12 +30,16 @@ G_BEGIN_DECLS +#ifndef G_DISABLE_DEPRECATED /** * G_VOLUME_IDENTIFIER_KIND_HAL_UDI: * * The string used to obtain a Hal UDI with g_volume_get_identifier(). + * + * Deprecated: 2.58: Do not use, HAL is deprecated. */ #define G_VOLUME_IDENTIFIER_KIND_HAL_UDI "hal-udi" +#endif /* G_DISABLE_DEPRECATED */ /** * G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE: diff --git a/gio/gwin32notificationbackend.c b/gio/gwin32notificationbackend.c index 7200fdffb..602f3f342 100644 --- a/gio/gwin32notificationbackend.c +++ b/gio/gwin32notificationbackend.c @@ -59,12 +59,18 @@ g_win32_notification_backend_send_notification (GNotificationBackend *backend, const gchar *id, GNotification *notification) { + static gsize warned = 0; + /* FIXME: See https://bugzilla.gnome.org/show_bug.cgi?id=776583. This backend * exists purely to stop crashes when applications use g_notification*() * on Windows, by providing a dummy backend implementation. (The alternative * was to modify all of the backend call sites in g_notification*(), which * seemed less scalable.) */ - g_warning ("Notifications are not yet supported on Windows."); + if (g_once_init_enter (&warned)) + { + g_warning ("Notifications are not yet supported on Windows."); + g_once_init_leave (&warned, 1); + } } static void diff --git a/gio/inotify/Makefile.am b/gio/inotify/Makefile.am index 8b4b3ae18..6dd9136b4 100644 --- a/gio/inotify/Makefile.am +++ b/gio/inotify/Makefile.am @@ -26,3 +26,7 @@ libinotify_la_CFLAGS = \ -DGIO_COMPILATION \ -DG_DISABLE_DEPRECATED +libinotify_la_LIBADD = \ + $(top_builddir)/glib/libglib-2.0.la \ + $(top_builddir)/gobject/libgobject-2.0.la \ + $(NULL) \ No newline at end of file diff --git a/gio/inotify/meson.build b/gio/inotify/meson.build index 1fa8e0464..8183f141e 100644 --- a/gio/inotify/meson.build +++ b/gio/inotify/meson.build @@ -10,6 +10,6 @@ inotify_sources = [ inotify_lib = static_library('inotify', sources : inotify_sources, include_directories : [configinc, glibinc, gmoduleinc], - dependencies : [gioenumtypes_dep], + dependencies : [gioenumtypes_dep, libglib_dep, libgobject_dep], pic : true, c_args : [ '-DG_DISABLE_DEPRECATED' ] + gio_c_args) diff --git a/gio/kqueue/gkqueuefilemonitor.c b/gio/kqueue/gkqueuefilemonitor.c index d6fea41cf..3088296b5 100644 --- a/gio/kqueue/gkqueuefilemonitor.c +++ b/gio/kqueue/gkqueuefilemonitor.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -52,19 +53,44 @@ static int kq_queue = -1; #define G_KQUEUE_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor)) +/* C11 allows type redefinition, but GLib is configured to use C89, which causes + * clang to show warnings when we use a C11 feature. Since the C89 requirement + * is mostly used to support MSVC, we simply ignore the warning here because + * this file is never going to be useful on Windows. */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtypedef-redefinition" +#endif + typedef GLocalFileMonitorClass GKqueueFileMonitorClass; -typedef struct +/* When the file we are monitoring is a directory, sub_dir is subscribed to the + * directory itself and sub_file is NULL. + * + * When the file we are monitoring is a regular file, sub_dir is subscribed to + * the directory containing the file and sub_file is subscribed to the file + * being monitored. We have to monitor both because it is possible that the + * file chosen for monitoring doesn't exist when the file monitor is started. + * We monitor on its parent in order to get notification when it is created. + * + * To distinguish between a directory monitor and a regular file monitor, check + * whether sub_file is NULL. */ +typedef struct _GKqueueFileMonitor { GLocalFileMonitor parent_instance; - kqueue_sub *sub; + kqueue_sub *sub_dir; + kqueue_sub *sub_file; #ifndef O_EVTONLY GFileMonitor *fallback; GFile *fbfile; #endif } GKqueueFileMonitor; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + GType g_kqueue_file_monitor_get_type (void); G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, @@ -78,12 +104,23 @@ G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL #define O_KQFLAG O_EVTONLY #endif -#define NOTE_ALL (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME) +static inline unsigned int +note_all (void) +{ + unsigned int notes = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME; +#ifdef NOTE_TRUNCATE + notes |= NOTE_TRUNCATE; +#endif +#ifdef NOTE_CLOSE_WRITE + notes |= NOTE_CLOSE_WRITE; +#endif + return notes; +} static gboolean g_kqueue_file_monitor_cancel (GFileMonitor* monitor); static gboolean g_kqueue_file_monitor_is_supported (void); -static kqueue_sub *_kqsub_new (const gchar *, GLocalFileMonitor *, GFileMonitorSource *); +static kqueue_sub *_kqsub_new (gchar *, gchar *, GKqueueFileMonitor *, GFileMonitorSource *); static void _kqsub_free (kqueue_sub *); static gboolean _kqsub_cancel (kqueue_sub *); @@ -108,7 +145,7 @@ _fallback_callback (GFileMonitor *unused, * Returns: TRUE if the file should be excluded from the kqueue-powered * monitoring, FALSE otherwise. **/ -gboolean +static gboolean _ke_is_excluded (const char *full_path) { GFile *f = NULL; @@ -121,7 +158,7 @@ _ke_is_excluded (const char *full_path) g_object_unref (f); } - if ((mount != NULL && (g_mount_can_unmount (mount))) || g_str_has_prefix (full_path, "/mnt/")) + if (mount != NULL && (g_str_has_prefix (full_path, "/media/") || g_str_has_prefix (full_path, "/run/media/"))) { g_warning ("Excluding %s from kernel notification, falling back to poll", full_path); if (mount) @@ -138,11 +175,18 @@ g_kqueue_file_monitor_finalize (GObject *object) { GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (object); - if (kqueue_monitor->sub) + if (kqueue_monitor->sub_dir) + { + _kqsub_cancel (kqueue_monitor->sub_dir); + _kqsub_free (kqueue_monitor->sub_dir); + kqueue_monitor->sub_dir = NULL; + } + + if (kqueue_monitor->sub_file) { - _kqsub_cancel (kqueue_monitor->sub); - _kqsub_free (kqueue_monitor->sub); - kqueue_monitor->sub = NULL; + _kqsub_cancel (kqueue_monitor->sub_file); + _kqsub_free (kqueue_monitor->sub_file); + kqueue_monitor->sub_file = NULL; } #ifndef O_EVTONLY @@ -165,17 +209,51 @@ g_kqueue_file_monitor_start (GLocalFileMonitor *local_monitor, GFileMonitorSource *source) { GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (local_monitor); - kqueue_sub *sub; - const gchar *path; - - path = filename; - if (path == NULL) - path = dirname; + kqueue_sub *sub_dir = NULL, *sub_file = NULL; + gchar *path_dir, *path_file, *file_basename; + + /* There are three possible cases here: + * + * 1. Directory: dirname != NULL, basename == NULL, filename == NULL + * 2. Regular file: dirname != NULL, basename != NULL, filename == NULL + * 3. Hard links: dirname == NULL, basename == NULL, filename != NULL + * + * Note that we don't distinguish between case 2 and 3. Kqueue monitors + * files based on file descriptors, so we always receive events come from + * hard links. + */ + if (filename != NULL) + { + path_dir = g_path_get_dirname (filename); + path_file = g_strdup (filename); + file_basename = g_path_get_basename (filename); + } + else + { + path_dir = g_strdup (dirname); + if (basename != NULL) + { + path_file = g_build_filename (dirname, basename, NULL); + file_basename = g_strdup (basename); + } + else + { + path_file = NULL; + file_basename = NULL; + } + } #ifndef O_EVTONLY - if (_ke_is_excluded (path)) + if (_ke_is_excluded (path_dir)) { - GFile *file = g_file_new_for_path (path); + GFile *file; + if (path_file != NULL) + file = g_file_new_for_path (path_file); + else + file = g_file_new_for_path (path_dir); + g_free (path_dir); + g_free (path_file); + g_free (file_basename); kqueue_monitor->fbfile = file; kqueue_monitor->fallback = _g_poll_file_monitor_new (file); g_signal_connect (kqueue_monitor->fallback, "changed", @@ -191,13 +269,30 @@ g_kqueue_file_monitor_start (GLocalFileMonitor *local_monitor, * file, GIO uses a GKqueueFileMonitor object for that. If a directory * will be created under that path, GKqueueFileMonitor will have to * handle the directory notifications. */ - sub = _kqsub_new (path, local_monitor, source); - if (sub == NULL) - return; + sub_dir = _kqsub_new (g_steal_pointer (&path_dir), NULL, + kqueue_monitor, source); + if (!_kqsub_start_watching (sub_dir)) + _km_add_missing (sub_dir); + + /* Unlike GInotifyFileMonitor, which always uses a directory monitor + * regardless of the type of the file being monitored, kqueue doesn't + * give us events generated by files under it when we are monitoring + * a directory. We have to monitor the file itself to know changes which + * was made to the file itself. */ + if (path_file != NULL) + { + sub_file = _kqsub_new (g_steal_pointer (&path_file), + g_steal_pointer (&file_basename), + kqueue_monitor, source); + if (!_kqsub_start_watching (sub_file)) + _km_add_missing (sub_file); + } - kqueue_monitor->sub = sub; - if (!_kqsub_start_watching (sub)) - _km_add_missing (sub); + kqueue_monitor->sub_dir = sub_dir; + kqueue_monitor->sub_file = sub_file; + g_clear_pointer (&path_dir, g_free); + g_clear_pointer (&path_file, g_free); + g_clear_pointer (&file_basename, g_free); } static void @@ -230,59 +325,127 @@ g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_d struct timespec ts; memset (&ts, 0, sizeof(ts)); + + /* We must hold the global lock before accessing any kqueue_sub because it is + * possible for other threads to call g_kqueue_file_monitor_cancel, which may + * free the kqueue_sub struct we are accessing. */ + G_LOCK (kq_lock); + while (kevent(fd, NULL, 0, &ev, 1, &ts) > 0) { - GFileMonitorEvent mask = 0; - if (ev.filter != EVFILT_VNODE || ev.udata == NULL) continue; - sub = ev.udata; + sub = ev.udata; source = sub->source; + /* When we are monitoring a regular file which already exists, ignore + * events generated by its parent directory. This has to be the first + * check to prevent the following code to emit useless events */ + if (sub->is_dir && sub->mon->sub_file != NULL && sub->mon->sub_file->fd != -1) + continue; + if (ev.flags & EV_ERROR) ev.fflags = NOTE_REVOKE; - if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE)) - { - _kqsub_cancel (sub); - _km_add_missing (sub); - } - if (sub->is_dir && ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) { - _kh_dir_diff (sub); + /* If we are monitoring on a non-existent regular file, trigger the + * rescan of missing files immediately so we don't have to wait for + * 4 seconds for discovering missing files. We pass the sub_file + * corresponding to the GKqueueFileMonitor to 'check_this_sub_only' + * argument to prevent _km_scan_missing from emiting 'CREATED' + * events because _kh_dir_diff will do it for us. */ + if (sub->mon->sub_file != NULL && sub->mon->sub_file->fd == -1) + _km_scan_missing (sub->mon->sub_file); + + /* If we are monitoring a regular file, don't emit 'DELETED' events + * from the directory monitor because it will be emitted from the + * file itself when a NOTE_DELETE is reported on sub_file. */ + _kh_dir_diff (sub, sub->mon->sub_file == NULL); + +#ifdef NOTE_TRUNCATE + ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND | NOTE_TRUNCATE); +#else ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND); +#endif } + /* Here starts the long section of mapping kqueue events to + * GFileMonitorEvent. Since kqueue can return multiple events in a + * single kevent struct, we must use 'if' instead of 'else if'. */ if (ev.fflags & NOTE_DELETE) { - mask = G_FILE_MONITOR_EVENT_DELETED; + struct stat st; + if (fstat (sub->fd, &st) < 0) + st.st_nlink = 0; + + g_file_monitor_source_handle_event (source, + G_FILE_MONITOR_EVENT_DELETED, + sub->basename, NULL, NULL, now); + + /* If the last reference to the file was removed, delete the + * subscription from kqueue and add it to the missing list. + * If you are monitoring a file which has hard link count higher + * than 1, it is possible for the same file to emit 'DELETED' + * events multiple times. */ + if (st.st_nlink == 0) + { + _kqsub_cancel (sub); + _km_add_missing (sub); + } } - else if (ev.fflags & NOTE_ATTRIB) + if (ev.fflags & NOTE_REVOKE) + { + g_file_monitor_source_handle_event (source, + G_FILE_MONITOR_EVENT_UNMOUNTED, + sub->basename, NULL, NULL, now); + _kqsub_cancel (sub); + _km_add_missing (sub); + } + if (ev.fflags & NOTE_ATTRIB) { - mask = G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; + g_file_monitor_source_handle_event (source, + G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED, + sub->basename, NULL, NULL, now); } - else if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) +#ifdef NOTE_TRUNCATE + if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND | NOTE_TRUNCATE)) +#else + if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) +#endif { - mask = G_FILE_MONITOR_EVENT_CHANGED; + g_file_monitor_source_handle_event (source, + G_FILE_MONITOR_EVENT_CHANGED, + sub->basename, NULL, NULL, now); } - else if (ev.fflags & NOTE_RENAME) + if (ev.fflags & NOTE_RENAME) { /* Since there’s apparently no way to get the new name of the * file out of kqueue(), all we can do is say that this one has * been deleted. */ - mask = G_FILE_MONITOR_EVENT_DELETED; + g_file_monitor_source_handle_event (source, + G_FILE_MONITOR_EVENT_DELETED, + sub->basename, NULL, NULL, now); } - else if (ev.fflags & NOTE_REVOKE) +#ifdef NOTE_CLOSE_WRITE + if (ev.fflags & NOTE_CLOSE_WRITE) { - mask = G_FILE_MONITOR_EVENT_UNMOUNTED; + g_file_monitor_source_handle_event (source, + G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, + sub->basename, NULL, NULL, now); } +#endif - if (mask) - g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, now); + /* Handle the case when a file is created again shortly after it was + * deleted. It has to be the last check because 'DELETED' must happen + * before 'CREATED'. */ + if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE)) + _km_scan_missing (NULL); } + G_UNLOCK (kq_lock); + return TRUE; } @@ -320,14 +483,28 @@ g_kqueue_file_monitor_cancel (GFileMonitor *monitor) { GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (monitor); - if (kqueue_monitor->sub) + /* We must hold the global lock before calling _kqsub_cancel. However, we + * cannot call G_LOCK in _kqsub_cancel because it is also used by + * g_kqueue_file_monitor_callback, which already holds the lock itself. */ + G_LOCK (kq_lock); + + if (kqueue_monitor->sub_dir) { - _kqsub_cancel (kqueue_monitor->sub); - _kqsub_free (kqueue_monitor->sub); - kqueue_monitor->sub = NULL; + _kqsub_cancel (kqueue_monitor->sub_dir); + _kqsub_free (kqueue_monitor->sub_dir); + kqueue_monitor->sub_dir = NULL; } + if (kqueue_monitor->sub_file) + { + _kqsub_cancel (kqueue_monitor->sub_file); + _kqsub_free (kqueue_monitor->sub_file); + kqueue_monitor->sub_file = NULL; + } + + G_UNLOCK (kq_lock); + #ifndef O_EVTONLY - else if (kqueue_monitor->fallback) + if (kqueue_monitor->fallback) { g_signal_handlers_disconnect_by_func (kqueue_monitor->fallback, _fallback_callback, kqueue_monitor); g_file_monitor_cancel (kqueue_monitor->fallback); @@ -341,12 +518,13 @@ g_kqueue_file_monitor_cancel (GFileMonitor *monitor) } static kqueue_sub * -_kqsub_new (const gchar *filename, GLocalFileMonitor *mon, GFileMonitorSource *source) +_kqsub_new (gchar *filename, gchar *basename, GKqueueFileMonitor *mon, GFileMonitorSource *source) { kqueue_sub *sub; sub = g_slice_new (kqueue_sub); - sub->filename = g_strdup (filename); + sub->filename = filename; + sub->basename = basename; sub->mon = mon; g_source_ref ((GSource *) source); sub->source = source; @@ -365,19 +543,23 @@ _kqsub_free (kqueue_sub *sub) g_source_unref ((GSource *) sub->source); g_free (sub->filename); + g_free (sub->basename); g_slice_free (kqueue_sub, sub); } static gboolean _kqsub_cancel (kqueue_sub *sub) { + /* WARNING: Before calling this function, you must hold a lock on kq_lock + * or you will cause use-after-free in g_kqueue_file_monitor_callback. */ + struct kevent ev; /* Remove the event and close the file descriptor to automatically * delete pending events. */ if (sub->fd != -1) { - EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, NOTE_ALL, 0, sub); + EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, note_all (), 0, sub); if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) { g_warning ("Unable to remove event for %s: %s", sub->filename, g_strerror (errno)); @@ -425,7 +607,7 @@ _kqsub_start_watching (kqueue_sub *sub) sub->deps = dl_listing (sub->filename); } - EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_ALL, 0, sub); + EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, note_all (), 0, sub); if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) { g_warning ("Unable to add event for %s: %s", sub->filename, g_strerror (errno)); diff --git a/gio/kqueue/kqueue-helper.c b/gio/kqueue/kqueue-helper.c index 497c30b15..36a5b58a7 100644 --- a/gio/kqueue/kqueue-helper.c +++ b/gio/kqueue/kqueue-helper.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ typedef struct { kqueue_sub *sub; GFileMonitorSource *source; + gboolean handle_deleted; } handle_ctx; /** @@ -53,6 +55,9 @@ static void handle_created (void *udata, const char *path, ino_t inode) { handle_ctx *ctx = NULL; + gint64 now; + gchar *fullname; + struct stat st; (void) inode; ctx = (handle_ctx *) udata; @@ -60,8 +65,16 @@ handle_created (void *udata, const char *path, ino_t inode) g_assert (ctx->sub != NULL); g_assert (ctx->source != NULL); + now = g_get_monotonic_time (); g_file_monitor_source_handle_event (ctx->source, G_FILE_MONITOR_EVENT_CREATED, path, - NULL, NULL, g_get_monotonic_time ()); + NULL, NULL, now); + + /* Copied from ih_event_callback to report 'CHANGES_DONE_HINT' earlier. */ + fullname = g_build_filename (ctx->sub->filename, path, NULL); + if (stat (fullname, &st) != 0 || !S_ISREG (st.st_mode) || st.st_nlink != 1) + g_file_monitor_source_handle_event (ctx->source, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, path, + NULL, NULL, now); + g_free (fullname); } /** @@ -84,6 +97,9 @@ handle_deleted (void *udata, const char *path, ino_t inode) g_assert (ctx->sub != NULL); g_assert (ctx->source != NULL); + if (!ctx->handle_deleted) + return; + g_file_monitor_source_handle_event (ctx->source, G_FILE_MONITOR_EVENT_DELETED, path, NULL, NULL, g_get_monotonic_time ()); } @@ -161,7 +177,7 @@ static const traverse_cbs cbs = { void -_kh_dir_diff (kqueue_sub *sub) +_kh_dir_diff (kqueue_sub *sub, gboolean handle_deleted) { dep_list *was; handle_ctx ctx; @@ -169,6 +185,7 @@ _kh_dir_diff (kqueue_sub *sub) memset (&ctx, 0, sizeof (handle_ctx)); ctx.sub = sub; ctx.source = sub->source; + ctx.handle_deleted = handle_deleted; was = sub->deps; sub->deps = dl_listing (sub->filename); diff --git a/gio/kqueue/kqueue-helper.h b/gio/kqueue/kqueue-helper.h index 38a32a2f9..418b38c08 100644 --- a/gio/kqueue/kqueue-helper.h +++ b/gio/kqueue/kqueue-helper.h @@ -28,26 +28,33 @@ #include "dep-list.h" +typedef struct _GKqueueFileMonitor GKqueueFileMonitor; + /** * kqueue_sub: + * @mon: a pointer to the GKqueueFileMonitor which holds this subscription * @filename: a name of the file to monitor * @fd: the associated file descriptor (used by kqueue) * - * Represents a subscription on a file or directory. + * Represents a subscription on a file or directory. To check whether a + * subscription is active, check the fd field. If fd is not -1, it is an + * active subscription which can emit events from kqueue. */ typedef struct { - GLocalFileMonitor *mon; + GKqueueFileMonitor *mon; GFileMonitorSource *source; gchar* filename; + gchar* basename; int fd; dep_list* deps; int is_dir; } kqueue_sub; gboolean _kqsub_start_watching (kqueue_sub *sub); -void _kh_dir_diff (kqueue_sub *sub); +void _kh_dir_diff (kqueue_sub *sub, gboolean handle_deleted); void _km_add_missing (kqueue_sub *sub); +gboolean _km_scan_missing (kqueue_sub *check_this_sub_only); void _km_remove (kqueue_sub *sub); #endif /* __KQUEUE_HELPER_H */ diff --git a/gio/kqueue/kqueue-missing.c b/gio/kqueue/kqueue-missing.c index 93135b962..37af82e5b 100644 --- a/gio/kqueue/kqueue-missing.c +++ b/gio/kqueue/kqueue-missing.c @@ -21,16 +21,13 @@ *******************************************************************************/ #include +#include "glib-private.h" #include "kqueue-helper.h" #define SCAN_MISSING_TIME 4 /* 1/4 Hz */ -void _kh_file_appeared_cb (kqueue_sub *sub); - -static gboolean km_scan_missing (gpointer user_data); - static gboolean km_debug_enabled = FALSE; #define KM_W if (km_debug_enabled) g_warning @@ -40,6 +37,12 @@ G_LOCK_DEFINE_STATIC (missing_lock); static volatile gboolean scan_missing_running = FALSE; +static gboolean +_km_scan_missing_cb (gpointer user_data) +{ + return _km_scan_missing (NULL); +} + /** * _km_add_missing: * @sub: a #kqueue_sub @@ -63,8 +66,12 @@ _km_add_missing (kqueue_sub *sub) if (!scan_missing_running) { + GSource *source; scan_missing_running = TRUE; - g_timeout_add_seconds (SCAN_MISSING_TIME, km_scan_missing, NULL); + source = g_timeout_source_new_seconds (SCAN_MISSING_TIME); + g_source_set_callback (source, _km_scan_missing_cb, NULL, NULL); + g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ()); + g_source_unref (source); } } @@ -77,10 +84,10 @@ _km_add_missing (kqueue_sub *sub) * Signals that a missing file has finally appeared in the filesystem. * Emits %G_FILE_MONITOR_EVENT_CREATED. **/ -void +static void _kh_file_appeared_cb (kqueue_sub *sub) { - GFile *child; + gint64 now = g_get_monotonic_time (); g_assert (sub != NULL); g_assert (sub->filename); @@ -88,18 +95,14 @@ _kh_file_appeared_cb (kqueue_sub *sub) if (!g_file_test (sub->filename, G_FILE_TEST_EXISTS)) return; - child = g_file_new_for_path (sub->filename); - - g_file_monitor_emit_event (G_FILE_MONITOR (sub->mon), - child, - NULL, - G_FILE_MONITOR_EVENT_CREATED); - - g_object_unref (child); + g_file_monitor_source_handle_event (sub->source, G_FILE_MONITOR_EVENT_CREATED, + sub->basename, NULL, NULL, now); + g_file_monitor_source_handle_event (sub->source, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, + sub->basename, NULL, NULL, now); } /** - * km_scan_missing: + * _km_scan_missing: * @user_data: unused * * The core missing files watching routine. @@ -110,8 +113,8 @@ _kh_file_appeared_cb (kqueue_sub *sub) * * Returns: %FALSE if no missing files left, %TRUE otherwise. **/ -static gboolean -km_scan_missing (gpointer user_data) +gboolean +_km_scan_missing (kqueue_sub *check_this_sub_only) { GSList *head; GSList *not_missing = NULL; @@ -128,10 +131,14 @@ km_scan_missing (gpointer user_data) g_assert (sub != NULL); g_assert (sub->filename != NULL); + if (check_this_sub_only != NULL && sub != check_this_sub_only) + continue; + if (_kqsub_start_watching (sub)) { KM_W ("file %s now exists, starting watching", sub->filename); - _kh_file_appeared_cb (sub); + if (check_this_sub_only == NULL) + _kh_file_appeared_cb (sub); not_missing = g_slist_prepend (not_missing, head); } } diff --git a/gio/meson.build b/gio/meson.build index 42f67715d..a6af822b5 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -164,12 +164,6 @@ if host_system != 'windows' endif -network_args_string = '' -foreach arg : network_args - network_args_string += arg + ' ' -endforeach -glib_conf.set('NETWORK_LIBS', network_args_string) - gnetworking_h_conf.set('WSPIAPI_INCLUDE', gnetworking_h_wspiapi_include) gnetworking_h_conf.set('NAMESER_COMPAT_INCLUDE', gnetworking_h_nameser_compat_include) @@ -240,7 +234,6 @@ subdir('gdbus-2.0/codegen') xdp_dbus_generated = custom_target('xdp-dbus', input : ['org.freedesktop.portal.Documents.xml', 'org.freedesktop.portal.OpenURI.xml', - 'org.freedesktop.portal.NetworkMonitor.xml', 'org.freedesktop.portal.ProxyResolver.xml'], output : ['xdp-dbus.h', 'xdp-dbus.c'], depend_files : gdbus_codegen_built_files, @@ -292,11 +285,6 @@ if host_system == 'windows' settings_sources += files('gregistrysettingsbackend.c') endif -# FIXME: -#if OS_COCOA -#settings_sources += files('gnextstepsettingsbackend.c') -#endif - application_headers = files( 'gapplication.h', 'gapplicationcommandline.h', @@ -412,19 +400,27 @@ if host_system != 'windows' ) if glib_have_cocoa - contenttype_sources += files('gosxcontenttype.c') - appinfo_sources += files('gosxappinfo.c') + settings_sources += files('gnextstepsettingsbackend.m') + contenttype_sources += files('gosxcontenttype.m') + appinfo_sources += files('gosxappinfo.m') if glib_have_os_x_9_or_later - unix_sources += files('gcocoanotificationbackend.c') + unix_sources += files('gcocoanotificationbackend.m') endif else contenttype_sources += files('gcontenttype.c') appinfo_sources += files('gdesktopappinfo.c') gio_unix_include_headers += files('gdesktopappinfo.h') - subdir('xdgmime') - internal_deps += [xdgmime_lib] + + executable('gio-launch-desktop', 'gio-launch-desktop.c', + install : true, + c_args : gio_c_args, + # intl.lib is not compatible with SAFESEH + link_args : noseh_link_args) endif + subdir('xdgmime') + internal_deps += [xdgmime_lib] + install_headers(gio_unix_include_headers, subdir : 'gio-unix-2.0/gio') if glib_conf.has('HAVE_NETLINK') @@ -762,15 +758,11 @@ if host_system == 'windows' internal_deps += [ giowin32_lib ] endif -# FIXME: FAM support -#if HAVE_FAM -# subdir('fam') -#endif - if have_bash install_data([ 'completion/gapplication', 'completion/gdbus', + 'completion/gio', 'completion/gsettings', 'completion/gresource' ], @@ -798,6 +790,7 @@ libgio = library('gio-2.0', libgobject_dep, libgmodule_dep, selinux_dep, xattr_dep, platform_deps, network_libs], c_args : gio_c_args, + objc_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : [noseh_link_args, glib_link_flags], ) @@ -857,9 +850,26 @@ else endif # Dependencies used by executables below +have_libelf = false libelf = dependency('libelf', version : '>= 0.8.12', required : false) if libelf.found() + have_libelf = true +else + # This fallback is necessary on *BSD. elfutils isn't the only libelf + # implementation, and *BSD usually includes their own libelf as a system + # library which doesn't have a corresponding .pc file. + libelf = cc.find_library('elf', required : false) + have_libelf = libelf.found() + have_libelf = have_libelf and cc.has_function('elf_begin', dependencies : libelf) + have_libelf = have_libelf and cc.has_function('elf_getshdrstrndx', dependencies : libelf) + have_libelf = have_libelf and cc.has_function('elf_getshdrnum', dependencies : libelf) + have_libelf = have_libelf and cc.has_header('libelf.h') +endif + +if have_libelf glib_conf.set('HAVE_LIBELF', 1) +else + libelf = [] endif gconstructor_as_data_h = custom_target('gconstructor_as_data.h', @@ -902,7 +912,7 @@ executable('gresource', 'gresource-tool.c', link_args : noseh_link_args, dependencies : [libelf, libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) -executable('gio-querymodules', 'gio-querymodules.c', 'giomodule-priv.c', +gio_querymodules = executable('gio-querymodules', 'gio-querymodules.c', 'giomodule-priv.c', install : true, c_args : gio_c_args, # intl.lib is not compatible with SAFESEH @@ -943,7 +953,7 @@ executable('gdbus', 'gdbus-tool.c', link_args : noseh_link_args, dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) -if host_system != 'windows' +if host_system != 'windows' and not glib_have_cocoa executable('gapplication', 'gapplication-tool.c', install : true, c_args : gio_c_args, @@ -960,6 +970,8 @@ if enable_systemtap install : true) endif +subdir('fam') + if host_system != 'windows' subdir('tests') endif diff --git a/gio/org.freedesktop.portal.NetworkMonitor.xml b/gio/org.freedesktop.portal.NetworkMonitor.xml deleted file mode 100644 index 8d3a471d5..000000000 --- a/gio/org.freedesktop.portal.NetworkMonitor.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index 410f11d95..e3e8da05a 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -15,7 +15,9 @@ LDADD = \ AM_CPPFLAGS = $(gio_INCLUDES) $(GLIB_DEBUG_FLAGS) -I$(top_builddir)/gio -I$(top_srcdir)/gio DEFS = -DG_LOG_DOMAIN=\"GLib-GIO\" -DTEST_SERVICES=\""$(abs_top_builddir)/gio/tests/services"\" AM_CFLAGS = $(GLIB_WARN_CFLAGS) -AM_TESTS_ENVIRONMENT += GIO_MODULE_DIR= +AM_TESTS_ENVIRONMENT += \ + GIO_MODULE_DIR= \ + GIO_LAUNCH_DESKTOP="$(top_builddir)/gio/gio-launch-desktop" # ----------------------------------------------------------------------------- # Test programs buildable on all platforms @@ -47,6 +49,7 @@ test_programs = \ memory-input-stream \ memory-output-stream \ monitor \ + mount-operation \ network-address \ network-monitor \ network-monitor-race \ @@ -273,6 +276,7 @@ test_programs += \ unix-mounts \ unix-streams \ g-file-info-filesystem-readonly \ + trash \ $(NULL) test_extra_programs += \ @@ -368,12 +372,14 @@ test.mo: de.po EXTRA_DIST += de.po dist_uninstalled_test_data += \ org.gtk.test.gschema.xml.orig \ + org.gtk.test.gschema.override.orig \ org.gtk.schemasourcecheck.gschema.xml \ testenum.h \ enums.xml.template # Generated while running the testcase itself... CLEANFILES += \ org.gtk.test.gschema.xml \ + org.gtk.test.gschema.override \ org.gtk.test.enums.xml \ gsettings.store \ gschemas.compiled \ @@ -551,7 +557,8 @@ nodist_resources_SOURCES = test_resources.c test_resources2.c test_resources2.h resources_DEPENDENCIES = test.gresource test_ltlibraries += libresourceplugin.la -libresourceplugin_la_SOURCES = resourceplugin.c plugin_resources.c +libresourceplugin_la_SOURCES = resourceplugin.c +nodist_libresourceplugin_la_SOURCES = plugin_resources.c libresourceplugin_la_LDFLAGS = -avoid-version -module -export-dynamic $(no_undefined) libresourceplugin_la_LIBADD = $(LDADD) diff --git a/gio/tests/appinfo.c b/gio/tests/appinfo.c index 2e69da051..a52bc7094 100644 --- a/gio/tests/appinfo.c +++ b/gio/tests/appinfo.c @@ -17,7 +17,7 @@ test_launch_for_app_info (GAppInfo *appinfo) if (g_getenv ("DISPLAY") == NULL || g_getenv ("DISPLAY")[0] == '\0') { - g_printerr ("No DISPLAY. Skipping test. "); + g_test_skip ("No DISPLAY set"); return; } @@ -128,10 +128,10 @@ static void test_locale (const char *locale) { GAppInfo *appinfo; - const gchar *orig; + gchar *orig = NULL; const gchar *path; - orig = setlocale (LC_ALL, NULL); + orig = g_strdup (setlocale (LC_ALL, NULL)); g_setenv ("LANGUAGE", locale, TRUE); setlocale (LC_ALL, ""); @@ -161,6 +161,7 @@ test_locale (const char *locale) g_setenv ("LANGUAGE", orig, TRUE); setlocale (LC_ALL, ""); + g_free (orig); } static void @@ -380,6 +381,7 @@ test_associations (void) "cmdline-app-test", G_APP_INFO_CREATE_SUPPORTS_URIS, NULL); + g_free (cmdline); error = NULL; result = g_app_info_set_as_default_for_type (appinfo, "application/x-glib-test", &error); diff --git a/gio/tests/dbus-appinfo.c b/gio/tests/dbus-appinfo.c index ee73d5833..8961a5495 100644 --- a/gio/tests/dbus-appinfo.c +++ b/gio/tests/dbus-appinfo.c @@ -254,11 +254,14 @@ test_dbus_appinfo (void) const gchar *argv[] = { "myapp", NULL }; TestApplication *app; int status; + gchar *desktop_file = NULL; - appinfo = g_desktop_app_info_new_from_filename (g_test_build_filename (G_TEST_DIST, - "org.gtk.test.dbusappinfo.desktop", - NULL)); + desktop_file = g_test_build_filename (G_TEST_DIST, + "org.gtk.test.dbusappinfo.desktop", + NULL); + appinfo = g_desktop_app_info_new_from_filename (desktop_file); g_assert (appinfo != NULL); + g_free (desktop_file); app = g_object_new (test_application_get_type (), "application-id", "org.gtk.test.dbusappinfo", diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c index 669db5769..4871d85a5 100644 --- a/gio/tests/desktop-app-info.c +++ b/gio/tests/desktop-app-info.c @@ -93,6 +93,8 @@ test_delete (void) res = g_app_info_delete (info); g_assert (!res); } + + g_free (filename); } static void @@ -115,6 +117,7 @@ test_default (void) info = g_app_info_get_default_for_type ("application/x-test", FALSE); g_assert (info != NULL); g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2)); + g_object_unref (info); /* now try adding something, but not setting as default */ g_app_info_add_supports_type (info3, "application/x-test", &error); @@ -124,6 +127,7 @@ test_default (void) info = g_app_info_get_default_for_type ("application/x-test", FALSE); g_assert (info != NULL); g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2)); + g_object_unref (info); /* now remove info1 again */ g_app_info_remove_supports_type (info1, "application/x-test", &error); @@ -133,6 +137,7 @@ test_default (void) info = g_app_info_get_default_for_type ("application/x-test", FALSE); g_assert (info != NULL); g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2)); + g_object_unref (info); /* now clean it all up */ g_app_info_reset_type_associations ("application/x-test"); @@ -146,6 +151,7 @@ test_default (void) g_object_unref (info1); g_object_unref (info2); + g_object_unref (info3); } static void @@ -324,6 +330,8 @@ cleanup_dir_recurse (GFile *parent, ret = TRUE; out: + g_clear_object (&enumerator); + return ret; } @@ -342,6 +350,7 @@ cleanup_subdirs (const char *base_dir) (void) cleanup_dir_recurse (file, file, &error); g_assert_no_error (error); g_object_unref (file); + g_object_unref (base); } static void @@ -788,6 +797,46 @@ test_show_in (void) assert_shown ("gcr-prompter.desktop", TRUE, "KDE:GNOME-Classic"); } +/* Test g_desktop_app_info_launch_uris_as_manager() and + * g_desktop_app_info_launch_uris_as_manager_with_fds() + */ +static void +test_launch_as_manager (void) +{ + GDesktopAppInfo *appinfo; + GError *error = NULL; + gboolean retval; + const gchar *path; + + if (g_getenv ("DISPLAY") == NULL || g_getenv ("DISPLAY")[0] == '\0') + { + g_test_skip ("No DISPLAY. Skipping test."); + return; + } + + path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL); + appinfo = g_desktop_app_info_new_from_filename (path); + g_assert_nonnull (appinfo); + + retval = g_desktop_app_info_launch_uris_as_manager (appinfo, NULL, NULL, 0, + NULL, NULL, + NULL, NULL, + &error); + g_assert_no_error (error); + g_assert_true (retval); + + retval = g_desktop_app_info_launch_uris_as_manager_with_fds (appinfo, + NULL, NULL, 0, + NULL, NULL, + NULL, NULL, + -1, -1, -1, + &error); + g_assert_no_error (error); + g_assert_true (retval); + + g_object_unref (appinfo); +} + int main (int argc, char *argv[]) @@ -816,6 +865,7 @@ main (int argc, g_test_add_func ("/desktop-app-info/search", test_search); g_test_add_func ("/desktop-app-info/implements", test_implements); g_test_add_func ("/desktop-app-info/show-in", test_show_in); + g_test_add_func ("/desktop-app-info/launch-as-manager", test_launch_as_manager); result = g_test_run (); diff --git a/gio/tests/file.c b/gio/tests/file.c index 04625fd68..d2f147419 100644 --- a/gio/tests/file.c +++ b/gio/tests/file.c @@ -477,7 +477,15 @@ test_create_delete (gconstpointer d) * that the monitor will notice a create immediately followed by a * delete, rather than coalescing them into nothing. */ - if (!strcmp (G_OBJECT_TYPE_NAME (data->monitor), "GPollFileMonitor")) + /* This test also doesn't work with GKqueueFileMonitor because of + * the same reason. Kqueue is able to return a kevent when a file is + * created or deleted in a directory. However, the kernel doesn't tell + * the program file names, so GKqueueFileMonitor has to calculate the + * difference itself. This is usually too slow for rapid file creation + * and deletion tests. + */ + if (strcmp (G_OBJECT_TYPE_NAME (data->monitor), "GPollFileMonitor") == 0 || + strcmp (G_OBJECT_TYPE_NAME (data->monitor), "GKqueueFileMonitor") == 0) { g_test_skip ("skipping test for this GFileMonitor implementation"); goto skip; @@ -897,14 +905,21 @@ splice_to_string (GInputStream *stream, return ret; } -static guint64 -get_size_from_du (const gchar *path) +static gboolean +get_size_from_du (const gchar *path, guint64 *size) { GSubprocess *du; + gboolean ok; gchar *result; gchar *endptr; - guint64 size; GError *error = NULL; + gchar *du_path = NULL; + + /* If we can’t find du, don’t try and run the test. */ + du_path = g_find_program_in_path ("du"); + if (du_path == NULL) + return FALSE; + g_free (du_path); du = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, @@ -914,12 +929,17 @@ get_size_from_du (const gchar *path) result = splice_to_string (g_subprocess_get_stdout_pipe (du), &error); g_assert_no_error (error); - size = g_ascii_strtoll (result, &endptr, 10); + *size = g_ascii_strtoll (result, &endptr, 10); + + g_subprocess_wait (du, NULL, &error); + g_assert_no_error (error); + + ok = g_subprocess_get_successful (du); g_object_unref (du); g_free (result); - return size; + return ok; } static void @@ -937,13 +957,9 @@ test_measure (void) path = g_test_build_filename (G_TEST_DIST, "desktop-files", NULL); file = g_file_new_for_path (path); - if (g_find_program_in_path ("du")) - { - size = get_size_from_du (path); - } - else + if (!get_size_from_du (path, &size)) { - g_test_message ("du not found, skipping byte measurement"); + g_test_message ("du not found or fail to run, skipping byte measurement"); size = 0; } @@ -1043,13 +1059,9 @@ test_measure_async (void) path = g_test_build_filename (G_TEST_DIST, "desktop-files", NULL); file = g_file_new_for_path (path); - if (g_find_program_in_path ("du")) - { - data->expected_bytes = get_size_from_du (path); - } - else + if (!get_size_from_du (path, &data->expected_bytes)) { - g_test_message ("du not found, skipping byte measurement"); + g_test_message ("du not found or fail to run, skipping byte measurement"); data->expected_bytes = 0; } diff --git a/gio/tests/g-file-info-filesystem-readonly.c b/gio/tests/g-file-info-filesystem-readonly.c index c2b0aa518..123dcd8a0 100644 --- a/gio/tests/g-file-info-filesystem-readonly.c +++ b/gio/tests/g-file-info-filesystem-readonly.c @@ -45,6 +45,8 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) { /* We need these because "mount --bind" requires root privileges */ g_test_skip ("'bindfs' and 'fusermount' commands are needed to run this test"); + g_free (fusermount); + g_free (bindfs); return; } diff --git a/gio/tests/gapplication.c b/gio/tests/gapplication.c index 336135cb4..f5491ec9e 100644 --- a/gio/tests/gapplication.c +++ b/gio/tests/gapplication.c @@ -972,6 +972,8 @@ test_api (void) int main (int argc, char **argv) { + g_setenv ("LC_ALL", "C", TRUE); + g_test_init (&argc, &argv, NULL); g_test_dbus_unset (); diff --git a/gio/tests/gdbus-addresses.c b/gio/tests/gdbus-addresses.c index 2e662d000..0ab05661a 100644 --- a/gio/tests/gdbus-addresses.c +++ b/gio/tests/gdbus-addresses.c @@ -39,65 +39,86 @@ test_empty_address (void) g_error_free (error); } +static void +assert_is_supported_address (const gchar *address) +{ + GError *error = NULL; + + g_assert_true (g_dbus_is_supported_address (address, NULL)); + g_assert_true (g_dbus_is_supported_address (address, &error)); + g_assert_no_error (error); +} + +static void +assert_not_supported_address (const gchar *address) +{ + GError *error = NULL; + + g_assert_false (g_dbus_is_supported_address (address, NULL)); + g_assert_false (g_dbus_is_supported_address (address, &error)); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT); + g_clear_error (&error); +} + #ifdef G_OS_UNIX static void test_unix_address (void) { - g_assert (!g_dbus_is_supported_address ("some-imaginary-transport:foo=bar", NULL)); - g_assert (g_dbus_is_supported_address ("unix:path=/tmp/dbus-test", NULL)); - g_assert (g_dbus_is_supported_address ("unix:abstract=/tmp/dbus-another-test", NULL)); + assert_not_supported_address ("some-imaginary-transport:foo=bar"); + assert_is_supported_address ("unix:path=/tmp/dbus-test"); + assert_is_supported_address ("unix:abstract=/tmp/dbus-another-test"); g_assert (g_dbus_is_address ("unix:foo=bar")); - g_assert (!g_dbus_is_supported_address ("unix:foo=bar", NULL)); + assert_not_supported_address ("unix:foo=bar"); g_assert (!g_dbus_is_address ("unix:path=/foo;abstract=/bar")); - g_assert (!g_dbus_is_supported_address ("unix:path=/foo;abstract=/bar", NULL)); - g_assert (g_dbus_is_supported_address ("unix:path=/tmp/concrete;unix:abstract=/tmp/abstract", NULL)); + assert_not_supported_address ("unix:path=/foo;abstract=/bar"); + assert_is_supported_address ("unix:path=/tmp/concrete;unix:abstract=/tmp/abstract"); g_assert (g_dbus_is_address ("some-imaginary-transport:foo=bar")); g_assert (g_dbus_is_address ("some-imaginary-transport:foo=bar;unix:path=/this/is/valid")); - g_assert (!g_dbus_is_supported_address ("some-imaginary-transport:foo=bar;unix:path=/this/is/valid", NULL)); + assert_not_supported_address ("some-imaginary-transport:foo=bar;unix:path=/this/is/valid"); } #endif static void test_nonce_tcp_address (void) { - g_assert (g_dbus_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar", NULL)); - g_assert (g_dbus_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar,family=ipv6", NULL)); - g_assert (g_dbus_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar,family=ipv4", NULL)); - - g_assert (!g_dbus_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar,family=blah", NULL)); - g_assert (!g_dbus_is_supported_address ("nonce-tcp:host=localhost,port=420000,noncefile=/foo/bar,family=ipv4", NULL)); - g_assert (!g_dbus_is_supported_address ("nonce-tcp:host=,port=x42,noncefile=/foo/bar,family=ipv4", NULL)); - g_assert (!g_dbus_is_supported_address ("nonce-tcp:host=,port=42x,noncefile=/foo/bar,family=ipv4", NULL)); - g_assert (!g_dbus_is_supported_address ("nonce-tcp:host=,port=420000,noncefile=/foo/bar,family=ipv4", NULL)); + assert_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar"); + assert_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar,family=ipv6"); + assert_is_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar,family=ipv4"); + + assert_not_supported_address ("nonce-tcp:host=localhost,port=42,noncefile=/foo/bar,family=blah"); + assert_not_supported_address ("nonce-tcp:host=localhost,port=420000,noncefile=/foo/bar,family=ipv4"); + assert_not_supported_address ("nonce-tcp:host=,port=x42,noncefile=/foo/bar,family=ipv4"); + assert_not_supported_address ("nonce-tcp:host=,port=42x,noncefile=/foo/bar,family=ipv4"); + assert_not_supported_address ("nonce-tcp:host=,port=420000,noncefile=/foo/bar,family=ipv4"); } static void test_tcp_address (void) { - g_assert (g_dbus_is_supported_address ("tcp:host=localhost", NULL)); - g_assert (!g_dbus_is_supported_address ("tcp:host=localhost,noncefile=/tmp/foo", NULL)); - g_assert (g_dbus_is_supported_address ("tcp:host=localhost,port=42", NULL)); - g_assert (!g_dbus_is_supported_address ("tcp:host=localhost,port=-1", NULL)); - g_assert (!g_dbus_is_supported_address ("tcp:host=localhost,port=420000", NULL)); - g_assert (!g_dbus_is_supported_address ("tcp:host=localhost,port=42x", NULL)); - g_assert (g_dbus_is_supported_address ("tcp:host=localhost,port=42,family=ipv4", NULL)); - g_assert (g_dbus_is_supported_address ("tcp:host=localhost,port=42,family=ipv6", NULL)); - g_assert (!g_dbus_is_supported_address ("tcp:host=localhost,port=42,family=sopranos", NULL)); + assert_is_supported_address ("tcp:host=localhost"); + assert_not_supported_address ("tcp:host=localhost,noncefile=/tmp/foo"); + assert_is_supported_address ("tcp:host=localhost,port=42"); + assert_not_supported_address ("tcp:host=localhost,port=-1"); + assert_not_supported_address ("tcp:host=localhost,port=420000"); + assert_not_supported_address ("tcp:host=localhost,port=42x"); + assert_is_supported_address ("tcp:host=localhost,port=42,family=ipv4"); + assert_is_supported_address ("tcp:host=localhost,port=42,family=ipv6"); + assert_not_supported_address ("tcp:host=localhost,port=42,family=sopranos"); } static void test_autolaunch_address (void) { - g_assert (g_dbus_is_supported_address ("autolaunch:", NULL)); + assert_is_supported_address ("autolaunch:"); } static void test_mixed_address (void) { - g_assert (g_dbus_is_supported_address ("unix:path=/tmp/dbus1;unix:path=/tmp/dbus2", NULL)); - g_assert (g_dbus_is_supported_address ("tcp:host=localhost,port=42;autolaunch:", NULL)); - g_assert (!g_dbus_is_supported_address ("tcp:host=localhost,port=42;tcp:family=bla", NULL)); + assert_is_supported_address ("unix:path=/tmp/dbus1;unix:path=/tmp/dbus2"); + assert_is_supported_address ("tcp:host=localhost,port=42;autolaunch:"); + assert_not_supported_address ("tcp:host=localhost,port=42;tcp:family=bla"); } static const struct { const char *before; const char *after; } escaping[] = { diff --git a/gio/tests/gdbus-connection-loss.c b/gio/tests/gdbus-connection-loss.c index 6f0140986..9dbbeb2a4 100644 --- a/gio/tests/gdbus-connection-loss.c +++ b/gio/tests/gdbus-connection-loss.c @@ -136,7 +136,10 @@ main (int argc, ret = g_test_run(); + session_bus_down (); + g_object_unref (c); + g_main_loop_unref (loop); return ret; } diff --git a/gio/tests/gdbus-example-peer.c b/gio/tests/gdbus-example-peer.c index b954f7426..179aabb7f 100644 --- a/gio/tests/gdbus-example-peer.c +++ b/gio/tests/gdbus-example-peer.c @@ -273,7 +273,8 @@ main (int argc, char *argv[]) "Negotiated capabilities: unix-fd-passing=%d\n", g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); - greeting = g_strdup_printf ("Hey, it's %" G_GUINT64_FORMAT " already!", (guint64) time (NULL)); + greeting = g_strdup_printf ("Hey, it's %" G_GINT64_FORMAT " already!", + g_get_real_time () / G_USEC_PER_SEC); value = g_dbus_connection_call_sync (connection, NULL, /* bus_name */ "/org/gtk/GDBus/TestObject", diff --git a/gio/tests/gdbus-example-unix-fd-client.c b/gio/tests/gdbus-example-unix-fd-client.c index cf1330fda..c676bcbb5 100644 --- a/gio/tests/gdbus-example-unix-fd-client.c +++ b/gio/tests/gdbus-example-unix-fd-client.c @@ -74,16 +74,14 @@ on_name_appeared (GDBusConnection *connection, } else { - gchar now_buf[256]; - time_t now; + gchar *now_buf = NULL; gssize len; gchar *str; + GDateTime *now = g_date_time_new_now_local (); - now = time (NULL); - strftime (now_buf, - sizeof now_buf, - "%Y-%m-%d %H:%M:%S", - localtime (&now)); + g_assert_nonnull (now); + now_buf = g_date_time_format (now, "%Y-%m-%d %H:%M:%S"); + g_date_time_unref (now); str = g_strdup_printf ("On %s, gdbus-example-unix-fd-client with pid %d was here!\n", now_buf, @@ -95,6 +93,7 @@ on_name_appeared (GDBusConnection *connection, g_print ("Wrote the following on server's stdout:\n%s", str); g_free (str); + g_free (now_buf); exit (0); } } diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index ef0dddeee..4d6d3a43e 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -813,7 +813,7 @@ test_dispatch_thread_func (gpointer user_data) NULL, &error); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Type of message, '(s)', does not match expected type '()'"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Type of message, “(s)â€, does not match expected type “()â€"); g_error_free (error); g_assert (value == NULL); @@ -826,7 +826,7 @@ test_dispatch_thread_func (gpointer user_data) NULL, &error); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method 'NonExistantMethod'"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method “NonExistantMethodâ€"); g_error_free (error); g_assert (value == NULL); @@ -874,7 +874,7 @@ test_dispatch_thread_func (gpointer user_data) &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: No such property 'ThisDoesntExist'"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: No such property “ThisDoesntExistâ€"); g_error_free (error); error = NULL; @@ -889,7 +889,7 @@ test_dispatch_thread_func (gpointer user_data) &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property 'NotReadable' is not readable"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property “NotReadable†is not readable"); g_error_free (error); error = NULL; @@ -926,7 +926,7 @@ test_dispatch_thread_func (gpointer user_data) &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property 'NotWritable' is not writable"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property “NotWritable†is not writable"); g_error_free (error); error = NULL; diff --git a/gio/tests/gdbus-peer-object-manager.c b/gio/tests/gdbus-peer-object-manager.c index 933cc529d..676c9f080 100644 --- a/gio/tests/gdbus-peer-object-manager.c +++ b/gio/tests/gdbus-peer-object-manager.c @@ -258,6 +258,8 @@ setup (Test *test, g_assert (test->server); g_assert (test->client); + + g_object_unref (stream); } static void diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index 101c2a8bb..7f35baae6 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -875,6 +875,7 @@ test_peer (void) getuid ()); g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==, getpid ()); + g_object_unref (credentials); #else g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); g_assert (credentials == NULL); @@ -1358,6 +1359,8 @@ test_nonce_tcp (void) g_main_loop_quit (service_loop); g_thread_join (service_thread); + + g_ptr_array_unref (data.current_connections); } static void @@ -1711,6 +1714,7 @@ codegen_test_peer (void) * change notifications anyway because those are done from an idle handler */ example_animal_call_poke_sync (animal2, TRUE, TRUE, NULL, &error); + g_clear_error (&error); g_object_unref (animal1); g_object_unref (animal2); diff --git a/gio/tests/gdbus-serialization.c b/gio/tests/gdbus-serialization.c index da28f1bc1..d2f0a6ce7 100644 --- a/gio/tests/gdbus-serialization.c +++ b/gio/tests/gdbus-serialization.c @@ -1085,6 +1085,7 @@ int main (int argc, char *argv[]) { + g_setenv ("LC_ALL", "C", TRUE); setlocale (LC_ALL, "C"); g_test_init (&argc, &argv, NULL); diff --git a/gio/tests/gdbus-unix-addresses.c b/gio/tests/gdbus-unix-addresses.c index 8b58513a8..746a7c2a7 100644 --- a/gio/tests/gdbus-unix-addresses.c +++ b/gio/tests/gdbus-unix-addresses.c @@ -106,7 +106,6 @@ set_up_mock_dbus_launch (void) { path = g_strconcat (g_test_get_dir (G_TEST_BUILT), ":", g_getenv ("PATH"), NULL); - g_debug ("PATH=%s", path); g_setenv ("PATH", path, TRUE); /* libdbus won't even try X11 autolaunch if DISPLAY is unset; GDBus diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c index 2f056ee95..2d18d4dd2 100644 --- a/gio/tests/gsettings.c +++ b/gio/tests/gsettings.c @@ -741,15 +741,18 @@ test_l10n (void) settings = g_settings_new ("org.gtk.test.localized"); + g_setenv ("LC_MESSAGES", "C", TRUE); setlocale (LC_MESSAGES, "C"); str = g_settings_get_string (settings, "error-message"); + g_setenv ("LC_MESSAGES", locale, TRUE); setlocale (LC_MESSAGES, locale); g_assert_cmpstr (str, ==, "Unnamed"); g_free (str); str = NULL; - setlocale (LC_MESSAGES, "de_DE"); + g_setenv ("LC_MESSAGES", "de_DE.UTF-8", TRUE); + setlocale (LC_MESSAGES, "de_DE.UTF-8"); /* Only do the test if translation is actually working... */ if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\"")) { @@ -762,6 +765,7 @@ test_l10n (void) else g_printerr ("warning: translation is not working... skipping test. "); + g_setenv ("LC_MESSAGES", locale, TRUE); setlocale (LC_MESSAGES, locale); g_free (locale); g_object_unref (settings); @@ -788,15 +792,18 @@ test_l10n_context (void) settings = g_settings_new ("org.gtk.test.localized"); + g_setenv ("LC_MESSAGES", "C", TRUE); setlocale (LC_MESSAGES, "C"); g_settings_get (settings, "backspace", "s", &str); + g_setenv ("LC_MESSAGES", locale, TRUE); setlocale (LC_MESSAGES, locale); g_assert_cmpstr (str, ==, "BackSpace"); g_free (str); str = NULL; - setlocale (LC_MESSAGES, "de_DE"); + g_setenv ("LC_MESSAGES", "de_DE.UTF-8", TRUE); + setlocale (LC_MESSAGES, "de_DE.UTF-8"); /* Only do the test if translation is actually working... */ if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\"")) { @@ -809,6 +816,7 @@ test_l10n_context (void) else g_printerr ("warning: translation is not working... skipping test. "); + g_setenv ("LC_MESSAGES", locale, TRUE); setlocale (LC_MESSAGES, locale); g_free (locale); g_object_unref (settings); @@ -2238,6 +2246,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS "org.gtk.test.range.direct", "org.gtk.test.mapped", "org.gtk.test.descriptions", + "org.gtk.test.per-desktop", NULL)); } @@ -2629,6 +2638,100 @@ test_default_value (void) g_object_unref (settings); } +static gboolean +string_map_func (GVariant *value, + gpointer *result, + gpointer user_data) +{ + const gchar *str; + + str = g_variant_get_string (value, NULL); + *result = g_variant_new_string (str); + + return TRUE; +} + +/* Test that per-desktop values from org.gtk.test.gschema.override + * does not change default value if current desktop is not listed in + * $XDG_CURRENT_DESKTOP. + */ +static void +test_per_desktop (void) +{ + GSettings *settings; + TestObject *obj; + gpointer p; + gchar *str; + + settings = g_settings_new ("org.gtk.test.per-desktop"); + obj = test_object_new (); + + if (!g_test_subprocess ()) + { + g_test_trap_subprocess ("/gsettings/per-desktop/subprocess", 0, 0); + g_test_trap_assert_passed (); + } + + str = g_settings_get_string (settings, "desktop"); + g_assert_cmpstr (str, ==, "GNOME"); + g_free (str); + + p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL); + + str = g_variant_dup_string (p, NULL); + g_assert_cmpstr (str, ==, "GNOME"); + g_free (str); + + g_variant_unref (p); + + g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT); + + g_object_get (obj, "string", &str, NULL); + g_assert_cmpstr (str, ==, "GNOME"); + g_free (str); + + g_object_unref (settings); + g_object_unref (obj); +} + +/* Test that per-desktop values from org.gtk.test.gschema.override + * are successfully loaded based on the value of $XDG_CURRENT_DESKTOP. + */ +static void +test_per_desktop_subprocess (void) +{ + GSettings *settings; + TestObject *obj; + gpointer p; + gchar *str; + + g_setenv ("XDG_CURRENT_DESKTOP", "GNOME-Classic:GNOME", TRUE); + + settings = g_settings_new ("org.gtk.test.per-desktop"); + obj = test_object_new (); + + str = g_settings_get_string (settings, "desktop"); + g_assert_cmpstr (str, ==, "GNOME Classic"); + g_free (str); + + p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL); + + str = g_variant_dup_string (p, NULL); + g_assert_cmpstr (str, ==, "GNOME Classic"); + g_free (str); + + g_variant_unref (p); + + g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT); + + g_object_get (obj, "string", &str, NULL); + g_assert_cmpstr (str, ==, "GNOME Classic"); + g_free (str); + + g_object_unref (settings); + g_object_unref (obj); +} + static void test_extended_schema (void) { @@ -2649,6 +2752,7 @@ int main (int argc, char *argv[]) { gchar *schema_text; + gchar *override_text; gchar *enums; gint result; @@ -2671,6 +2775,7 @@ main (int argc, char *argv[]) g_setenv ("XDG_DATA_DIRS", ".", TRUE); g_setenv ("XDG_DATA_HOME", ".", TRUE); g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE); + g_setenv ("XDG_CURRENT_DESKTOP", "", TRUE); if (!backend_set) g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); @@ -2693,6 +2798,10 @@ main (int argc, char *argv[]) g_assert (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL)); g_free (schema_text); + g_assert (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL)); + g_assert (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL)); + g_free (override_text); + /* Meson build defines this, autotools build does not */ #ifndef GLIB_COMPILE_SCHEMAS #define GLIB_COMPILE_SCHEMAS "../glib-compile-schemas" @@ -2701,7 +2810,8 @@ main (int argc, char *argv[]) g_remove ("gschemas.compiled"); g_assert (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. " "--schema-file=org.gtk.test.enums.xml " - "--schema-file=org.gtk.test.gschema.xml", + "--schema-file=org.gtk.test.gschema.xml " + "--override-file=org.gtk.test.gschema.override", NULL, NULL, &result, NULL)); g_assert (result == 0); @@ -2782,6 +2892,8 @@ main (int argc, char *argv[]) g_test_add_func ("/gsettings/read-descriptions", test_read_descriptions); g_test_add_func ("/gsettings/test-extended-schema", test_extended_schema); g_test_add_func ("/gsettings/default-value", test_default_value); + g_test_add_func ("/gsettings/per-desktop", test_per_desktop); + g_test_add_func ("/gsettings/per-desktop/subprocess", test_per_desktop_subprocess); result = g_test_run (); diff --git a/gio/tests/live-g-file.c b/gio/tests/live-g-file.c index ba9d8d230..240fa8b25 100644 --- a/gio/tests/live-g-file.c +++ b/gio/tests/live-g-file.c @@ -417,6 +417,15 @@ test_attributes (struct StructureItem item, GFileInfo * info) G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN); g_assert_cmpint (is_hidden, ==, TRUE); } + + /* unix::is-mountpoint */ + if (posix_compat) + { + gboolean is_mountpoint = + g_file_info_get_attribute_boolean (info, + G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT); + g_assert_false (is_mountpoint); + } } static void @@ -853,6 +862,33 @@ test_copy_move (gconstpointer test_data) g_object_unref (root); } +/* Test that G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT is TRUE for / and for another + * known mountpoint. The FALSE case is tested for many directories and files by + * test_initial_structure(), via test_attributes(). + */ +static void +test_unix_is_mountpoint (gconstpointer data) +{ + const gchar *path = data; + GFile *file = g_file_new_for_path (path); + GFileInfo *info; + gboolean is_mountpoint; + GError *error = NULL; + + info = g_file_query_info (file, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT, + G_FILE_QUERY_INFO_NONE, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (info); + + is_mountpoint = + g_file_info_get_attribute_boolean (info, + G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT); + g_assert_true (is_mountpoint); + + g_clear_object (&info); + g_clear_object (&file); +} + static void test_create (gconstpointer test_data) { @@ -1342,6 +1378,18 @@ main (int argc, char *argv[]) if (!only_create_struct) g_test_add_data_func ("/live-g-file/test_open", target_path, test_open); + if (posix_compat) + { + g_test_add_data_func ("/live-g-file/test_unix_is_mountpoint/sysroot", + "/", + test_unix_is_mountpoint); +#ifdef __linux__ + g_test_add_data_func ("/live-g-file/test_unix_is_mountpoint/proc", + "/proc", + test_unix_is_mountpoint); +#endif + } + /* Write test - create */ if (write_test && (!only_create_struct)) g_test_add_data_func ("/live-g-file/test_create", target_path, diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 96229bd8b..85d31d622 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -43,6 +43,7 @@ gio_tests = [ 'memory-input-stream', 'memory-output-stream', 'monitor', + 'mount-operation', 'network-address', 'network-monitor', 'network-monitor-race', @@ -63,6 +64,14 @@ gio_tests = [ 'glistmodel', 'testfilemonitor', 'thumbnail-verification', + 'tls-certificate', + 'tls-interaction', +] +slow_tests = [ + 'actions', + 'gdbus-export', + 'gdbus-threading', + 'testfilemonitor', ] test_extra_programs = [ @@ -70,11 +79,11 @@ test_extra_programs = [ ['gdbus-testserver'], ] -test_env = [ - 'G_TEST_SRCDIR=' + meson.current_source_dir(), - 'G_TEST_BUILDDIR=' + meson.current_build_dir(), - 'GIO_MODULE_DIR=', -] +test_env = environment() +test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) +test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) +test_env.set('GIO_MODULE_DIR', '') +test_env.set('GIO_LAUNCH_DESKTOP', meson.build_root() + '/gio/gio-launch-desktop') test_c_args = [ '-DG_LOG_DOMAIN="GLib-GIO"', @@ -106,7 +115,7 @@ if dbus1_dep.found() install : false, c_args : test_c_args, dependencies : common_gio_tests_deps + [dbus1_dep]) - test('gdbus-serialization', exe, env : test_env) + test('gdbus-serialization', exe, env : test_env, suite : ['gio']) endif # Test programs buildable on UNIX only @@ -123,6 +132,7 @@ if host_machine.system() != 'windows' 'unix-streams', 'g-file-info-filesystem-readonly', 'gschema-compile', + 'trash', ] # Uninstalled because of the check-for-executable logic in DesktopAppInfo @@ -194,7 +204,7 @@ if host_machine.system() != 'windows' ] if not glib_have_cocoa - gio_dbus_tests = [['dbus-appinfo', [], []]] + gio_dbus_tests += [['dbus-appinfo', [], []]] endif # separate loop because extra source files for each test @@ -207,7 +217,12 @@ if host_machine.system() != 'windows' install : false, c_args : test_c_args, dependencies : common_gio_tests_deps + extra_deps) - test(test_name, exe, env : test_env) + # These tests may take more than 30 seconds to run on the CI infrastructure + if slow_tests.contains(test_name) + test(test_name, exe, env : test_env, timeout : 120, suite : ['gio', 'slow']) + else + test(test_name, exe, env : test_env, suite : ['gio']) + endif endforeach exe = executable('gdbus-test-codegen-old', 'gdbus-test-codegen.c', @@ -215,7 +230,7 @@ if host_machine.system() != 'windows' install : false, c_args : test_c_args + ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36', '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_36'], dependencies : common_gio_tests_deps) - test('gdbus-test-codegen-old', exe, env : test_env) + test('gdbus-test-codegen-old', exe, env : test_env, suite : ['gio']) # There is already a gapplication exe target in gio so need to use a # different name for the unit test executable, since we can't have two @@ -228,7 +243,7 @@ if host_machine.system() != 'windows' c_args : test_c_args, dependencies : common_gio_tests_deps) endif - test('gapplication', exe, env : test_env) + test('gapplication', exe, env : test_env, suite : ['gio']) gio_tests += ['gdbus-unix-addresses'] endif # have_dbus_daemon @@ -244,14 +259,14 @@ if host_machine.system() != 'windows' install : false, c_args : test_c_args, dependencies : common_gio_tests_deps) - test('gdbus-connection-flush', exe, env : test_env) + test('gdbus-connection-flush', exe, env : test_env, suite : ['gio']) exe = executable('gdbus-non-socket', 'gdbus-non-socket.c', 'gdbus-tests.c', 'test-io-stream.c', 'test-pipe-unix.c', install : false, c_args : test_c_args, dependencies : common_gio_tests_deps) - test('gdbus-non-socket', exe, env : test_env) + test('gdbus-non-socket', exe, env : test_env, suite : ['gio']) # Generate test.mo from de.po using msgfmt msgfmt = find_program('msgfmt', required : false) @@ -265,7 +280,7 @@ if host_machine.system() != 'windows' '-DTEST_LOCALE_PATH="@0@"'.format(test_mo_dir), ], dependencies : common_gio_tests_deps) - test('gsettings', exe, env : test_env) + test('gsettings', exe, env : test_env, suite : ['gio']) endif endif # unix @@ -290,15 +305,18 @@ foreach test_name : gio_tests # This is peer to peer so it doesn't need a session bus, so we can run # it automatically as a test by default extra_deps = [libgdbus_example_objectmanager_dep] + elif test_name == 'tls-certificate' or test_name == 'tls-interaction' + srcs += ['gtesttlsbackend.c'] endif exe = executable(test_name, srcs, install : false, c_args : test_c_args, dependencies : common_gio_tests_deps + extra_deps) - if test_name == 'testfilemonitor' - test(test_name, exe, env : test_env, timeout : 45) + # These tests may take more than 30 seconds to run on the CI infrastructure + if slow_tests.contains(test_name) + test(test_name, exe, env : test_env, timeout : 120, suite : ['gio', 'slow']) else - test(test_name, exe, env : test_env) + test(test_name, exe, env : test_env, suite : ['gio']) endif endforeach @@ -329,8 +347,6 @@ uninstalled_test_extra_programs = [ ['send-data'], ['socket-server'], ['socket-client', ['gtlsconsoleinteraction.c']], - ['tls-certificate', ['gtesttlsbackend.c']], - ['tls-interaction', ['gtesttlsbackend.c']], # These three are manual-run tests because they need a session bus but don't bring one up themselves # FIXME: these build but don't seem to work! ['gdbus-example-objectmanager-client', [], [libgdbus_example_objectmanager_dep]], @@ -375,7 +391,7 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() resource_plugin_platform_link_args = [] endif shared_module ('resourceplugin', 'resourceplugin.c', plugin_resources_c, - link_args : ['-export-dynamic'] + resource_plugin_platform_link_args, + link_args : export_dynamic_ldflags + resource_plugin_platform_link_args, dependencies : common_gio_tests_deps) test_gresource = custom_target('test.gresource', @@ -422,7 +438,7 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() # referenced by test.gresource.xml test_generated_txt = configure_file(input : 'test1.txt', output : 'test-generated.txt', - configuration : configuration_data(), + copy : true, install : false) exe = executable('resources', 'resources.c', test_gresource, @@ -430,7 +446,7 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() install : false, c_args : test_c_args, dependencies : common_gio_tests_deps) - test('resources', exe, env : test_env) + test('resources', exe, env : test_env, suite : ['gio']) endif # FIXME: subdir('services') diff --git a/gio/tests/monitor.c b/gio/tests/monitor.c index 69eae346b..4d64fa826 100644 --- a/gio/tests/monitor.c +++ b/gio/tests/monitor.c @@ -84,6 +84,19 @@ delete_file_idle (gpointer data) return G_SOURCE_REMOVE; } +static gboolean +stop_loop_idle (gpointer data) +{ + MonitorData *d = data; + + g_assert (d->state == 6); + + if (d->loop) + g_main_loop_quit (d->loop); + + return G_SOURCE_REMOVE; +} + static void changed_cb (GFileMonitor *monitor, GFile *file, @@ -112,8 +125,7 @@ changed_cb (GFileMonitor *monitor, case 5: g_assert (event == G_FILE_MONITOR_EVENT_DELETED); d->state = 6; - if (d->loop) - g_main_loop_quit (d->loop); + g_idle_add (stop_loop_idle, data); break; default: g_assert_not_reached (); diff --git a/gio/tests/mount-operation.c b/gio/tests/mount-operation.c new file mode 100644 index 000000000..0f8566ac7 --- /dev/null +++ b/gio/tests/mount-operation.c @@ -0,0 +1,132 @@ +/* GLib testing framework examples and tests + * + * Copyright © 2018 Endless Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Author: Philip Withnall + */ + +#include +#include + + +/* Smoketest for construction of a #GMountOperation. */ +static void +test_construction (void) +{ + GMountOperation *op = NULL; + + op = g_mount_operation_new (); + g_assert_nonnull (op); + g_assert_true (G_IS_MOUNT_OPERATION (op)); + g_object_unref (op); +} + +/* Test the property getters and setters on #GMountOperation work correctly. */ +static void +test_properties (void) +{ + GMountOperation *op = NULL; + gchar *username = NULL; + gchar *password = NULL; + gboolean anonymous; + gchar *domain = NULL; + GPasswordSave password_save; + int choice; + gboolean hidden_volume; + gboolean system_volume; + guint pim; + + op = g_mount_operation_new (); + + g_object_get (op, + "username", &username, + "password", &password, + "anonymous", &anonymous, + "domain", &domain, + "password-save", &password_save, + "choice", &choice, + "is-tcrypt-hidden-volume", &hidden_volume, + "is-tcrypt-system-volume", &system_volume, + "pim", &pim, + NULL); + + g_assert_cmpstr (username, ==, g_mount_operation_get_username (op)); + g_assert_cmpstr (password, ==, g_mount_operation_get_password (op)); + g_assert_cmpint (anonymous, ==, g_mount_operation_get_anonymous (op)); + g_assert_cmpstr (domain, ==, g_mount_operation_get_domain (op)); + g_assert_cmpint (password_save, ==, g_mount_operation_get_password_save (op)); + g_assert_cmpint (choice, ==, g_mount_operation_get_choice (op)); + g_assert_cmpint (hidden_volume, ==, g_mount_operation_get_is_tcrypt_hidden_volume (op)); + g_assert_cmpint (system_volume, ==, g_mount_operation_get_is_tcrypt_system_volume (op)); + g_assert_cmpuint (pim, ==, g_mount_operation_get_pim (op)); + + g_mount_operation_set_username (op, "username"); + g_assert_cmpstr (g_mount_operation_get_username (op), ==, "username"); + + g_mount_operation_set_password (op, "password"); + g_assert_cmpstr (g_mount_operation_get_password (op), ==, "password"); + + g_mount_operation_set_anonymous (op, !anonymous); + g_assert_cmpint (g_mount_operation_get_anonymous (op), ==, !anonymous); + + g_mount_operation_set_domain (op, "domain"); + g_assert_cmpstr (g_mount_operation_get_domain (op), ==, "domain"); + + g_mount_operation_set_password_save (op, G_PASSWORD_SAVE_NEVER); + g_assert_cmpint (g_mount_operation_get_password_save (op), ==, G_PASSWORD_SAVE_NEVER); + + g_mount_operation_set_choice (op, 5); + g_assert_cmpint (g_mount_operation_get_choice (op), ==, 5); + + g_mount_operation_set_is_tcrypt_hidden_volume (op, !hidden_volume); + g_assert_cmpint (g_mount_operation_get_is_tcrypt_hidden_volume (op), ==, !hidden_volume); + + g_mount_operation_set_is_tcrypt_system_volume (op, !system_volume); + g_assert_cmpint (g_mount_operation_get_is_tcrypt_system_volume (op), ==, !system_volume); + + g_mount_operation_set_pim (op, 5); + g_assert_cmpuint (g_mount_operation_get_pim (op), ==, 5); + + g_object_set (op, + "username", "other-username", + "password", "other-password", + "anonymous", FALSE, + "domain", "other-domain", + "password-save", G_PASSWORD_SAVE_PERMANENTLY, + "choice", 4, + "is-tcrypt-hidden-volume", FALSE, + "is-tcrypt-system-volume", FALSE, + "pim", 4, + NULL); + + g_free (domain); + g_free (password); + g_free (username); + g_object_unref (op); +} + +int +main (int argc, + char *argv[]) +{ + setlocale (LC_ALL, ""); + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/mount-operation/construction", test_construction); + g_test_add_func ("/mount-operation/properties", test_properties); + + return g_test_run (); +} diff --git a/gio/tests/org.gtk.test.gschema.override.orig b/gio/tests/org.gtk.test.gschema.override.orig new file mode 100644 index 000000000..6694baace --- /dev/null +++ b/gio/tests/org.gtk.test.gschema.override.orig @@ -0,0 +1,2 @@ +[org.gtk.test.per-desktop:GNOME-Classic] +desktop = "GNOME Classic" diff --git a/gio/tests/org.gtk.test.gschema.xml.orig b/gio/tests/org.gtk.test.gschema.xml.orig index 3c9d7b779..aad4e54df 100644 --- a/gio/tests/org.gtk.test.gschema.xml.orig +++ b/gio/tests/org.gtk.test.gschema.xml.orig @@ -213,4 +213,10 @@ + + + "GNOME" + + + diff --git a/gio/tests/resources.c b/gio/tests/resources.c index 8163aa141..6ae8e7d64 100644 --- a/gio/tests/resources.c +++ b/gio/tests/resources.c @@ -32,14 +32,24 @@ test_resource (GResource *resource) char **children; GInputStream *in; char buffer[128]; + const gchar *not_found_paths[] = + { + "/not/there", + "/", + "", + }; + gsize i; - found = g_resource_get_info (resource, - "/not/there", - G_RESOURCE_LOOKUP_FLAGS_NONE, - &size, &flags, &error); - g_assert (!found); - g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); - g_clear_error (&error); + for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++) + { + found = g_resource_get_info (resource, + not_found_paths[i], + G_RESOURCE_LOOKUP_FLAGS_NONE, + &size, &flags, &error); + g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); + g_clear_error (&error); + g_assert_false (found); + } found = g_resource_get_info (resource, "/test1.txt", @@ -68,6 +78,17 @@ test_resource (GResource *resource) g_assert_cmpint (size, ==, 6); g_assert_cmpuint (flags, ==, 0); + for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++) + { + data = g_resource_lookup_data (resource, + not_found_paths[i], + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); + g_clear_error (&error); + g_assert_null (data); + } + data = g_resource_lookup_data (resource, "/test1.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, @@ -76,6 +97,17 @@ test_resource (GResource *resource) g_assert_no_error (error); g_bytes_unref (data); + for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++) + { + in = g_resource_open_stream (resource, + not_found_paths[i], + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); + g_clear_error (&error); + g_assert_null (in); + } + in = g_resource_open_stream (resource, "/test1.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, @@ -118,13 +150,19 @@ test_resource (GResource *resource) g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n"); g_bytes_unref (data); - children = g_resource_enumerate_children (resource, - "/not/here", - G_RESOURCE_LOOKUP_FLAGS_NONE, - &error); - g_assert (children == NULL); - g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); - g_clear_error (&error); + for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++) + { + if (g_str_equal (not_found_paths[i], "/")) + continue; + + children = g_resource_enumerate_children (resource, + not_found_paths[i], + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); + g_clear_error (&error); + g_assert_null (children); + } children = g_resource_enumerate_children (resource, "/a_prefix", @@ -547,7 +585,8 @@ test_uri_query_info (void) GBytes *data; GFile *file; GFileInfo *info; - const char *content_type, *mime_type; + const char *content_type; + gchar *mime_type = NULL; const char *fs_type; gboolean readonly; @@ -573,6 +612,7 @@ test_uri_query_info (void) mime_type = g_content_type_get_mime_type (content_type); g_assert (mime_type); g_assert_cmpstr (mime_type, ==, "text/plain"); + g_free (mime_type); g_object_unref (info); diff --git a/gio/tests/simple-proxy.c b/gio/tests/simple-proxy.c index f1eb6af9b..ffc16eddd 100644 --- a/gio/tests/simple-proxy.c +++ b/gio/tests/simple-proxy.c @@ -77,6 +77,7 @@ test_uris (void) g_assert_cmpstr (error->message, ==, str); g_clear_error (&error); g_assert_null (proxies); + g_object_unref (result); g_object_unref (resolver); g_free (str); diff --git a/gio/tests/task.c b/gio/tests/task.c index 08d78e5ef..934262e40 100644 --- a/gio/tests/task.c +++ b/gio/tests/task.c @@ -1902,6 +1902,7 @@ legacy_error_callback (GObject *object, g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); *result_out = -2; + g_clear_error (&error); } else { diff --git a/gio/tests/testfilemonitor.c b/gio/tests/testfilemonitor.c index 6ef5d38f5..0fa72d3d9 100644 --- a/gio/tests/testfilemonitor.c +++ b/gio/tests/testfilemonitor.c @@ -9,12 +9,25 @@ * the tests, e.g. the length of timeouts */ +typedef enum { + NONE = 0, + INOTIFY = (1 << 1), + KQUEUE = (1 << 2) +} Environment; + typedef struct { gint event_type; gchar *file; gchar *other_file; gint step; + + /* Since different file monitor implementation has different capabilities, + * we cannot expect all implementations to report all kind of events without + * any loss. This 'optional' field is a bit mask used to mark events which + * may be lost under specific platforms. + */ + Environment optional; } RecordedEvent; static void @@ -68,41 +81,158 @@ output_events (GList *list) /* a placeholder for temp file names we don't want to compare */ static const gchar DONT_CARE[] = ""; -static void -check_expected_event (gint i, - RecordedEvent *e1, - RecordedEvent *e2) +static Environment +get_environment (GFileMonitor *monitor) { - g_assert_cmpint (e1->step, ==, e2->step); - if (e1->step < 0) - return; - - g_assert_cmpint (e1->event_type, ==, e2->event_type); - - if (e1->file != DONT_CARE) - g_assert_cmpstr (e1->file, ==, e2->file); - - if (e1->other_file != DONT_CARE) - g_assert_cmpstr (e1->other_file, ==, e2->other_file); + if (g_str_equal (G_OBJECT_TYPE_NAME (monitor), "GInotifyFileMonitor")) + return INOTIFY; + if (g_str_equal (G_OBJECT_TYPE_NAME (monitor), "GKqueueFileMonitor")) + return KQUEUE; + return NONE; } static void check_expected_events (RecordedEvent *expected, gsize n_expected, - GList *recorded) + GList *recorded, + Environment env) { - gint i; + gint i, li; GList *l; - g_assert_cmpint (n_expected, ==, g_list_length (recorded)); - - for (i = 0, l = recorded; i < n_expected; i++, l = l->next) + for (i = 0, li = 0, l = recorded; i < n_expected && l != NULL;) { RecordedEvent *e1 = &expected[i]; - RecordedEvent *e2 = (RecordedEvent *)l->data; + RecordedEvent *e2 = l->data; + gboolean mismatch = TRUE; + gboolean l_extra_step = FALSE; - check_expected_event (i, e1, e2); + do + { + gboolean ignore_other_file = FALSE; + + if (e1->step != e2->step) + break; + + /* Kqueue isn't good at detecting file renaming, so + * G_FILE_MONITOR_WATCH_MOVES is mostly useless there. */ + if (e1->event_type != e2->event_type && env & KQUEUE) + { + /* It is possible for kqueue file monitor to emit 'RENAMED' event, + * but most of the time it is reported as a 'DELETED' event and + * a 'CREATED' event. */ + if (e1->event_type == G_FILE_MONITOR_EVENT_RENAMED) + { + RecordedEvent *e2_next; + + if (l->next == NULL) + break; + e2_next = l->next->data; + + if (e2->event_type != G_FILE_MONITOR_EVENT_DELETED) + break; + if (e2_next->event_type != G_FILE_MONITOR_EVENT_CREATED) + break; + + if (e1->step != e2_next->step) + break; + + if (e1->file != DONT_CARE && + (g_strcmp0 (e1->file, e2->file) != 0 || + e2->other_file != NULL)) + break; + + if (e1->other_file != DONT_CARE && + (g_strcmp0 (e1->other_file, e2_next->file) != 0 || + e2_next->other_file != NULL)) + break; + + l_extra_step = TRUE; + mismatch = FALSE; + break; + } + /* Kqueue won't report 'MOVED_IN' and 'MOVED_OUT' events. We set + * 'ignore_other_file' here to let the following code know that + * 'other_file' may not match. */ + else if (e1->event_type == G_FILE_MONITOR_EVENT_MOVED_IN) + { + if (e2->event_type != G_FILE_MONITOR_EVENT_CREATED) + break; + ignore_other_file = TRUE; + } + else if (e1->event_type == G_FILE_MONITOR_EVENT_MOVED_OUT) + { + if (e2->event_type != G_FILE_MONITOR_EVENT_DELETED) + break; + ignore_other_file = TRUE; + } + else + break; + } + + if (e1->file != DONT_CARE && + g_strcmp0 (e1->file, e2->file) != 0) + break; + + if (e1->other_file != DONT_CARE && !ignore_other_file && + g_strcmp0 (e1->other_file, e2->other_file) != 0) + break; + + mismatch = FALSE; + } + while (0); + + if (mismatch) + { + /* Sometimes the emission of 'CHANGES_DONE_HINT' may be late because + * it depends on the ability of file monitor implementation to report + * 'CHANGES_DONE_HINT' itself. If the file monitor implementation + * doesn't report 'CHANGES_DONE_HINT' itself, it may be emitted by + * GLocalFileMonitor after a few seconds, which causes the event to + * mix with results from different steps. Since 'CHANGES_DONE_HINT' + * is just a hint, we don't require it to be reliable and we simply + * ignore unexpected 'CHANGES_DONE_HINT' events here. */ + if (e1->event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT && + e2->event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) + { + g_test_message ("Event CHANGES_DONE_HINT ignored at " + "expected index %d, recorded index %d", i, li); + li++, l = l->next; + continue; + } + /* If an event is marked as optional in the current environment and + * the event doesn't match, it means the expected event has lost. */ + else if (env & e1->optional) + { + g_test_message ("Event %d at expected index %d skipped because " + "it is marked as optional", e1->event_type, i); + i++; + continue; + } + /* Run above checks under g_assert_* again to provide more useful + * error messages. */ + else + { + g_assert_cmpint (e1->step, ==, e2->step); + g_assert_cmpint (e1->event_type, ==, e2->event_type); + + if (e1->file != DONT_CARE) + g_assert_cmpstr (e1->file, ==, e2->file); + + if (e1->other_file != DONT_CARE) + g_assert_cmpstr (e1->other_file, ==, e2->other_file); + + g_assert_not_reached (); + } + } + + i++, li++, l = l->next; + if (l_extra_step) + li++, l = l->next; } + + g_assert_cmpint (i, ==, n_expected); + g_assert_cmpint (li, ==, g_list_length (recorded)); } static void @@ -180,15 +310,15 @@ atomic_replace_step (gpointer user_data) /* this is the output we expect from the above steps */ static RecordedEvent atomic_replace_output[] = { - { -1, NULL, NULL, 0 }, - { G_FILE_MONITOR_EVENT_CREATED, "atomic_replace_file", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGED, "atomic_replace_file", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "atomic_replace_file", NULL, -1 }, - { -1, NULL, NULL, 1 }, - { G_FILE_MONITOR_EVENT_RENAMED, (gchar*)DONT_CARE, "atomic_replace_file", -1 }, - { -1, NULL, NULL, 2 }, - { G_FILE_MONITOR_EVENT_DELETED, "atomic_replace_file", NULL, -1 }, - { -1, NULL, NULL, 3 } + { -1, NULL, NULL, 0, NONE }, + { G_FILE_MONITOR_EVENT_CREATED, "atomic_replace_file", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGED, "atomic_replace_file", NULL, -1, KQUEUE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "atomic_replace_file", NULL, -1, KQUEUE }, + { -1, NULL, NULL, 1, NONE }, + { G_FILE_MONITOR_EVENT_RENAMED, (gchar*)DONT_CARE, "atomic_replace_file", -1, NONE }, + { -1, NULL, NULL, 2, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "atomic_replace_file", NULL, -1, NONE }, + { -1, NULL, NULL, 3, NONE } }; static void @@ -216,7 +346,10 @@ test_atomic_replace (void) g_main_loop_run (data.loop); /*output_events (data.events);*/ - check_expected_events (atomic_replace_output, G_N_ELEMENTS (atomic_replace_output), data.events); + check_expected_events (atomic_replace_output, + G_N_ELEMENTS (atomic_replace_output), + data.events, + get_environment (data.monitor)); g_list_free_full (data.events, (GDestroyNotify)free_recorded_event); g_main_loop_unref (data.loop); @@ -277,18 +410,18 @@ change_step (gpointer user_data) /* this is the output we expect from the above steps */ static RecordedEvent change_output[] = { - { -1, NULL, NULL, 0 }, - { G_FILE_MONITOR_EVENT_CREATED, "change_file", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGED, "change_file", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "change_file", NULL, -1 }, - { -1, NULL, NULL, 1 }, - { G_FILE_MONITOR_EVENT_CHANGED, "change_file", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "change_file", NULL, -1 }, - { -1, NULL, NULL, 2 }, - { G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED, "change_file", NULL, -1 }, - { -1, NULL, NULL, 3 }, - { G_FILE_MONITOR_EVENT_DELETED, "change_file", NULL, -1 }, - { -1, NULL, NULL, 4 } + { -1, NULL, NULL, 0, NONE }, + { G_FILE_MONITOR_EVENT_CREATED, "change_file", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGED, "change_file", NULL, -1, KQUEUE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "change_file", NULL, -1, KQUEUE }, + { -1, NULL, NULL, 1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGED, "change_file", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "change_file", NULL, -1, NONE }, + { -1, NULL, NULL, 2, NONE }, + { G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED, "change_file", NULL, -1, NONE }, + { -1, NULL, NULL, 3, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "change_file", NULL, -1, NONE }, + { -1, NULL, NULL, 4, NONE } }; static void @@ -316,7 +449,10 @@ test_file_changes (void) g_main_loop_run (data.loop); /*output_events (data.events);*/ - check_expected_events (change_output, G_N_ELEMENTS (change_output), data.events); + check_expected_events (change_output, + G_N_ELEMENTS (change_output), + data.events, + get_environment (data.monitor)); g_list_free_full (data.events, (GDestroyNotify)free_recorded_event); g_main_loop_unref (data.loop); @@ -391,16 +527,16 @@ dir_step (gpointer user_data) /* this is the output we expect from the above steps */ static RecordedEvent dir_output[] = { - { -1, NULL, NULL, 1 }, - { -1, NULL, NULL, 2 }, - { G_FILE_MONITOR_EVENT_MOVED_IN, "dir_test_file", NULL, -1 }, - { -1, NULL, NULL, 3 }, - { G_FILE_MONITOR_EVENT_RENAMED, "dir_test_file", "dir_test_file2", -1 }, - { -1, NULL, NULL, 4 }, - { G_FILE_MONITOR_EVENT_MOVED_OUT, "dir_test_file2", NULL, -1 }, - { -1, NULL, NULL, 5 }, - { G_FILE_MONITOR_EVENT_DELETED, "dir_monitor_test", NULL, -1 }, - { -1, NULL, NULL, 6 } + { -1, NULL, NULL, 1, NONE }, + { -1, NULL, NULL, 2, NONE }, + { G_FILE_MONITOR_EVENT_MOVED_IN, "dir_test_file", NULL, -1, NONE }, + { -1, NULL, NULL, 3, NONE }, + { G_FILE_MONITOR_EVENT_RENAMED, "dir_test_file", "dir_test_file2", -1, NONE }, + { -1, NULL, NULL, 4, NONE }, + { G_FILE_MONITOR_EVENT_MOVED_OUT, "dir_test_file2", NULL, -1, NONE }, + { -1, NULL, NULL, 5, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "dir_monitor_test", NULL, -1, NONE }, + { -1, NULL, NULL, 6, NONE } }; static void @@ -429,7 +565,10 @@ test_dir_monitor (void) g_main_loop_run (data.loop); /*output_events (data.events);*/ - check_expected_events (dir_output, G_N_ELEMENTS (dir_output), data.events); + check_expected_events (dir_output, + G_N_ELEMENTS (dir_output), + data.events, + get_environment (data.monitor)); g_list_free_full (data.events, (GDestroyNotify)free_recorded_event); g_main_loop_unref (data.loop); @@ -482,17 +621,17 @@ nodir_step (gpointer user_data) } static RecordedEvent nodir_output[] = { - { -1, NULL, NULL, 0 }, - { G_FILE_MONITOR_EVENT_CREATED, "nosuchfile", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "nosuchfile", NULL, -1 }, - { -1, NULL, NULL, 1 }, - { G_FILE_MONITOR_EVENT_CREATED, "nosuchfile", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGED, "nosuchfile", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "nosuchfile", NULL, -1 }, - { -1, NULL, NULL, 2 }, - { G_FILE_MONITOR_EVENT_DELETED, "nosuchfile", NULL, -1 }, - { -1, NULL, NULL, 3 }, - { -1, NULL, NULL, 4 } + { -1, NULL, NULL, 0, NONE }, + { G_FILE_MONITOR_EVENT_CREATED, "nosuchfile", NULL, -1, KQUEUE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "nosuchfile", NULL, -1, KQUEUE }, + { -1, NULL, NULL, 1, NONE }, + { G_FILE_MONITOR_EVENT_CREATED, "nosuchfile", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGED, "nosuchfile", NULL, -1, KQUEUE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "nosuchfile", NULL, -1, KQUEUE }, + { -1, NULL, NULL, 2, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "nosuchfile", NULL, -1, NONE }, + { -1, NULL, NULL, 3, NONE }, + { -1, NULL, NULL, 4, NONE } }; static void @@ -521,7 +660,10 @@ test_dir_non_existent (void) g_main_loop_run (data.loop); /*output_events (data.events);*/ - check_expected_events (nodir_output, G_N_ELEMENTS (nodir_output), data.events); + check_expected_events (nodir_output, + G_N_ELEMENTS (nodir_output), + data.events, + get_environment (data.monitor)); g_list_free_full (data.events, (GDestroyNotify)free_recorded_event); g_main_loop_unref (data.loop); @@ -578,26 +720,26 @@ cross_dir_step (gpointer user_data) } static RecordedEvent cross_dir_a_output[] = { - { -1, NULL, NULL, 0 }, - { -1, NULL, NULL, 1 }, - { G_FILE_MONITOR_EVENT_CREATED, "a", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "a", NULL, -1 }, - { -1, NULL, NULL, 2 }, - { G_FILE_MONITOR_EVENT_DELETED, "a", NULL, -1 }, - { G_FILE_MONITOR_EVENT_DELETED, "cross_dir_a", NULL, -1 }, - { -1, NULL, NULL, 3 }, + { -1, NULL, NULL, 0, NONE }, + { -1, NULL, NULL, 1, NONE }, + { G_FILE_MONITOR_EVENT_CREATED, "a", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "a", NULL, -1, KQUEUE }, + { -1, NULL, NULL, 2, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "a", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "cross_dir_a", NULL, -1, NONE }, + { -1, NULL, NULL, 3, NONE }, }; static RecordedEvent cross_dir_b_output[] = { - { -1, NULL, NULL, 0 }, - { G_FILE_MONITOR_EVENT_CREATED, "a", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGED, "a", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "a", NULL, -1 }, - { -1, NULL, NULL, 1 }, - { G_FILE_MONITOR_EVENT_MOVED_OUT, "a", "a", -1 }, - { -1, NULL, NULL, 2 }, - { G_FILE_MONITOR_EVENT_DELETED, "cross_dir_b", NULL, -1 }, - { -1, NULL, NULL, 3 }, + { -1, NULL, NULL, 0, NONE }, + { G_FILE_MONITOR_EVENT_CREATED, "a", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGED, "a", NULL, -1, KQUEUE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "a", NULL, -1, KQUEUE }, + { -1, NULL, NULL, 1, NONE }, + { G_FILE_MONITOR_EVENT_MOVED_OUT, "a", "a", -1, NONE }, + { -1, NULL, NULL, 2, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "cross_dir_b", NULL, -1, NONE }, + { -1, NULL, NULL, 3, NONE }, }; static void test_cross_dir_moves (void) @@ -644,8 +786,14 @@ test_cross_dir_moves (void) output_events (data[1].events); #endif - check_expected_events (cross_dir_a_output, G_N_ELEMENTS (cross_dir_a_output), data[0].events); - check_expected_events (cross_dir_b_output, G_N_ELEMENTS (cross_dir_b_output), data[1].events); + check_expected_events (cross_dir_a_output, + G_N_ELEMENTS (cross_dir_a_output), + data[0].events, + get_environment (data[0].monitor)); + check_expected_events (cross_dir_b_output, + G_N_ELEMENTS (cross_dir_b_output), + data[1].events, + get_environment (data[1].monitor)); g_list_free_full (data[0].events, (GDestroyNotify)free_recorded_event); g_main_loop_unref (data[0].loop); @@ -742,19 +890,26 @@ file_hard_links_step (gpointer user_data) } static RecordedEvent file_hard_links_output[] = { - { -1, NULL, NULL, 0 }, - { G_FILE_MONITOR_EVENT_CHANGED, "testfilemonitor.db", NULL, -1 }, - { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "testfilemonitor.db", NULL, -1 }, - { -1, NULL, NULL, 1 }, - { G_FILE_MONITOR_EVENT_RENAMED, NULL /* .goutputstream-XXXXXX */, "testfilemonitor.db", -1 }, - { -1, NULL, NULL, 2 }, - { -1, NULL, NULL, 3 }, - /* FIXME: There should be a EVENT_CHANGED and EVENT_CHANGES_DONE_HINT here - * from the modification of the hard link. */ - { -1, NULL, NULL, 4 }, - { G_FILE_MONITOR_EVENT_DELETED, "testfilemonitor.db", NULL, -1 }, - { -1, NULL, NULL, 5 }, - { -1, NULL, NULL, 6 }, + { -1, NULL, NULL, 0, NONE }, + { G_FILE_MONITOR_EVENT_CHANGED, "testfilemonitor.db", NULL, -1, NONE }, + { G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, "testfilemonitor.db", NULL, -1, NONE }, + { -1, NULL, NULL, 1, NONE }, + { G_FILE_MONITOR_EVENT_RENAMED, (gchar*)DONT_CARE /* .goutputstream-XXXXXX */, "testfilemonitor.db", -1, NONE }, + { -1, NULL, NULL, 2, NONE }, + { -1, NULL, NULL, 3, NONE }, + /* Kqueue is based on file descriptors. You can get events from all hard + * links by just monitoring one open file descriptor, and it is not possible + * to know whether it is done on the file name we use to open the file. Since + * the hard link count of 'testfilemonitor.db' is 2, it is expected to see + * two 'DELETED' events reported here. You have to call 'unlink' twice on + * different file names to remove 'testfilemonitor.db' from the file system, + * and each 'unlink' call generates a 'DELETED' event. */ + { G_FILE_MONITOR_EVENT_CHANGED, "testfilemonitor.db", NULL, -1, INOTIFY }, + { -1, NULL, NULL, 4, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "testfilemonitor.db", NULL, -1, NONE }, + { -1, NULL, NULL, 5, NONE }, + { G_FILE_MONITOR_EVENT_DELETED, "testfilemonitor.db", NULL, -1, INOTIFY }, + { -1, NULL, NULL, 6, NONE }, }; static void @@ -800,7 +955,9 @@ test_file_hard_links (void) /* output_events (data.events); */ check_expected_events (file_hard_links_output, - G_N_ELEMENTS (file_hard_links_output), data.events); + G_N_ELEMENTS (file_hard_links_output), + data.events, + get_environment (data.monitor)); g_list_free_full (data.events, (GDestroyNotify) free_recorded_event); g_main_loop_unref (data.loop); diff --git a/gio/tests/trash.c b/gio/tests/trash.c new file mode 100644 index 000000000..2abe0aa0c --- /dev/null +++ b/gio/tests/trash.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 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 + * licence, or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +#include + +#ifndef G_OS_UNIX +#error This is a Unix-specific test +#endif + +#include +#include +#include + +/* Test that g_file_trash() returns G_IO_ERROR_NOT_SUPPORTED for files on system mounts. */ +static void +test_trash_not_supported (void) +{ + GFile *file; + GFileIOStream *stream; + GUnixMountEntry *mount; + GFileInfo *info; + GError *error = NULL; + gboolean ret; + GStatBuf file_stat, home_stat; + + /* The test assumes that tmp file is located on system internal mount. */ + file = g_file_new_tmp ("test-trashXXXXXX", &stream, &error); + g_assert_no_error (error); + g_assert_cmpint (g_lstat (g_file_peek_path (file), &file_stat), ==, 0); + g_test_message ("File: %s (dev: %" G_GUINT64_FORMAT ")", + g_file_peek_path (file), (guint64) file_stat.st_dev); + + g_assert_cmpint (g_stat (g_get_home_dir (), &home_stat), ==, 0); + g_test_message ("Home: %s (dev: %" G_GUINT64_FORMAT ")", + g_get_home_dir (), (guint64) home_stat.st_dev); + + if (file_stat.st_dev == home_stat.st_dev) + { + g_test_skip ("The file has to be on another filesystem than the home trash to run this test"); + + g_object_unref (stream); + g_object_unref (file); + + return; + } + + mount = g_unix_mount_for (g_file_peek_path (file), NULL); + g_assert_true (mount == NULL || g_unix_mount_is_system_internal (mount)); + g_test_message ("Mount: %s", (mount != NULL) ? g_unix_mount_get_mount_path (mount) : "(null)"); + g_clear_pointer (&mount, g_unix_mount_free); + + /* g_file_trash() shouldn't be supported on system internal mounts, + * because those are not monitored by gvfsd-trash. + */ + ret = g_file_trash (file, NULL, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); + g_test_message ("Error: %s", error->message); + g_assert_false (ret); + g_clear_error (&error); + + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, + &error); + g_assert_no_error (error); + + g_assert_false (g_file_info_get_attribute_boolean (info, + G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)); + + g_io_stream_close (G_IO_STREAM (stream), NULL, &error); + g_assert_no_error (error); + + g_object_unref (info); + g_object_unref (stream); + g_object_unref (file); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_bug_base ("htps://gitlab.gnome.org/GNOME/glib/issues/"); + g_test_bug ("251"); + + g_test_add_func ("/trash/not-supported", test_trash_not_supported); + + return g_test_run (); +} + diff --git a/gio/tests/unix-mounts.c b/gio/tests/unix-mounts.c index 3d54047dc..67b8c8d98 100644 --- a/gio/tests/unix-mounts.c +++ b/gio/tests/unix-mounts.c @@ -33,6 +33,12 @@ test_is_system_fs_type (void) { g_assert_true (g_unix_is_system_fs_type ("tmpfs")); g_assert_false (g_unix_is_system_fs_type ("ext4")); + + /* Check that some common network file systems aren’t considered ‘system’. */ + g_assert_false (g_unix_is_system_fs_type ("cifs")); + g_assert_false (g_unix_is_system_fs_type ("nfs")); + g_assert_false (g_unix_is_system_fs_type ("nfs4")); + g_assert_false (g_unix_is_system_fs_type ("smbfs")); } static void diff --git a/gio/tests/unix-streams.c b/gio/tests/unix-streams.c index dafaf66aa..67a90d83d 100644 --- a/gio/tests/unix-streams.c +++ b/gio/tests/unix-streams.c @@ -178,6 +178,7 @@ main_thread_read (GObject *source, GAsyncResult *res, gpointer user_data) if (g_cancellable_is_cancelled (main_cancel)) { do_main_cancel (out); + g_clear_error (&err); return; } @@ -214,6 +215,7 @@ main_thread_wrote (GObject *source, GAsyncResult *res, gpointer user_data) if (g_cancellable_is_cancelled (main_cancel)) { do_main_cancel (out); + g_clear_error (&err); return; } diff --git a/gio/thumbnail-verify.c b/gio/thumbnail-verify.c index 44fde6bc7..1a722e40c 100644 --- a/gio/thumbnail-verify.c +++ b/gio/thumbnail-verify.c @@ -232,7 +232,7 @@ thumbnail_verify (const char *thumbnail_path, return FALSE; expected_info.uri = file_uri; - expected_info.mtime = file_stat_buf->st_mtime; + expected_info.mtime = (guint64) file_stat_buf->st_mtime; expected_info.size = file_stat_buf->st_size; file = g_mapped_file_new (thumbnail_path, FALSE, NULL); diff --git a/glib-gettextize.in b/glib-gettextize.in index b07078bc5..af7052f6f 100755 --- a/glib-gettextize.in +++ b/glib-gettextize.in @@ -35,7 +35,7 @@ Usage: glib-gettextize [OPTION]... [package-dir] --version print version information and exit -c, --copy copy files instead of making symlinks -f, --force force writing of new files even if old exist -Report bugs to http://bugzilla.gnome.org/." +Report bugs to https://gitlab.gnome.org/GNOME/glib/issues/new." package=@PACKAGE@ version=@VERSION@ try_ln_s=: diff --git a/glib-zip.in b/glib-zip.in deleted file mode 100755 index 40d3c6722..000000000 --- a/glib-zip.in +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh - -# Build zipfiles for GLib on Win32: Separate runtime and developer ones. -# After running make install, run this. - -ZIP=/tmp/glib-@GLIB_VERSION@.zip -DEVZIP=/tmp/glib-dev-@GLIB_VERSION@.zip - -cd @prefix@ - -mkdir -p share/doc/glib-@GLIB_VERSION@ -cp -p @abs_srcdir@/COPYING share/doc/glib-@GLIB_VERSION@ - -mkdir -p share/doc/glib-dev-@GLIB_VERSION@ -cp -p @abs_srcdir@/COPYING share/doc/glib-dev-@GLIB_VERSION@ - -if test @LIB_EXE_MACHINE_FLAG@ = X64; then - helperbits=64 -else - helperbits=32 -fi - -rm $ZIP -zip $ZIP -@ < - + diff --git a/glib.supp b/glib.supp index e3ce6bc49..f64826b3c 100644 --- a/glib.supp +++ b/glib.supp @@ -17,7 +17,7 @@ # This file should be updated if GLib introduces a new deliberate one-time leak, # or another false race positive in Valgrind: please file bugs at: # -# https://bugzilla.gnome.org/enter_bug.cgi?product=glib +# https://gitlab.gnome.org/GNOME/glib/issues/new { gnutls-init-calloc @@ -51,6 +51,16 @@ fun:initialize_module_inlock_reentrant } +# One-time allocation from libc for getpwnam() results +{ + g-local-vfs-getpwnam + Memcheck:Leak + fun:malloc + ... + fun:getpwnam + fun:g_local_vfs_parse_name +} + { gobject-init-malloc Memcheck:Leak @@ -232,6 +242,18 @@ fun:_g_io_module_get_default } +# One-time getaddrinfo() configuration loading +{ + g-threaded-resolver-getaddrinfo-config + Memcheck:Leak + fun:malloc + ... + fun:__resolv_conf_allocate + ... + fun:getaddrinfo + fun:do_lookup_by_name +} + # memcheck checks that the third argument to ioctl() is a valid pointer, but # some ioctls use that argument as an integer { diff --git a/glib/.gitignore b/glib/.gitignore index 17142a60c..f79e130df 100644 --- a/glib/.gitignore +++ b/glib/.gitignore @@ -1,5 +1,4 @@ glibconfig.h -glibconfig.h.win32 glibconfig-stamp gtester diff --git a/glib/Makefile.am b/glib/Makefile.am index 8da549c7f..8f6536c6d 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -1,6 +1,8 @@ ## Process this file with automake to produce Makefile.in include $(top_srcdir)/glib.mk +bin_PROGRAMS = + # # Generate glibconfig.h # @@ -9,15 +11,13 @@ include $(top_srcdir)/glib.mk # to config.status will not result in changes to glibconfig.h so we # avoid touching its timestamp (in order not to rebuild the whole tree). # -DISTCLEANFILES += glibconfig-stamp glibconfig.h glibconfig.h.win32 +DISTCLEANFILES += glibconfig-stamp glibconfig.h BUILT_SOURCES += glibconfig-stamp configexecincludedir = $(libdir)/glib-2.0/include nodist_configexecinclude_HEADERS = glibconfig.h glibconfig-stamp: ../config.status $(AM_V_GEN) cd $(top_builddir) && \ $(SHELL) ./config.status glib/glibconfig.h - $(AM_V_GEN) cd $(top_builddir) && \ - $(SHELL) ./config.status glib/glibconfig.h.win32 @touch glibconfig-stamp @@ -57,7 +57,6 @@ MIRRORING_TAB_SOURCE = \ EXTRA_DIST += \ glib.rc.in \ gen-unicode-tables.pl \ - glibconfig.h.win32.in \ gregex.c \ gregex.h \ win_iconv.c \ @@ -70,7 +69,6 @@ CLEANFILES += libglib-gdb.py # These may be in the builddir too BUILT_EXTRA_DIST += \ - glibconfig.h.win32 \ glib.rc lib_LTLIBRARIES = libglib-2.0.la @@ -100,6 +98,7 @@ deprecated_sources = \ libglib_2_0_la_SOURCES = \ $(deprecated_sources) \ glib_probes.d \ + garcbox.c \ garray.c \ gasyncqueue.c \ gasyncqueueprivate.h \ @@ -153,6 +152,10 @@ libglib_2_0_la_SOURCES = \ gquark.c \ gqueue.c \ grand.c \ + grcbox.c \ + grcboxprivate.h \ + grefcount.c \ + grefstring.c \ gregex.c \ gscanner.c \ gscripttable.h \ @@ -160,6 +163,7 @@ libglib_2_0_la_SOURCES = \ gshell.c \ gslice.c \ gslist.c \ + gspawn-private.h \ gstdio.c \ gstdioprivate.h \ gstrfuncs.c \ @@ -188,6 +192,7 @@ libglib_2_0_la_SOURCES = \ gurifuncs.c \ gutils.c \ guuid.c \ + gvalgrind.h \ gvariant.h \ gvariant.c \ gvariant-core.h \ @@ -218,12 +223,21 @@ libglib_2_0_la_SOURCES += gthread-posix.c endif endif -EXTRA_libglib_2_0_la_SOURCES = \ - giounix.c \ - giowin32.c \ - gspawn.c \ - gspawn-win32.c \ - gwin32.c +if PLATFORM_WIN32 +libglib_2_0_la_SOURCES += gwin32.c +endif + +if G_SPAWN_WIN32 +libglib_2_0_la_SOURCES += gspawn-win32.c +else +libglib_2_0_la_SOURCES += gspawn.c +endif + +if G_IO_CHANNEL_WIN32 +libglib_2_0_la_SOURCES += giowin32.c +else +libglib_2_0_la_SOURCES += giounix.c +endif glibincludedir=$(includedir)/glib-2.0 glibinclude_HEADERS = \ @@ -287,6 +301,9 @@ glibsubinclude_HEADERS = \ gquark.h \ gqueue.h \ grand.h \ + grcbox.h \ + grefcount.h \ + grefstring.h \ gregex.h \ gscanner.h \ gsequence.h \ @@ -352,16 +369,14 @@ pcre_inc = endif libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS) -libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD) $(LIBSYSTEMD_LIBS) -libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) $(glib_def) +libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD) $(LIBSYSTEMD_LIBS) +libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) $(glib_win32_res) $(glib_def) libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \ $(glib_win32_res_ldflag) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -export-dynamic $(no_undefined) -INSTALL_PROGS= - if ENABLE_DTRACE glib_probes.h: glib_probes.d $(AM_V_GEN) $(DTRACE) -C -h -s $< -o $@.tmp @@ -404,15 +419,26 @@ gspawn-win64-helper-console.c: echo '#define HELPER_CONSOLE' >$@ echo '#include "gspawn-win32-helper.c"' >>$@ +nodist_win_helper_sources = \ + gspawn-win32-helper-console.c \ + gspawn-win64-helper.c \ + gspawn-win64-helper-console.c \ + $(NULL) + +BUILT_SOURCES += $(nodist_win_helper_sources) +CLEANFILES += $(nodist_win_helper_sources) if OS_WIN32 if OS_WIN32_X64 -INSTALL_PROGS += gspawn-win64-helper gspawn-win64-helper-console +bin_PROGRAMS += gspawn-win64-helper gspawn-win64-helper-console +nodist_gspawn_win64_helper_SOURCES = gspawn-win64-helper.c +nodist_gspawn_win64_helper_console_SOURCES = gspawn-win64-helper-console.c gspawn_win64_helper_LDADD = libglib-2.0.la gspawn_win64_helper_LDFLAGS = -mwindows gspawn_win64_helper_console_LDADD = libglib-2.0.la else -INSTALL_PROGS += gspawn-win32-helper gspawn-win32-helper-console +bin_PROGRAMS += gspawn-win32-helper gspawn-win32-helper-console +nodist_gspawn_win32_helper_console_SOURCES = gspawn-win32-helper-console.c gspawn_win32_helper_LDADD = libglib-2.0.la gspawn_win32_helper_LDFLAGS = -mwindows gspawn_win32_helper_console_LDADD = libglib-2.0.la @@ -422,11 +448,9 @@ endif glib-win32-res.o: glib.rc $(WINDRES) glib.rc $@ -bin_PROGRAMS = ${INSTALL_PROGS} - if OS_UNIX -INSTALL_PROGS += gtester +bin_PROGRAMS += gtester gtester_SOURCES = gtester.c gtester_LDADD = libglib-2.0.la @@ -457,19 +481,7 @@ glib.def: libglib-2.0.la glib-2.0.lib: libglib-2.0.la glib.def $(AM_V_GEN) lib.exe -machine:@LIB_EXE_MACHINE_FLAG@ -name:libglib-2.0-$(LT_CURRENT_MINUS_AGE).dll -def:$(builddir)/glib.def -out:$@ -# ------ MSVC Project File Generation ------ -MSVCPROJS = glib - -glib_FILES = $(libglib_2_0_la_SOURCES) -glib_EXCLUDES = *-unix.c|gthread-*.c - -glib_HEADERS_DIR = $(glibsubincludedir) -glib_HEADERS_INST = $(deprecatedinclude_HEADERS) $(glibsubinclude_HEADERS) -glib_HEADERS_EXCLUDES = dummy - -include $(top_srcdir)/win32/Makefile.msvcproj - -dist-hook: $(BUILT_EXTRA_DIST) $(top_builddir)/win32/vs9/glib.vcproj $(top_builddir)/win32/vs9/glib.headers +dist-hook: $(BUILT_EXTRA_DIST) files='$(BUILT_EXTRA_DIST)'; \ for f in $$files; do \ if test -f $$f; then d=.; else d=$(srcdir); fi; \ diff --git a/glib/docs.c b/glib/docs.c index 080c1b0de..5a786311c 100644 --- a/glib/docs.c +++ b/glib/docs.c @@ -1788,6 +1788,26 @@ * Returns: the value of @x clamped to the range between @low and @high */ +/** + * G_APPROX_VALUE: + * @a: a numeric value + * @b: a numeric value + * @epsilon: a numeric value that expresses the tolerance between @a and @b + * + * Evaluates to a truth value if the absolute difference between @a and @b is + * smaller than @epsilon, and to a false value otherwise. + * + * For example, + * - `G_APPROX_VALUE (5, 6, 2)` evaluates to true + * - `G_APPROX_VALUE (3.14, 3.15, 0.001)` evaluates to false + * - `G_APPROX_VALUE (n, 0.f, FLT_EPSILON)` evaluates to true if `n` is within + * the single precision floating point epsilon from zero + * + * Returns: %TRUE if the two values are within the desired range + * + * Since: 2.58 + */ + /** * G_STRUCT_MEMBER: * @member_type: the type of the struct field diff --git a/glib/garcbox.c b/glib/garcbox.c new file mode 100644 index 000000000..9c1bd8fe5 --- /dev/null +++ b/glib/garcbox.c @@ -0,0 +1,373 @@ +/* garcbox.c: Atomically reference counted data + * + * Copyright 2018 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "config.h" + +#include "grcboxprivate.h" + +#include "gmessages.h" +#include "grefcount.h" + +#ifdef ENABLE_VALGRIND +#include "valgrind.h" +#endif + +#include "glib_trace.h" + +#include + +#define G_ARC_BOX(p) (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE) + +/** + * SECTION:arcbox + * @Title: Atomically reference counted data + * @Short_description: Allocated memory with atomic reference counting semantics + * + * An "atomically reference counted box", or "ArcBox", is an opaque wrapper + * data type that is guaranteed to be as big as the size of a given data type, + * and which augments the given data type with thread safe reference counting + * semantics for its memory management. + * + * ArcBox is useful if you have a plain old data type, like a structure + * typically placed on the stack, and you wish to provide additional API + * to use it on the heap; or if you want to implement a new type to be + * passed around by reference without necessarily implementing copy/free + * semantics or your own reference counting. + * + * The typical use is: + * + * |[ + * typedef struct { + * char *name; + * char *address; + * char *city; + * char *state; + * int age; + * } Person; + * + * Person * + * person_new (void) + * { + * return g_atomic_rc_box_new0 (Person); + * } + * ]| + * + * Every time you wish to acquire a reference on the memory, you should + * call g_atomic_rc_box_acquire(); similarly, when you wish to release a reference + * you should call g_atomic_rc_box_release(): + * + * |[ + * // Add a Person to the Database; the Database acquires ownership + * // of the Person instance + * void + * add_person_to_database (Database *db, Person *p) + * { + * db->persons = g_list_prepend (db->persons, g_atomic_rc_box_acquire (p)); + * } + * + * // Removes a Person from the Database; the reference acquired by + * // add_person_to_database() is released here + * void + * remove_person_from_database (Database *db, Person *p) + * { + * db->persons = g_list_remove (db->persons, p); + * g_atomic_rc_box_release (p); + * } + * ]| + * + * If you have additional memory allocated inside the structure, you can + * use g_atomic_rc_box_release_full(), which takes a function pointer, which + * will be called if the reference released was the last: + * + * |[ + * void + * person_clear (Person *p) + * { + * g_free (p->name); + * g_free (p->address); + * g_free (p->city); + * g_free (p->state); + * } + * + * void + * remove_person_from_database (Database *db, Person *p) + * { + * db->persons = g_list_remove (db->persons, p); + * g_atomic_rc_box_release_full (p, (GDestroyNotify) person_clear); + * } + * ]| + * + * If you wish to transfer the ownership of a reference counted data + * type without increasing the reference count, you can use g_steal_pointer(): + * + * |[ + * Person *p = g_atomic_rc_box_new (Person); + * + * fill_person_details (p); + * + * add_person_to_database (db, g_steal_pointer (&p)); + * ]| + * + * ## Thread safety + * + * The reference counting operations on data allocated using g_atomic_rc_box_alloc(), + * g_atomic_rc_box_new(), and g_atomic_rc_box_dup() are guaranteed to be atomic, and thus + * can be safely be performed by different threads. It is important to note that + * only the reference acquisition and release are atomic; changes to the content + * of the data are your responsibility. + * + * ## Automatic pointer clean up + * + * If you want to add g_autoptr() support to your plain old data type through + * reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and + * g_atomic_rc_box_release(): + * + * |[ + * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_atomic_rc_box_release) + * ]| + * + * If you need to clear the contents of the data, you will need to use an + * ancillary function that calls g_rc_box_release_full(): + * + * |[ + * static void + * my_data_struct_release (MyDataStruct *data) + * { + * // my_data_struct_clear() is defined elsewhere + * g_atomic_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear); + * } + * + * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_clear) + * ]| + * + * Since: 2.58. + */ + +/** + * g_atomic_rc_box_alloc: + * @block_size: the size of the allocation, must be greater than 0 + * + * Allocates @block_size bytes of memory, and adds atomic + * reference counting semantics to it. + * + * The data will be freed when its reference count drops to + * zero. + * + * Returns: (transfer full) (not nullable): a pointer to the allocated memory + * + * Since: 2.58 + */ +gpointer +g_atomic_rc_box_alloc (gsize block_size) +{ + g_return_val_if_fail (block_size > 0, NULL); + + return g_rc_box_alloc_full (block_size, TRUE, FALSE); +} + +/** + * g_atomic_rc_box_alloc0: + * @block_size: the size of the allocation, must be greater than 0 + * + * Allocates @block_size bytes of memory, and adds atomic + * referenc counting semantics to it. + * + * The contents of the returned data is set to zero. + * + * The data will be freed when its reference count drops to + * zero. + * + * Returns: (transfer full) (not nullable): a pointer to the allocated memory + * + * Since: 2.58 + */ +gpointer +g_atomic_rc_box_alloc0 (gsize block_size) +{ + g_return_val_if_fail (block_size > 0, NULL); + + return g_rc_box_alloc_full (block_size, TRUE, TRUE); +} + +/** + * g_atomic_rc_box_new: + * @type: the type to allocate, typically a structure name + * + * A convenience macro to allocate atomically reference counted + * data with the size of the given @type. + * + * This macro calls g_atomic_rc_box_alloc() with `sizeof (@type)` and + * casts the returned pointer to a pointer of the given @type, + * avoiding a type cast in the source code. + * + * Returns: (transfer full) (not nullable): a pointer to the allocated + * memory, cast to a pointer for the given @type + * + * Since: 2.58 + */ + +/** + * g_atomic_rc_box_new0: + * @type: the type to allocate, typically a structure name + * + * A convenience macro to allocate atomically reference counted + * data with the size of the given @type, and set its contents + * to zero. + * + * This macro calls g_atomic_rc_box_alloc0() with `sizeof (@type)` and + * casts the returned pointer to a pointer of the given @type, + * avoiding a type cast in the source code. + * + * Returns: (transfer full) (not nullable): a pointer to the allocated + * memory, cast to a pointer for the given @type + * + * Since: 2.58 + */ + +/** + * g_atomic_rc_box_dup: + * @block_size: the number of bytes to copy, must be greater than 0 + * @mem_block: (not nullable): the memory to copy + * + * Allocates a new block of data with atomit reference counting + * semantics, and copies @block_size bytes of @mem_block + * into it. + * + * Returns: (transfer full) (not nullable): a pointer to the allocated + * memory + * + * Since: 2.58 + */ +gpointer +(g_atomic_rc_box_dup) (gsize block_size, + gconstpointer mem_block) +{ + gpointer res; + + g_return_val_if_fail (block_size > 0, NULL); + g_return_val_if_fail (mem_block != NULL, NULL); + + res = g_rc_box_alloc_full (block_size, TRUE, FALSE); + memcpy (res, mem_block, block_size); + + return res; +} + +/** + * g_atomic_rc_box_acquire: + * @mem_block: (not nullable): a pointer to reference counted data + * + * Atomically acquires a reference on the data pointed by @mem_block. + * + * Returns: (transfer full) (not nullable): a pointer to the data, + * with its reference count increased + * + * Since: 2.58 + */ +gpointer +(g_atomic_rc_box_acquire) (gpointer mem_block) +{ + GArcBox *real_box = G_ARC_BOX (mem_block); + + g_return_val_if_fail (mem_block != NULL, NULL); +#ifndef G_DISABLE_ASSERT + g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL); +#endif + + g_atomic_ref_count_inc (&real_box->ref_count); + + TRACE (GLIB_RCBOX_ACQUIRE (mem_block, 1)); + + return mem_block; +} + +/** + * g_atomic_rc_box_release: + * @mem_block: (transfer full) (not nullable): a pointer to reference counted data + * + * Atomically releases a reference on the data pointed by @mem_block. + * + * If the reference was the last one, it will free the + * resources allocated for @mem_block. + * + * Since: 2.58 + */ +void +g_atomic_rc_box_release (gpointer mem_block) +{ + g_atomic_rc_box_release_full (mem_block, NULL); +} + +/** + * g_atomic_rc_box_release_full: + * @mem_block: (transfer full) (not nullable): a pointer to reference counted data + * @clear_func: (not nullable): a function to call when clearing the data + * + * Atomically releases a reference on the data pointed by @mem_block. + * + * If the reference was the last one, it will call @clear_func + * to clear the contents of @mem_block, and then will free the + * resources allocated for @mem_block. + * + * Since: 2.58 + */ +void +g_atomic_rc_box_release_full (gpointer mem_block, + GDestroyNotify clear_func) +{ + GArcBox *real_box = G_ARC_BOX (mem_block); + + g_return_if_fail (mem_block != NULL); +#ifndef G_DISABLE_ASSERT + g_return_if_fail (real_box->magic == G_BOX_MAGIC); +#endif + + if (g_atomic_ref_count_dec (&real_box->ref_count)) + { + TRACE (GLIB_RCBOX_RELEASE (mem_block, 1)); + + if (clear_func != NULL) + clear_func (mem_block); + + TRACE (GLIB_RCBOX_FREE (mem_block)); + g_free (real_box); + } +} + +/** + * g_atomic_rc_box_get_size: + * @mem_block: (not nullable): a pointer to reference counted data + * + * Retrieves the size of the reference counted data pointed by @mem_block. + * + * Returns: the size of the data, in bytes + * + * Since: 2.58 + */ +gsize +g_atomic_rc_box_get_size (gpointer mem_block) +{ + GArcBox *real_box = G_ARC_BOX (mem_block); + + g_return_val_if_fail (mem_block != NULL, 0); +#ifndef G_DISABLE_ASSERT + g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, 0); +#endif + + return real_box->mem_size; +} diff --git a/glib/garray.c b/glib/garray.c index 914eaee34..5b71c887a 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -41,7 +41,7 @@ #include "gthread.h" #include "gmessages.h" #include "gqsort.h" - +#include "grefcount.h" /** * SECTION:arrays @@ -106,7 +106,7 @@ struct _GRealArray guint elt_size; guint zero_terminated : 1; guint clear : 1; - gint ref_count; + gatomicrefcount ref_count; GDestroyNotify clear_func; }; @@ -139,9 +139,9 @@ struct _GRealArray g_array_elt_zero ((array), (array)->len, 1); \ }G_STMT_END -static guint g_nearest_pow (gint num) G_GNUC_CONST; +static guint g_nearest_pow (guint num) G_GNUC_CONST; static void g_array_maybe_expand (GRealArray *array, - gint len); + guint len); /** * g_array_new: @@ -199,9 +199,10 @@ g_array_sized_new (gboolean zero_terminated, array->zero_terminated = (zero_terminated ? 1 : 0); array->clear = (clear ? 1 : 0); array->elt_size = elt_size; - array->ref_count = 1; array->clear_func = NULL; + g_atomic_ref_count_init (&array->ref_count); + if (array->zero_terminated || reserved_size != 0) { g_array_maybe_expand (array, reserved_size); @@ -257,7 +258,7 @@ g_array_ref (GArray *array) GRealArray *rarray = (GRealArray*) array; g_return_val_if_fail (array, NULL); - g_atomic_int_inc (&rarray->ref_count); + g_atomic_ref_count_inc (&rarray->ref_count); return array; } @@ -287,7 +288,7 @@ g_array_unref (GArray *array) GRealArray *rarray = (GRealArray*) array; g_return_if_fail (array); - if (g_atomic_int_dec_and_test (&rarray->ref_count)) + if (g_atomic_ref_count_dec (&rarray->ref_count)) array_free (rarray, FREE_SEGMENT); } @@ -346,7 +347,7 @@ g_array_free (GArray *farray, flags = (free_segment ? FREE_SEGMENT : 0); /* if others are holding a reference, preserve the wrapper but do free/return the data */ - if (!g_atomic_int_dec_and_test (&array->ref_count)) + if (!g_atomic_ref_count_dec (&array->ref_count)) flags |= PRESERVE_WRAPPER; return array_free (array, flags); @@ -439,11 +440,14 @@ g_array_append_vals (GArray *farray, /** * g_array_prepend_vals: * @array: a #GArray - * @data: (not nullable): a pointer to the elements to prepend to the start of the array - * @len: the number of elements to prepend + * @data: (nullable): a pointer to the elements to prepend to the start of the array + * @len: the number of elements to prepend, which may be zero * * Adds @len elements onto the start of the array. * + * @data may be %NULL if (and only if) @len is zero. If @len is zero, this + * function is a no-op. + * * This operation is slower than g_array_append_vals() since the * existing elements in the array have to be moved to make space for * the new elements. @@ -498,11 +502,19 @@ g_array_prepend_vals (GArray *farray, * g_array_insert_vals: * @array: a #GArray * @index_: the index to place the elements at - * @data: (not nullable): a pointer to the elements to insert + * @data: (nullable): a pointer to the elements to insert * @len: the number of elements to insert * * Inserts @len elements into a #GArray at the given index. * + * If @index_ is greater than the array’s current length, the array is expanded. + * The elements between the old end of the array and the newly inserted elements + * will be initialised to zero if the array was configured to clear elements; + * otherwise their values will be undefined. + * + * @data may be %NULL if (and only if) @len is zero. If @len is zero, this + * function is a no-op. + * * Returns: the #GArray */ /** @@ -532,6 +544,14 @@ g_array_insert_vals (GArray *farray, if (len == 0) return farray; + /* Is the index off the end of the array, and hence do we need to over-allocate + * and clear some elements? */ + if (index_ >= array->len) + { + g_array_maybe_expand (array, index_ - array->len + len); + return g_array_append_vals (g_array_set_size (farray, index_), data, len); + } + g_array_maybe_expand (array, len); memmove (g_array_elt_pos (array, len + index_), @@ -769,7 +789,7 @@ g_array_sort_with_data (GArray *farray, * such power does not fit in a guint */ static guint -g_nearest_pow (gint num) +g_nearest_pow (guint num) { guint n = 1; @@ -781,7 +801,7 @@ g_nearest_pow (gint num) static void g_array_maybe_expand (GRealArray *array, - gint len) + guint len) { guint want_alloc = g_array_elt_len (array, array->len + len + array->zero_terminated); @@ -863,7 +883,7 @@ struct _GRealPtrArray gpointer *pdata; guint len; guint alloc; - gint ref_count; + gatomicrefcount ref_count; GDestroyNotify element_free_func; }; @@ -917,9 +937,10 @@ g_ptr_array_sized_new (guint reserved_size) array->pdata = NULL; array->len = 0; array->alloc = 0; - array->ref_count = 1; array->element_free_func = NULL; + g_atomic_ref_count_init (&array->ref_count); + if (reserved_size != 0) g_ptr_array_maybe_expand (array, reserved_size); @@ -1022,7 +1043,7 @@ g_ptr_array_ref (GPtrArray *array) g_return_val_if_fail (array, NULL); - g_atomic_int_inc (&rarray->ref_count); + g_atomic_ref_count_inc (&rarray->ref_count); return array; } @@ -1047,7 +1068,7 @@ g_ptr_array_unref (GPtrArray *array) g_return_if_fail (array); - if (g_atomic_int_dec_and_test (&rarray->ref_count)) + if (g_atomic_ref_count_dec (&rarray->ref_count)) ptr_array_free (array, FREE_SEGMENT); } @@ -1088,7 +1109,7 @@ g_ptr_array_free (GPtrArray *array, /* if others are holding a reference, preserve the wrapper but * do free/return the data */ - if (!g_atomic_int_dec_and_test (&rarray->ref_count)) + if (!g_atomic_ref_count_dec (&rarray->ref_count)) flags |= PRESERVE_WRAPPER; return ptr_array_free (array, flags); @@ -1168,27 +1189,31 @@ g_ptr_array_set_size (GPtrArray *array, gint length) { GRealPtrArray *rarray = (GRealPtrArray *)array; + guint length_unsigned; g_return_if_fail (rarray); g_return_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL)); + g_return_if_fail (length >= 0); - if (length > rarray->len) + length_unsigned = (guint) length; + + if (length_unsigned > rarray->len) { - int i; - g_ptr_array_maybe_expand (rarray, (length - rarray->len)); + guint i; + g_ptr_array_maybe_expand (rarray, (length_unsigned - rarray->len)); /* This is not * memset (array->pdata + array->len, 0, - * sizeof (gpointer) * (length - array->len)); + * sizeof (gpointer) * (length_unsigned - array->len)); * to make it really portable. Remember (void*)NULL needn't be * bitwise zero. It of course is silly not to use memset (..,0,..). */ - for (i = rarray->len; i < length; i++) + for (i = rarray->len; i < length_unsigned; i++) rarray->pdata[i] = NULL; } - else if (length < rarray->len) - g_ptr_array_remove_range (array, length, rarray->len - length); + else if (length_unsigned < rarray->len) + g_ptr_array_remove_range (array, length_unsigned, rarray->len - length_unsigned); - rarray->len = length; + rarray->len = length_unsigned; } static gpointer diff --git a/glib/gasyncqueue.c b/glib/gasyncqueue.c index 8529beb8b..3eb38393d 100644 --- a/glib/gasyncqueue.c +++ b/glib/gasyncqueue.c @@ -539,6 +539,8 @@ g_async_queue_timeout_pop (GAsyncQueue *queue, gint64 end_time = g_get_monotonic_time () + timeout; gpointer retval; + g_return_val_if_fail (queue != NULL, NULL); + g_mutex_lock (&queue->mutex); retval = g_async_queue_pop_intern_unlocked (queue, TRUE, end_time); g_mutex_unlock (&queue->mutex); @@ -567,6 +569,8 @@ g_async_queue_timeout_pop_unlocked (GAsyncQueue *queue, { gint64 end_time = g_get_monotonic_time () + timeout; + g_return_val_if_fail (queue != NULL, NULL); + return g_async_queue_pop_intern_unlocked (queue, TRUE, end_time); } diff --git a/glib/gatomic.h b/glib/gatomic.h index 8e5efccb4..971176eb9 100644 --- a/glib/gatomic.h +++ b/glib/gatomic.h @@ -109,7 +109,8 @@ G_END_DECLS #define g_atomic_pointer_get(atomic) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - (gpointer) __atomic_load_8 ((atomic), __ATOMIC_SEQ_CST); \ + guint64 gapg_temp = __atomic_load_8 ((atomic), __ATOMIC_SEQ_CST); \ + (gpointer) gapg_temp; \ })) #define g_atomic_pointer_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ @@ -127,7 +128,8 @@ G_END_DECLS #define g_atomic_pointer_get(atomic) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - (gpointer) __atomic_load_4 ((atomic), __ATOMIC_SEQ_CST); \ + guint32 gapg_temp = __atomic_load_4 ((atomic), __ATOMIC_SEQ_CST); \ + (gpointer) gapg_temp; \ })) #define g_atomic_pointer_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ @@ -186,7 +188,7 @@ G_END_DECLS (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \ (void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \ - (gboolean) __sync_bool_compare_and_swap ((atomic), (oldval), (newval)); \ + __sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \ })) #define g_atomic_int_add(atomic, val) \ (G_GNUC_EXTENSION ({ \ @@ -217,7 +219,7 @@ G_END_DECLS (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ - (gboolean) __sync_bool_compare_and_swap ((atomic), (oldval), (newval)); \ + __sync_bool_compare_and_swap ((atomic), (oldval), (newval)) ? TRUE : FALSE; \ })) #define g_atomic_pointer_add(atomic, val) \ (G_GNUC_EXTENSION ({ \ diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c index d29f4fad6..e83079985 100644 --- a/glib/gbacktrace.c +++ b/glib/gbacktrace.c @@ -68,18 +68,6 @@ #include "gprintfint.h" #include "gutils.h" - -#ifndef NO_FD_SET -# define SELECT_MASK fd_set -#else -# if defined(_IBMR2) -# define SELECT_MASK void -# else -# define SELECT_MASK int -# endif -#endif - - #ifndef G_OS_WIN32 static void stack_trace (const char * const *args); #endif @@ -274,8 +262,8 @@ stack_trace (const char * const *args) pid_t pid; int in_fd[2]; int out_fd[2]; - SELECT_MASK fdset; - SELECT_MASK readset; + fd_set fdset; + fd_set readset; struct timeval tv; int sel, idx, state; char buffer[256]; diff --git a/glib/gbookmarkfile.c b/glib/gbookmarkfile.c index bbbc66e5d..e6f885e6b 100644 --- a/glib/gbookmarkfile.c +++ b/glib/gbookmarkfile.c @@ -210,7 +210,7 @@ struct _GBookmarkFile }; /* parser state machine */ -enum +typedef enum { STATE_STARTED = 0, @@ -228,7 +228,7 @@ enum STATE_ICON, STATE_FINISHED -}; +} ParserState; static void g_bookmark_file_init (GBookmarkFile *bookmark); static void g_bookmark_file_clear (GBookmarkFile *bookmark); @@ -681,7 +681,7 @@ g_bookmark_file_clear (GBookmarkFile *bookmark) struct _ParseData { - gint state; + ParserState state; GHashTable *namespaces; @@ -1083,6 +1083,43 @@ is_element_full (ParseData *parse_data, #define IS_ELEMENT(p,s,e) (is_element_full ((p), (s), NULL, (e), '\0')) #define IS_ELEMENT_NS(p,s,n,e) (is_element_full ((p), (s), (n), (e), '|')) +static const gchar * +parser_state_to_element_name (ParserState state) +{ + switch (state) + { + case STATE_STARTED: + case STATE_FINISHED: + return "(top-level)"; + case STATE_ROOT: + return XBEL_ROOT_ELEMENT; + case STATE_BOOKMARK: + return XBEL_BOOKMARK_ELEMENT; + case STATE_TITLE: + return XBEL_TITLE_ELEMENT; + case STATE_DESC: + return XBEL_DESC_ELEMENT; + case STATE_INFO: + return XBEL_INFO_ELEMENT; + case STATE_METADATA: + return XBEL_METADATA_ELEMENT; + case STATE_APPLICATIONS: + return BOOKMARK_APPLICATIONS_ELEMENT; + case STATE_APPLICATION: + return BOOKMARK_APPLICATION_ELEMENT; + case STATE_GROUPS: + return BOOKMARK_GROUPS_ELEMENT; + case STATE_GROUP: + return BOOKMARK_GROUP_ELEMENT; + case STATE_MIME: + return MIME_TYPE_ELEMENT; + case STATE_ICON: + return BOOKMARK_ICON_ELEMENT; + default: + g_assert_not_reached (); + } +} + static void start_element_raw_cb (GMarkupParseContext *context, const gchar *element_name, @@ -1263,8 +1300,23 @@ start_element_raw_cb (GMarkupParseContext *context, element_name, BOOKMARK_GROUP_ELEMENT); break; + + case STATE_TITLE: + case STATE_DESC: + case STATE_APPLICATION: + case STATE_GROUP: + case STATE_MIME: + case STATE_ICON: + case STATE_FINISHED: + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + _("Unexpected tag “%s†inside “%sâ€"), + element_name, + parser_state_to_element_name (parse_data->state)); + break; + default: - g_warn_if_reached (); + g_assert_not_reached (); break; } } @@ -1774,7 +1826,7 @@ find_file_in_data_dirs (const gchar *file, * This function looks for a desktop bookmark file named @file in the * paths returned from g_get_user_data_dir() and g_get_system_data_dirs(), * loads the file into @bookmark and returns the file's full path in - * @full_path. If the file could not be loaded then an %error is + * @full_path. If the file could not be loaded then @error is * set to either a #GFileError or #GBookmarkFileError. * * Returns: %TRUE if a key file could be loaded, %FALSE otherwise diff --git a/glib/gbsearcharray.h b/glib/gbsearcharray.h index 832522e27..39afa3f79 100644 --- a/glib/gbsearcharray.h +++ b/glib/gbsearcharray.h @@ -116,11 +116,7 @@ static inline void g_bsearch_array_free (GBSearchArray /* --- implementation --- */ /* helper macro to cut down realloc()s */ -#ifdef DISABLE_MEM_POOLS -#define G_BSEARCH_UPPER_POWER2(n) (n) -#else /* !DISABLE_MEM_POOLS */ #define G_BSEARCH_UPPER_POWER2(n) ((n) ? 1 << g_bit_storage ((n) - 1) : 0) -#endif /* !DISABLE_MEM_POOLS */ #define G_BSEARCH_ARRAY_NODES(barray) (((guint8*) (barray)) + sizeof (GBSearchArray)) static inline GBSearchArray* g_bsearch_array_create (const GBSearchConfig *bconfig) diff --git a/glib/gbytes.c b/glib/gbytes.c index 3b14a51cd..74f8148f6 100644 --- a/glib/gbytes.c +++ b/glib/gbytes.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -69,7 +70,7 @@ struct _GBytes { gconstpointer data; /* may be NULL iff (size == 0) */ gsize size; /* may be 0 */ - gint ref_count; + gatomicrefcount ref_count; GDestroyNotify free_func; gpointer user_data; }; @@ -187,7 +188,7 @@ g_bytes_new_with_free_func (gconstpointer data, bytes->size = size; bytes->free_func = free_func; bytes->user_data = user_data; - bytes->ref_count = 1; + g_atomic_ref_count_init (&bytes->ref_count); return (GBytes *)bytes; } @@ -310,7 +311,7 @@ g_bytes_ref (GBytes *bytes) { g_return_val_if_fail (bytes != NULL, NULL); - g_atomic_int_inc (&bytes->ref_count); + g_atomic_ref_count_inc (&bytes->ref_count); return bytes; } @@ -330,7 +331,7 @@ g_bytes_unref (GBytes *bytes) if (bytes == NULL) return; - if (g_atomic_int_dec_and_test (&bytes->ref_count)) + if (g_atomic_ref_count_dec (&bytes->ref_count)) { if (bytes->free_func != NULL) bytes->free_func (bytes->user_data); @@ -438,7 +439,7 @@ try_steal_and_unref (GBytes *bytes, return NULL; /* Are we the only reference? */ - if (g_atomic_int_get (&bytes->ref_count) == 1) + if (g_atomic_ref_count_compare (&bytes->ref_count, 1)) { *size = bytes->size; result = (gpointer)bytes->data; diff --git a/glib/gchecksum.c b/glib/gchecksum.c index f151ced49..5530aad2f 100644 --- a/glib/gchecksum.c +++ b/glib/gchecksum.c @@ -1118,46 +1118,46 @@ sha256_sum_digest (Sha256sum *sha256, /* SHA-384 and SHA-512 constants [§4.2.3] */ static const guint64 SHA2_K[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, - 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, - 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, - 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, - 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, - 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, - 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, - 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, - 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, - 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, - 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, - 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, - 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, - 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, - 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, - 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, - 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, - 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, - 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, - 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, - 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 + G_GUINT64_CONSTANT (0x428a2f98d728ae22), G_GUINT64_CONSTANT (0x7137449123ef65cd), + G_GUINT64_CONSTANT (0xb5c0fbcfec4d3b2f), G_GUINT64_CONSTANT (0xe9b5dba58189dbbc), + G_GUINT64_CONSTANT (0x3956c25bf348b538), G_GUINT64_CONSTANT (0x59f111f1b605d019), + G_GUINT64_CONSTANT (0x923f82a4af194f9b), G_GUINT64_CONSTANT (0xab1c5ed5da6d8118), + G_GUINT64_CONSTANT (0xd807aa98a3030242), G_GUINT64_CONSTANT (0x12835b0145706fbe), + G_GUINT64_CONSTANT (0x243185be4ee4b28c), G_GUINT64_CONSTANT (0x550c7dc3d5ffb4e2), + G_GUINT64_CONSTANT (0x72be5d74f27b896f), G_GUINT64_CONSTANT (0x80deb1fe3b1696b1), + G_GUINT64_CONSTANT (0x9bdc06a725c71235), G_GUINT64_CONSTANT (0xc19bf174cf692694), + G_GUINT64_CONSTANT (0xe49b69c19ef14ad2), G_GUINT64_CONSTANT (0xefbe4786384f25e3), + G_GUINT64_CONSTANT (0x0fc19dc68b8cd5b5), G_GUINT64_CONSTANT (0x240ca1cc77ac9c65), + G_GUINT64_CONSTANT (0x2de92c6f592b0275), G_GUINT64_CONSTANT (0x4a7484aa6ea6e483), + G_GUINT64_CONSTANT (0x5cb0a9dcbd41fbd4), G_GUINT64_CONSTANT (0x76f988da831153b5), + G_GUINT64_CONSTANT (0x983e5152ee66dfab), G_GUINT64_CONSTANT (0xa831c66d2db43210), + G_GUINT64_CONSTANT (0xb00327c898fb213f), G_GUINT64_CONSTANT (0xbf597fc7beef0ee4), + G_GUINT64_CONSTANT (0xc6e00bf33da88fc2), G_GUINT64_CONSTANT (0xd5a79147930aa725), + G_GUINT64_CONSTANT (0x06ca6351e003826f), G_GUINT64_CONSTANT (0x142929670a0e6e70), + G_GUINT64_CONSTANT (0x27b70a8546d22ffc), G_GUINT64_CONSTANT (0x2e1b21385c26c926), + G_GUINT64_CONSTANT (0x4d2c6dfc5ac42aed), G_GUINT64_CONSTANT (0x53380d139d95b3df), + G_GUINT64_CONSTANT (0x650a73548baf63de), G_GUINT64_CONSTANT (0x766a0abb3c77b2a8), + G_GUINT64_CONSTANT (0x81c2c92e47edaee6), G_GUINT64_CONSTANT (0x92722c851482353b), + G_GUINT64_CONSTANT (0xa2bfe8a14cf10364), G_GUINT64_CONSTANT (0xa81a664bbc423001), + G_GUINT64_CONSTANT (0xc24b8b70d0f89791), G_GUINT64_CONSTANT (0xc76c51a30654be30), + G_GUINT64_CONSTANT (0xd192e819d6ef5218), G_GUINT64_CONSTANT (0xd69906245565a910), + G_GUINT64_CONSTANT (0xf40e35855771202a), G_GUINT64_CONSTANT (0x106aa07032bbd1b8), + G_GUINT64_CONSTANT (0x19a4c116b8d2d0c8), G_GUINT64_CONSTANT (0x1e376c085141ab53), + G_GUINT64_CONSTANT (0x2748774cdf8eeb99), G_GUINT64_CONSTANT (0x34b0bcb5e19b48a8), + G_GUINT64_CONSTANT (0x391c0cb3c5c95a63), G_GUINT64_CONSTANT (0x4ed8aa4ae3418acb), + G_GUINT64_CONSTANT (0x5b9cca4f7763e373), G_GUINT64_CONSTANT (0x682e6ff3d6b2b8a3), + G_GUINT64_CONSTANT (0x748f82ee5defb2fc), G_GUINT64_CONSTANT (0x78a5636f43172f60), + G_GUINT64_CONSTANT (0x84c87814a1f0ab72), G_GUINT64_CONSTANT (0x8cc702081a6439ec), + G_GUINT64_CONSTANT (0x90befffa23631e28), G_GUINT64_CONSTANT (0xa4506cebde82bde9), + G_GUINT64_CONSTANT (0xbef9a3f7b2c67915), G_GUINT64_CONSTANT (0xc67178f2e372532b), + G_GUINT64_CONSTANT (0xca273eceea26619c), G_GUINT64_CONSTANT (0xd186b8c721c0c207), + G_GUINT64_CONSTANT (0xeada7dd6cde0eb1e), G_GUINT64_CONSTANT (0xf57d4f7fee6ed178), + G_GUINT64_CONSTANT (0x06f067aa72176fba), G_GUINT64_CONSTANT (0x0a637dc5a2c898a6), + G_GUINT64_CONSTANT (0x113f9804bef90dae), G_GUINT64_CONSTANT (0x1b710b35131c471b), + G_GUINT64_CONSTANT (0x28db77f523047d84), G_GUINT64_CONSTANT (0x32caab7b40c72493), + G_GUINT64_CONSTANT (0x3c9ebe0a15c9bebc), G_GUINT64_CONSTANT (0x431d67c49c100d4c), + G_GUINT64_CONSTANT (0x4cc5d4becb3e42b6), G_GUINT64_CONSTANT (0x597f299cfc657e2a), + G_GUINT64_CONSTANT (0x5fcb6fab3ad6faec), G_GUINT64_CONSTANT (0x6c44198c4a475817) }; @@ -1165,14 +1165,14 @@ static void sha384_sum_init (Sha512sum *sha512) { /* Initial Hash Value [§5.3.4] */ - sha512->H[0] = 0xcbbb9d5dc1059ed8; - sha512->H[1] = 0x629a292a367cd507; - sha512->H[2] = 0x9159015a3070dd17; - sha512->H[3] = 0x152fecd8f70e5939; - sha512->H[4] = 0x67332667ffc00b31; - sha512->H[5] = 0x8eb44a8768581511; - sha512->H[6] = 0xdb0c2e0d64f98fa7; - sha512->H[7] = 0x47b5481dbefa4fa4; + sha512->H[0] = G_GUINT64_CONSTANT (0xcbbb9d5dc1059ed8); + sha512->H[1] = G_GUINT64_CONSTANT (0x629a292a367cd507); + sha512->H[2] = G_GUINT64_CONSTANT (0x9159015a3070dd17); + sha512->H[3] = G_GUINT64_CONSTANT (0x152fecd8f70e5939); + sha512->H[4] = G_GUINT64_CONSTANT (0x67332667ffc00b31); + sha512->H[5] = G_GUINT64_CONSTANT (0x8eb44a8768581511); + sha512->H[6] = G_GUINT64_CONSTANT (0xdb0c2e0d64f98fa7); + sha512->H[7] = G_GUINT64_CONSTANT (0x47b5481dbefa4fa4); sha512->block_len = 0; @@ -1184,14 +1184,14 @@ static void sha512_sum_init (Sha512sum *sha512) { /* Initial Hash Value [§5.3.5] */ - sha512->H[0] = 0x6a09e667f3bcc908; - sha512->H[1] = 0xbb67ae8584caa73b; - sha512->H[2] = 0x3c6ef372fe94f82b; - sha512->H[3] = 0xa54ff53a5f1d36f1; - sha512->H[4] = 0x510e527fade682d1; - sha512->H[5] = 0x9b05688c2b3e6c1f; - sha512->H[6] = 0x1f83d9abfb41bd6b; - sha512->H[7] = 0x5be0cd19137e2179; + sha512->H[0] = G_GUINT64_CONSTANT (0x6a09e667f3bcc908); + sha512->H[1] = G_GUINT64_CONSTANT (0xbb67ae8584caa73b); + sha512->H[2] = G_GUINT64_CONSTANT (0x3c6ef372fe94f82b); + sha512->H[3] = G_GUINT64_CONSTANT (0xa54ff53a5f1d36f1); + sha512->H[4] = G_GUINT64_CONSTANT (0x510e527fade682d1); + sha512->H[5] = G_GUINT64_CONSTANT (0x9b05688c2b3e6c1f); + sha512->H[6] = G_GUINT64_CONSTANT (0x1f83d9abfb41bd6b); + sha512->H[7] = G_GUINT64_CONSTANT (0x5be0cd19137e2179); sha512->block_len = 0; diff --git a/glib/gconvert.h b/glib/gconvert.h index d0d372150..c2e69a5a0 100644 --- a/glib/gconvert.h +++ b/glib/gconvert.h @@ -164,7 +164,7 @@ gchar *g_filename_to_uri (const gchar *filename, GLIB_AVAILABLE_IN_ALL gchar *g_filename_display_name (const gchar *filename) G_GNUC_MALLOC; GLIB_AVAILABLE_IN_ALL -gboolean g_get_filename_charsets (const gchar ***charsets); +gboolean g_get_filename_charsets (const gchar ***filename_charsets); GLIB_AVAILABLE_IN_ALL gchar *g_filename_display_basename (const gchar *filename) G_GNUC_MALLOC; diff --git a/glib/gdate.c b/glib/gdate.c index 13a16aaeb..6e163b8a7 100644 --- a/glib/gdate.c +++ b/glib/gdate.c @@ -1088,7 +1088,7 @@ g_date_prepare_to_parse (const gchar *str, { gchar *casefold; - g_date_set_dmy (&d, 1, i, 1); + g_date_set_dmy (&d, 1, i, 1976); g_return_if_fail (g_date_valid (&d)); @@ -1387,7 +1387,10 @@ g_date_set_parse (GDate *d, * * To set the value of a date to the current day, you could write: * |[ - * g_date_set_time_t (date, time (NULL)); + * time_t now = time (NULL); + * if (now == (time_t) -1) + * // handle the error + * g_date_set_time_t (date, now); * ]| * * Since: 2.10 diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 380c8d147..1e7a771a9 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -1173,6 +1173,17 @@ write_to_temp_file (const gchar *contents, * lists, metadata etc. may be lost. If @filename is a symbolic link, * the link itself will be replaced, not the linked file. * + * - On UNIX, if @filename already exists and is non-empty, and if the system + * supports it (via a journalling filesystem or equivalent), the fsync() + * call (or equivalent) will be used to ensure atomic replacement: @filename + * will contain either its old contents or @contents, even in the face of + * system power loss, the disk being unsafely removed, etc. + * + * - On UNIX, if @filename does not already exist or is empty, there is a + * possibility that system power loss etc. after calling this function will + * leave @filename empty or full of NUL bytes, depending on the underlying + * filesystem. + * * - On Windows renaming a file will not remove an existing file with the * new name, so on Windows there is a race condition between the existing * file being removed and the temporary file being renamed. diff --git a/glib/ghash.c b/glib/ghash.c index 87218114f..433004cf8 100644 --- a/glib/ghash.c +++ b/glib/ghash.c @@ -37,7 +37,7 @@ #include "gatomic.h" #include "gtestutils.h" #include "gslice.h" - +#include "grefcount.h" /** * SECTION:hash_tables @@ -227,7 +227,7 @@ struct _GHashTable GHashFunc hash_func; GEqualFunc key_equal_func; - gint ref_count; + gatomicrefcount ref_count; #ifndef G_DISABLE_ASSERT /* * Tracks the structure of the hash table, not its contents: is only @@ -374,7 +374,7 @@ g_hash_table_lookup_node (GHashTable *hash_table, * (as keys, etc. will be NULL). * Applications need to either use g_hash_table_destroy, or ensure the hash * table is empty prior to removing the last reference using g_hash_table_unref(). */ - g_assert (hash_table->ref_count > 0); + g_assert (!g_atomic_ref_count_compare (&hash_table->ref_count, 0)); hash_value = hash_table->hash_func (key); if (G_UNLIKELY (!HASH_IS_REAL (hash_value))) @@ -716,11 +716,11 @@ g_hash_table_new_full (GHashFunc hash_func, hash_table = g_slice_new (GHashTable); g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT); + g_atomic_ref_count_init (&hash_table->ref_count); hash_table->nnodes = 0; hash_table->noccupied = 0; hash_table->hash_func = hash_func ? hash_func : g_direct_hash; hash_table->key_equal_func = key_equal_func; - hash_table->ref_count = 1; #ifndef G_DISABLE_ASSERT hash_table->version = 0; #endif @@ -1077,7 +1077,7 @@ g_hash_table_ref (GHashTable *hash_table) { g_return_val_if_fail (hash_table != NULL, NULL); - g_atomic_int_inc (&hash_table->ref_count); + g_atomic_ref_count_inc (&hash_table->ref_count); return hash_table; } @@ -1098,7 +1098,7 @@ g_hash_table_unref (GHashTable *hash_table) { g_return_if_fail (hash_table != NULL); - if (g_atomic_int_dec_and_test (&hash_table->ref_count)) + if (g_atomic_ref_count_dec (&hash_table->ref_count)) { g_hash_table_remove_all_nodes (hash_table, TRUE, TRUE); if (hash_table->keys != hash_table->values) @@ -1909,9 +1909,9 @@ g_hash_table_get_values (GHashTable *hash_table) * @key_equal_func parameter, when using non-%NULL strings as keys in a * #GHashTable. * - * Note that this function is primarily meant as a hash table comparison - * function. For a general-purpose, %NULL-safe string comparison function, - * see g_strcmp0(). + * This function is typically used for hash table comparisons, but can be used + * for general purpose comparisons of non-%NULL strings. For a %NULL-safe string + * comparison function, see g_strcmp0(). * * Returns: %TRUE if the two keys match */ diff --git a/glib/glib-autocleanups.h b/glib/glib-autocleanups.h index 9f86bd99c..ce1690b78 100644 --- a/glib/glib-autocleanups.h +++ b/glib/glib-autocleanups.h @@ -87,3 +87,4 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantDict, g_variant_dict_unref) G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GVariantDict, g_variant_dict_clear) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantType, g_variant_type_free) G_DEFINE_AUTO_CLEANUP_FREE_FUNC(GStrv, g_strfreev, NULL) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GRefString, g_ref_string_release) diff --git a/glib/glib-init.c b/glib/glib-init.c index 5f312113a..6cb4e4a0d 100644 --- a/glib/glib-init.c +++ b/glib/glib-init.c @@ -74,11 +74,8 @@ G_STATIC_ASSERT (_g_alignof (TestInt) == _g_alignof (int)); * This variable is %TRUE if the `G_DEBUG` environment variable * includes the key `gc-friendly`. */ -#ifdef ENABLE_GC_FRIENDLY_DEFAULT -gboolean g_mem_gc_friendly = TRUE; -#else gboolean g_mem_gc_friendly = FALSE; -#endif + GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG; GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK; @@ -295,6 +292,8 @@ DllMain (HINSTANCE hinstDLL, g_thread_win32_init (); #endif glib_init (); + /* must go after glib_init */ + g_console_win32_init (); break; case DLL_THREAD_DETACH: diff --git a/glib/glib-init.h b/glib/glib-init.h index 5da33c052..695dc044b 100644 --- a/glib/glib-init.h +++ b/glib/glib-init.h @@ -34,6 +34,7 @@ void g_quark_init (void); void g_thread_win32_process_detach (void); void g_thread_win32_thread_detach (void); void g_thread_win32_init (void); +void g_console_win32_init (void); void g_clock_win32_init (void); extern HMODULE glib_dll; #endif diff --git a/glib/glib.h b/glib/glib.h index 4f5a7f702..94a11fb62 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -69,6 +69,9 @@ #include #include #include +#include +#include +#include #include #include #include diff --git a/glib/glib.stp.in b/glib/glib.stp.in index dc80e708d..0577d8ca2 100644 --- a/glib/glib.stp.in +++ b/glib/glib.stp.in @@ -598,3 +598,48 @@ probe glib.thread_spawned = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0. name = user_string($arg3); probestr = sprintf("glib.thread_spawned(%p, %p, %s)", func, data, name); } + +/** + * probe glib.rcbox_alloc - Called when a refcounted block is initially requested + * @mem: Raw memory pointer returned + * @n_bytes: number of bytes + * @atomic: Boolean value, %TRUE if this block is atomically refcounted + * @zeroed: Boolean value, %TRUE if this block was filled with NUL bytes + */ +probe glib.rcbox_alloc = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("rcbox__alloc") +{ + mem = $arg1; + n_bytes = $arg2; + atomic = $arg3; + zeroed = $arg4; + probestr = sprintf("glib.rcbox_alloc(n_bytes=%d) -> %p", n_bytes, mem); +} + +/** + * probe glib.rcbox_acquire - Called when a refcounted block acquires a ref + */ +probe glib.rcbox_acquire = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("rcbox__acquire") +{ + mem = $arg1; /* ARG: @mem: Raw memory pointer */ + atomic = $arg2; /* ARG: @atomic: Boolean value, %TRUE if the reference was acquired atomically */ + probestr = sprintf("glib.rcbox_acquire(mem=%p)", mem); +} + +/** + * probe glib.rcbox_release - Called when a refcounted block acquires a ref + */ +probe glib.rcbox_acquire = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("rcbox__release") +{ + mem = $arg1; /* ARG: @mem: Raw memory pointer */ + atomic = $arg2; /* ARG: @atomic: Boolean value, %TRUE if the reference was released atomically */ + probestr = sprintf("glib.rcbox_release(mem=%p)", mem); +} + +/** + * probe glib.rcbox_free - Called when a refcounted block is freed + */ +probe glib.rcbox_free = process("@ABS_GLIB_RUNTIME_LIBDIR@/libglib-2.0.so.0.@LT_CURRENT@.@LT_REVISION@").mark("rcbox__free") +{ + mem = $arg1; /* ARG: @mem: Raw memory pointer */ + probestr = sprintf("glib.rcbox_free(mem=%p)", mem); +} diff --git a/glib/glib_gdb.py b/glib/glib_gdb.py index 38f101ad5..1cf2ed936 100644 --- a/glib/glib_gdb.py +++ b/glib/glib_gdb.py @@ -9,7 +9,7 @@ def read_global_var (symname): return gdb.selected_frame().read_var(symname) def g_quark_to_string (quark): - if quark == None: + if quark is None: return None quark = long(quark) if quark == 0: @@ -171,7 +171,7 @@ def pretty_printer_lookup (val): return None def register (obj): - if obj == None: + if obj is None: obj = gdb obj.pretty_printers.append(pretty_printer_lookup) diff --git a/glib/glib_probes.d b/glib/glib_probes.d index 29f7ff12e..d6b1f8d15 100644 --- a/glib/glib_probes.d +++ b/glib/glib_probes.d @@ -43,4 +43,8 @@ provider glib { probe source__set_name(void*, const char*); probe source__before_free(void*, void*, void*); probe thread__spawned(void*, void*, char*); + probe rcbox__alloc(void*, unsigned int, unsigned int, unsigned int); + probe rcbox__acquire(void*, unsigned int); + probe rcbox__release(void*, unsigned int); + probe rcbox__free(void*); }; diff --git a/glib/glibconfig.h.win32.in b/glib/glibconfig.h.win32.in deleted file mode 100644 index b8214c009..000000000 --- a/glib/glibconfig.h.win32.in +++ /dev/null @@ -1,262 +0,0 @@ -/* glibconfig.h.win32.in. Originally merged from two versions of - * glibconfig.h, generated by the GLib configure script, for gcc and - * MSVC. - */ - -/* glibconfig.h - * - * This is a generated file. Please modify 'glibconfig.h.win32.in' - */ - -#ifndef __G_LIBCONFIG_H__ -#define __G_LIBCONFIG_H__ - -#include - -#include -#include -/* #undef GLIB_HAVE_ALLOCA_H */ - -/* Specifies that GLib's g_print*() functions wrap the - * system printf functions. This is useful to know, for example, - * when using glibc's register_printf_function(). - */ -#define GLIB_USING_SYSTEM_PRINTF - -G_BEGIN_DECLS - -#define G_MINFLOAT FLT_MIN -#define G_MAXFLOAT FLT_MAX -#define G_MINDOUBLE DBL_MIN -#define G_MAXDOUBLE DBL_MAX -#define G_MINSHORT SHRT_MIN -#define G_MAXSHORT SHRT_MAX -#define G_MAXUSHORT USHRT_MAX -#define G_MININT INT_MIN -#define G_MAXINT INT_MAX -#define G_MAXUINT UINT_MAX -#define G_MINLONG LONG_MIN -#define G_MAXLONG LONG_MAX -#define G_MAXULONG ULONG_MAX - -typedef signed char gint8; -typedef unsigned char guint8; -typedef signed short gint16; -typedef unsigned short guint16; -#define G_GINT16_MODIFIER "h" -#define G_GINT16_FORMAT "hi" -#define G_GUINT16_FORMAT "hu" -typedef signed int gint32; -typedef unsigned int guint32; -#define G_GINT32_MODIFIER "" -#define G_GINT32_FORMAT "i" -#define G_GUINT32_FORMAT "u" -#define G_HAVE_GINT64 1 /* deprecated, always true */ - -G_GNUC_EXTENSION typedef signed long long gint64; -G_GNUC_EXTENSION typedef unsigned long long guint64; - -#define G_GINT64_CONSTANT(val) (G_GNUC_EXTENSION (val##LL)) -#define G_GUINT64_CONSTANT(val) (G_GNUC_EXTENSION (val##ULL)) -#define G_GINT64_MODIFIER "I64" -#define G_GINT64_FORMAT "I64i" -#define G_GUINT64_FORMAT "I64u" - -#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64) - -#define GLIB_SIZEOF_VOID_P 8 -#define GLIB_SIZEOF_LONG 4 -#define GLIB_SIZEOF_SIZE_T 8 - -typedef signed long long gssize; -typedef unsigned long long gsize; -#define G_GSIZE_MODIFIER "I64" -#define G_GSSIZE_MODIFIER "I64" -#define G_GSIZE_FORMAT "I64u" -#define G_GSSIZE_FORMAT "I64i" - -#define G_MAXSIZE G_MAXUINT64 -#define G_MINSSIZE G_MININT64 -#define G_MAXSSIZE G_MAXINT64 - -#else - -#define GLIB_SIZEOF_VOID_P 4 -#define GLIB_SIZEOF_LONG 4 -#define GLIB_SIZEOF_SIZE_T 4 - -typedef signed int gssize; -typedef unsigned int gsize; -#define G_GSIZE_MODIFIER "" -#define G_GSSIZE_MODIFIER "" -#define G_GSIZE_FORMAT "u" -#define G_GSSIZE_FORMAT "i" - -#define G_MAXSIZE G_MAXUINT -#define G_MINSSIZE G_MININT -#define G_MAXSSIZE G_MAXINT - -#endif - -typedef gint64 goffset; -#define G_MINOFFSET G_MININT64 -#define G_MAXOFFSET G_MAXINT64 - -#define G_GOFFSET_MODIFIER G_GINT64_MODIFIER -#define G_GOFFSET_FORMAT G_GINT64_FORMAT -#define G_GOFFSET_CONSTANT(val) G_GINT64_CONSTANT(val) - - -#ifdef _WIN64 -# define G_POLLFD_FORMAT "%#I64x" -# define GPOINTER_TO_INT(p) ((gint) (gint64) (p)) -# define GPOINTER_TO_UINT(p) ((guint) (guint64) (p)) - -# define GINT_TO_POINTER(i) ((gpointer) (gint64) (i)) -# define GUINT_TO_POINTER(u) ((gpointer) (guint64) (u)) - -typedef signed long long gintptr; -typedef unsigned long long guintptr; - -# define G_GINTPTR_MODIFIER "I64" -# define G_GINTPTR_FORMAT "I64i" -# define G_GUINTPTR_FORMAT "I64u" -#else -# define G_POLLFD_FORMAT "%#x" - -# define GPOINTER_TO_INT(p) ((gint) (gint) (p)) -# define GPOINTER_TO_UINT(p) ((guint) (guint) (p)) - -# define GINT_TO_POINTER(i) ((gpointer) (gint) (i)) -# define GUINT_TO_POINTER(u) ((gpointer) (guint) (u)) - -typedef signed int gintptr; -typedef unsigned int guintptr; - -# define G_GINTPTR_MODIFIER "" -# define G_GINTPTR_FORMAT "i" -# define G_GUINTPTR_FORMAT "u" -#endif - -#ifndef G_DISABLE_DEPRECATED -#define g_ATEXIT(proc) (atexit (proc)) - -#define g_memmove(dest,src,len) G_STMT_START { memmove ((dest), (src), (len)); } G_STMT_END -#endif - -#define GLIB_MAJOR_VERSION @GLIB_MAJOR_VERSION@ -#define GLIB_MINOR_VERSION @GLIB_MINOR_VERSION@ -#define GLIB_MICRO_VERSION @GLIB_MICRO_VERSION@ - -#define G_OS_WIN32 -#define G_PLATFORM_WIN32 -@GLIB_WIN32_STATIC_COMPILATION_DEFINE@ - -#if !defined (_MSC_VER) || (_MSC_VER >= 1800) -#define G_VA_COPY va_copy -#endif /* not _MSC_VER or 2013 or later */ - -#ifndef _MSC_VER -# define G_HAVE_ISO_VARARGS 1 -# define G_HAVE_GNUC_VARARGS 1 -# define G_HAVE_GNUC_VISIBILITY 1 - -/* gcc-2.95.x supports both gnu style and ISO varargs, but if -ansi - * is passed ISO vararg support is turned off, and there is no work - * around to turn it on, so we unconditionally turn it off. - */ -#if __GNUC__ == 2 && __GNUC_MINOR__ == 95 -# undef G_HAVE_ISO_VARARGS -#endif - -#define G_HAVE_GROWING_STACK 0 - -#else /* _MSC_VER */ -# define G_HAVE_ISO_VARARGS 1 -#endif /* not _MSC_VER */ - -#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) -# define G_GNUC_INTERNAL __attribute__((visibility("hidden"))) -#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) -# define G_GNUC_INTERNAL __hidden -#elif defined (__GNUC__) && defined (G_HAVE_GNUC_VISIBILITY) -# define G_GNUC_INTERNAL __attribute__((visibility("hidden"))) -#else -# define G_GNUC_INTERNAL -#endif - -#define G_THREADS_ENABLED -#define G_THREADS_IMPL_WIN32 - -#define G_ATOMIC_LOCK_FREE - -#define GINT16_TO_LE(val) ((gint16) (val)) -#define GUINT16_TO_LE(val) ((guint16) (val)) -#define GINT16_TO_BE(val) ((gint16) GUINT16_SWAP_LE_BE (val)) -#define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE (val)) -#define GINT32_TO_LE(val) ((gint32) (val)) -#define GUINT32_TO_LE(val) ((guint32) (val)) -#define GINT32_TO_BE(val) ((gint32) GUINT32_SWAP_LE_BE (val)) -#define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE (val)) -#define GINT64_TO_LE(val) ((gint64) (val)) -#define GUINT64_TO_LE(val) ((guint64) (val)) -#define GINT64_TO_BE(val) ((gint64) GUINT64_SWAP_LE_BE (val)) -#define GUINT64_TO_BE(val) (GUINT64_SWAP_LE_BE (val)) -#define GLONG_TO_LE(val) ((glong) GINT32_TO_LE (val)) -#define GULONG_TO_LE(val) ((gulong) GUINT32_TO_LE (val)) -#define GLONG_TO_BE(val) ((glong) GINT32_TO_BE (val)) -#define GULONG_TO_BE(val) ((gulong) GUINT32_TO_BE (val)) -#define GINT_TO_LE(val) ((gint) GINT32_TO_LE (val)) -#define GUINT_TO_LE(val) ((guint) GUINT32_TO_LE (val)) -#define GINT_TO_BE(val) ((gint) GINT32_TO_BE (val)) -#define GUINT_TO_BE(val) ((guint) GUINT32_TO_BE (val)) - -#ifdef _WIN64 -# define GSIZE_TO_LE(val) ((gsize) GUINT64_TO_LE (val)) -# define GSSIZE_TO_LE(val) ((gssize) GINT64_TO_LE (val)) -# define GSIZE_TO_BE(val) ((gsize) GUINT64_TO_BE (val)) -# define GSSIZE_TO_BE(val) ((gssize) GINT64_TO_BE (val)) -#else -# define GSIZE_TO_LE(val) ((gsize) GUINT32_TO_LE (val)) -# define GSSIZE_TO_LE(val) ((gssize) GINT32_TO_LE (val)) -# define GSIZE_TO_BE(val) ((gsize) GUINT32_TO_BE (val)) -# define GSSIZE_TO_BE(val) ((gssize) GINT32_TO_BE (val)) -#endif - -#define G_BYTE_ORDER G_LITTLE_ENDIAN - -#define GLIB_SYSDEF_POLLIN =768 -#define GLIB_SYSDEF_POLLOUT =16 -#define GLIB_SYSDEF_POLLPRI =1024 -#define GLIB_SYSDEF_POLLHUP =2 -#define GLIB_SYSDEF_POLLERR =1 -#define GLIB_SYSDEF_POLLNVAL =4 - -#define G_MODULE_SUFFIX "dll" - -/* A GPid is an abstraction for a process "handle". It is *not* an - * abstraction for a process identifier in general. GPid is used in - * GLib only for descendant processes spawned with the g_spawn* - * functions. On POSIX there is no "process handle" concept as such, - * but on Windows a GPid is a handle to a process, a kind of pointer, - * not a process identifier. - */ -typedef void * GPid; -#define G_PID_FORMAT "p" - -#define GLIB_SYSDEF_AF_UNIX 1 -#define GLIB_SYSDEF_AF_INET 2 -#define GLIB_SYSDEF_AF_INET6 23 - -#define GLIB_SYSDEF_MSG_OOB 1 -#define GLIB_SYSDEF_MSG_PEEK 2 -#define GLIB_SYSDEF_MSG_DONTROUTE 4 - -#define G_DIR_SEPARATOR '\\' -#define G_DIR_SEPARATOR_S "\\" -#define G_SEARCHPATH_SEPARATOR ';' -#define G_SEARCHPATH_SEPARATOR_S ";" - -G_END_DECLS - -#endif /* GLIBCONFIG_H */ diff --git a/glib/gmacros.h b/glib/gmacros.h index 55fb81e5b..9b8ef0e89 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -110,6 +110,18 @@ #define G_GNUC_NULL_TERMINATED #endif +/* + * We can only use __typeof__ on GCC >= 4.8, and not when compiling C++. Since + * __typeof__ is used in a few places in GLib, provide a pre-processor symbol + * to factor the check out from callers. + * + * This symbol is private. + */ +#undef g_has_typeof +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && !defined(__cplusplus) +#define g_has_typeof +#endif + /* * Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html * These are not available on GCC, but since the pre-processor doesn't do @@ -329,6 +341,9 @@ #undef CLAMP #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define G_APPROX_VALUE(a, b, epsilon) \ + (((a) > (b) ? (a) - (b) : (b) - (a)) < (epsilon)) + /* Count the number of elements in an array. The array must be defined * as such; using this with a dynamically allocated array will give * incorrect results. @@ -482,9 +497,9 @@ typedef GList *_GLIB_AUTOPTR_LIST_TYPENAME(TypeName); \ typedef GSList *_GLIB_AUTOPTR_SLIST_TYPENAME(TypeName); \ G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - static inline void _GLIB_AUTOPTR_FUNC_NAME(TypeName) (TypeName **_ptr) { if (*_ptr) (func) (*_ptr); } \ - static inline void _GLIB_AUTOPTR_LIST_FUNC_NAME(TypeName) (GList **_l) { g_list_free_full (*_l, (GDestroyNotify) func); } \ - static inline void _GLIB_AUTOPTR_SLIST_FUNC_NAME(TypeName) (GSList **_l) { g_slist_free_full (*_l, (GDestroyNotify) func); } \ + static G_GNUC_UNUSED inline void _GLIB_AUTOPTR_FUNC_NAME(TypeName) (TypeName **_ptr) { if (*_ptr) (func) (*_ptr); } \ + static G_GNUC_UNUSED inline void _GLIB_AUTOPTR_LIST_FUNC_NAME(TypeName) (GList **_l) { g_list_free_full (*_l, (GDestroyNotify) (void(*)(void)) func); } \ + static G_GNUC_UNUSED inline void _GLIB_AUTOPTR_SLIST_FUNC_NAME(TypeName) (GSList **_l) { g_slist_free_full (*_l, (GDestroyNotify) (void(*)(void)) func); } \ G_GNUC_END_IGNORE_DEPRECATIONS #define G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(TypeName, func) \ G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ diff --git a/glib/gmain.c b/glib/gmain.c index 181483527..0a6857ce8 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -1296,6 +1296,11 @@ g_source_destroy (GSource *source) * context. The reverse * mapping from ID to source is done by g_main_context_find_source_by_id(). * + * You can only call this function while the source is associated to a + * #GMainContext instance; calling this function before g_source_attach() + * or after g_source_destroy() yields undefined behavior. The ID returned + * is unique within the #GMainContext instance passed to g_source_attach(). + * * Returns: the ID (greater than 0) for the source **/ guint @@ -1628,7 +1633,8 @@ g_source_set_callback_indirect (GSource *source, * * The exact type of @func depends on the type of source; ie. you * should not count on @func being called with @data as its first - * parameter. + * parameter. Cast @func with G_SOURCE_FUNC() to avoid warnings about + * incompatible function types. * * See [memory management of sources][mainloop-memory-management] for details * on how to handle memory management of @data. @@ -2437,8 +2443,7 @@ g_clear_handle_id (guint *tag_ptr, if (_handle_id > 0) { *tag_ptr = 0; - if (clear_func != NULL) - clear_func (_handle_id); + clear_func (_handle_id); } } @@ -3302,25 +3307,10 @@ g_main_context_release (GMainContext *context) UNLOCK_CONTEXT (context); } -/** - * g_main_context_wait: - * @context: a #GMainContext - * @cond: a condition variable - * @mutex: a mutex, currently held - * - * Tries to become the owner of the specified context, - * as with g_main_context_acquire(). But if another thread - * is the owner, atomically drop @mutex and wait on @cond until - * that owner releases ownership or until @cond is signaled, then - * try again (once) to become the owner. - * - * Returns: %TRUE if the operation succeeded, and - * this thread is now the owner of @context. - **/ -gboolean -g_main_context_wait (GMainContext *context, - GCond *cond, - GMutex *mutex) +static gboolean +g_main_context_wait_internal (GMainContext *context, + GCond *cond, + GMutex *mutex) { gboolean result = FALSE; GThread *self = G_THREAD_SELF; @@ -3329,18 +3319,6 @@ g_main_context_wait (GMainContext *context, if (context == NULL) context = g_main_context_default (); - if G_UNLIKELY (cond != &context->cond || mutex != &context->mutex) - { - static gboolean warned; - - if (!warned) - { - g_critical ("WARNING!! g_main_context_wait() will be removed in a future release. " - "If you see this message, please file a bug immediately."); - warned = TRUE; - } - } - loop_internal_waiter = (mutex == &context->mutex); if (!loop_internal_waiter) @@ -3356,10 +3334,10 @@ g_main_context_wait (GMainContext *context, context->waiters = g_slist_append (context->waiters, &waiter); if (!loop_internal_waiter) - UNLOCK_CONTEXT (context); + UNLOCK_CONTEXT (context); g_cond_wait (cond, mutex); - if (!loop_internal_waiter) - LOCK_CONTEXT (context); + if (!loop_internal_waiter) + LOCK_CONTEXT (context); context->waiters = g_slist_remove (context->waiters, &waiter); } @@ -3382,6 +3360,45 @@ g_main_context_wait (GMainContext *context, return result; } +/** + * g_main_context_wait: + * @context: a #GMainContext + * @cond: a condition variable + * @mutex: a mutex, currently held + * + * Tries to become the owner of the specified context, + * as with g_main_context_acquire(). But if another thread + * is the owner, atomically drop @mutex and wait on @cond until + * that owner releases ownership or until @cond is signaled, then + * try again (once) to become the owner. + * + * Returns: %TRUE if the operation succeeded, and + * this thread is now the owner of @context. + * Deprecated: 2.58: Use g_main_context_is_owner() and separate locking instead. + */ +gboolean +g_main_context_wait (GMainContext *context, + GCond *cond, + GMutex *mutex) +{ + if (context == NULL) + context = g_main_context_default (); + + if (G_UNLIKELY (cond != &context->cond || mutex != &context->mutex)) + { + static gboolean warned; + + if (!warned) + { + g_critical ("WARNING!! g_main_context_wait() will be removed in a future release. " + "If you see this message, please file a bug immediately."); + warned = TRUE; + } + } + + return g_main_context_wait_internal (context, cond, mutex); +} + /** * g_main_context_prepare: * @context: a #GMainContext @@ -3859,9 +3876,9 @@ g_main_context_iterate (GMainContext *context, if (!block) return FALSE; - got_ownership = g_main_context_wait (context, - &context->cond, - &context->mutex); + got_ownership = g_main_context_wait_internal (context, + &context->cond, + &context->mutex); if (!got_ownership) return FALSE; @@ -4068,9 +4085,9 @@ g_main_loop_run (GMainLoop *loop) loop->is_running = TRUE; while (loop->is_running && !got_ownership) - got_ownership = g_main_context_wait (loop->context, - &loop->context->cond, - &loop->context->mutex); + got_ownership = g_main_context_wait_internal (loop->context, + &loop->context->cond, + &loop->context->mutex); if (!loop->is_running) { @@ -5234,6 +5251,68 @@ unref_unix_signal_handler_unlocked (int signum) } } +/* Return a const string to avoid allocations. We lose precision in the case the + * @signum is unrecognised, but that’ll do. */ +static const gchar * +signum_to_string (int signum) +{ + /* See `man 0P signal.h` */ +#define SIGNAL(s) \ + case (s): \ + return ("GUnixSignalSource: " #s); + switch (signum) + { + /* These signals are guaranteed to exist by POSIX. */ + SIGNAL (SIGABRT) + SIGNAL (SIGFPE) + SIGNAL (SIGILL) + SIGNAL (SIGINT) + SIGNAL (SIGSEGV) + SIGNAL (SIGTERM) + /* Frustratingly, these are not, and hence for brevity the list is + * incomplete. */ +#ifdef SIGALRM + SIGNAL (SIGALRM) +#endif +#ifdef SIGCHLD + SIGNAL (SIGCHLD) +#endif +#ifdef SIGHUP + SIGNAL (SIGHUP) +#endif +#ifdef SIGKILL + SIGNAL (SIGKILL) +#endif +#ifdef SIGPIPE + SIGNAL (SIGPIPE) +#endif +#ifdef SIGQUIT + SIGNAL (SIGQUIT) +#endif +#ifdef SIGSTOP + SIGNAL (SIGSTOP) +#endif +#ifdef SIGUSR1 + SIGNAL (SIGUSR1) +#endif +#ifdef SIGUSR2 + SIGNAL (SIGUSR2) +#endif +#ifdef SIGPOLL + SIGNAL (SIGPOLL) +#endif +#ifdef SIGPROF + SIGNAL (SIGPROF) +#endif +#ifdef SIGTRAP + SIGNAL (SIGTRAP) +#endif + default: + return "GUnixSignalSource: Unrecognized signal"; + } +#undef SIGNAL +} + GSource * _g_main_create_unix_signal_watch (int signum) { @@ -5246,6 +5325,9 @@ _g_main_create_unix_signal_watch (int signum) unix_signal_source->signum = signum; unix_signal_source->pending = FALSE; + /* Set a default name on the source, just in case the caller does not. */ + g_source_set_name (source, signum_to_string (signum)); + G_LOCK (unix_signal_lock); ref_unix_signal_handler_unlocked (signum); unix_signal_watches = g_slist_prepend (unix_signal_watches, unix_signal_source); @@ -5374,6 +5456,9 @@ g_child_watch_source_new (GPid pid) source = g_source_new (&g_child_watch_funcs, sizeof (GChildWatchSource)); child_watch_source = (GChildWatchSource *)source; + /* Set a default name on the source, just in case the caller does not. */ + g_source_set_name (source, "GChildWatchSource"); + child_watch_source->pid = pid; #ifdef G_OS_WIN32 @@ -5560,6 +5645,9 @@ g_idle_source_new (void) source = g_source_new (&g_idle_funcs, sizeof (GSource)); g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE); + /* Set a default name on the source, just in case the caller does not. */ + g_source_set_name (source, "GIdleSource"); + return source; } diff --git a/glib/gmain.h b/glib/gmain.h index 76e2c14c1..eca14d7d5 100644 --- a/glib/gmain.h +++ b/glib/gmain.h @@ -163,11 +163,33 @@ typedef struct _GSourceFuncs GSourceFuncs; * Specifies the type of function passed to g_timeout_add(), * g_timeout_add_full(), g_idle_add(), and g_idle_add_full(). * + * When calling g_source_set_callback(), you may need to cast a function of a + * different type to this type. Use G_SOURCE_FUNC() to avoid warnings about + * incompatible function types. + * * Returns: %FALSE if the source should be removed. #G_SOURCE_CONTINUE and * #G_SOURCE_REMOVE are more memorable names for the return value. */ typedef gboolean (*GSourceFunc) (gpointer user_data); +/** + * G_SOURCE_FUNC: + * @f: a function pointer. + * + * Cast a function pointer to a #GSourceFunc, suppressing warnings from GCC 8 + * onwards with `-Wextra` or `-Wcast-function-type` enabled about the function + * types being incompatible. + * + * For example, the correct type of callback for a source created by + * g_child_watch_source_new() is #GChildWatchFunc, which accepts more arguments + * than #GSourceFunc. Casting the function with `(GSourceFunc)` to call + * g_source_set_callback() will trigger a warning, even though it will be cast + * back to the correct type before it is called by the source. + * + * Since: 2.58 + */ +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) + /** * GChildWatchFunc: * @pid: the process id of the child process @@ -354,7 +376,7 @@ GLIB_AVAILABLE_IN_ALL void g_main_context_release (GMainContext *context); GLIB_AVAILABLE_IN_ALL gboolean g_main_context_is_owner (GMainContext *context); -GLIB_AVAILABLE_IN_ALL +GLIB_DEPRECATED_IN_2_58_FOR(g_main_context_is_owner) gboolean g_main_context_wait (GMainContext *context, GCond *cond, GMutex *mutex); @@ -590,8 +612,7 @@ void g_clear_handle_id (guint *tag_ptr, if (_handle_id > 0) \ { \ *_tag_ptr = 0; \ - if (clear_func != NULL) \ - clear_func (_handle_id); \ + clear_func (_handle_id); \ } \ } G_STMT_END diff --git a/glib/gmarkup.c b/glib/gmarkup.c index ed30ed297..f1ab94e56 100644 --- a/glib/gmarkup.c +++ b/glib/gmarkup.c @@ -458,7 +458,7 @@ slow_name_validate (GMarkupParseContext *context, if (!g_utf8_validate (name, strlen (name), NULL)) { set_error (context, error, G_MARKUP_ERROR_BAD_UTF8, - _("Invalid UTF-8 encoded text in name - not valid '%s'"), name); + _("Invalid UTF-8 encoded text in name — not valid “%sâ€"), name); return FALSE; } @@ -469,7 +469,7 @@ slow_name_validate (GMarkupParseContext *context, g_unichar_isalpha (g_utf8_get_char (p)))))) { set_error (context, error, G_MARKUP_ERROR_PARSE, - _("'%s' is not a valid name"), name); + _("“%s†is not a valid name"), name); return FALSE; } @@ -485,7 +485,7 @@ slow_name_validate (GMarkupParseContext *context, g_unichar_isalpha (g_utf8_get_char (p)))))) { set_error (context, error, G_MARKUP_ERROR_PARSE, - _("'%s' is not a valid name: '%c'"), name, *p); + _("“%s†is not a valid name: “%câ€"), name, *p); return FALSE; } } @@ -541,7 +541,7 @@ text_validate (GMarkupParseContext *context, if (!g_utf8_validate (p, len, NULL)) { set_error (context, error, G_MARKUP_ERROR_BAD_UTF8, - _("Invalid UTF-8 encoded text in name - not valid '%s'"), p); + _("Invalid UTF-8 encoded text in name — not valid “%sâ€"), p); return FALSE; } else @@ -557,11 +557,23 @@ char_str (gunichar c, return buf; } +/* Format the next UTF-8 character as a gchar* for printing in error output + * when we encounter a syntax error. This correctly handles invalid UTF-8, + * emitting it as hex escapes. */ static gchar* utf8_str (const gchar *utf8, gchar *buf) { - char_str (g_utf8_get_char (utf8), buf); + gunichar c = g_utf8_get_char_validated (utf8, -1); + if (c == (gunichar) -1 || c == (gunichar) -2) + { + gchar *temp = g_strdup_printf ("\\x%02x", (guint)(guchar)*utf8); + memset (buf, 0, 8); + memcpy (buf, temp, strlen (temp)); + g_free (temp); + } + else + char_str (c, buf); return buf; } @@ -672,10 +684,10 @@ unescape_gstring_inplace (GMarkupParseContext *context, { set_unescape_error (context, error, from, G_MARKUP_ERROR_PARSE, - _("Failed to parse '%-.*s', which " + _("Failed to parse “%-.*sâ€, which " "should have been a digit " "inside a character reference " - "(ê for example) - perhaps " + "(ê for example) — perhaps " "the digit is too large"), (int)(end - from), from); return FALSE; @@ -688,7 +700,7 @@ unescape_gstring_inplace (GMarkupParseContext *context, "semicolon; " "most likely you used an ampersand " "character without intending to start " - "an entity - escape ampersand as &")); + "an entity — escape ampersand as &")); return FALSE; } else @@ -710,7 +722,7 @@ unescape_gstring_inplace (GMarkupParseContext *context, { set_unescape_error (context, error, from, G_MARKUP_ERROR_PARSE, - _("Character reference '%-.*s' does not " + _("Character reference “%-.*s†does not " "encode a permitted character"), (int)(end - from), from); return FALSE; @@ -748,7 +760,7 @@ unescape_gstring_inplace (GMarkupParseContext *context, if (*from == ';') set_unescape_error (context, error, from, G_MARKUP_ERROR_PARSE, - _("Empty entity '&;' seen; valid " + _("Empty entity “&;†seen; valid " "entities are: & " < > '")); else { @@ -756,7 +768,7 @@ unescape_gstring_inplace (GMarkupParseContext *context, if (end) set_unescape_error (context, error, from, G_MARKUP_ERROR_PARSE, - _("Entity name '%-.*s' is not known"), + _("Entity name “%-.*s†is not known"), (int)(end - from), from); else set_unescape_error (context, error, @@ -764,7 +776,7 @@ unescape_gstring_inplace (GMarkupParseContext *context, _("Entity did not end with a semicolon; " "most likely you used an ampersand " "character without intending to start " - "an entity - escape ampersand as &")); + "an entity — escape ampersand as &")); } return FALSE; } @@ -1207,8 +1219,8 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("'%s' is not a valid character following " - "a '<' character; it may not begin an " + _("“%s†is not a valid character following " + "a “<†character; it may not begin an " "element name"), utf8_str (context->iter, buf)); } @@ -1249,8 +1261,8 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Odd character '%s', expected a '>' character " - "to end the empty-element tag '%s'"), + _("Odd character “%sâ€, expected a “>†character " + "to end the empty-element tag “%sâ€"), utf8_str (context->iter, buf), current_element (context)); } @@ -1330,8 +1342,8 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Odd character '%s', expected a '=' after " - "attribute name '%s' of element '%s'"), + _("Odd character “%sâ€, expected a “=†after " + "attribute name “%s†of element “%sâ€"), utf8_str (context->iter, buf), current_attribute (context), current_element (context)); @@ -1371,9 +1383,9 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Odd character '%s', expected a '>' or '/' " + _("Odd character “%sâ€, expected a “>†or “/†" "character to end the start tag of " - "element '%s', or optionally an attribute; " + "element “%sâ€, or optionally an attribute; " "perhaps you used an invalid character in " "an attribute name"), utf8_str (context->iter, buf), @@ -1415,9 +1427,9 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Odd character '%s', expected an open quote mark " + _("Odd character “%sâ€, expected an open quote mark " "after the equals sign when giving value for " - "attribute '%s' of element '%s'"), + "attribute “%s†of element “%sâ€"), utf8_str (context->iter, buf), current_attribute (context), current_element (context)); @@ -1548,8 +1560,8 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("'%s' is not a valid character following " - "the characters 'iter, buf), utf8_str (context->iter, buf)); @@ -1584,9 +1596,9 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("'%s' is not a valid character following " - "the close element name '%s'; the allowed " - "character is '>'"), + _("“%s†is not a valid character following " + "the close element name “%sâ€; the allowed " + "character is “>â€"), utf8_str (context->iter, buf), close_name->str); } @@ -1595,7 +1607,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Element '%s' was closed, no element " + _("Element “%s†was closed, no element " "is currently open"), close_name->str); } @@ -1604,8 +1616,8 @@ g_markup_parse_context_parse (GMarkupParseContext *context, set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Element '%s' was closed, but the currently " - "open element is '%s'"), + _("Element “%s†was closed, but the currently " + "open element is “%sâ€"), close_name->str, current_element (context)); } @@ -1771,7 +1783,7 @@ g_markup_parse_context_end_parse (GMarkupParseContext *context, case STATE_AFTER_OPEN_ANGLE: set_error_literal (context, error, G_MARKUP_ERROR_PARSE, - _("Document ended unexpectedly just after an open angle bracket '<'")); + _("Document ended unexpectedly just after an open angle bracket “<â€")); break; case STATE_AFTER_CLOSE_ANGLE: @@ -1779,8 +1791,8 @@ g_markup_parse_context_end_parse (GMarkupParseContext *context, { /* Error message the same as for INSIDE_TEXT */ set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Document ended unexpectedly with elements still open - " - "'%s' was the last element opened"), + _("Document ended unexpectedly with elements still open — " + "“%s†was the last element opened"), current_element (context)); } break; @@ -1824,17 +1836,22 @@ g_markup_parse_context_end_parse (GMarkupParseContext *context, case STATE_INSIDE_TEXT: g_assert (context->tag_stack != NULL); set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Document ended unexpectedly with elements still open - " - "'%s' was the last element opened"), + _("Document ended unexpectedly with elements still open — " + "“%s†was the last element opened"), current_element (context)); break; case STATE_AFTER_CLOSE_TAG_SLASH: case STATE_INSIDE_CLOSE_TAG_NAME: case STATE_AFTER_CLOSE_TAG_NAME: - set_error (context, error, G_MARKUP_ERROR_PARSE, - _("Document ended unexpectedly inside the close tag for " - "element '%s'"), current_element (context)); + if (context->tag_stack != NULL) + set_error (context, error, G_MARKUP_ERROR_PARSE, + _("Document ended unexpectedly inside the close tag for " + "element “%sâ€"), current_element (context)); + else + set_error (context, error, G_MARKUP_ERROR_PARSE, + _("Document ended unexpectedly inside the close tag for an " + "unopened element")); break; case STATE_INSIDE_PASSTHROUGH: diff --git a/glib/gmem.h b/glib/gmem.h index 9530512d0..1860d014f 100644 --- a/glib/gmem.h +++ b/glib/gmem.h @@ -110,6 +110,16 @@ gpointer g_try_realloc_n (gpointer mem, gsize n_blocks, gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT; +#if defined(g_has_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58 +#define g_clear_pointer(pp, destroy) \ + G_STMT_START { \ + G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \ + __typeof__(*(pp)) _ptr = *(pp); \ + *(pp) = NULL; \ + if (_ptr) \ + (destroy) (_ptr); \ + } G_STMT_END +#else /* __GNUC__ */ #define g_clear_pointer(pp, destroy) \ G_STMT_START { \ G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \ @@ -127,6 +137,7 @@ gpointer g_try_realloc_n (gpointer mem, _destroy (_p); \ } \ } G_STMT_END +#endif /* __GNUC__ */ /** * g_steal_pointer: @@ -196,8 +207,14 @@ g_steal_pointer (gpointer pp) } /* type safety */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && !defined(__cplusplus) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58 +#define g_steal_pointer(pp) ((__typeof__(*pp)) (g_steal_pointer) (pp)) +#else /* __GNUC__ */ +/* This version does not depend on gcc extensions, but gcc does not warn + * about incompatible-pointer-types: */ #define g_steal_pointer(pp) \ (0 ? (*(pp)) : (g_steal_pointer) (pp)) +#endif /* __GNUC__ */ /* Optimise: avoid the call to the (slower) _n function if we can * determine at compile-time that no overflow happens. diff --git a/glib/gmessages.c b/glib/gmessages.c index eaca78387..b468ef3b7 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -211,47 +211,6 @@ #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif -/* XXX: Remove once XP support really dropped */ -#if _WIN32_WINNT < 0x0600 - -typedef enum _FILE_INFO_BY_HANDLE_CLASS -{ - FileBasicInfo = 0, - FileStandardInfo = 1, - FileNameInfo = 2, - FileRenameInfo = 3, - FileDispositionInfo = 4, - FileAllocationInfo = 5, - FileEndOfFileInfo = 6, - FileStreamInfo = 7, - FileCompressionInfo = 8, - FileAttributeTagInfo = 9, - FileIdBothDirectoryInfo = 10, - FileIdBothDirectoryRestartInfo = 11, - FileIoPriorityHintInfo = 12, - FileRemoteProtocolInfo = 13, - FileFullDirectoryInfo = 14, - FileFullDirectoryRestartInfo = 15, - FileStorageInfo = 16, - FileAlignmentInfo = 17, - FileIdInfo = 18, - FileIdExtdDirectoryInfo = 19, - FileIdExtdDirectoryRestartInfo = 20, - MaximumFileInfoByHandlesClass -} FILE_INFO_BY_HANDLE_CLASS; - -typedef struct _FILE_NAME_INFO -{ - DWORD FileNameLength; - WCHAR FileName[1]; -} FILE_NAME_INFO; - -typedef BOOL (WINAPI fGetFileInformationByHandleEx) (HANDLE, - FILE_INFO_BY_HANDLE_CLASS, - LPVOID, - DWORD); -#endif - #if defined (_MSC_VER) && (_MSC_VER >=1400) /* This is ugly, but we need it for isatty() in case we have bad fd's, * otherwise Windows will abort() the program on msvcrt80.dll and later @@ -1539,34 +1498,13 @@ win32_is_pipe_tty (int fd) wchar_t *name = NULL; gint length; - /* XXX: Remove once XP support really dropped */ -#if _WIN32_WINNT < 0x0600 - HANDLE h_kerneldll = NULL; - fGetFileInformationByHandleEx *GetFileInformationByHandleEx; -#endif - h_fd = (HANDLE) _get_osfhandle (fd); if (h_fd == INVALID_HANDLE_VALUE || GetFileType (h_fd) != FILE_TYPE_PIPE) goto done_query; - /* The following check is available on Vista or later, so on XP, no color support */ /* mintty uses a pipe, in the form of \{cygwin|msys}-xxxxxxxxxxxxxxxx-ptyN-{from|to}-master */ - /* XXX: Remove once XP support really dropped */ -#if _WIN32_WINNT < 0x0600 - h_kerneldll = LoadLibraryW (L"kernel32.dll"); - - if (h_kerneldll == NULL) - goto done_query; - - GetFileInformationByHandleEx = - (fGetFileInformationByHandleEx *) GetProcAddress (h_kerneldll, "GetFileInformationByHandleEx"); - - if (GetFileInformationByHandleEx == NULL) - goto done_query; -#endif - info = g_try_malloc (info_size); if (info == NULL || @@ -1614,12 +1552,6 @@ done_query: if (info != NULL) g_free (info); - /* XXX: Remove once XP support really dropped */ -#if _WIN32_WINNT < 0x0600 - if (h_kerneldll != NULL) - FreeLibrary (h_kerneldll); -#endif - return result; } #endif diff --git a/glib/goption.c b/glib/goption.c index dc9ec3bc9..4b2abc057 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -2028,7 +2028,7 @@ g_option_context_parse (GOptionContext *context, /* Now look for ---