summaryrefslogtreecommitdiff
path: root/gio
diff options
context:
space:
mode:
Diffstat (limited to 'gio')
-rw-r--r--gio/Makefile.am1016
-rw-r--r--gio/fam/Makefile.am39
-rw-r--r--gio/gdbus-2.0/codegen/Makefile.am28
-rw-r--r--gio/gdbusprivate.c11
-rw-r--r--gio/gdbusprivate.h1
-rw-r--r--gio/gdbusproxy.c22
-rw-r--r--gio/gdtlsconnection.c6
-rw-r--r--gio/gfileinfo.c3
-rw-r--r--gio/gioenums.h30
-rw-r--r--gio/giomodule.c61
-rw-r--r--gio/gioprivate.h1
-rw-r--r--gio/gkeyfilesettingsbackend.c415
-rw-r--r--gio/gliststore.c14
-rw-r--r--gio/glocalfileoutputstream.c95
-rw-r--r--gio/gnetworkaddress.c5
-rw-r--r--gio/goutputstream.c796
-rw-r--r--gio/goutputstream.h68
-rw-r--r--gio/gpollableoutputstream.c172
-rw-r--r--gio/gpollableoutputstream.h13
-rw-r--r--gio/gresource.c32
-rw-r--r--gio/gsettingsbackendinternal.h2
-rw-r--r--gio/gsocket.c298
-rw-r--r--gio/gsocket.h15
-rw-r--r--gio/gsocketoutputstream.c56
-rw-r--r--gio/gtask.c11
-rw-r--r--gio/gtlsconnection.c4
-rw-r--r--gio/gunixoutputstream.c198
-rw-r--r--gio/gwin32appinfo.c2
-rw-r--r--gio/inotify/Makefile.am32
-rw-r--r--gio/kqueue/Makefile.am21
-rw-r--r--gio/tests/Makefile.am709
-rw-r--r--gio/tests/desktop-app-info.c3
-rw-r--r--gio/tests/file.c566
-rw-r--r--gio/tests/gdbus-object-manager-example/Makefile.am49
-rw-r--r--gio/tests/gdbus-proxy.c23
-rw-r--r--gio/tests/gdbus-test-codegen.c2
-rw-r--r--gio/tests/glistmodel.c29
-rw-r--r--gio/tests/gschema-compile.c7
-rw-r--r--gio/tests/gsettings.c29
-rw-r--r--gio/tests/memory-output-stream.c90
-rw-r--r--gio/tests/meson.build15
-rw-r--r--gio/tests/modules/Makefile.am41
-rw-r--r--gio/tests/resources.c33
-rw-r--r--gio/tests/services/Makefile.am2
-rw-r--r--gio/tests/socket-service.c312
-rw-r--r--gio/tests/socket.c152
-rw-r--r--gio/tests/test1.overlay1
-rw-r--r--gio/tests/unix-streams.c489
-rw-r--r--gio/win32/Makefile.am28
-rw-r--r--gio/xdgmime/Makefile.am24
50 files changed, 3818 insertions, 2253 deletions
diff --git a/gio/Makefile.am b/gio/Makefile.am
deleted file mode 100644
index 05b20cdef..000000000
--- a/gio/Makefile.am
+++ /dev/null
@@ -1,1016 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-SUBDIRS = gdbus-2.0/codegen
-
-if OS_UNIX
-SUBDIRS += xdgmime
-endif
-
-if OS_WIN32_AND_DLL_COMPILATION
-if MS_LIB_AVAILABLE
-noinst_DATA += gio-2.0.lib
-
-install_ms_lib_cmd = $(INSTALL) gio-2.0.lib $(DESTDIR)$(libdir)
-uninstall_ms_lib_cmd = -rm $(DESTDIR)$(libdir)/gio-2.0.lib
-endif
-endif
-
-install-ms-lib:
- $(install_ms_lib_cmd)
-
-uninstall-ms-lib:
- $(uninstall_ms_lib_cmd)
-
-AM_CPPFLAGS = \
- -DG_LOG_DOMAIN=\"GLib-GIO\" \
- $(gmodule_INCLUDES) \
- $(GLIB_DEBUG_FLAGS) \
- -DGIO_COMPILATION \
- -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\"
-
-AM_CFLAGS = $(GLIB_WARN_CFLAGS)
-
-lib_LTLIBRARIES = libgio-2.0.la
-
-gdbus_headers = \
- gdbusauthobserver.h \
- gcredentials.h \
- gdbusutils.h \
- gdbuserror.h \
- gdbusaddress.h \
- gdbusconnection.h \
- gdbusmessage.h \
- gdbusnameowning.h \
- gdbusnamewatching.h \
- gdbusproxy.h \
- gdbusintrospection.h \
- gdbusmethodinvocation.h \
- gdbusserver.h \
- gdbusinterface.h \
- gdbusinterfaceskeleton.h \
- gdbusobject.h \
- gdbusobjectskeleton.h \
- gdbusobjectproxy.h \
- gdbusobjectmanager.h \
- gdbusobjectmanagerclient.h \
- gdbusobjectmanagerserver.h \
- gtestdbus.h \
- $(NULL)
-
-gdbus_sources = \
- gdbusutils.h gdbusutils.c \
- gdbusaddress.h gdbusaddress.c \
- gdbusauthobserver.h gdbusauthobserver.c \
- gdbusauth.h gdbusauth.c \
- gdbusauthmechanism.h gdbusauthmechanism.c \
- gdbusauthmechanismanon.h gdbusauthmechanismanon.c \
- gdbusauthmechanismexternal.h gdbusauthmechanismexternal.c \
- gdbusauthmechanismsha1.h gdbusauthmechanismsha1.c \
- gdbuserror.h gdbuserror.c \
- gdbusconnection.h gdbusconnection.c \
- gdbusmessage.h gdbusmessage.c \
- gdbusnameowning.h gdbusnameowning.c \
- gdbusnamewatching.h gdbusnamewatching.c \
- gdbusproxy.h gdbusproxy.c \
- gdbusprivate.h gdbusprivate.c \
- gdbusintrospection.h gdbusintrospection.c \
- gdbusmethodinvocation.h gdbusmethodinvocation.c \
- gdbusserver.h gdbusserver.c \
- gdbusinterface.h gdbusinterface.c \
- gdbusinterfaceskeleton.h gdbusinterfaceskeleton.c \
- gdbusobject.h gdbusobject.c \
- gdbusobjectskeleton.h gdbusobjectskeleton.c \
- gdbusobjectproxy.h gdbusobjectproxy.c \
- gdbusobjectmanager.h gdbusobjectmanager.c \
- gdbusobjectmanagerclient.h gdbusobjectmanagerclient.c \
- gdbusobjectmanagerserver.h gdbusobjectmanagerserver.c \
- gtestdbus.h gtestdbus.c \
- $(NULL)
-
-# These are not built into the library yet
-EXTRA_DIST += gdbusdaemon.c gdbusdaemon.h dbus-daemon.xml
-
-GDBUS_PYTHON_DEPS = \
- $(srcdir)/gdbus-2.0/codegen/gdbus-codegen.in \
- $(srcdir)/gdbus-2.0/codegen/codegen_main.py \
- $(srcdir)/gdbus-2.0/codegen/parser.py \
- $(srcdir)/gdbus-2.0/codegen/codegen_docbook.py \
- $(srcdir)/gdbus-2.0/codegen/codegen.py \
- $(srcdir)/gdbus-2.0/codegen/__init__.py \
- $(srcdir)/gdbus-2.0/codegen/dbustypes.py \
- $(builddir)/gdbus-2.0/codegen/config.py \
- $(srcdir)/gdbus-2.0/codegen/utils.py
-
-gdbus-daemon-generated.h gdbus-daemon-generated.c: $(srcdir)/dbus-daemon.xml $(GDBUS_PYTHON_DEPS)
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(srcdir)/gdbus-2.0/codegen/gdbus-codegen.in \
- --interface-prefix org. \
- --generate-c-code gdbus-daemon-generated \
- --c-namespace _G \
- $(srcdir)/dbus-daemon.xml \
- $(NULL)
-
-settings_headers = \
- gsettingsbackend.h \
- gsettingsschema.h \
- gsettings.h
-
-settings_base_sources = \
- gvdb/gvdb-format.h \
- gvdb/gvdb-reader.h \
- gvdb/gvdb-reader.c \
- gdelayedsettingsbackend.h \
- gdelayedsettingsbackend.c \
- gkeyfilesettingsbackend.c \
- gmemorysettingsbackend.c \
- gnullsettingsbackend.c \
- gsettingsbackendinternal.h \
- gsettingsbackend.c \
- gsettingsschema.h \
- gsettingsschema-internal.h \
- gsettingsschema.c \
- gsettings-mapping.h \
- gsettings-mapping.c \
- gsettings.c
-
-settings_sources = $(settings_base_sources)
-
-if OS_WIN32
-win32_settings_sources = \
- gregistrysettingsbackend.h \
- gregistrysettingsbackend.c
-
-settings_sources += $(win32_settings_sources)
-endif
-
-application_headers = \
- gapplication.h \
- gapplicationcommandline.h \
- \
- gactiongroup.h \
- gactionmap.h \
- gsimpleactiongroup.h \
- gremoteactiongroup.h \
- gactiongroupexporter.h \
- gdbusactiongroup.h \
- gaction.h \
- gpropertyaction.h \
- gsimpleaction.h \
- \
- gmenumodel.h \
- gmenu.h \
- gmenuexporter.h \
- gdbusmenumodel.h \
- gnotification.h \
- $(NULL)
-
-application_sources = \
- gapplication.c \
- gapplicationcommandline.c \
- gapplicationimpl-dbus.c \
- gapplicationimpl.h \
- \
- gactiongroup.c \
- gactionmap.c \
- gsimpleactiongroup.c \
- gremoteactiongroup.c \
- gactiongroupexporter.c \
- gdbusactiongroup-private.h \
- gdbusactiongroup.c \
- gaction.c \
- gpropertyaction.c \
- gsimpleaction.c \
- \
- gmenumodel.c \
- gmenu.c \
- gmenuexporter.c \
- gdbusmenumodel.c \
- gnotification-private.h \
- gnotificationbackend.h \
- gnotification.c \
- gnotificationbackend.c \
- $(NULL)
-
-local_sources = \
- ghttpproxy.c \
- ghttpproxy.h \
- glocalfile.c \
- glocalfile.h \
- glocalfileprivate.h \
- glocalfileenumerator.c \
- glocalfileenumerator.h \
- glocalfileinfo.c \
- glocalfileinfo.h \
- glocalfileinputstream.c \
- glocalfileinputstream.h \
- glocalfilemonitor.c \
- glocalfilemonitor.h \
- glocalfileoutputstream.c \
- glocalfileoutputstream.h \
- glocalfileiostream.c \
- glocalfileiostream.h \
- glocalvfs.c \
- glocalvfs.h \
- gsocks4proxy.c \
- gsocks4proxy.h \
- gsocks4aproxy.c \
- gsocks4aproxy.h \
- gsocks5proxy.c \
- gsocks5proxy.h \
- thumbnail-verify.h \
- thumbnail-verify.c \
- $(NULL)
-
-platform_libadd =
-platform_deps =
-appinfo_sources =
-appinfo_headers =
-contenttype_sources =
-
-if HAVE_INOTIFY
-SUBDIRS += inotify
-platform_libadd += inotify/libinotify.la
-platform_deps += inotify/libinotify.la
-endif
-
-if HAVE_KQUEUE
-SUBDIRS += kqueue
-platform_libadd += kqueue/libkqueue.la
-platform_deps += kqueue/libkqueue.la
-endif
-
-if OS_WIN32
-SUBDIRS += win32
-platform_libadd += win32/libgiowin32.la
-platform_deps += win32/libgiowin32.la
-endif
-
-SUBDIRS += . tests
-
-if HAVE_FAM
-SUBDIRS += fam
-endif
-
-if OS_UNIX
-platform_libadd += xdgmime/libxdgmime.la
-platform_deps += xdgmime/libxdgmime.la
-if !OS_COCOA
-appinfo_headers += gdesktopappinfo.h
-endif
-
-
-unix_sources = \
- gfiledescriptorbased.c \
- gunixconnection.c \
- gunixcredentialsmessage.c \
- gunixfdlist.c \
- gunixfdmessage.c \
- gunixmount.c \
- gunixmount.h \
- gunixmounts.c \
- gunixsocketaddress.c \
- gunixvolume.c \
- gunixvolume.h \
- gunixvolumemonitor.c \
- gunixvolumemonitor.h \
- gunixinputstream.c \
- gunixoutputstream.c \
- gcontenttypeprivate.h \
- gfdonotificationbackend.c \
- ggtknotificationbackend.c \
- gportalnotificationbackend.c \
- gdocumentportal.c \
- gdocumentportal.h \
- gopenuriportal.c \
- gopenuriportal.h \
- gportalsupport.c \
- gportalsupport.h \
- $(portal_sources) \
- $(NULL)
-nodist_unix_sources = \
- $(nodist_portal_sources) \
- $(NULL)
-
-giounixincludedir=$(includedir)/gio-unix-2.0/gio
-giounixinclude_HEADERS = \
- gfiledescriptorbased.h \
- gunixconnection.h \
- gunixcredentialsmessage.h \
- gunixmounts.h \
- gunixfdlist.h \
- gunixfdmessage.h \
- gunixinputstream.h \
- gunixoutputstream.h \
- gunixsocketaddress.h \
- $(appinfo_headers) \
- $(NULL)
-
-if HAVE_NETLINK
-unix_sources += \
- gnetworkmonitornetlink.c \
- gnetworkmonitornetlink.h \
- gnetworkmonitornm.c \
- gnetworkmonitornm.h \
- $(NULL)
-endif
-endif
-
-gdbus_daemon_sources = \
- gdbusdaemon.c \
- gdbusdaemon.h \
- $(NULL)
-nodist_gdbus_daemon_sources = \
- gdbus-daemon-generated.c \
- gdbus-daemon-generated.h \
- $(NULL)
-
-win32_actual_sources = \
- $(gdbus_daemon_sources) \
- gwin32registrykey.c \
- gwin32registrykey.h \
- gwin32mount.c \
- gwin32mount.h \
- gwin32volumemonitor.c \
- gwin32volumemonitor.h \
- gwin32inputstream.c \
- gwin32outputstream.c \
- gwin32outputstream.h \
- gwin32networking.h \
- gwin32networkmonitor.c \
- gwin32networkmonitor.h \
- gwin32notificationbackend.c \
- $(NULL)
-nodist_win32_actual_sources = \
- $(nodist_gdbus_daemon_sources) \
- $(NULL)
-
-win32_more_sources_for_vcproj = \
- gwin32appinfo.c \
- gcontenttype-win32.c \
- gregistrysettingsbackend.c \
- win32/gwinhttpfile.c \
- win32/gwinhttpfileinputstream.c \
- win32/gwinhttpfileoutputstream.c \
- win32/gwinhttpvfs.c \
- win32/gwin32fsmonitorutils.c \
- win32/gwin32filemonitor.c
-
-if OS_WIN32
-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 = \
- gwin32inputstream.h \
- gwin32outputstream.h \
- $(NULL)
-
-endif
-
-xdp_dbus_built_sources = xdp-dbus.c xdp-dbus.h
-BUILT_SOURCES += $(xdp_dbus_built_sources)
-CLEANFILES += $(xdp_dbus_built_sources)
-
-portal_interfaces = \
- org.freedesktop.portal.Documents.xml \
- org.freedesktop.portal.OpenURI.xml \
- org.freedesktop.portal.ProxyResolver.xml \
- $(NULL)
-
-EXTRA_DIST += $(portal_interfaces)
-
-$(xdp_dbus_built_sources) : $(portal_interfaces)
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(srcdir)/gdbus-2.0/codegen/gdbus-codegen.in \
- --interface-prefix org.freedesktop.portal. \
- --c-namespace GXdp \
- --generate-c-code $(builddir)/xdp-dbus \
- --annotate "org.freedesktop.portal.Documents.Add()" "org.gtk.GDBus.C.UnixFD" "true" \
- --annotate "org.freedesktop.portal.Documents.AddNamed()" "org.gtk.GDBus.C.UnixFD" "true" \
- --annotate "org.freedesktop.portal.Documents.AddFull()" "org.gtk.GDBus.C.UnixFD" "true" \
- --annotate "org.freedesktop.portal.OpenURI.OpenFile()" "org.gtk.GDBus.C.UnixFD" "true" \
- $^
-
-portal_sources = \
- gnetworkmonitorportal.c \
- gnetworkmonitorportal.h \
- gproxyresolverportal.c \
- gproxyresolverportal.h \
- $(NULL)
-nodist_portal_sources = \
- $(xdp_dbus_built_sources) \
- $(NULL)
-
-if OS_UNIX
-if !OS_COCOA
-contenttype_sources += gcontenttype.c
-appinfo_sources += gdesktopappinfo.c
-endif
-endif
-
-gio_base_sources = \
- gappinfo.c \
- gappinfoprivate.h \
- gasynchelper.c \
- gasynchelper.h \
- gasyncinitable.c \
- gasyncresult.c \
- gbufferedinputstream.c \
- gbufferedoutputstream.c \
- gbytesicon.c \
- gcancellable.c \
- gcharsetconverter.c \
- gcontextspecificgroup.c \
- gcontextspecificgroup.h \
- gconverter.c \
- gconverterinputstream.c \
- gconverteroutputstream.c \
- gcredentials.c \
- gcredentialsprivate.h \
- gdatagrambased.c \
- gdatainputstream.c \
- gdataoutputstream.c \
- gdrive.c \
- gdummyfile.h \
- gdummyfile.c \
- gdummyproxyresolver.c \
- gdummyproxyresolver.h \
- gdummytlsbackend.c \
- gdummytlsbackend.h \
- gemblem.h \
- gemblem.c \
- gemblemedicon.h \
- gemblemedicon.c \
- gfile.c \
- gfileattribute.c \
- gfileattribute-priv.h \
- gfileenumerator.c \
- gfileicon.c \
- gfileinfo.c \
- gfileinfo-priv.h \
- gfileinputstream.c \
- gfilemonitor.c \
- gfilenamecompleter.c \
- gfileoutputstream.c \
- gfileiostream.c \
- gfilterinputstream.c \
- gfilteroutputstream.c \
- gicon.c \
- ginetaddress.c \
- ginetaddressmask.c \
- ginetsocketaddress.c \
- ginitable.c \
- ginputstream.c \
- gio_probes.d \
- gio_trace.h \
- gioenums.h \
- gioerror.c \
- giomodule.c \
- giomodule-priv.c \
- giomodule-priv.h \
- gioscheduler.c \
- giostream.c \
- gioprivate.h \
- giowin32-priv.h \
- gloadableicon.c \
- gmount.c \
- gmemoryinputstream.c \
- gmemoryoutputstream.c \
- gmountoperation.c \
- gnativevolumemonitor.c \
- gnativevolumemonitor.h \
- gnativesocketaddress.c \
- gnativesocketaddress.h \
- gnetworkaddress.c \
- gnetworking.c \
- gnetworkingprivate.h \
- gnetworkmonitor.c \
- gnetworkmonitorbase.c \
- gnetworkmonitorbase.h \
- gnetworkservice.c \
- goutputstream.c \
- gpermission.c \
- gpollableinputstream.c \
- gpollableoutputstream.c \
- gpollableutils.c \
- gpollfilemonitor.c \
- gpollfilemonitor.h \
- gproxy.c \
- gproxyaddress.c \
- gproxyaddressenumerator.c \
- gproxyresolver.c \
- gresolver.c \
- gresource.c \
- gresourcefile.c \
- gresourcefile.h \
- gseekable.c \
- gsimpleasyncresult.c \
- gsimpleiostream.c \
- gsimplepermission.c \
- gsocket.c \
- gsocketaddress.c \
- gsocketaddressenumerator.c \
- gsocketclient.c \
- gsocketconnectable.c \
- gsocketconnection.c \
- gsocketcontrolmessage.c \
- gsocketinputstream.c \
- gsocketinputstream.h \
- gsocketlistener.c \
- gsocketoutputstream.c \
- gsocketoutputstream.h \
- gsubprocesslauncher.c \
- gsubprocess.c \
- gsubprocesslauncher-private.h \
- gsocketservice.c \
- gsrvtarget.c \
- gsimpleproxyresolver.c \
- gtask.c \
- gtcpconnection.c \
- gtcpwrapperconnection.c \
- gthreadedsocketservice.c\
- gthemedicon.c \
- gthreadedresolver.c \
- gthreadedresolver.h \
- gtlsbackend.c \
- gtlscertificate.c \
- gtlsclientconnection.c \
- gtlsconnection.c \
- gtlsdatabase.c \
- gtlsfiledatabase.c \
- gtlsinteraction.c \
- gtlspassword.c \
- gtlsserverconnection.c \
- gdtlsconnection.c \
- gdtlsclientconnection.c \
- gdtlsserverconnection.c \
- gunionvolumemonitor.c \
- gunionvolumemonitor.h \
- gvfs.c \
- gvolume.c \
- gvolumemonitor.c \
- gzlibcompressor.c \
- gzlibdecompressor.c \
- gmountprivate.h \
- 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) \
- $(appinfo_sources) \
- $(contenttype_sources) \
- $(unix_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
-
-libgio_2_0_la_LIBADD = \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(platform_libadd) \
- $(ZLIB_LIBS) \
- $(SELINUX_LIBS) \
- $(GLIB_LIBS) \
- $(XATTR_LIBS) \
- $(NETWORK_LIBS) \
- $(NULL)
-
-libgio_2_0_la_CPPFLAGS = $(ZLIB_CFLAGS) $(AM_CPPFLAGS)
-
-if PLATFORM_WIN32
-no_undefined = -no-undefined
-endif
-
-if OS_WIN32_AND_DLL_COMPILATION
-gio_win32_res = gio-win32-res.o
-gio_win32_res_ldflag = -Wl,$(gio_win32_res)
-endif
-
-install-data-local: install-ms-lib
- $(mkinstalldirs) $(DESTDIR)$(GIO_MODULE_DIR)
-
-uninstall-local: uninstall-ms-lib
-
-libgio_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS)
-libgio_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \
- $(gio_win32_res_ldflag) \
- -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
-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
-libgio_objc_2_0_la_SOURCES = \
- gnextstepsettingsbackend.c \
- gosxcontenttype.c \
- gosxappinfo.c \
- gosxappinfo.h
-if MAC_OS_X_9
-libgio_objc_2_0_la_SOURCES += \
- gcocoanotificationbackend.c
-endif
-
-noinst_LTLIBRARIES += libgio-objc-2.0.la
-libgio_2_0_la_LIBADD += libgio-objc-2.0.la
-endif
-
-if HAVE_LIBMOUNT
-libgio_2_0_la_CFLAGS += $(LIBMOUNT_CFLAGS)
-libgio_2_0_la_LIBADD += $(LIBMOUNT_LIBS)
-endif
-
-EXTRA_libgio_2_0_la_DEPENDENCIES = $(gio_win32_res) $(gio_def) $(platform_deps)
-
-gio-win32-res.o: gio.rc
- $(WINDRES) gio.rc $@
-
-gio_headers = \
- gappinfo.h \
- gasyncinitable.h \
- gasyncresult.h \
- gbufferedinputstream.h \
- gbufferedoutputstream.h \
- gbytesicon.h \
- gcancellable.h \
- gcontenttype.h \
- gcharsetconverter.h \
- gconverter.h \
- gconverterinputstream.h \
- gconverteroutputstream.h \
- gdatagrambased.h \
- gdatainputstream.h \
- gdataoutputstream.h \
- gdrive.h \
- gemblem.h \
- gemblemedicon.h \
- gfile.h \
- gfileattribute.h \
- gfileenumerator.h \
- gfileicon.h \
- gfileinfo.h \
- gfileinputstream.h \
- gfilemonitor.h \
- gfilenamecompleter.h \
- gfileoutputstream.h \
- gfileiostream.h \
- gfilterinputstream.h \
- gfilteroutputstream.h \
- gicon.h \
- ginetaddress.h \
- ginetaddressmask.h \
- ginetsocketaddress.h \
- ginputstream.h \
- ginitable.h \
- gio.h \
- gio-autocleanups.h \
- giotypes.h \
- gioenums.h \
- gioerror.h \
- giomodule.h \
- gioscheduler.h \
- giostream.h \
- gloadableicon.h \
- gmount.h \
- gmemoryinputstream.h \
- gmemoryoutputstream.h \
- gmountoperation.h \
- gnativevolumemonitor.h \
- gnetworkaddress.h \
- gnetworkmonitor.h \
- gnetworkservice.h \
- goutputstream.h \
- gpermission.h \
- gpollableinputstream.h \
- gpollableoutputstream.h \
- gpollableutils.h \
- gproxyaddress.h \
- gproxy.h \
- gproxyaddressenumerator.h \
- gproxyresolver.h \
- gresolver.h \
- gresource.h \
- gseekable.h \
- gsimpleasyncresult.h \
- gsimpleiostream.h \
- gsimplepermission.h \
- gsocket.h \
- gsocketaddress.h \
- gsocketaddressenumerator.h \
- gsocketclient.h \
- gsocketconnectable.h \
- gsocketconnection.h \
- gsocketcontrolmessage.h \
- gsocketlistener.h \
- gsocketservice.h \
- gsrvtarget.h \
- gsimpleproxyresolver.h \
- gtask.h \
- gsubprocess.h \
- gsubprocesslauncher.h \
- gtcpconnection.h \
- gtcpwrapperconnection.h \
- gthreadedsocketservice.h\
- gthemedicon.h \
- gtlsbackend.h \
- gtlscertificate.h \
- gtlsclientconnection.h \
- gtlsconnection.h \
- gtlsdatabase.h \
- gtlsfiledatabase.h \
- gtlsinteraction.h \
- gtlspassword.h \
- gtlsserverconnection.h \
- gdtlsconnection.h \
- gdtlsclientconnection.h \
- gdtlsserverconnection.h \
- gvfs.h \
- gvolume.h \
- gvolumemonitor.h \
- gzlibcompressor.h \
- gzlibdecompressor.h \
- glistmodel.h \
- gliststore.h \
- $(application_headers) \
- $(settings_headers) \
- $(gdbus_headers) \
- $(NULL)
-
-gioincludedir=$(includedir)/glib-2.0/gio/
-gioinclude_HEADERS = \
- $(gio_headers) \
- $(NULL)
-nodist_gioinclude_HEADERS = \
- gioenumtypes.h \
- gnetworking.h \
- $(NULL)
-
-# these sources (also mentioned above) are generated.
-BUILT_SOURCES += \
- gconstructor_as_data.h \
- gioenumtypes.h \
- gioenumtypes.c \
- gdbus-daemon-generated.c \
- gdbus-daemon-generated.h \
- gnetworking.h \
- $(NULL)
-
-EXTRA_DIST += \
- data-to-c.py \
- gioenumtypes.h.template \
- gioenumtypes.c.template \
- gio.rc.in \
- gschema.dtd \
- $(NULL)
-
-BUILT_EXTRA_DIST += \
- gio.rc
-
-# This is read by gobject-introspection/misc/ and gtk-doc
-gio-public-headers.txt: Makefile
- $(AM_V_GEN) echo $(gioinclude_HEADERS) $(giowin32include_HEADERS) $(giounixinclude_HEADERS) > $@.tmp && mv $@.tmp $@
-
-CLEANFILES += gdbus-daemon-generated.c gdbus-daemon-generated.h gio-public-headers.txt gconstructor_as_data.h
-
-
-DISTCLEANFILES += \
- gioenumtypes.h \
- gioenumtypes.c
-
-all-local: gio-public-headers.txt
-
-gioenumtypes.h: $(gio_headers) gioenumtypes.h.template
- $(AM_V_GEN) $(top_builddir)/gobject/glib-mkenums --template $(filter %.template,$^) $(filter-out %.template,$^) > \
- gioenumtypes.h.tmp && mv gioenumtypes.h.tmp gioenumtypes.h
-
-gioenumtypes.c: $(gio_headers) gioenumtypes.c.template
- $(AM_V_GEN) $(top_builddir)/gobject/glib-mkenums --template $(filter %.template,$^) $(filter-out %.template,$^) > \
- gioenumtypes.c.tmp && mv gioenumtypes.c.tmp gioenumtypes.c
-
-gio.def: libgio-2.0.la
- $(AM_V_GEN) dumpbin.exe -exports .libs/libgio-2.0-0.dll | awk 'BEGIN { print "EXPORTS" } / +[[:digit:]]+ +[[:xdigit:]]+ +[[:xdigit:]]+/{ print $$4 }' > gio.def.tmp && mv gio.def.tmp gio.def
-
-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 gio-launch-desktop
-
-glib_compile_resources_LDADD = libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-
-glib_compile_resources_SOURCES = \
- gvdb/gvdb-format.h \
- gvdb/gvdb-builder.h \
- gvdb/gvdb-builder.c \
- glib-compile-resources.c
-
-gio_querymodules_SOURCES = gio-querymodules.c giomodule-priv.c
-gio_querymodules_LDADD = libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-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) $(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 = \
- 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 \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-gsettings_SOURCES = gsettings-tool.c
-
-schemadir = $(datadir)/glib-2.0/schemas
-dist_schema_DATA = gschema.dtd
-
-itsdir = $(datadir)/gettext/its
-dist_its_DATA = gschema.loc gschema.its
-
-# ------------------------------------------------------------------------
-# SystemTap and dtrace
-
-if ENABLE_DTRACE
-gio_probes.h: gio_probes.d
- $(AM_V_GEN) $(DTRACE) -C -h -s $< -o $@.tmp
- @$(SED) \
- -e "s,define STAP_HAS_SEMAPHORES 1,undef STAP_HAS_SEMAPHORES," \
- -e "s,define _SDT_HAS_SEMAPHORES 1,undef _SDT_HAS_SEMAPHORES," \
- < $@.tmp > $@ && rm -f $@.tmp
-
-gio_probes.lo: gio_probes.d
- $(AM_V_GEN) $(LIBTOOL) --mode=compile $(AM_V_lt) --tag=CC env CFLAGS="$(CFLAGS)" $(DTRACE) -G -s $< -o $@
-
-BUILT_SOURCES += gio_probes.h gio_probes.lo
-CLEANFILES += gio_probes.h gio_probes.h.tmp
-libgio_2_0_la_LIBADD += gio_probes.lo
-endif
-
-tapsetdir = @ABS_TAPSET_DIR@
-EXTRA_DIST += gio.stp.in
-
-if ENABLE_SYSTEMTAP
-tapset_DATA = libgio-2.0.so.0.@LT_CURRENT@.@LT_REVISION@.stp
-CLEANFILES += $(tapset_DATA)
-
-$(tapset_DATA): gio.stp.in Makefile
- $(AM_V_GEN)$(SED) \
- -e 's|[@]ABS_GLIB_RUNTIME_LIBDIR[@]|$(ABS_GLIB_RUNTIME_LIBDIR)|g' \
- -e 's|[@]LT_CURRENT[@]|$(LT_CURRENT)|g' \
- -e 's|[@]LT_REVISION[@]|$(LT_REVISION)|g' \
- $< > $@
-endif
-
-# ------------------------------------------------------------------------
-# gdbus(1) tool
-
-bin_PROGRAMS += gdbus
-gdbus_SOURCES = gdbus-tool.c
-gdbus_LDADD = libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-
-if OS_UNIX
-if !OS_COCOA
-# ------------------------------------------------------------------------
-# gapplication(1) tool
-bin_PROGRAMS += gapplication
-gapplication_SOURCES = gapplication-tool.c
-gapplication_LDADD = libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-endif
-endif
-
-completiondir = $(datadir)/bash-completion/completions
-completion_DATA = \
- completion/gapplication \
- completion/gdbus \
- completion/gio \
- completion/gsettings \
- completion/gresource
-EXTRA_DIST += $(completion_DATA)
-
-# ------------------------------------------------------------------------
-# gresource tool
-
-bin_PROGRAMS += gresource
-gresource_SOURCES = gresource-tool.c
-gresource_CPPFLAGS = $(LIBELF_CFLAGS) $(AM_CPPFLAGS)
-gresource_LDADD = libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(LIBELF_LIBS)
-
-# ------------------------------------------------------------------------
-# gio tool
-
-bin_PROGRAMS += gio
-gio_SOURCES = \
- gio-tool.c \
- gio-tool.h \
- gio-tool-cat.c \
- gio-tool-copy.c \
- gio-tool-info.c \
- gio-tool-list.c \
- gio-tool-mime.c \
- gio-tool-mkdir.c \
- gio-tool-monitor.c \
- gio-tool-mount.c \
- gio-tool-move.c \
- gio-tool-open.c \
- gio-tool-rename.c \
- gio-tool-remove.c \
- gio-tool-save.c \
- gio-tool-set.c \
- gio-tool-trash.c \
- gio-tool-tree.c \
- $(NULL)
-gio_LDADD = libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-
-dist-hook: $(BUILT_EXTRA_DIST)
- files='$(BUILT_EXTRA_DIST)'; \
- for f in $$files; do \
- if test -f $$f; then d=.; else d=$(srcdir); fi; \
- cp $$d/$$f $(distdir) || exit 1; done
-
-if HAVE_GLIB_RUNTIME_LIBDIR
-ABS_GLIB_RUNTIME_LIBDIR = $(realpath $(libdir)/$(GLIB_RUNTIME_LIBDIR))
-else
-ABS_GLIB_RUNTIME_LIBDIR = $(libdir)
-endif
-
-if HAVE_GLIB_RUNTIME_LIBDIR
-install-data-hook:
- mkdir -p $(DESTDIR)$(libdir)/$(GLIB_RUNTIME_LIBDIR)
- mv $(DESTDIR)$(libdir)/libgio-2.0.so.0 $(DESTDIR)$(libdir)/$(GLIB_RUNTIME_LIBDIR)
- mv $(DESTDIR)$(libdir)/libgio-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/$(GLIB_RUNTIME_LIBDIR)
- rm -f $(DESTDIR)$(libdir)/libgio-2.0.so
- ln -s $(GLIB_RUNTIME_LIBDIR)/libgio-2.0.so.0.$(LT_CURRENT).$(LT_REVISION) $(DESTDIR)$(libdir)/libgio-2.0.so
-endif
diff --git a/gio/fam/Makefile.am b/gio/fam/Makefile.am
deleted file mode 100644
index d064943a3..000000000
--- a/gio/fam/Makefile.am
+++ /dev/null
@@ -1,39 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload|query)'
-
-giomodule_LTLIBRARIES = libgiofam.la
-giomoduledir = $(GIO_MODULE_DIR)
-
-libgiofam_la_SOURCES = gfamfilemonitor.c
-
-libgiofam_la_CFLAGS = \
- -DG_LOG_DOMAIN=\"GLib-GIO\" \
- $(gio_INCLUDES) \
- $(GLIB_DEBUG_FLAGS) \
- -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
- -DGIO_COMPILATION \
- -DG_DISABLE_DEPRECATED
-
-libgiofam_la_LDFLAGS = $(module_flags)
-libgiofam_la_LIBADD = \
- $(top_builddir)/gio/libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(GLIB_LIBS) \
- $(FAM_LIBS) \
- $(NULL)
-
-if CROSS_COMPILING
-RUN_QUERY_MODULES=false
-else
-RUN_QUERY_MODULES=true
-endif
-
-install-data-hook:
- if $(RUN_QUERY_MODULES) && test -z "$(DESTDIR)" ; then \
- $(top_builddir)/gio/gio-querymodules$(EXEEXT) $(DESTDIR)$(GIO_MODULE_DIR) ; \
- fi
-
-uninstall-local:
- $(RM) $(DESTDIR)$(GIO_MODULE_DIR)/giomodule.cache
diff --git a/gio/gdbus-2.0/codegen/Makefile.am b/gio/gdbus-2.0/codegen/Makefile.am
deleted file mode 100644
index b4e500cb0..000000000
--- a/gio/gdbus-2.0/codegen/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-bin_SCRIPTS =
-
-codegendir = $(datadir)/glib-2.0/codegen
-codegen_PYTHON = \
- __init__.py \
- codegen.py \
- codegen_main.py \
- codegen_docbook.py \
- config.py \
- dbustypes.py \
- parser.py \
- utils.py \
- $(NULL)
-
-CLEANFILES += config.pyc
-
-bin_SCRIPTS += gdbus-codegen
-CLEANFILES += gdbus-codegen
-EXTRA_DIST += gdbus-codegen.in
-
-gdbus-codegen: gdbus-codegen.in Makefile $(codegen_PYTHON)
- $(AM_V_GEN) sed -e 's,@DATADIR\@,$(datadir),' -e 's,@PYTHON\@,$(PYTHON),' $< > $@.tmp && mv $@.tmp $@
- @chmod a+x $@
-
-clean-local:
- rm -f *~
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index b5f8b6509..c2a04ae12 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -1817,6 +1817,7 @@ _g_dbus_worker_flush_sync (GDBusWorker *worker,
#define G_DBUS_DEBUG_RETURN (1<<7)
#define G_DBUS_DEBUG_EMISSION (1<<8)
#define G_DBUS_DEBUG_ADDRESS (1<<9)
+#define G_DBUS_DEBUG_PROXY (1<<10)
static gint _gdbus_debug_flags = 0;
@@ -1890,6 +1891,13 @@ _g_dbus_debug_address (void)
return (_gdbus_debug_flags & G_DBUS_DEBUG_ADDRESS) != 0;
}
+gboolean
+_g_dbus_debug_proxy (void)
+{
+ _g_dbus_initialize ();
+ return (_gdbus_debug_flags & G_DBUS_DEBUG_PROXY) != 0;
+}
+
G_LOCK_DEFINE_STATIC (print_lock);
void
@@ -1938,7 +1946,8 @@ _g_dbus_initialize (void)
{ "incoming", G_DBUS_DEBUG_INCOMING },
{ "return", G_DBUS_DEBUG_RETURN },
{ "emission", G_DBUS_DEBUG_EMISSION },
- { "address", G_DBUS_DEBUG_ADDRESS }
+ { "address", G_DBUS_DEBUG_ADDRESS },
+ { "proxy", G_DBUS_DEBUG_PROXY }
};
_gdbus_debug_flags = g_parse_debug_string (debug, keys, G_N_ELEMENTS (keys));
diff --git a/gio/gdbusprivate.h b/gio/gdbusprivate.h
index 0d85c1d85..a319166ee 100644
--- a/gio/gdbusprivate.h
+++ b/gio/gdbusprivate.h
@@ -91,6 +91,7 @@ gboolean _g_dbus_debug_incoming (void);
gboolean _g_dbus_debug_return (void);
gboolean _g_dbus_debug_emission (void);
gboolean _g_dbus_debug_address (void);
+gboolean _g_dbus_debug_proxy (void);
void _g_dbus_debug_print_lock (void);
void _g_dbus_debug_print_unlock (void);
diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c
index 6a1be4220..0ab117854 100644
--- a/gio/gdbusproxy.c
+++ b/gio/gdbusproxy.c
@@ -1235,11 +1235,14 @@ on_name_owner_changed_get_all_cb (GDBusConnection *connection,
*
* Either way, apps can know about this by using
* get_cached_property_names() or get_cached_property().
- *
- * TODO: handle G_DBUS_DEBUG flag 'proxy' and, if enabled, log the
- * fact that GetAll() failed
*/
- //g_debug ("error: %d %d %s", error->domain, error->code, error->message);
+ if (G_UNLIKELY (_g_dbus_debug_proxy ()))
+ {
+ g_debug ("error: %d %d %s",
+ error->domain,
+ error->code,
+ error->message);
+ }
g_error_free (error);
}
@@ -1432,11 +1435,14 @@ async_init_get_all_cb (GDBusConnection *connection,
*
* Either way, apps can know about this by using
* get_cached_property_names() or get_cached_property().
- *
- * TODO: handle G_DBUS_DEBUG flag 'proxy' and, if enabled, log the
- * fact that GetAll() failed
*/
- //g_debug ("error: %d %d %s", error->domain, error->code, error->message);
+ if (G_UNLIKELY (_g_dbus_debug_proxy ()))
+ {
+ g_debug ("error: %d %d %s",
+ error->domain,
+ error->code,
+ error->message);
+ }
g_error_free (error);
}
diff --git a/gio/gdtlsconnection.c b/gio/gdtlsconnection.c
index 254537198..cbc25d4f2 100644
--- a/gio/gdtlsconnection.c
+++ b/gio/gdtlsconnection.c
@@ -295,8 +295,8 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface)
* let the user decide whether or not to accept the certificate, you
* would have to return %FALSE from the signal handler on the first
* attempt, and then after the connection attempt returns a
- * %G_TLS_ERROR_HANDSHAKE, you can interact with the user, and if
- * the user decides to accept the certificate, remember that fact,
+ * %G_TLS_ERROR_BAD_CERTIFICATE, you can interact with the user, and
+ * if the user decides to accept the certificate, remember that fact,
* create a new connection, and return %TRUE from the signal handler
* the next time.
*
@@ -1050,7 +1050,7 @@ g_dtls_connection_set_advertised_protocols (GDtlsConnection *conn,
if (iface->set_advertised_protocols == NULL)
return;
- return iface->set_advertised_protocols (conn, protocols);
+ iface->set_advertised_protocols (conn, protocols);
}
/**
diff --git a/gio/gfileinfo.c b/gio/gfileinfo.c
index fa53a9c49..420e46d56 100644
--- a/gio/gfileinfo.c
+++ b/gio/gfileinfo.c
@@ -1180,7 +1180,8 @@ _g_file_info_set_attribute_stringv_by_id (GFileInfo *info,
* g_file_info_set_attribute_stringv:
* @info: a #GFileInfo.
* @attribute: a file attribute key
- * @attr_value: (array) (element-type utf8): a %NULL terminated array of UTF-8 strings.
+ * @attr_value: (array zero-terminated=1) (element-type utf8): a %NULL
+ * terminated array of UTF-8 strings.
*
* Sets the @attribute to contain the given @attr_value,
* if possible.
diff --git a/gio/gioenums.h b/gio/gioenums.h
index d6d1e59f1..9c7d9b6ac 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -512,6 +512,9 @@ typedef enum {
* ]|
* but should instead treat all unrecognized error codes the same as
* #G_IO_ERROR_FAILED.
+ *
+ * See also #GPollableReturn for a cheaper way of returning
+ * %G_IO_ERROR_WOULD_BLOCK to callers without allocating a #GError.
**/
typedef enum {
G_IO_ERROR_FAILED,
@@ -1505,7 +1508,8 @@ typedef enum
* GTlsError:
* @G_TLS_ERROR_UNAVAILABLE: No TLS provider is available
* @G_TLS_ERROR_MISC: Miscellaneous TLS error
- * @G_TLS_ERROR_BAD_CERTIFICATE: A certificate could not be parsed
+ * @G_TLS_ERROR_BAD_CERTIFICATE: The certificate presented could not
+ * be parsed or failed validation.
* @G_TLS_ERROR_NOT_TLS: The TLS handshake failed because the
* peer does not seem to be a TLS server.
* @G_TLS_ERROR_HANDSHAKE: The TLS handshake failed because the
@@ -1921,6 +1925,30 @@ typedef enum {
G_NETWORK_CONNECTIVITY_FULL = 4
} GNetworkConnectivity;
+/**
+ * GPollableReturn:
+ * @G_POLLABLE_RETURN_FAILED: Generic error condition for when an operation fails.
+ * @G_POLLABLE_RETURN_OK: The operation was successfully finished.
+ * @G_POLLABLE_RETURN_WOULD_BLOCK: The operation would block.
+ *
+ * Return value for various IO operations that signal errors via the
+ * return value and not necessarily via a #GError.
+ *
+ * This enum exists to be able to return errors to callers without having to
+ * allocate a #GError. Allocating #GErrors can be quite expensive for
+ * regularly happening errors like %G_IO_ERROR_WOULD_BLOCK.
+ *
+ * In case of %G_POLLABLE_RETURN_FAILED a #GError should be set for the
+ * operation to give details about the error that happened.
+ *
+ * Since: 2.60
+ */
+typedef enum {
+ G_POLLABLE_RETURN_FAILED = 0,
+ G_POLLABLE_RETURN_OK = 1,
+ G_POLLABLE_RETURN_WOULD_BLOCK = -G_IO_ERROR_WOULD_BLOCK
+} GPollableReturn;
+
G_END_DECLS
#endif /* __GIO_ENUMS_H__ */
diff --git a/gio/giomodule.c b/gio/giomodule.c
index 36c0cefed..b92162dcc 100644
--- a/gio/giomodule.c
+++ b/gio/giomodule.c
@@ -700,6 +700,35 @@ try_class (GIOExtension *extension,
return NULL;
}
+static void
+print_help (const char *envvar,
+ GIOExtensionPoint *ep)
+{
+ g_print ("Supported arguments for %s environment variable:\n", envvar);
+
+ if (g_io_extension_point_get_extensions (ep) == NULL)
+ g_print (" (none)\n");
+ else
+ {
+ GList *l;
+ GIOExtension *extension;
+ int width = 0;
+
+ for (l = g_io_extension_point_get_extensions (ep); l; l = l->next)
+ {
+ extension = l->data;
+ width = MAX (width, strlen (g_io_extension_get_name (extension)));
+ }
+
+ for (l = g_io_extension_point_get_extensions (ep); l; l = l->next)
+ {
+ extension = l->data;
+
+ g_print (" %*s - %d\n", width, g_io_extension_get_name (extension), g_io_extension_get_priority (extension));
+ }
+ }
+}
+
/**
* _g_io_module_get_default_type:
* @extension_point: the name of an extension point
@@ -766,6 +795,12 @@ _g_io_module_get_default_type (const gchar *extension_point,
}
use_this = envvar ? g_getenv (envvar) : NULL;
+ if (g_strcmp0 (use_this, "help") == 0)
+ {
+ print_help (envvar, ep);
+ use_this = NULL;
+ }
+
if (use_this)
{
preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
@@ -874,7 +909,7 @@ _g_io_module_get_default (const gchar *extension_point,
const char *use_this;
GList *l;
GIOExtensionPoint *ep;
- GIOExtension *extension, *preferred;
+ GIOExtension *extension = NULL, *preferred;
gpointer impl;
g_rec_mutex_lock (&default_modules_lock);
@@ -885,6 +920,8 @@ _g_io_module_get_default (const gchar *extension_point,
if (g_hash_table_lookup_extended (default_modules, extension_point,
&key, &impl))
{
+ /* Don’t debug here, since we’re returning a cached object which was
+ * already printed earlier. */
g_rec_mutex_unlock (&default_modules_lock);
return impl;
}
@@ -899,23 +936,32 @@ _g_io_module_get_default (const gchar *extension_point,
if (!ep)
{
+ g_debug ("%s: Failed to find extension point ‘%s’",
+ G_STRFUNC, extension_point);
g_warn_if_reached ();
g_rec_mutex_unlock (&default_modules_lock);
return NULL;
}
use_this = envvar ? g_getenv (envvar) : NULL;
+ if (g_strcmp0 (use_this, "help") == 0)
+ {
+ print_help (envvar, ep);
+ use_this = NULL;
+ }
+
if (use_this)
{
preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
if (preferred)
{
impl = try_implementation (extension_point, preferred, verify_func);
+ extension = preferred;
if (impl)
goto done;
}
else
- g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
+ g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
}
else
preferred = NULL;
@@ -939,6 +985,17 @@ _g_io_module_get_default (const gchar *extension_point,
impl ? g_object_ref (impl) : NULL);
g_rec_mutex_unlock (&default_modules_lock);
+ if (impl != NULL)
+ {
+ g_assert (extension != NULL);
+ g_debug ("%s: Found default implementation %s (%s) for ‘%s’",
+ G_STRFUNC, g_io_extension_get_name (extension),
+ G_OBJECT_TYPE_NAME (impl), extension_point);
+ }
+ else
+ g_debug ("%s: Failed to find default implementation for ‘%s’",
+ G_STRFUNC, extension_point);
+
return impl;
}
diff --git a/gio/gioprivate.h b/gio/gioprivate.h
index b79192566..a917510b9 100644
--- a/gio/gioprivate.h
+++ b/gio/gioprivate.h
@@ -29,6 +29,7 @@ G_BEGIN_DECLS
gboolean g_input_stream_async_read_is_via_threads (GInputStream *stream);
gboolean g_input_stream_async_close_is_via_threads (GInputStream *stream);
gboolean g_output_stream_async_write_is_via_threads (GOutputStream *stream);
+gboolean g_output_stream_async_writev_is_via_threads (GOutputStream *stream);
gboolean g_output_stream_async_close_is_via_threads (GOutputStream *stream);
void g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
index a37978e83..d5796b706 100644
--- a/gio/gkeyfilesettingsbackend.c
+++ b/gio/gkeyfilesettingsbackend.c
@@ -21,14 +21,20 @@
#include "config.h"
+#include <glib.h>
+#include <glibintl.h>
+
#include <stdio.h>
#include <string.h>
#include "gfile.h"
#include "gfileinfo.h"
+#include "gfileenumerator.h"
#include "gfilemonitor.h"
#include "gsimplepermission.h"
-#include "gsettingsbackend.h"
+#include "gsettingsbackendinternal.h"
+#include "giomodule-priv.h"
+#include "gportalsupport.h"
#define G_TYPE_KEYFILE_SETTINGS_BACKEND (g_keyfile_settings_backend_get_type ())
@@ -41,6 +47,13 @@
typedef GSettingsBackendClass GKeyfileSettingsBackendClass;
+typedef enum {
+ PROP_FILENAME = 1,
+ PROP_ROOT_PATH,
+ PROP_ROOT_GROUP,
+ PROP_DEFAULTS_DIR
+} GKeyfileSettingsBackendProperty;
+
typedef struct
{
GSettingsBackend parent_instance;
@@ -48,6 +61,9 @@ typedef struct
GKeyFile *keyfile;
GPermission *permission;
gboolean writable;
+ char *defaults_dir;
+ GKeyFile *system_keyfile;
+ GHashTable *system_locks; /* Used as a set, owning the strings it contains */
gchar *prefix;
gint prefix_len;
@@ -61,10 +77,18 @@ typedef struct
GFileMonitor *dir_monitor;
} GKeyfileSettingsBackend;
-static GType g_keyfile_settings_backend_get_type (void);
-G_DEFINE_TYPE (GKeyfileSettingsBackend,
- g_keyfile_settings_backend,
- G_TYPE_SETTINGS_BACKEND)
+#ifdef G_OS_WIN32
+#define EXTENSION_PRIORITY 10
+#else
+#define EXTENSION_PRIORITY (glib_should_use_portal () ? 110 : 10)
+#endif
+
+G_DEFINE_TYPE_WITH_CODE (GKeyfileSettingsBackend,
+ g_keyfile_settings_backend,
+ G_TYPE_SETTINGS_BACKEND,
+ _g_io_modules_ensure_extension_points_registered ();
+ g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME,
+ g_define_type_id, "keyfile", EXTENSION_PRIORITY))
static void
compute_checksum (guint8 *digest,
@@ -184,17 +208,47 @@ get_from_keyfile (GKeyfileSettingsBackend *kfsb,
if (convert_path (kfsb, key, &group, &name))
{
gchar *str;
+ gchar *sysstr;
g_assert (*name);
+ sysstr = g_key_file_get_value (kfsb->system_keyfile, group, name, NULL);
str = g_key_file_get_value (kfsb->keyfile, group, name, NULL);
+ if (sysstr &&
+ (g_hash_table_contains (kfsb->system_locks, key) ||
+ str == NULL))
+ {
+ g_free (str);
+ str = g_steal_pointer (&sysstr);
+ }
if (str)
{
return_value = g_variant_parse (type, str, NULL, NULL, NULL);
+ if (return_value == NULL &&
+ g_variant_type_equal (type, G_VARIANT_TYPE_STRING) &&
+ str[0] != '\"')
+ {
+ GString *s = g_string_sized_new (strlen (str) + 2);
+ char *p = str;
+
+ g_string_append_c (s, '\"');
+ while (*p)
+ {
+ if (*p == '\"')
+ g_string_append_c (s, '\\');
+ g_string_append_c (s, *p);
+ p++;
+ }
+ g_string_append_c (s, '\"');
+ return_value = g_variant_parse (type, s->str, NULL, NULL, NULL);
+ g_string_free (s, TRUE);
+ }
g_free (str);
}
+ g_free (sysstr);
+
g_free (group);
g_free (name);
}
@@ -209,6 +263,9 @@ set_to_keyfile (GKeyfileSettingsBackend *kfsb,
{
gchar *group, *name;
+ if (g_hash_table_contains (kfsb->system_locks, key))
+ return FALSE;
+
if (convert_path (kfsb, key, &group, &name))
{
if (value)
@@ -287,7 +344,8 @@ g_keyfile_settings_backend_check_one (gpointer key,
{
WriteManyData *data = user_data;
- return data->failed = !path_is_valid (data->kfsb, key);
+ return data->failed = g_hash_table_contains (data->kfsb->system_locks, key) ||
+ !path_is_valid (data->kfsb, key);
}
static gboolean
@@ -355,7 +413,9 @@ g_keyfile_settings_backend_get_writable (GSettingsBackend *backend,
{
GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (backend);
- return kfsb->writable && path_is_valid (kfsb, name);
+ return kfsb->writable &&
+ !g_hash_table_contains (kfsb->system_locks, name) &&
+ path_is_valid (kfsb, name);
}
static GPermission *
@@ -501,6 +561,9 @@ g_keyfile_settings_backend_finalize (GObject *object)
g_key_file_free (kfsb->keyfile);
g_object_unref (kfsb->permission);
+ g_key_file_unref (kfsb->system_keyfile);
+ g_hash_table_unref (kfsb->system_locks);
+ g_free (kfsb->defaults_dir);
g_file_monitor_cancel (kfsb->file_monitor);
g_object_unref (kfsb->file_monitor);
@@ -523,25 +586,6 @@ g_keyfile_settings_backend_init (GKeyfileSettingsBackend *kfsb)
}
static void
-g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- object_class->finalize = g_keyfile_settings_backend_finalize;
-
- class->read = g_keyfile_settings_backend_read;
- class->write = g_keyfile_settings_backend_write;
- class->write_tree = g_keyfile_settings_backend_write_tree;
- class->reset = g_keyfile_settings_backend_reset;
- class->get_writable = g_keyfile_settings_backend_get_writable;
- class->get_permission = g_keyfile_settings_backend_get_permission;
- /* No need to implement subscribed/unsubscribe: the only point would be to
- * stop monitoring the file when there's no GSettings anymore, which is no
- * big win.
- */
-}
-
-static void
file_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
@@ -567,6 +611,282 @@ dir_changed (GFileMonitor *monitor,
g_keyfile_settings_backend_keyfile_writable (kfsb);
}
+static void
+load_system_settings (GKeyfileSettingsBackend *kfsb)
+{
+ GError *error = NULL;
+ const char *dir = "/etc/glib-2.0/settings";
+ char *path;
+ char *contents;
+
+ kfsb->system_keyfile = g_key_file_new ();
+ kfsb->system_locks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ if (kfsb->defaults_dir)
+ dir = kfsb->defaults_dir;
+
+ path = g_build_filename (dir, "defaults", NULL);
+
+ /* The defaults are in the same keyfile format that we use for the settings.
+ * It can be produced from a dconf database using: dconf dump
+ */
+ if (!g_key_file_load_from_file (kfsb->system_keyfile, path, G_KEY_FILE_NONE, &error))
+ {
+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ g_warning ("Failed to read %s: %s", path, error->message);
+ g_clear_error (&error);
+ }
+ else
+ g_debug ("Loading default settings from %s", path);
+
+ g_free (path);
+
+ path = g_build_filename (dir, "locks", NULL);
+
+ /* The locks file is a text file containing a list paths to lock, one per line.
+ * It can be produced from a dconf database using: dconf list-locks
+ */
+ if (!g_file_get_contents (path, &contents, NULL, &error))
+ {
+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ g_warning ("Failed to read %s: %s", path, error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ char **lines;
+ gsize i;
+
+ g_debug ("Loading locks from %s", path);
+
+ lines = g_strsplit (contents, "\n", 0);
+ for (i = 0; lines[i]; i++)
+ {
+ char *line = lines[i];
+ if (line[0] == '#' || line[0] == '\0')
+ {
+ g_free (line);
+ continue;
+ }
+
+ g_debug ("Locking key %s", line);
+ g_hash_table_add (kfsb->system_locks, g_steal_pointer (&line));
+ }
+
+ g_free (lines);
+ }
+ g_free (contents);
+
+ g_free (path);
+}
+
+static void
+g_keyfile_settings_backend_constructed (GObject *object)
+{
+ GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
+
+ if (kfsb->file == NULL)
+ {
+ char *filename = g_build_filename (g_get_user_config_dir (),
+ "glib-2.0", "settings", "keyfile",
+ NULL);
+ kfsb->file = g_file_new_for_path (filename);
+ g_free (filename);
+ }
+
+ if (kfsb->prefix == NULL)
+ {
+ kfsb->prefix = g_strdup ("/");
+ kfsb->prefix_len = 1;
+ }
+
+ kfsb->keyfile = g_key_file_new ();
+ kfsb->permission = g_simple_permission_new (TRUE);
+
+ kfsb->dir = g_file_get_parent (kfsb->file);
+ g_file_make_directory_with_parents (kfsb->dir, NULL, NULL);
+
+ kfsb->file_monitor = g_file_monitor (kfsb->file, G_FILE_MONITOR_NONE, NULL, NULL);
+ kfsb->dir_monitor = g_file_monitor (kfsb->dir, G_FILE_MONITOR_NONE, NULL, NULL);
+
+ compute_checksum (kfsb->digest, NULL, 0);
+
+ g_signal_connect (kfsb->file_monitor, "changed",
+ G_CALLBACK (file_changed), kfsb);
+ g_signal_connect (kfsb->dir_monitor, "changed",
+ G_CALLBACK (dir_changed), kfsb);
+
+ g_keyfile_settings_backend_keyfile_writable (kfsb);
+ g_keyfile_settings_backend_keyfile_reload (kfsb);
+
+ load_system_settings (kfsb);
+}
+
+static void
+g_keyfile_settings_backend_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
+
+ switch ((GKeyfileSettingsBackendProperty)prop_id)
+ {
+ case PROP_FILENAME:
+ /* Construct only. */
+ g_assert (kfsb->file == NULL);
+ kfsb->file = g_file_new_for_path (g_value_get_string (value));
+ break;
+
+ case PROP_ROOT_PATH:
+ /* Construct only. */
+ g_assert (kfsb->prefix == NULL);
+ kfsb->prefix = g_value_dup_string (value);
+ if (kfsb->prefix)
+ kfsb->prefix_len = strlen (kfsb->prefix);
+ break;
+
+ case PROP_ROOT_GROUP:
+ /* Construct only. */
+ g_assert (kfsb->root_group == NULL);
+ kfsb->root_group = g_value_dup_string (value);
+ if (kfsb->root_group)
+ kfsb->root_group_len = strlen (kfsb->root_group);
+ break;
+
+ case PROP_DEFAULTS_DIR:
+ /* Construct only. */
+ g_assert (kfsb->defaults_dir == NULL);
+ kfsb->defaults_dir = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_keyfile_settings_backend_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GKeyfileSettingsBackend *kfsb = G_KEYFILE_SETTINGS_BACKEND (object);
+
+ switch ((GKeyfileSettingsBackendProperty)prop_id)
+ {
+ case PROP_FILENAME:
+ g_value_set_string (value, g_file_peek_path (kfsb->file));
+ break;
+
+ case PROP_ROOT_PATH:
+ g_value_set_string (value, kfsb->prefix);
+ break;
+
+ case PROP_ROOT_GROUP:
+ g_value_set_string (value, kfsb->root_group);
+ break;
+
+ case PROP_DEFAULTS_DIR:
+ g_value_set_string (value, kfsb->defaults_dir);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_keyfile_settings_backend_class_init (GKeyfileSettingsBackendClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = g_keyfile_settings_backend_finalize;
+ object_class->constructed = g_keyfile_settings_backend_constructed;
+ object_class->get_property = g_keyfile_settings_backend_get_property;
+ object_class->set_property = g_keyfile_settings_backend_set_property;
+
+ class->read = g_keyfile_settings_backend_read;
+ class->write = g_keyfile_settings_backend_write;
+ class->write_tree = g_keyfile_settings_backend_write_tree;
+ class->reset = g_keyfile_settings_backend_reset;
+ class->get_writable = g_keyfile_settings_backend_get_writable;
+ class->get_permission = g_keyfile_settings_backend_get_permission;
+ /* No need to implement subscribed/unsubscribe: the only point would be to
+ * stop monitoring the file when there's no GSettings anymore, which is no
+ * big win.
+ */
+
+ /**
+ * GKeyfileSettingsBackend:filename:
+ *
+ * The location where the settings are stored on disk.
+ *
+ * Defaults to `$XDG_CONFIG_HOME/glib-2.0/settings/keyfile`.
+ */
+ g_object_class_install_property (object_class,
+ PROP_FILENAME,
+ g_param_spec_string ("filename",
+ P_("Filename"),
+ P_("The filename"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GKeyfileSettingsBackend:root-path:
+ *
+ * All settings read to or written from the backend must fall under the
+ * path given in @root_path (which must start and end with a slash and
+ * not contain two consecutive slashes). @root_path may be "/".
+ *
+ * Defaults to "/".
+ */
+ g_object_class_install_property (object_class,
+ PROP_ROOT_PATH,
+ g_param_spec_string ("root-path",
+ P_("Root path"),
+ P_("The root path"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GKeyfileSettingsBackend:root-group:
+ *
+ * If @root_group is non-%NULL then it specifies the name of the keyfile
+ * group used for keys that are written directly below the root path.
+ *
+ * Defaults to NULL.
+ */
+ g_object_class_install_property (object_class,
+ PROP_ROOT_GROUP,
+ g_param_spec_string ("root-group",
+ P_("Root group"),
+ P_("The root group"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GKeyfileSettingsBackend:default-dir:
+ *
+ * The directory where the system defaults and locks are located.
+ *
+ * Defaults to `/etc/glib-2.0/settings`.
+ */
+ g_object_class_install_property (object_class,
+ PROP_DEFAULTS_DIR,
+ g_param_spec_string ("defaults-dir",
+ P_("Default dir"),
+ P_("Defaults dir"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
/**
* g_keyfile_settings_backend_new:
* @filename: the filename of the keyfile
@@ -619,6 +939,11 @@ dir_changed (GFileMonitor *monitor,
* characters in your path names or '=' in your key names you may be in
* trouble.
*
+ * The backend reads default values from a keyfile called `defaults` in
+ * the directory specified by the #GKeyfileSettingsBackend:defaults-dir property,
+ * and a list of locked keys from a text file with the name `locks` in
+ * the same location.
+ *
* Returns: (transfer full): a keyfile-backed #GSettingsBackend
**/
GSettingsBackend *
@@ -626,43 +951,15 @@ g_keyfile_settings_backend_new (const gchar *filename,
const gchar *root_path,
const gchar *root_group)
{
- GKeyfileSettingsBackend *kfsb;
-
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (root_path != NULL, NULL);
g_return_val_if_fail (g_str_has_prefix (root_path, "/"), NULL);
g_return_val_if_fail (g_str_has_suffix (root_path, "/"), NULL);
g_return_val_if_fail (strstr (root_path, "//") == NULL, NULL);
- kfsb = g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND, NULL);
- kfsb->keyfile = g_key_file_new ();
- kfsb->permission = g_simple_permission_new (TRUE);
-
- kfsb->file = g_file_new_for_path (filename);
- kfsb->dir = g_file_get_parent (kfsb->file);
- g_file_make_directory_with_parents (kfsb->dir, NULL, NULL);
-
- kfsb->file_monitor = g_file_monitor (kfsb->file, 0, NULL, NULL);
- kfsb->dir_monitor = g_file_monitor (kfsb->dir, 0, NULL, NULL);
-
- kfsb->prefix_len = strlen (root_path);
- kfsb->prefix = g_strdup (root_path);
-
- if (root_group)
- {
- kfsb->root_group_len = strlen (root_group);
- kfsb->root_group = g_strdup (root_group);
- }
-
- compute_checksum (kfsb->digest, NULL, 0);
-
- g_signal_connect (kfsb->file_monitor, "changed",
- G_CALLBACK (file_changed), kfsb);
- g_signal_connect (kfsb->dir_monitor, "changed",
- G_CALLBACK (dir_changed), kfsb);
-
- g_keyfile_settings_backend_keyfile_writable (kfsb);
- g_keyfile_settings_backend_keyfile_reload (kfsb);
-
- return G_SETTINGS_BACKEND (kfsb);
+ return G_SETTINGS_BACKEND (g_object_new (G_TYPE_KEYFILE_SETTINGS_BACKEND,
+ "filename", filename,
+ "root-path", root_path,
+ "root-group", root_group,
+ NULL));
}
diff --git a/gio/gliststore.c b/gio/gliststore.c
index ae8e2c1d8..7b2a453d6 100644
--- a/gio/gliststore.c
+++ b/gio/gliststore.c
@@ -55,6 +55,7 @@ struct _GListStore
/* cache */
guint last_position;
GSequenceIter *last_iter;
+ gboolean last_position_valid;
};
enum
@@ -79,7 +80,8 @@ g_list_store_items_changed (GListStore *store,
if (position <= store->last_position)
{
store->last_iter = NULL;
- store->last_position = -1u;
+ store->last_position = 0;
+ store->last_position_valid = FALSE;
}
g_list_model_items_changed (G_LIST_MODEL (store), position, removed, added);
@@ -179,11 +181,11 @@ g_list_store_get_item (GListModel *list,
GListStore *store = G_LIST_STORE (list);
GSequenceIter *it = NULL;
- if (store->last_position != -1u)
+ if (store->last_position_valid)
{
- if (store->last_position == position + 1)
+ if (position < G_MAXUINT && store->last_position == position + 1)
it = g_sequence_iter_prev (store->last_iter);
- else if (store->last_position == position - 1)
+ else if (position > 0 && store->last_position == position - 1)
it = g_sequence_iter_next (store->last_iter);
else if (store->last_position == position)
it = store->last_iter;
@@ -194,6 +196,7 @@ g_list_store_get_item (GListModel *list,
store->last_iter = it;
store->last_position = position;
+ store->last_position_valid = TRUE;
if (g_sequence_iter_is_end (it))
return NULL;
@@ -213,7 +216,8 @@ static void
g_list_store_init (GListStore *store)
{
store->items = g_sequence_new (g_object_unref);
- store->last_position = -1u;
+ store->last_position = 0;
+ store->last_position_valid = FALSE;
}
/**
diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c
index 57d2d5dfe..6d44989bf 100644
--- a/gio/glocalfileoutputstream.c
+++ b/gio/glocalfileoutputstream.c
@@ -38,6 +38,7 @@
#ifdef G_OS_UNIX
#include <unistd.h>
#include "gfiledescriptorbased.h"
+#include <sys/uio.h>
#endif
#include "glib-private.h"
@@ -93,6 +94,14 @@ static gssize g_local_file_output_stream_write (GOutputStream *s
gsize count,
GCancellable *cancellable,
GError **error);
+#ifdef G_OS_UNIX
+static gboolean g_local_file_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
+#endif
static gboolean g_local_file_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
@@ -142,6 +151,9 @@ g_local_file_output_stream_class_init (GLocalFileOutputStreamClass *klass)
gobject_class->finalize = g_local_file_output_stream_finalize;
stream_class->write_fn = g_local_file_output_stream_write;
+#ifdef G_OS_UNIX
+ stream_class->writev_fn = g_local_file_output_stream_writev;
+#endif
stream_class->close_fn = g_local_file_output_stream_close;
file_stream_class->query_info = g_local_file_output_stream_query_info;
file_stream_class->get_etag = g_local_file_output_stream_get_etag;
@@ -203,6 +215,89 @@ g_local_file_output_stream_write (GOutputStream *stream,
return res;
}
+/* On Windows there is no equivalent API for files. The closest API to that is
+ * WriteFileGather() but it is useless in general: it requires, among other
+ * things, that each chunk is the size of a whole page and in memory aligned
+ * to a page. We can't possibly guarantee that in GLib.
+ */
+#ifdef G_OS_UNIX
+/* Macro to check if struct iovec and GOutputVector have the same ABI */
+#define G_OUTPUT_VECTOR_IS_IOVEC (sizeof (struct iovec) == sizeof (GOutputVector) && \
+ sizeof ((struct iovec *) 0)->iov_base == sizeof ((GOutputVector *) 0)->buffer && \
+ G_STRUCT_OFFSET (struct iovec, iov_base) == G_STRUCT_OFFSET (GOutputVector, buffer) && \
+ sizeof ((struct iovec *) 0)->iov_len == sizeof((GOutputVector *) 0)->size && \
+ G_STRUCT_OFFSET (struct iovec, iov_len) == G_STRUCT_OFFSET (GOutputVector, size))
+
+static gboolean
+g_local_file_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GLocalFileOutputStream *file;
+ gssize res;
+ struct iovec *iov;
+
+ if (bytes_written)
+ *bytes_written = 0;
+
+ /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
+ * We handle this like a short write in this case
+ */
+ if (n_vectors > G_MAXINT)
+ n_vectors = G_MAXINT;
+
+ file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
+
+ if (G_OUTPUT_VECTOR_IS_IOVEC)
+ {
+ /* ABI is compatible */
+ iov = (struct iovec *) vectors;
+ }
+ else
+ {
+ gsize i;
+
+ /* ABI is incompatible */
+ iov = g_newa (struct iovec, n_vectors);
+ for (i = 0; i < n_vectors; i++)
+ {
+ iov[i].iov_base = (void *)vectors[i].buffer;
+ iov[i].iov_len = vectors[i].size;
+ }
+ }
+
+ while (1)
+ {
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+ res = writev (file->priv->fd, iov, n_vectors);
+ if (res == -1)
+ {
+ int errsv = errno;
+
+ if (errsv == EINTR)
+ continue;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error writing to file: %s"),
+ g_strerror (errsv));
+ }
+ else if (bytes_written)
+ {
+ *bytes_written = res;
+ }
+
+ break;
+ }
+
+ return res != -1;
+}
+#endif
+
void
_g_local_file_output_stream_set_do_close (GLocalFileOutputStream *out,
gboolean do_close)
diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c
index 1651f89ed..60736874e 100644
--- a/gio/gnetworkaddress.c
+++ b/gio/gnetworkaddress.c
@@ -1120,12 +1120,17 @@ on_address_timeout (gpointer user_data)
{
GNetworkAddressAddressEnumerator *addr_enum = user_data;
+ /* Upon completion it may get unref'd by the owner */
+ g_object_ref (addr_enum);
+
/* If ipv6 didn't come in yet, just complete the task */
if (addr_enum->queued_task != NULL)
complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->queued_task),
g_steal_pointer (&addr_enum->last_error));
g_clear_pointer (&addr_enum->wait_source, g_source_unref);
+ g_object_unref (addr_enum);
+
return G_SOURCE_REMOVE;
}
diff --git a/gio/goutputstream.c b/gio/goutputstream.c
index 3e658e88a..10f9aa732 100644
--- a/gio/goutputstream.c
+++ b/gio/goutputstream.c
@@ -72,6 +72,23 @@ static void g_output_stream_real_write_async (GOutputStream *s
static gssize g_output_stream_real_write_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
+static gboolean g_output_stream_real_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
+static void g_output_stream_real_writev_async (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean g_output_stream_real_writev_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error);
static void g_output_stream_real_splice_async (GOutputStream *stream,
GInputStream *source,
GOutputStreamSpliceFlags flags,
@@ -134,6 +151,9 @@ g_output_stream_class_init (GOutputStreamClass *klass)
klass->write_async = g_output_stream_real_write_async;
klass->write_finish = g_output_stream_real_write_finish;
+ klass->writev_fn = g_output_stream_real_writev;
+ klass->writev_async = g_output_stream_real_writev_async;
+ klass->writev_finish = g_output_stream_real_writev_finish;
klass->splice_async = g_output_stream_real_splice_async;
klass->splice_finish = g_output_stream_real_splice_finish;
klass->flush_async = g_output_stream_real_flush_async;
@@ -286,9 +306,7 @@ g_output_stream_write_all (GOutputStream *stream,
*bytes_written = _bytes_written;
return FALSE;
}
-
- if (res == 0)
- g_warning ("Write returned zero without error");
+ g_return_val_if_fail (res > 0, FALSE);
_bytes_written += res;
}
@@ -300,6 +318,203 @@ g_output_stream_write_all (GOutputStream *stream,
}
/**
+ * g_output_stream_writev:
+ * @stream: a #GOutputStream.
+ * @vectors: (array length=n_vectors): the buffer containing the #GOutputVectors to write.
+ * @n_vectors: the number of vectors to write
+ * @bytes_written: (out) (optional): location to store the number of bytes that were
+ * written to the stream
+ * @cancellable: (nullable): optional cancellable object
+ * @error: location to store the error occurring, or %NULL to ignore
+ *
+ * Tries to write the bytes contained in the @n_vectors @vectors into the
+ * stream. Will block during the operation.
+ *
+ * If @n_vectors is 0 or the sum of all bytes in @vectors is 0, returns 0 and
+ * does nothing.
+ *
+ * On success, the number of bytes written to the stream is returned.
+ * It is not an error if this is not the same as the requested size, as it
+ * can happen e.g. on a partial I/O error, or if there is not enough
+ * storage in the stream. All writes block until at least one byte
+ * is written or an error occurs; 0 is never returned (unless
+ * @n_vectors is 0 or the sum of all bytes in @vectors is 0).
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
+ * operation was partially finished when the operation was cancelled the
+ * partial result will be returned, without an error.
+ *
+ * Some implementations of g_output_stream_writev() may have limitations on the
+ * aggregate buffer size, and will return %G_IO_ERROR_INVALID_ARGUMENT if these
+ * are exceeded. For example, when writing to a local file on UNIX platforms,
+ * the aggregate buffer size must not exceed %G_MAXSSIZE bytes.
+ *
+ * Virtual: writev_fn
+ *
+ * Returns: %TRUE on success, %FALSE if there was an error
+ *
+ * Since: 2.60
+ */
+gboolean
+g_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GOutputStreamClass *class;
+ gboolean res;
+ gsize _bytes_written = 0;
+
+ if (bytes_written)
+ *bytes_written = 0;
+
+ g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+ g_return_val_if_fail (vectors != NULL || n_vectors == 0, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (n_vectors == 0)
+ return TRUE;
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+
+ g_return_val_if_fail (class->writev_fn != NULL, FALSE);
+
+ if (!g_output_stream_set_pending (stream, error))
+ return FALSE;
+
+ if (cancellable)
+ g_cancellable_push_current (cancellable);
+
+ res = class->writev_fn (stream, vectors, n_vectors, &_bytes_written, cancellable, error);
+
+ g_warn_if_fail (res || _bytes_written == 0);
+ g_warn_if_fail (res || (error == NULL || *error != NULL));
+
+ if (cancellable)
+ g_cancellable_pop_current (cancellable);
+
+ g_output_stream_clear_pending (stream);
+
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ return res;
+}
+
+/**
+ * g_output_stream_writev_all:
+ * @stream: a #GOutputStream.
+ * @vectors: (array length=n_vectors): the buffer containing the #GOutputVectors to write.
+ * @n_vectors: the number of vectors to write
+ * @bytes_written: (out) (optional): location to store the number of bytes that were
+ * written to the stream
+ * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
+ * @error: location to store the error occurring, or %NULL to ignore
+ *
+ * Tries to write the bytes contained in the @n_vectors @vectors into the
+ * stream. Will block during the operation.
+ *
+ * This function is similar to g_output_stream_writev(), except it tries to
+ * write as many bytes as requested, only stopping on an error.
+ *
+ * On a successful write of all @n_vectors vectors, %TRUE is returned, and
+ * @bytes_written is set to the sum of all the sizes of @vectors.
+ *
+ * If there is an error during the operation %FALSE is returned and @error
+ * is set to indicate the error status.
+ *
+ * As a special exception to the normal conventions for functions that
+ * use #GError, if this function returns %FALSE (and sets @error) then
+ * @bytes_written will be set to the number of bytes that were
+ * successfully written before the error was encountered. This
+ * functionality is only available from C. If you need it from another
+ * language then you must write your own loop around
+ * g_output_stream_write().
+ *
+ * The content of the individual elements of @vectors might be changed by this
+ * function.
+ *
+ * Returns: %TRUE on success, %FALSE if there was an error
+ *
+ * Since: 2.60
+ */
+gboolean
+g_output_stream_writev_all (GOutputStream *stream,
+ GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gsize _bytes_written = 0;
+ gsize i, to_be_written = 0;
+
+ if (bytes_written)
+ *bytes_written = 0;
+
+ g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+ g_return_val_if_fail (vectors != NULL || n_vectors == 0, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* We can't write more than G_MAXSIZE bytes overall, otherwise we
+ * would overflow the bytes_written counter */
+ for (i = 0; i < n_vectors; i++)
+ {
+ if (to_be_written > G_MAXSIZE - vectors[i].size)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Sum of vectors passed to %s too large"), G_STRFUNC);
+ return FALSE;
+ }
+ to_be_written += vectors[i].size;
+ }
+
+ _bytes_written = 0;
+ while (n_vectors > 0 && to_be_written > 0)
+ {
+ gsize n_written = 0;
+ gboolean res;
+
+ res = g_output_stream_writev (stream, vectors, n_vectors, &n_written, cancellable, error);
+
+ if (!res)
+ {
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+ return FALSE;
+ }
+
+ g_return_val_if_fail (n_written > 0, FALSE);
+ _bytes_written += n_written;
+
+ /* skip vectors that have been written in full */
+ while (n_vectors > 0 && n_written >= vectors[0].size)
+ {
+ n_written -= vectors[0].size;
+ ++vectors;
+ --n_vectors;
+ }
+ /* skip partially written vector data */
+ if (n_written > 0 && n_vectors > 0)
+ {
+ vectors[0].size -= n_written;
+ vectors[0].buffer = ((guint8 *) vectors[0].buffer) + n_written;
+ }
+ }
+
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ return TRUE;
+}
+
+/**
* g_output_stream_printf:
* @stream: a #GOutputStream.
* @bytes_written: (out) (optional): location to store the number of bytes that was
@@ -923,7 +1138,6 @@ write_all_callback (GObject *stream,
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
-
else
g_output_stream_write_async (G_OUTPUT_STREAM (stream),
data->buffer + data->bytes_written,
@@ -1060,6 +1274,329 @@ g_output_stream_write_all_finish (GOutputStream *stream,
return g_task_propagate_boolean (task, error);
}
+/**
+ * g_output_stream_writev_async:
+ * @stream: A #GOutputStream.
+ * @vectors: (array length=n_vectors): the buffer containing the #GOutputVectors to write.
+ * @n_vectors: the number of vectors to write
+ * @io_priority: the I/O priority of the request.
+ * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
+ * @callback: (scope async): callback to call when the request is satisfied
+ * @user_data: (closure): the data to pass to callback function
+ *
+ * Request an asynchronous write of the bytes contained in @n_vectors @vectors into
+ * the stream. When the operation is finished @callback will be called.
+ * You can then call g_output_stream_writev_finish() to get the result of the
+ * operation.
+ *
+ * During an async request no other sync and async calls are allowed,
+ * and will result in %G_IO_ERROR_PENDING errors.
+ *
+ * On success, the number of bytes written will be passed to the
+ * @callback. It is not an error if this is not the same as the
+ * requested size, as it can happen e.g. on a partial I/O error,
+ * but generally we try to write as many bytes as requested.
+ *
+ * You are guaranteed that this method will never fail with
+ * %G_IO_ERROR_WOULD_BLOCK — if @stream can't accept more data, the
+ * method will just wait until this changes.
+ *
+ * Any outstanding I/O request with higher priority (lower numerical
+ * value) will be executed before an outstanding request with lower
+ * priority. Default priority is %G_PRIORITY_DEFAULT.
+ *
+ * The asynchronous methods have a default fallback that uses threads
+ * to implement asynchronicity, so they are optional for inheriting
+ * classes. However, if you override one you must override all.
+ *
+ * For the synchronous, blocking version of this function, see
+ * g_output_stream_writev().
+ *
+ * Note that no copy of @vectors will be made, so it must stay valid
+ * until @callback is called.
+ *
+ * Since: 2.60
+ */
+void
+g_output_stream_writev_async (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GOutputStreamClass *class;
+
+ g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
+ g_return_if_fail (vectors != NULL || n_vectors == 0);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+ g_return_if_fail (class->writev_async != NULL);
+
+ class->writev_async (stream, vectors, n_vectors, io_priority, cancellable,
+ callback, user_data);
+}
+
+/**
+ * g_output_stream_writev_finish:
+ * @stream: a #GOutputStream.
+ * @result: a #GAsyncResult.
+ * @bytes_written: (out) (optional): location to store the number of bytes that were written to the stream
+ * @error: a #GError location to store the error occurring, or %NULL to
+ * ignore.
+ *
+ * Finishes a stream writev operation.
+ *
+ * Returns: %TRUE on success, %FALSE if there was an error
+ *
+ * Since: 2.60
+ */
+gboolean
+g_output_stream_writev_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error)
+{
+ GOutputStreamClass *class;
+ gboolean res;
+ gsize _bytes_written = 0;
+
+ g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+ g_return_val_if_fail (class->writev_finish != NULL, FALSE);
+
+ res = class->writev_finish (stream, result, &_bytes_written, error);
+
+ g_warn_if_fail (res || _bytes_written == 0);
+ g_warn_if_fail (res || (error == NULL || *error != NULL));
+
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ return res;
+}
+
+typedef struct
+{
+ GOutputVector *vectors;
+ gsize n_vectors; /* (unowned) */
+ gsize bytes_written;
+} AsyncWritevAll;
+
+static void
+free_async_writev_all (gpointer data)
+{
+ g_slice_free (AsyncWritevAll, data);
+}
+
+static void
+writev_all_callback (GObject *stream,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GTask *task = user_data;
+ AsyncWritevAll *data = g_task_get_task_data (task);
+ gint priority = g_task_get_priority (task);
+ GCancellable *cancellable = g_task_get_cancellable (task);
+
+ if (result)
+ {
+ GError *error = NULL;
+ gboolean res;
+ gsize n_written = 0;
+
+ res = g_output_stream_writev_finish (G_OUTPUT_STREAM (stream), result, &n_written, &error);
+
+ if (!res)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ g_object_unref (task);
+ return;
+ }
+
+ g_warn_if_fail (n_written > 0);
+ data->bytes_written += n_written;
+
+ /* skip vectors that have been written in full */
+ while (data->n_vectors > 0 && n_written >= data->vectors[0].size)
+ {
+ n_written -= data->vectors[0].size;
+ ++data->vectors;
+ --data->n_vectors;
+ }
+ /* skip partially written vector data */
+ if (n_written > 0 && data->n_vectors > 0)
+ {
+ data->vectors[0].size -= n_written;
+ data->vectors[0].buffer = ((guint8 *) data->vectors[0].buffer) + n_written;
+ }
+ }
+
+ if (data->n_vectors == 0)
+ {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ }
+ else
+ g_output_stream_writev_async (G_OUTPUT_STREAM (stream),
+ data->vectors,
+ data->n_vectors,
+ priority,
+ cancellable,
+ writev_all_callback, g_steal_pointer (&task));
+}
+
+static void
+writev_all_async_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GOutputStream *stream = G_OUTPUT_STREAM (source_object);
+ AsyncWritevAll *data = task_data;
+ GError *error = NULL;
+
+ if (g_output_stream_writev_all (stream, data->vectors, data->n_vectors, &data->bytes_written,
+ g_task_get_cancellable (task), &error))
+ g_task_return_boolean (task, TRUE);
+ else
+ g_task_return_error (task, g_steal_pointer (&error));
+}
+
+/**
+ * g_output_stream_writev_all_async:
+ * @stream: A #GOutputStream
+ * @vectors: (array length=n_vectors): the buffer containing the #GOutputVectors to write.
+ * @n_vectors: the number of vectors to write
+ * @io_priority: the I/O priority of the request
+ * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
+ * @callback: (scope async): callback to call when the request is satisfied
+ * @user_data: (closure): the data to pass to callback function
+ *
+ * Request an asynchronous write of the bytes contained in the @n_vectors @vectors into
+ * the stream. When the operation is finished @callback will be called.
+ * You can then call g_output_stream_writev_all_finish() to get the result of the
+ * operation.
+ *
+ * This is the asynchronous version of g_output_stream_writev_all().
+ *
+ * Call g_output_stream_writev_all_finish() to collect the result.
+ *
+ * Any outstanding I/O request with higher priority (lower numerical
+ * value) will be executed before an outstanding request with lower
+ * priority. Default priority is %G_PRIORITY_DEFAULT.
+ *
+ * Note that no copy of @vectors will be made, so it must stay valid
+ * until @callback is called. The content of the individual elements
+ * of @vectors might be changed by this function.
+ *
+ * Since: 2.60
+ */
+void
+g_output_stream_writev_all_async (GOutputStream *stream,
+ GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ AsyncWritevAll *data;
+ GTask *task;
+ gsize i, to_be_written = 0;
+
+ g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
+ g_return_if_fail (vectors != NULL || n_vectors == 0);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (stream, cancellable, callback, user_data);
+ data = g_slice_new0 (AsyncWritevAll);
+ data->vectors = vectors;
+ data->n_vectors = n_vectors;
+
+ g_task_set_source_tag (task, g_output_stream_writev_all_async);
+ g_task_set_task_data (task, data, free_async_writev_all);
+ g_task_set_priority (task, io_priority);
+
+ /* We can't write more than G_MAXSIZE bytes overall, otherwise we
+ * would overflow the bytes_written counter */
+ for (i = 0; i < n_vectors; i++)
+ {
+ if (to_be_written > G_MAXSIZE - vectors[i].size)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Sum of vectors passed to %s too large"),
+ G_STRFUNC);
+ g_object_unref (task);
+ return;
+ }
+ to_be_written += vectors[i].size;
+ }
+
+ /* If async writes are going to be handled via the threadpool anyway
+ * then we may as well do it with a single dispatch instead of
+ * bouncing in and out.
+ */
+ if (g_output_stream_async_writev_is_via_threads (stream))
+ {
+ g_task_run_in_thread (task, writev_all_async_thread);
+ g_object_unref (task);
+ }
+ else
+ writev_all_callback (G_OBJECT (stream), NULL, g_steal_pointer (&task));
+}
+
+/**
+ * g_output_stream_writev_all_finish:
+ * @stream: a #GOutputStream
+ * @result: a #GAsyncResult
+ * @bytes_written: (out) (optional): location to store the number of bytes that were written to the stream
+ * @error: a #GError location to store the error occurring, or %NULL to ignore.
+ *
+ * Finishes an asynchronous stream write operation started with
+ * g_output_stream_writev_all_async().
+ *
+ * As a special exception to the normal conventions for functions that
+ * use #GError, if this function returns %FALSE (and sets @error) then
+ * @bytes_written will be set to the number of bytes that were
+ * successfully written before the error was encountered. This
+ * functionality is only available from C. If you need it from another
+ * language then you must write your own loop around
+ * g_output_stream_writev_async().
+ *
+ * Returns: %TRUE on success, %FALSE if there was an error
+ *
+ * Since: 2.60
+ */
+gboolean
+g_output_stream_writev_all_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error)
+{
+ GTask *task;
+
+ g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ task = G_TASK (result);
+
+ if (bytes_written)
+ {
+ AsyncWritevAll *data = (AsyncWritevAll *)g_task_get_task_data (task);
+
+ *bytes_written = data->bytes_written;
+ }
+
+ return g_task_propagate_boolean (task, error);
+}
+
static void
write_bytes_callback (GObject *stream,
GAsyncResult *result,
@@ -1713,6 +2250,28 @@ g_output_stream_async_write_is_via_threads (GOutputStream *stream)
}
/*< internal >
+ * g_output_stream_async_writev_is_via_threads:
+ * @stream: a #GOutputStream.
+ *
+ * Checks if an output stream's writev_async function uses threads.
+ *
+ * Returns: %TRUE if @stream's writev_async function uses threads.
+ **/
+gboolean
+g_output_stream_async_writev_is_via_threads (GOutputStream *stream)
+{
+ GOutputStreamClass *class;
+
+ g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+
+ return (class->writev_async == g_output_stream_real_writev_async &&
+ !(G_IS_POLLABLE_OUTPUT_STREAM (stream) &&
+ g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (stream))));
+}
+
+/*< internal >
* g_output_stream_async_close_is_via_threads:
* @stream: output stream
*
@@ -1733,6 +2292,69 @@ g_output_stream_async_close_is_via_threads (GOutputStream *stream)
}
/********************************************
+ * Default implementation of sync ops *
+ ********************************************/
+static gboolean
+g_output_stream_real_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GOutputStreamClass *class;
+ gsize _bytes_written = 0;
+ gsize i;
+ GError *err = NULL;
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+
+ if (bytes_written)
+ *bytes_written = 0;
+
+ for (i = 0; i < n_vectors; i++)
+ {
+ gssize res = 0;
+
+ /* Would we overflow here? In that case simply return and let the caller
+ * handle this like a short write */
+ if (_bytes_written > G_MAXSIZE - vectors[i].size)
+ break;
+
+ res = class->write_fn (stream, vectors[i].buffer, vectors[i].size, cancellable, &err);
+
+ if (res == -1)
+ {
+ /* If we already wrote something we handle this like a short write
+ * and assume that on the next call the same error happens again, or
+ * everything finishes successfully without data loss then
+ */
+ if (_bytes_written > 0)
+ {
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ g_clear_error (&err);
+ return TRUE;
+ }
+
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ _bytes_written += res;
+ /* if we had a short write break the loop here */
+ if (res < vectors[i].size)
+ break;
+ }
+
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ return TRUE;
+}
+
+/********************************************
* Default implementation of async ops *
********************************************/
@@ -1853,6 +2475,172 @@ g_output_stream_real_write_finish (GOutputStream *stream,
}
typedef struct {
+ const GOutputVector *vectors;
+ gsize n_vectors; /* (unowned) */
+ gsize bytes_written;
+} WritevData;
+
+static void
+free_writev_data (WritevData *op)
+{
+ g_slice_free (WritevData, op);
+}
+
+static void
+writev_async_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GOutputStream *stream = source_object;
+ WritevData *op = task_data;
+ GOutputStreamClass *class;
+ GError *error = NULL;
+ gboolean res;
+
+ class = G_OUTPUT_STREAM_GET_CLASS (stream);
+ res = class->writev_fn (stream, op->vectors, op->n_vectors,
+ &op->bytes_written, cancellable, &error);
+
+ g_warn_if_fail (res || op->bytes_written == 0);
+ g_warn_if_fail (res || error != NULL);
+
+ if (!res)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+static void writev_async_pollable (GPollableOutputStream *stream,
+ GTask *task);
+
+static gboolean
+writev_async_pollable_ready (GPollableOutputStream *stream,
+ gpointer user_data)
+{
+ GTask *task = user_data;
+
+ writev_async_pollable (stream, task);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+writev_async_pollable (GPollableOutputStream *stream,
+ GTask *task)
+{
+ GError *error = NULL;
+ WritevData *op = g_task_get_task_data (task);
+ GPollableReturn res;
+ gsize bytes_written = 0;
+
+ if (g_task_return_error_if_cancelled (task))
+ return;
+
+ res = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->
+ writev_nonblocking (stream, op->vectors, op->n_vectors, &bytes_written, &error);
+
+ switch (res)
+ {
+ case G_POLLABLE_RETURN_WOULD_BLOCK:
+ {
+ GSource *source;
+
+ g_warn_if_fail (error == NULL);
+ g_warn_if_fail (bytes_written == 0);
+
+ source = g_pollable_output_stream_create_source (stream,
+ g_task_get_cancellable (task));
+ g_task_attach_source (task, source,
+ (GSourceFunc) writev_async_pollable_ready);
+ g_source_unref (source);
+ }
+ break;
+ case G_POLLABLE_RETURN_OK:
+ g_warn_if_fail (error == NULL);
+ op->bytes_written = bytes_written;
+ g_task_return_boolean (task, TRUE);
+ break;
+ case G_POLLABLE_RETURN_FAILED:
+ g_warn_if_fail (bytes_written == 0);
+ g_warn_if_fail (error != NULL);
+ g_task_return_error (task, g_steal_pointer (&error));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+g_output_stream_real_writev_async (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ WritevData *op;
+ GError *error = NULL;
+
+ op = g_slice_new0 (WritevData);
+ task = g_task_new (stream, cancellable, callback, user_data);
+ op->vectors = vectors;
+ op->n_vectors = n_vectors;
+
+ g_task_set_check_cancellable (task, FALSE);
+ g_task_set_source_tag (task, g_output_stream_writev_async);
+ g_task_set_priority (task, io_priority);
+ g_task_set_task_data (task, op, (GDestroyNotify) free_writev_data);
+
+ if (n_vectors == 0)
+ {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+ }
+
+ if (!g_output_stream_set_pending (stream, &error))
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ g_object_unref (task);
+ return;
+ }
+
+ if (!g_output_stream_async_writev_is_via_threads (stream))
+ writev_async_pollable (G_POLLABLE_OUTPUT_STREAM (stream), task);
+ else
+ g_task_run_in_thread (task, writev_async_thread);
+
+ g_object_unref (task);
+}
+
+static gboolean
+g_output_stream_real_writev_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error)
+{
+ GTask *task;
+
+ g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
+ g_return_val_if_fail (g_async_result_is_tagged (result, g_output_stream_writev_async), FALSE);
+
+ g_output_stream_clear_pending (stream);
+
+ task = G_TASK (result);
+
+ if (bytes_written)
+ {
+ WritevData *op = g_task_get_task_data (task);
+
+ *bytes_written = op->bytes_written;
+ }
+
+ return g_task_propagate_boolean (task, error);
+}
+
+typedef struct {
GInputStream *source;
GOutputStreamSpliceFlags flags;
gssize n_read;
diff --git a/gio/goutputstream.h b/gio/goutputstream.h
index fef1b8fdf..dc0f4925a 100644
--- a/gio/goutputstream.h
+++ b/gio/goutputstream.h
@@ -119,11 +119,28 @@ struct _GOutputStreamClass
GAsyncResult *result,
GError **error);
+ gboolean (* writev_fn) (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
+
+ void (* writev_async) (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ gboolean (* writev_finish) (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error);
+
/*< private >*/
/* Padding for future expansion */
- void (*_g_reserved1) (void);
- void (*_g_reserved2) (void);
- void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
void (*_g_reserved6) (void);
@@ -147,6 +164,22 @@ gboolean g_output_stream_write_all (GOutputStream *stream,
gsize *bytes_written,
GCancellable *cancellable,
GError **error);
+
+GLIB_AVAILABLE_IN_2_60
+gboolean g_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
+GLIB_AVAILABLE_IN_2_60
+gboolean g_output_stream_writev_all (GOutputStream *stream,
+ GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
+
GLIB_AVAILABLE_IN_2_40
gboolean g_output_stream_printf (GOutputStream *stream,
gsize *bytes_written,
@@ -208,6 +241,35 @@ gboolean g_output_stream_write_all_finish (GOutputStream *stream,
gsize *bytes_written,
GError **error);
+GLIB_AVAILABLE_IN_2_60
+void g_output_stream_writev_async (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GLIB_AVAILABLE_IN_2_60
+gboolean g_output_stream_writev_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error);
+
+GLIB_AVAILABLE_IN_2_60
+void g_output_stream_writev_all_async (GOutputStream *stream,
+ GOutputVector *vectors,
+ gsize n_vectors,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GLIB_AVAILABLE_IN_2_60
+gboolean g_output_stream_writev_all_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ gsize *bytes_written,
+ GError **error);
+
GLIB_AVAILABLE_IN_2_34
void g_output_stream_write_bytes_async (GOutputStream *stream,
GBytes *bytes,
diff --git a/gio/gpollableoutputstream.c b/gio/gpollableoutputstream.c
index 40c649f0d..c17cf9268 100644
--- a/gio/gpollableoutputstream.c
+++ b/gio/gpollableoutputstream.c
@@ -41,17 +41,23 @@
G_DEFINE_INTERFACE (GPollableOutputStream, g_pollable_output_stream, G_TYPE_OUTPUT_STREAM)
-static gboolean g_pollable_output_stream_default_can_poll (GPollableOutputStream *stream);
-static gssize g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream,
- const void *buffer,
- gsize count,
- GError **error);
+static gboolean g_pollable_output_stream_default_can_poll (GPollableOutputStream *stream);
+static gssize g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GError **error);
+static GPollableReturn g_pollable_output_stream_default_writev_nonblocking (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GError **error);
static void
g_pollable_output_stream_default_init (GPollableOutputStreamInterface *iface)
{
- iface->can_poll = g_pollable_output_stream_default_can_poll;
- iface->write_nonblocking = g_pollable_output_stream_default_write_nonblocking;
+ iface->can_poll = g_pollable_output_stream_default_can_poll;
+ iface->write_nonblocking = g_pollable_output_stream_default_write_nonblocking;
+ iface->writev_nonblocking = g_pollable_output_stream_default_writev_nonblocking;
}
static gboolean
@@ -157,6 +163,67 @@ g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stre
write_fn (G_OUTPUT_STREAM (stream), buffer, count, NULL, error);
}
+static GPollableReturn
+g_pollable_output_stream_default_writev_nonblocking (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GError **error)
+{
+ gsize _bytes_written = 0;
+ GPollableOutputStreamInterface *iface = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream);
+ gsize i;
+ GError *err = NULL;
+
+ for (i = 0; i < n_vectors; i++)
+ {
+ gssize res;
+
+ /* Would we overflow here? In that case simply return and let the caller
+ * handle this like a short write */
+ if (_bytes_written > G_MAXSIZE - vectors[i].size)
+ break;
+
+ res = iface->write_nonblocking (stream, vectors[i].buffer, vectors[i].size, &err);
+ if (res == -1)
+ {
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ /* If something was written already we handle this like a short
+ * write and assume that the next call would either give the same
+ * error again or successfully finish writing without errors or data
+ * loss
+ */
+ if (_bytes_written > 0)
+ {
+ g_clear_error (&err);
+ return G_POLLABLE_RETURN_OK;
+ }
+ else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
+ {
+ g_clear_error (&err);
+ return G_POLLABLE_RETURN_WOULD_BLOCK;
+ }
+ else
+ {
+ g_propagate_error (error, err);
+ return G_POLLABLE_RETURN_FAILED;
+ }
+ }
+
+ _bytes_written += res;
+ /* if we had a short write break the loop here */
+ if (res < vectors[i].size)
+ break;
+ }
+
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ return G_POLLABLE_RETURN_OK;
+}
+
/**
* g_pollable_output_stream_write_nonblocking:
* @stream: a #GPollableOutputStream
@@ -179,7 +246,8 @@ g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stre
* to having been cancelled.
*
* Also note that if %G_IO_ERROR_WOULD_BLOCK is returned some underlying
- * transports like D/TLS require that you send the same @buffer and @count.
+ * transports like D/TLS require that you re-send the same @buffer and
+ * @count in the next write call.
*
* Virtual: write_nonblocking
* Returns: the number of bytes written, or -1 on error (including
@@ -221,3 +289,91 @@ g_pollable_output_stream_write_nonblocking (GPollableOutputStream *stream,
return res;
}
+
+/**
+ * g_pollable_output_stream_writev_nonblocking:
+ * @stream: a #GPollableOutputStream
+ * @vectors: (array length=n_vectors): the buffer containing the #GOutputVectors to write.
+ * @n_vectors: the number of vectors to write
+ * @bytes_written: (out) (optional): location to store the number of bytes that were
+ * written to the stream
+ * @cancellable: (nullable): a #GCancellable, or %NULL
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Attempts to write the bytes contained in the @n_vectors @vectors to @stream,
+ * as with g_output_stream_writev(). If @stream is not currently writable,
+ * this will immediately return %@G_POLLABLE_RETURN_WOULD_BLOCK, and you can
+ * use g_pollable_output_stream_create_source() to create a #GSource
+ * that will be triggered when @stream is writable. @error will *not* be
+ * set in that case.
+ *
+ * Note that since this method never blocks, you cannot actually
+ * use @cancellable to cancel it. However, it will return an error
+ * if @cancellable has already been cancelled when you call, which
+ * may happen if you call this method after a source triggers due
+ * to having been cancelled.
+ *
+ * Also note that if %G_POLLABLE_RETURN_WOULD_BLOCK is returned some underlying
+ * transports like D/TLS require that you re-send the same @vectors and
+ * @n_vectors in the next write call.
+ *
+ * Virtual: writev_nonblocking
+ *
+ * Returns: %@G_POLLABLE_RETURN_OK on success, %G_POLLABLE_RETURN_WOULD_BLOCK
+ * if the stream is not currently writable (and @error is *not* set), or
+ * %G_POLLABLE_RETURN_FAILED if there was an error in which case @error will
+ * be set.
+ *
+ * Since: 2.60
+ */
+GPollableReturn
+g_pollable_output_stream_writev_nonblocking (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GPollableOutputStreamInterface *iface;
+ GPollableReturn res;
+ gsize _bytes_written = 0;
+
+ if (bytes_written)
+ *bytes_written = 0;
+
+ g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (vectors != NULL || n_vectors == 0, G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_POLLABLE_RETURN_FAILED);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return G_POLLABLE_RETURN_FAILED;
+
+ if (n_vectors == 0)
+ return G_POLLABLE_RETURN_OK;
+
+ iface = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream);
+ g_return_val_if_fail (iface->writev_nonblocking != NULL, G_POLLABLE_RETURN_FAILED);
+
+ if (cancellable)
+ g_cancellable_push_current (cancellable);
+
+ res = iface->
+ writev_nonblocking (stream, vectors, n_vectors, &_bytes_written, error);
+
+ if (cancellable)
+ g_cancellable_pop_current (cancellable);
+
+ if (res == G_POLLABLE_RETURN_FAILED)
+ g_warn_if_fail (error == NULL || (*error != NULL && !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)));
+ else if (res == G_POLLABLE_RETURN_WOULD_BLOCK)
+ g_warn_if_fail (error == NULL || *error == NULL);
+
+ /* in case of not-OK nothing must've been written */
+ g_warn_if_fail (res == G_POLLABLE_RETURN_OK || _bytes_written == 0);
+
+ if (bytes_written)
+ *bytes_written = _bytes_written;
+
+ return res;
+}
diff --git a/gio/gpollableoutputstream.h b/gio/gpollableoutputstream.h
index bf13584d5..1ef830b57 100644
--- a/gio/gpollableoutputstream.h
+++ b/gio/gpollableoutputstream.h
@@ -77,6 +77,11 @@ struct _GPollableOutputStreamInterface
const void *buffer,
gsize count,
GError **error);
+ GPollableReturn (*writev_nonblocking) (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GError **error);
};
GLIB_AVAILABLE_IN_ALL
@@ -98,6 +103,14 @@ gssize g_pollable_output_stream_write_nonblocking (GPollableOutputStream *str
GCancellable *cancellable,
GError **error);
+GLIB_AVAILABLE_IN_2_60
+GPollableReturn g_pollable_output_stream_writev_nonblocking (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
diff --git a/gio/gresource.c b/gio/gresource.c
index 2844f4808..e71db43ed 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -285,6 +285,27 @@ enumerate_overlay_dir (const gchar *candidate,
return FALSE;
}
+typedef struct {
+ gsize size;
+ guint32 flags;
+} InfoData;
+
+static gboolean
+get_overlay_info (const gchar *candidate,
+ gpointer user_data)
+{
+ InfoData *info = user_data;
+ GStatBuf buf;
+
+ if (g_stat (candidate, &buf) < 0)
+ return FALSE;
+
+ info->size = buf.st_size;
+ info->flags = G_RESOURCE_FLAGS_NONE;
+
+ return TRUE;
+}
+
static gboolean
g_resource_find_overlay (const gchar *path,
CheckCandidate check,
@@ -1251,6 +1272,17 @@ g_resources_get_info (const gchar *path,
gboolean res = FALSE;
GList *l;
gboolean r_res;
+ InfoData info;
+
+ if (g_resource_find_overlay (path, get_overlay_info, &info))
+ {
+ if (size)
+ *size = info.size;
+ if (flags)
+ *flags = info.flags;
+
+ return TRUE;
+ }
register_lazy_static_resources ();
diff --git a/gio/gsettingsbackendinternal.h b/gio/gsettingsbackendinternal.h
index 2a76a80bc..9e1d51dba 100644
--- a/gio/gsettingsbackendinternal.h
+++ b/gio/gsettingsbackendinternal.h
@@ -87,6 +87,8 @@ GType g_null_settings_backend_get_type (void);
GType g_memory_settings_backend_get_type (void);
+GType g_keyfile_settings_backend_get_type (void);
+
#ifdef HAVE_COCOA
GType g_nextstep_settings_backend_get_type (void);
#endif
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 8ceaa16d3..b1db8e645 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -151,14 +151,14 @@ static gint g_socket_datagram_based_receive_messages (GDatagramBased *self,
GInputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
static gint g_socket_datagram_based_send_messages (GDatagramBased *self,
GOutputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
static GSource *g_socket_datagram_based_create_source (GDatagramBased *self,
@@ -168,7 +168,7 @@ static GIOCondition g_socket_datagram_based_condition_check (GDatagramBased
GIOCondition condition);
static gboolean g_socket_datagram_based_condition_wait (GDatagramBased *datagram_based,
GIOCondition condition,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
@@ -183,7 +183,7 @@ g_socket_receive_message_with_timeout (GSocket *socket,
GSocketControlMessage ***messages,
gint *num_messages,
gint *flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
static gint
@@ -191,26 +191,15 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
GInputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
-static gssize
-g_socket_send_message_with_timeout (GSocket *socket,
- GSocketAddress *address,
- GOutputVector *vectors,
- gint num_vectors,
- GSocketControlMessage **messages,
- gint num_messages,
- gint flags,
- gint64 timeout,
- GCancellable *cancellable,
- GError **error);
static gint
g_socket_send_messages_with_timeout (GSocket *socket,
GOutputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
@@ -1157,7 +1146,7 @@ g_socket_datagram_based_receive_messages (GDatagramBased *self,
GInputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -1165,7 +1154,7 @@ g_socket_datagram_based_receive_messages (GDatagramBased *self,
return FALSE;
return g_socket_receive_messages_with_timeout (G_SOCKET (self), messages,
- num_messages, flags, timeout,
+ num_messages, flags, timeout_us,
cancellable, error);
}
@@ -1174,7 +1163,7 @@ g_socket_datagram_based_send_messages (GDatagramBased *self,
GOutputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -1182,7 +1171,7 @@ g_socket_datagram_based_send_messages (GDatagramBased *self,
return FALSE;
return g_socket_send_messages_with_timeout (G_SOCKET (self), messages,
- num_messages, flags, timeout,
+ num_messages, flags, timeout_us,
cancellable, error);
}
@@ -1210,7 +1199,7 @@ g_socket_datagram_based_condition_check (GDatagramBased *datagram_based,
static gboolean
g_socket_datagram_based_condition_wait (GDatagramBased *datagram_based,
GIOCondition condition,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -1218,7 +1207,7 @@ g_socket_datagram_based_condition_wait (GDatagramBased *datagram_based,
return FALSE;
return g_socket_condition_timed_wait (G_SOCKET (datagram_based), condition,
- timeout, cancellable, error);
+ timeout_us, cancellable, error);
}
/**
@@ -3017,21 +3006,21 @@ g_socket_get_available_bytes (GSocket *socket)
static gboolean
block_on_timeout (GSocket *socket,
GIOCondition condition,
- gint64 timeout,
+ gint64 timeout_us,
gint64 start_time,
GCancellable *cancellable,
GError **error)
{
gint64 wait_timeout = -1;
- g_return_val_if_fail (timeout != 0, TRUE);
+ g_return_val_if_fail (timeout_us != 0, TRUE);
/* check if we've timed out or how much time to wait at most */
- if (timeout >= 0)
+ if (timeout_us >= 0)
{
gint64 elapsed = g_get_monotonic_time () - start_time;
- if (elapsed >= timeout)
+ if (elapsed >= timeout_us)
{
g_set_error_literal (error,
G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
@@ -3039,7 +3028,7 @@ block_on_timeout (GSocket *socket,
return FALSE;
}
- wait_timeout = timeout - elapsed;
+ wait_timeout = timeout_us - elapsed;
}
return g_socket_condition_timed_wait (socket, condition, wait_timeout,
@@ -3050,7 +3039,7 @@ static gssize
g_socket_receive_with_timeout (GSocket *socket,
guint8 *buffer,
gsize size,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -3088,9 +3077,9 @@ g_socket_receive_with_timeout (GSocket *socket,
{
win32_unset_event_mask (socket, FD_READ);
- if (timeout != 0)
+ if (timeout_us != 0)
{
- if (!block_on_timeout (socket, G_IO_IN, timeout, start_time,
+ if (!block_on_timeout (socket, G_IO_IN, timeout_us, start_time,
cancellable, error))
return -1;
@@ -3249,7 +3238,7 @@ static gssize
g_socket_send_with_timeout (GSocket *socket,
const guint8 *buffer,
gsize size,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -3287,9 +3276,9 @@ g_socket_send_with_timeout (GSocket *socket,
{
win32_unset_event_mask (socket, FD_WRITE);
- if (timeout != 0)
+ if (timeout_us != 0)
{
- if (!block_on_timeout (socket, G_IO_OUT, timeout, start_time,
+ if (!block_on_timeout (socket, G_IO_OUT, timeout_us, start_time,
cancellable, error))
return -1;
@@ -4126,25 +4115,25 @@ g_socket_condition_wait (GSocket *socket,
* g_socket_condition_timed_wait:
* @socket: a #GSocket
* @condition: a #GIOCondition mask to wait for
- * @timeout: the maximum time (in microseconds) to wait, or -1
+ * @timeout_us: the maximum time (in microseconds) to wait, or -1
* @cancellable: (nullable): a #GCancellable, or %NULL
* @error: a #GError pointer, or %NULL
*
- * Waits for up to @timeout microseconds for @condition to become true
+ * Waits for up to @timeout_us microseconds for @condition to become true
* on @socket. If the condition is met, %TRUE is returned.
*
* If @cancellable is cancelled before the condition is met, or if
- * @timeout (or the socket's #GSocket:timeout) is reached before the
+ * @timeout_us (or the socket's #GSocket:timeout) is reached before the
* condition is met, then %FALSE is returned and @error, if non-%NULL,
* is set to the appropriate value (%G_IO_ERROR_CANCELLED or
* %G_IO_ERROR_TIMED_OUT).
*
* If you don't want a timeout, use g_socket_condition_wait().
- * (Alternatively, you can pass -1 for @timeout.)
+ * (Alternatively, you can pass -1 for @timeout_us.)
*
- * Note that although @timeout is in microseconds for consistency with
+ * Note that although @timeout_us is in microseconds for consistency with
* other GLib APIs, this function actually only has millisecond
- * resolution, and the behavior is undefined if @timeout is not an
+ * resolution, and the behavior is undefined if @timeout_us is not an
* exact number of milliseconds.
*
* Returns: %TRUE if the condition was met, %FALSE otherwise
@@ -4154,11 +4143,12 @@ g_socket_condition_wait (GSocket *socket,
gboolean
g_socket_condition_timed_wait (GSocket *socket,
GIOCondition condition,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
gint64 start_time;
+ gint64 timeout_ms;
g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
@@ -4169,10 +4159,12 @@ g_socket_condition_timed_wait (GSocket *socket,
return FALSE;
if (socket->priv->timeout &&
- (timeout < 0 || socket->priv->timeout < timeout / G_USEC_PER_SEC))
- timeout = (gint64) socket->priv->timeout * 1000;
- else if (timeout != -1)
- timeout = timeout / 1000;
+ (timeout_us < 0 || socket->priv->timeout < timeout_us / G_USEC_PER_SEC))
+ timeout_ms = (gint64) socket->priv->timeout * 1000;
+ else if (timeout_us != -1)
+ timeout_ms = timeout_us / 1000;
+ else
+ timeout_ms = -1;
start_time = g_get_monotonic_time ();
@@ -4195,8 +4187,8 @@ g_socket_condition_timed_wait (GSocket *socket,
if (g_cancellable_make_pollfd (cancellable, &cancel_fd))
events[num_events++] = (WSAEVENT)cancel_fd.fd;
- if (timeout == -1)
- timeout = WSA_INFINITE;
+ if (timeout_ms == -1)
+ timeout_ms = WSA_INFINITE;
g_mutex_lock (&socket->priv->win32_source_lock);
current_condition = update_condition_unlocked (socket);
@@ -4208,7 +4200,7 @@ g_socket_condition_timed_wait (GSocket *socket,
socket->priv->waiting_result = 0;
g_mutex_unlock (&socket->priv->win32_source_lock);
- res = WSAWaitForMultipleEvents (num_events, events, FALSE, timeout, FALSE);
+ res = WSAWaitForMultipleEvents (num_events, events, FALSE, timeout_ms, FALSE);
g_mutex_lock (&socket->priv->win32_source_lock);
socket->priv->waiting = FALSE;
@@ -4217,9 +4209,9 @@ g_socket_condition_timed_wait (GSocket *socket,
}
else
{
- if (timeout != WSA_INFINITE)
+ if (timeout_ms != WSA_INFINITE)
{
- if (!g_cond_wait_until (&socket->priv->win32_source_cond, &socket->priv->win32_source_lock, timeout))
+ if (!g_cond_wait_until (&socket->priv->win32_source_cond, &socket->priv->win32_source_lock, timeout_ms))
{
res = WSA_WAIT_TIMEOUT;
break;
@@ -4258,11 +4250,11 @@ g_socket_condition_timed_wait (GSocket *socket,
current_condition = update_condition_unlocked (socket);
- if (timeout != WSA_INFINITE)
+ if (timeout_ms != WSA_INFINITE)
{
- timeout -= (g_get_monotonic_time () - start_time) * 1000;
- if (timeout < 0)
- timeout = 0;
+ timeout_ms -= (g_get_monotonic_time () - start_time) * 1000;
+ if (timeout_ms < 0)
+ timeout_ms = 0;
}
}
g_mutex_unlock (&socket->priv->win32_source_lock);
@@ -4288,16 +4280,16 @@ g_socket_condition_timed_wait (GSocket *socket,
while (TRUE)
{
int errsv;
- result = g_poll (poll_fd, num, timeout);
+ result = g_poll (poll_fd, num, timeout_ms);
errsv = errno;
if (result != -1 || errsv != EINTR)
break;
- if (timeout != -1)
+ if (timeout_ms != -1)
{
- timeout -= (g_get_monotonic_time () - start_time) / 1000;
- if (timeout < 0)
- timeout = 0;
+ timeout_ms -= (g_get_monotonic_time () - start_time) / 1000;
+ if (timeout_ms < 0)
+ timeout_ms = 0;
}
}
@@ -4548,7 +4540,7 @@ input_message_from_msghdr (const struct msghdr *msg,
* @messages: (array length=num_messages) (nullable): a pointer to an
* array of #GSocketControlMessages, or %NULL.
* @num_messages: number of elements in @messages, or -1.
- * @flags: an int containing #GSocketMsgFlags flags
+ * @flags: (type GSocketMsgFlags): an int containing #GSocketMsgFlags flags
* @cancellable: (nullable): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
@@ -4606,22 +4598,61 @@ g_socket_send_message (GSocket *socket,
GCancellable *cancellable,
GError **error)
{
- return g_socket_send_message_with_timeout (socket, address,
- vectors, num_vectors,
- messages, num_messages, flags,
- socket->priv->blocking ? -1 : 0,
- cancellable, error);
+ GPollableReturn res;
+ gsize bytes_written = 0;
+
+ res = g_socket_send_message_with_timeout (socket, address,
+ vectors, num_vectors,
+ messages, num_messages, flags,
+ socket->priv->blocking ? -1 : 0,
+ &bytes_written,
+ cancellable, error);
+
+ if (res == G_POLLABLE_RETURN_WOULD_BLOCK)
+ socket_set_error_lazy (error, EWOULDBLOCK, _("Error sending message: %s"));
+
+ return res == G_POLLABLE_RETURN_OK ? bytes_written : -1;
}
-static gssize
+/**
+ * g_socket_send_message_with_timeout:
+ * @socket: a #GSocket
+ * @address: (nullable): a #GSocketAddress, or %NULL
+ * @vectors: (array length=num_vectors): an array of #GOutputVector structs
+ * @num_vectors: the number of elements in @vectors, or -1
+ * @messages: (array length=num_messages) (nullable): a pointer to an
+ * array of #GSocketControlMessages, or %NULL.
+ * @num_messages: number of elements in @messages, or -1.
+ * @flags: (type GSocketMsgFlags): an int containing #GSocketMsgFlags flags
+ * @timeout_us: the maximum time (in microseconds) to wait, or -1
+ * @bytes_written: (out) (optional): location to store the number of bytes that were written to the socket
+ * @cancellable: (nullable): a %GCancellable or %NULL
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * This behaves exactly the same as g_socket_send_message(), except that
+ * the choice of timeout behavior is determined by the @timeout_us argument
+ * rather than by @socket's properties.
+ *
+ * On error %G_POLLABLE_RETURN_FAILED is returned and @error is set accordingly, or
+ * if the socket is currently not writable %G_POLLABLE_RETURN_WOULD_BLOCK is
+ * returned. @bytes_written will contain 0 in both cases.
+ *
+ * Returns: %G_POLLABLE_RETURN_OK if all data was successfully written,
+ * %G_POLLABLE_RETURN_WOULD_BLOCK if the socket is currently not writable, or
+ * %G_POLLABLE_RETURN_FAILED if an error happened and @error is set.
+ *
+ * Since: 2.60
+ */
+GPollableReturn
g_socket_send_message_with_timeout (GSocket *socket,
GSocketAddress *address,
- GOutputVector *vectors,
+ const GOutputVector *vectors,
gint num_vectors,
GSocketControlMessage **messages,
gint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
+ gsize *bytes_written,
GCancellable *cancellable,
GError **error)
{
@@ -4629,23 +4660,26 @@ g_socket_send_message_with_timeout (GSocket *socket,
char zero;
gint64 start_time;
- g_return_val_if_fail (G_IS_SOCKET (socket), -1);
- g_return_val_if_fail (address == NULL || G_IS_SOCKET_ADDRESS (address), -1);
- g_return_val_if_fail (num_vectors == 0 || vectors != NULL, -1);
- g_return_val_if_fail (num_messages == 0 || messages != NULL, -1);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
- g_return_val_if_fail (error == NULL || *error == NULL, -1);
+ if (bytes_written)
+ *bytes_written = 0;
+
+ g_return_val_if_fail (G_IS_SOCKET (socket), G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (address == NULL || G_IS_SOCKET_ADDRESS (address), G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (num_vectors == 0 || vectors != NULL, G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (num_messages == 0 || messages != NULL, G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_POLLABLE_RETURN_FAILED);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_POLLABLE_RETURN_FAILED);
start_time = g_get_monotonic_time ();
if (!check_socket (socket, error))
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
if (!check_timeout (socket, error))
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
if (num_vectors == -1)
{
@@ -4681,7 +4715,7 @@ g_socket_send_message_with_timeout (GSocket *socket,
GError *child_error = NULL;
output_message.address = address;
- output_message.vectors = vectors;
+ output_message.vectors = (GOutputVector *) vectors;
output_message.num_vectors = num_vectors;
output_message.bytes_sent = 0;
output_message.control_messages = messages;
@@ -4692,7 +4726,7 @@ g_socket_send_message_with_timeout (GSocket *socket,
if (child_error != NULL)
{
g_propagate_error (error, child_error);
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
}
while (1)
@@ -4705,24 +4739,30 @@ g_socket_send_message_with_timeout (GSocket *socket,
if (errsv == EINTR)
continue;
- if (timeout != 0 &&
- (errsv == EWOULDBLOCK ||
- errsv == EAGAIN))
+ if (errsv == EWOULDBLOCK || errsv == EAGAIN)
{
- if (!block_on_timeout (socket, G_IO_OUT, timeout, start_time,
- cancellable, error))
- return -1;
+ if (timeout_us != 0)
+ {
+ if (!block_on_timeout (socket, G_IO_OUT, timeout_us, start_time,
+ cancellable, error))
+ return G_POLLABLE_RETURN_FAILED;
- continue;
+ continue;
+ }
+
+ return G_POLLABLE_RETURN_WOULD_BLOCK;
}
- socket_set_error_lazy (error, errsv, _("Error sending message: %s"));
- return -1;
+ socket_set_error_lazy (error, errsv, _("Error sending message: %s"));
+ return G_POLLABLE_RETURN_FAILED;
}
break;
}
- return result;
+ if (bytes_written)
+ *bytes_written = result;
+
+ return G_POLLABLE_RETURN_OK;
}
#else
{
@@ -4741,7 +4781,7 @@ g_socket_send_message_with_timeout (GSocket *socket,
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("GSocketControlMessage not supported on Windows"));
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
}
/* iov */
@@ -4758,7 +4798,7 @@ g_socket_send_message_with_timeout (GSocket *socket,
{
addrlen = g_socket_address_get_native_size (address);
if (!g_socket_address_to_native (address, &addr, sizeof addr, error))
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
}
while (1)
@@ -4786,23 +4826,27 @@ g_socket_send_message_with_timeout (GSocket *socket,
{
win32_unset_event_mask (socket, FD_WRITE);
- if (timeout != 0)
+ if (timeout_us != 0)
{
- if (!block_on_timeout (socket, G_IO_OUT, timeout,
+ if (!block_on_timeout (socket, G_IO_OUT, timeout_us,
start_time, cancellable, error))
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
continue;
}
+
+ return G_POLLABLE_RETURN_WOULD_BLOCK;
}
socket_set_error_lazy (error, errsv, _("Error sending message: %s"));
- return -1;
+ return G_POLLABLE_RETURN_FAILED;
}
break;
}
- return bytes_sent;
+ if (bytes_written)
+ *bytes_written = bytes_sent;
+ return G_POLLABLE_RETURN_OK;
}
#endif
}
@@ -4812,7 +4856,7 @@ g_socket_send_message_with_timeout (GSocket *socket,
* @socket: a #GSocket
* @messages: (array length=num_messages): an array of #GOutputMessage structs
* @num_messages: the number of elements in @messages
- * @flags: an int containing #GSocketMsgFlags flags
+ * @flags: (type GSocketMsgFlags): an int containing #GSocketMsgFlags flags
* @cancellable: (nullable): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore.
*
@@ -4877,7 +4921,7 @@ g_socket_send_messages_with_timeout (GSocket *socket,
GOutputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -4951,11 +4995,11 @@ g_socket_send_messages_with_timeout (GSocket *socket,
if (errsv == EINTR)
continue;
- if (timeout != 0 &&
+ if (timeout_us != 0 &&
(errsv == EWOULDBLOCK ||
errsv == EAGAIN))
{
- if (!block_on_timeout (socket, G_IO_OUT, timeout, start_time,
+ if (!block_on_timeout (socket, G_IO_OUT, timeout_us, start_time,
cancellable, error))
{
if (num_sent > 0)
@@ -4993,26 +5037,34 @@ g_socket_send_messages_with_timeout (GSocket *socket,
gint i;
gint64 wait_timeout;
- wait_timeout = timeout;
+ wait_timeout = timeout_us;
for (i = 0; i < num_messages; ++i)
{
GOutputMessage *msg = &messages[i];
GError *msg_error = NULL;
+ GPollableReturn pollable_result;
+ gsize bytes_written = 0;
- result = g_socket_send_message_with_timeout (socket, msg->address,
- msg->vectors,
- msg->num_vectors,
- msg->control_messages,
- msg->num_control_messages,
- flags, wait_timeout,
- cancellable, &msg_error);
+ pollable_result = g_socket_send_message_with_timeout (socket, msg->address,
+ msg->vectors,
+ msg->num_vectors,
+ msg->control_messages,
+ msg->num_control_messages,
+ flags, wait_timeout,
+ &bytes_written,
+ cancellable, &msg_error);
+
+ if (pollable_result == G_POLLABLE_RETURN_WOULD_BLOCK)
+ socket_set_error_lazy (&msg_error, EWOULDBLOCK, _("Error sending message: %s"));
+
+ result = pollable_result == G_POLLABLE_RETURN_OK ? bytes_written : -1;
/* check if we've timed out or how much time to wait at most */
- if (timeout > 0)
+ if (timeout_us > 0)
{
gint64 elapsed = g_get_monotonic_time () - start_time;
- wait_timeout = MAX (timeout - elapsed, 1);
+ wait_timeout = MAX (timeout_us - elapsed, 1);
}
if (result < 0)
@@ -5101,7 +5153,7 @@ g_socket_receive_message_with_timeout (GSocket *socket,
GSocketControlMessage ***messages,
gint *num_messages,
gint *flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -5182,11 +5234,11 @@ g_socket_receive_message_with_timeout (GSocket *socket,
if (errsv == EINTR)
continue;
- if (timeout != 0 &&
+ if (timeout_us != 0 &&
(errsv == EWOULDBLOCK ||
errsv == EAGAIN))
{
- if (!block_on_timeout (socket, G_IO_IN, timeout, start_time,
+ if (!block_on_timeout (socket, G_IO_IN, timeout_us, start_time,
cancellable, error))
return -1;
@@ -5256,9 +5308,9 @@ g_socket_receive_message_with_timeout (GSocket *socket,
{
win32_unset_event_mask (socket, FD_READ);
- if (timeout != 0)
+ if (timeout_us != 0)
{
- if (!block_on_timeout (socket, G_IO_IN, timeout,
+ if (!block_on_timeout (socket, G_IO_IN, timeout_us,
start_time, cancellable, error))
return -1;
@@ -5298,7 +5350,7 @@ g_socket_receive_message_with_timeout (GSocket *socket,
* @socket: a #GSocket
* @messages: (array length=num_messages): an array of #GInputMessage structs
* @num_messages: the number of elements in @messages
- * @flags: an int containing #GSocketMsgFlags flags for the overall operation
+ * @flags: (type GSocketMsgFlags): an int containing #GSocketMsgFlags flags for the overall operation
* @cancellable: (nullable): a %GCancellable or %NULL
* @error: #GError for error reporting, or %NULL to ignore
*
@@ -5382,7 +5434,7 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
GInputMessage *messages,
guint num_messages,
gint flags,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error)
{
@@ -5469,11 +5521,11 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
if (errsv == EINTR)
continue;
- if (timeout != 0 &&
+ if (timeout_us != 0 &&
(errsv == EWOULDBLOCK ||
errsv == EAGAIN))
{
- if (!block_on_timeout (socket, G_IO_IN, timeout, start_time,
+ if (!block_on_timeout (socket, G_IO_IN, timeout_us, start_time,
cancellable, error))
{
if (num_received > 0)
@@ -5519,7 +5571,7 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
guint i;
gint64 wait_timeout;
- wait_timeout = timeout;
+ wait_timeout = timeout_us;
for (i = 0; i < num_messages; i++)
{
@@ -5541,10 +5593,10 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
&msg_error);
/* check if we've timed out or how much time to wait at most */
- if (timeout > 0)
+ if (timeout_us > 0)
{
gint64 elapsed = g_get_monotonic_time () - start_time;
- wait_timeout = MAX (timeout - elapsed, 1);
+ wait_timeout = MAX (timeout_us - elapsed, 1);
}
if (len >= 0)
@@ -5584,7 +5636,7 @@ g_socket_receive_messages_with_timeout (GSocket *socket,
* which may be filled with an array of #GSocketControlMessages, or %NULL
* @num_messages: (out): a pointer which will be filled with the number of
* elements in @messages, or %NULL
- * @flags: (inout): a pointer to an int containing #GSocketMsgFlags flags
+ * @flags: (type GSocketMsgFlags): (inout): a pointer to an int containing #GSocketMsgFlags flags
* @cancellable: a %GCancellable or %NULL
* @error: a #GError pointer, or %NULL
*
diff --git a/gio/gsocket.h b/gio/gsocket.h
index a65cbc22f..97411355d 100644
--- a/gio/gsocket.h
+++ b/gio/gsocket.h
@@ -192,7 +192,7 @@ gboolean g_socket_condition_wait (GSocket
GLIB_AVAILABLE_IN_2_32
gboolean g_socket_condition_timed_wait (GSocket *socket,
GIOCondition condition,
- gint64 timeout,
+ gint64 timeout_us,
GCancellable *cancellable,
GError **error);
GLIB_AVAILABLE_IN_ALL
@@ -298,7 +298,18 @@ gssize g_socket_send_with_blocking (GSocket
gboolean blocking,
GCancellable *cancellable,
GError **error);
-
+GLIB_AVAILABLE_IN_2_60
+GPollableReturn g_socket_send_message_with_timeout (GSocket *socket,
+ GSocketAddress *address,
+ const GOutputVector *vectors,
+ gint num_vectors,
+ GSocketControlMessage **messages,
+ gint num_messages,
+ gint flags,
+ gint64 timeout_us,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
GLIB_AVAILABLE_IN_2_36
gboolean g_socket_get_option (GSocket *socket,
gint level,
diff --git a/gio/gsocketoutputstream.c b/gio/gsocketoutputstream.c
index de1f4226b..fcca56efc 100644
--- a/gio/gsocketoutputstream.c
+++ b/gio/gsocketoutputstream.c
@@ -125,14 +125,43 @@ g_socket_output_stream_write (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
- GSocketOutputStream *onput_stream = G_SOCKET_OUTPUT_STREAM (stream);
+ GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (stream);
- return g_socket_send_with_blocking (onput_stream->priv->socket,
+ return g_socket_send_with_blocking (output_stream->priv->socket,
buffer, count, TRUE,
cancellable, error);
}
static gboolean
+g_socket_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (stream);
+ GPollableReturn res;
+
+ /* Clamp the number of vectors if more given than we can write in one go.
+ * The caller has to handle short writes anyway.
+ */
+ if (n_vectors > G_MAXINT)
+ n_vectors = G_MAXINT;
+
+ res = g_socket_send_message_with_timeout (output_stream->priv->socket, NULL,
+ vectors, n_vectors,
+ NULL, 0, G_SOCKET_MSG_NONE,
+ -1, bytes_written,
+ cancellable, error);
+
+ /* we have a non-zero timeout so this can't happen */
+ g_assert (res != G_POLLABLE_RETURN_WOULD_BLOCK);
+
+ return res == G_POLLABLE_RETURN_OK;
+}
+
+static gboolean
g_socket_output_stream_pollable_is_writable (GPollableOutputStream *pollable)
{
GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (pollable);
@@ -153,6 +182,27 @@ g_socket_output_stream_pollable_write_nonblocking (GPollableOutputStream *polla
NULL, error);
}
+static GPollableReturn
+g_socket_output_stream_pollable_writev_nonblocking (GPollableOutputStream *pollable,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GError **error)
+{
+ GSocketOutputStream *output_stream = G_SOCKET_OUTPUT_STREAM (pollable);
+
+ /* Clamp the number of vectors if more given than we can write in one go.
+ * The caller has to handle short writes anyway.
+ */
+ if (n_vectors > G_MAXINT)
+ n_vectors = G_MAXINT;
+
+ return g_socket_send_message_with_timeout (output_stream->priv->socket,
+ NULL, vectors, n_vectors,
+ NULL, 0, G_SOCKET_MSG_NONE, 0,
+ bytes_written, NULL, error);
+}
+
static GSource *
g_socket_output_stream_pollable_create_source (GPollableOutputStream *pollable,
GCancellable *cancellable)
@@ -191,6 +241,7 @@ g_socket_output_stream_class_init (GSocketOutputStreamClass *klass)
gobject_class->set_property = g_socket_output_stream_set_property;
goutputstream_class->write_fn = g_socket_output_stream_write;
+ goutputstream_class->writev_fn = g_socket_output_stream_writev;
g_object_class_install_property (gobject_class, PROP_SOCKET,
g_param_spec_object ("socket",
@@ -214,6 +265,7 @@ g_socket_output_stream_pollable_iface_init (GPollableOutputStreamInterface *ifac
iface->is_writable = g_socket_output_stream_pollable_is_writable;
iface->create_source = g_socket_output_stream_pollable_create_source;
iface->write_nonblocking = g_socket_output_stream_pollable_write_nonblocking;
+ iface->writev_nonblocking = g_socket_output_stream_pollable_writev_nonblocking;
}
static void
diff --git a/gio/gtask.c b/gio/gtask.c
index a2f316d2e..aa98f752c 100644
--- a/gio/gtask.c
+++ b/gio/gtask.c
@@ -1132,7 +1132,8 @@ g_task_get_check_cancellable (GTask *task)
{
g_return_val_if_fail (G_IS_TASK (task), FALSE);
- return task->check_cancellable;
+ /* Convert from a bit field to a boolean. */
+ return task->check_cancellable ? TRUE : FALSE;
}
/**
@@ -1149,7 +1150,8 @@ g_task_get_return_on_cancel (GTask *task)
{
g_return_val_if_fail (G_IS_TASK (task), FALSE);
- return task->return_on_cancel;
+ /* Convert from a bit field to a boolean. */
+ return task->return_on_cancel ? TRUE : FALSE;
}
/**
@@ -1952,7 +1954,8 @@ g_task_get_completed (GTask *task)
{
g_return_val_if_fail (G_IS_TASK (task), FALSE);
- return task->completed;
+ /* Convert from a bit field to a boolean. */
+ return task->completed ? TRUE : FALSE;
}
/**
@@ -2055,7 +2058,7 @@ g_task_get_property (GObject *object,
switch ((GTaskProperty) prop_id)
{
case PROP_COMPLETED:
- g_value_set_boolean (value, task->completed);
+ g_value_set_boolean (value, g_task_get_completed (task));
break;
}
}
diff --git a/gio/gtlsconnection.c b/gio/gtlsconnection.c
index a1e98c0c9..02a3098c1 100644
--- a/gio/gtlsconnection.c
+++ b/gio/gtlsconnection.c
@@ -323,8 +323,8 @@ g_tls_connection_class_init (GTlsConnectionClass *klass)
* let the user decide whether or not to accept the certificate, you
* would have to return %FALSE from the signal handler on the first
* attempt, and then after the connection attempt returns a
- * %G_TLS_ERROR_HANDSHAKE, you can interact with the user, and if
- * the user decides to accept the certificate, remember that fact,
+ * %G_TLS_ERROR_BAD_CERTIFICATE, you can interact with the user, and
+ * if the user decides to accept the certificate, remember that fact,
* create a new connection, and return %TRUE from the signal handler
* the next time.
*
diff --git a/gio/gunixoutputstream.c b/gio/gunixoutputstream.c
index 3cf96cf19..5536e00b4 100644
--- a/gio/gunixoutputstream.c
+++ b/gio/gunixoutputstream.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
+#include <sys/uio.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -91,6 +92,12 @@ static gssize g_unix_output_stream_write (GOutputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error);
+static gboolean g_unix_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error);
static gboolean g_unix_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
@@ -107,6 +114,11 @@ static gboolean g_unix_output_stream_pollable_can_poll (GPollableOutputStre
static gboolean g_unix_output_stream_pollable_is_writable (GPollableOutputStream *stream);
static GSource *g_unix_output_stream_pollable_create_source (GPollableOutputStream *stream,
GCancellable *cancellable);
+static GPollableReturn g_unix_output_stream_pollable_writev_nonblocking (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GError **error);
static void
g_unix_output_stream_class_init (GUnixOutputStreamClass *klass)
@@ -118,6 +130,7 @@ g_unix_output_stream_class_init (GUnixOutputStreamClass *klass)
gobject_class->set_property = g_unix_output_stream_set_property;
stream_class->write_fn = g_unix_output_stream_write;
+ stream_class->writev_fn = g_unix_output_stream_writev;
stream_class->close_fn = g_unix_output_stream_close;
stream_class->close_async = g_unix_output_stream_close_async;
stream_class->close_finish = g_unix_output_stream_close_finish;
@@ -159,6 +172,7 @@ g_unix_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface)
iface->can_poll = g_unix_output_stream_pollable_can_poll;
iface->is_writable = g_unix_output_stream_pollable_is_writable;
iface->create_source = g_unix_output_stream_pollable_create_source;
+ iface->writev_nonblocking = g_unix_output_stream_pollable_writev_nonblocking;
}
static void
@@ -325,19 +339,18 @@ g_unix_output_stream_write (GOutputStream *stream,
GUnixOutputStream *unix_stream;
gssize res = -1;
GPollFD poll_fds[2];
- int nfds;
+ int nfds = 0;
int poll_ret;
unix_stream = G_UNIX_OUTPUT_STREAM (stream);
poll_fds[0].fd = unix_stream->priv->fd;
poll_fds[0].events = G_IO_OUT;
+ nfds++;
if (unix_stream->priv->is_pipe_or_socket &&
g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
- nfds = 2;
- else
- nfds = 1;
+ nfds++;
while (1)
{
@@ -387,6 +400,116 @@ g_unix_output_stream_write (GOutputStream *stream,
return res;
}
+/* Macro to check if struct iovec and GOutputVector have the same ABI */
+#define G_OUTPUT_VECTOR_IS_IOVEC (sizeof (struct iovec) == sizeof (GOutputVector) && \
+ sizeof ((struct iovec *) 0)->iov_base == sizeof ((GOutputVector *) 0)->buffer && \
+ G_STRUCT_OFFSET (struct iovec, iov_base) == G_STRUCT_OFFSET (GOutputVector, buffer) && \
+ sizeof ((struct iovec *) 0)->iov_len == sizeof((GOutputVector *) 0)->size && \
+ G_STRUCT_OFFSET (struct iovec, iov_len) == G_STRUCT_OFFSET (GOutputVector, size))
+
+static gboolean
+g_unix_output_stream_writev (GOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GUnixOutputStream *unix_stream;
+ gssize res = -1;
+ GPollFD poll_fds[2];
+ int nfds = 0;
+ int poll_ret;
+ struct iovec *iov;
+
+ if (bytes_written)
+ *bytes_written = 0;
+
+ /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
+ * We handle this like a short write in this case
+ */
+ if (n_vectors > G_MAXINT)
+ n_vectors = G_MAXINT;
+
+ unix_stream = G_UNIX_OUTPUT_STREAM (stream);
+
+ if (G_OUTPUT_VECTOR_IS_IOVEC)
+ {
+ /* ABI is compatible */
+ iov = (struct iovec *) vectors;
+ }
+ else
+ {
+ gsize i;
+
+ /* ABI is incompatible */
+ iov = g_newa (struct iovec, n_vectors);
+ for (i = 0; i < n_vectors; i++)
+ {
+ iov[i].iov_base = (void *)vectors[i].buffer;
+ iov[i].iov_len = vectors[i].size;
+ }
+ }
+
+ poll_fds[0].fd = unix_stream->priv->fd;
+ poll_fds[0].events = G_IO_OUT;
+ nfds++;
+
+ if (unix_stream->priv->is_pipe_or_socket &&
+ g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
+ nfds++;
+
+ while (1)
+ {
+ int errsv;
+
+ poll_fds[0].revents = poll_fds[1].revents = 0;
+ do
+ {
+ poll_ret = g_poll (poll_fds, nfds, -1);
+ errsv = errno;
+ }
+ while (poll_ret == -1 && errsv == EINTR);
+
+ if (poll_ret == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error writing to file descriptor: %s"),
+ g_strerror (errsv));
+ break;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ break;
+
+ if (!poll_fds[0].revents)
+ continue;
+
+ res = writev (unix_stream->priv->fd, iov, n_vectors);
+ errsv = errno;
+ if (res == -1)
+ {
+ if (errsv == EINTR || errsv == EAGAIN)
+ continue;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error writing to file descriptor: %s"),
+ g_strerror (errsv));
+ }
+
+ if (bytes_written)
+ *bytes_written = res;
+
+ break;
+ }
+
+ if (nfds == 2)
+ g_cancellable_release_fd (cancellable);
+ return res != -1;
+}
+
static gboolean
g_unix_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
@@ -494,3 +617,70 @@ g_unix_output_stream_pollable_create_source (GPollableOutputStream *stream,
return pollable_source;
}
+
+static GPollableReturn
+g_unix_output_stream_pollable_writev_nonblocking (GPollableOutputStream *stream,
+ const GOutputVector *vectors,
+ gsize n_vectors,
+ gsize *bytes_written,
+ GError **error)
+{
+ GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream);
+ struct iovec *iov;
+ gssize res = -1;
+
+ if (!g_pollable_output_stream_is_writable (stream))
+ {
+ *bytes_written = 0;
+ return G_POLLABLE_RETURN_WOULD_BLOCK;
+ }
+
+ /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors.
+ * We handle this like a short write in this case
+ */
+ if (n_vectors > G_MAXINT)
+ n_vectors = G_MAXINT;
+
+ if (G_OUTPUT_VECTOR_IS_IOVEC)
+ {
+ /* ABI is compatible */
+ iov = (struct iovec *) vectors;
+ }
+ else
+ {
+ gsize i;
+
+ /* ABI is incompatible */
+ iov = g_newa (struct iovec, n_vectors);
+ for (i = 0; i < n_vectors; i++)
+ {
+ iov[i].iov_base = (void *)vectors[i].buffer;
+ iov[i].iov_len = vectors[i].size;
+ }
+ }
+
+ while (1)
+ {
+ int errsv;
+
+ res = writev (unix_stream->priv->fd, iov, n_vectors);
+ errsv = errno;
+ if (res == -1)
+ {
+ if (errsv == EINTR)
+ continue;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error writing to file descriptor: %s"),
+ g_strerror (errsv));
+ }
+
+ if (bytes_written)
+ *bytes_written = res;
+
+ break;
+ }
+
+ return res != -1 ? G_POLLABLE_RETURN_OK : G_POLLABLE_RETURN_FAILED;
+}
diff --git a/gio/gwin32appinfo.c b/gio/gwin32appinfo.c
index 499bbb351..9f335b370 100644
--- a/gio/gwin32appinfo.c
+++ b/gio/gwin32appinfo.c
@@ -1426,7 +1426,7 @@ collect_capable_apps_from_clients (GPtrArray *capable_apps,
GWin32RegistrySubkeyIter subkey_iter;
GWin32RegistryKey *system_client_type;
GWin32RegistryValueType default_type;
- gunichar2 *default_value;
+ gunichar2 *default_value = NULL;
gunichar2 *client_name;
gsize client_name_len;
diff --git a/gio/inotify/Makefile.am b/gio/inotify/Makefile.am
deleted file mode 100644
index 6dd9136b4..000000000
--- a/gio/inotify/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-noinst_LTLIBRARIES += libinotify.la
-
-libinotify_la_SOURCES = \
- inotify-kernel.c \
- inotify-sub.c \
- inotify-path.c \
- inotify-missing.c \
- inotify-helper.c \
- inotify-kernel.h \
- inotify-missing.h \
- inotify-path.h \
- inotify-sub.h \
- inotify-helper.h \
- ginotifyfilemonitor.c \
- ginotifyfilemonitor.h \
- $(NULL)
-
-libinotify_la_CFLAGS = \
- $(GLIB_HIDDEN_VISIBILITY_CFLAGS) \
- -DG_LOG_DOMAIN=\"GLib-GIO\" \
- $(gio_INCLUDES) \
- $(GLIB_DEBUG_FLAGS) \
- -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
- -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/kqueue/Makefile.am b/gio/kqueue/Makefile.am
deleted file mode 100644
index 24e9724e5..000000000
--- a/gio/kqueue/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-noinst_LTLIBRARIES += libkqueue.la
-
-libkqueue_la_SOURCES = \
- gkqueuefilemonitor.c \
- kqueue-helper.c \
- kqueue-helper.h \
- kqueue-missing.c \
- dep-list.c \
- dep-list.h \
- $(NULL)
-
-libkqueue_la_CFLAGS = \
- $(GLIB_HIDDEN_VISIBILITY_CFLAGS) \
- -DG_LOG_DOMAIN=\"GLib-GIO\" \
- $(gio_INCLUDES) \
- $(GLIB_DEBUG_FLAGS) \
- -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
- -DGIO_COMPILATION \
- -DG_DISABLE_DEPRECATED
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am
deleted file mode 100644
index e8baa0101..000000000
--- a/gio/tests/Makefile.am
+++ /dev/null
@@ -1,709 +0,0 @@
-include $(top_srcdir)/glib-tap.mk
-
-dist_uninstalled_test_data =
-test_ltlibraries =
-
-SUBDIRS = gdbus-object-manager-example services modules
-
-LDADD = \
- $(top_builddir)/gio/libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-
-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= \
- GIO_LAUNCH_DESKTOP="$(top_builddir)/gio/gio-launch-desktop"
-
-# -----------------------------------------------------------------------------
-# Test programs buildable on all platforms
-
-test_programs = \
- appmonitor \
- async-close-output-stream \
- async-splice-output-stream \
- buffered-input-stream \
- buffered-output-stream \
- cancellable \
- contexts \
- contenttype \
- converter-stream \
- credentials \
- data-input-stream \
- data-output-stream \
- fileattributematcher \
- filter-streams \
- giomodule \
- gsubprocess \
- g-file \
- g-file-info \
- g-icon \
- gdbus-addresses \
- gdbus-message \
- inet-address \
- io-stream \
- memory-input-stream \
- memory-output-stream \
- monitor \
- mount-operation \
- network-monitor \
- network-monitor-race \
- permission \
- pollable \
- proxy-test \
- readwrite \
- simple-async-result \
- simple-proxy \
- sleepy-stream \
- socket \
- socket-listener \
- socket-service \
- srvtarget \
- task \
- tls-database \
- tls-interaction \
- vfs \
- volumemonitor \
- glistmodel \
- testfilemonitor \
- $(NULL)
-
-uninstalled_test_programs = \
- $(NULL)
-
-dist_test_data = \
- contexts.c \
- g-icon.c \
- $(NULL)
-
-test_data = \
- $(NULL)
-
-uninstalled_test_extra_programs = \
- gio-du \
- echo-server \
- filter-cat \
- gapplication-example-actions \
- gapplication-example-cmdline \
- gapplication-example-cmdline2 \
- gapplication-example-cmdline3 \
- gapplication-example-cmdline4 \
- gapplication-example-dbushooks \
- gapplication-example-open \
- gdbus-example-export \
- gdbus-example-own-name \
- gdbus-example-peer \
- gdbus-example-proxy-subclass \
- gdbus-example-server \
- gdbus-example-subtree \
- gdbus-example-watch-name \
- gdbus-example-watch-proxy \
- gsubprocess-testprog \
- httpd \
- proxy \
- resolver \
- send-data \
- socket-server \
- $(NULL)
-
-test_extra_programs = \
- gdbus-connection-flush-helper \
- gdbus-testserver \
- $(NULL)
-
-dist_uninstalled_test_data += $(addprefix schema-tests/,$(schema_tests))
-schema_tests = \
- array-default-not-in-choices.gschema.xml \
- bad-choice.gschema.xml \
- bad-key.gschema.xml \
- bad-key2.gschema.xml \
- bad-key3.gschema.xml \
- bad-key4.gschema.xml \
- bad-type.gschema.xml \
- bare-alias.gschema.xml \
- choice-alias.gschema.xml \
- choice-bad.gschema.xml \
- choice-badtype.gschema.xml \
- choice-invalid-alias.gschema.xml \
- choice-missing-value.gschema.xml \
- choice-shadowed-alias.gschema.xml \
- choice-upside-down.gschema.xml \
- choice.gschema.xml \
- choices-wrong-type.gschema.xml \
- default-in-aliases.gschema.xml \
- default-not-in-choices.gschema.xml \
- default-out-of-range.gschema.xml \
- description-xmllang.gschema.xml \
- empty-key.gschema.xml \
- enum-with-aliases.gschema.xml \
- enum-with-bad-default.gschema.xml \
- enum-with-chained-alias.gschema.xml \
- enum-with-choice.gschema.xml \
- enum-with-invalid-alias.gschema.xml \
- enum-with-invalid-value.gschema.xml \
- enum-with-repeated-alias.gschema.xml \
- enum-with-repeated-nick.gschema.xml \
- enum-with-repeated-value.gschema.xml \
- enum-with-shadow-alias.gschema.xml \
- enum.gschema.xml \
- extend-and-shadow-indirect.gschema.xml \
- extend-and-shadow.gschema.xml \
- extend-missing.gschema.xml \
- extend-nonlist.gschema.xml \
- extend-self.gschema.xml \
- extend-wrong-list-indirect.gschema.xml \
- extend-wrong-list.gschema.xml \
- extending.gschema.xml \
- flags-aliased-default.gschema.xml \
- flags-bad-default.gschema.xml \
- flags-more-than-one-bit.gschema.xml \
- flags-with-enum-attr.gschema.xml \
- flags-with-enum-tag.gschema.xml \
- from-docs.gschema.xml \
- incomplete-list.gschema.xml \
- inherit-gettext-domain.gschema.xml \
- invalid-path.gschema.xml \
- key-in-list-indirect.gschema.xml \
- key-in-list.gschema.xml \
- list-of-missing.gschema.xml \
- missing-quotes.gschema.xml \
- no-default.gschema.xml \
- overflow.gschema.xml \
- override-missing.gschema.xml \
- override-range-error.gschema.xml \
- override-then-key.gschema.xml \
- override-twice.gschema.xml \
- override-type-error.gschema.xml \
- override.gschema.xml \
- range-badtype.gschema.xml \
- range-default-high.gschema.xml \
- range-default-low.gschema.xml \
- range-high-default.gschema.xml \
- range-low-default.gschema.xml \
- range-missing-max.gschema.xml \
- range-missing-min.gschema.xml \
- range-parse-error.gschema.xml \
- range-wrong-type.gschema.xml \
- range.gschema.xml \
- summary-xmllang.gschema.xml \
- summary-xmllang-and-attrs.gschema.xml \
- wrong-category.gschema.xml \
- $(NULL)
-
-test_programs += network-address
-network_address_SOURCES = \
- network-address.c \
- mock-resolver.c \
- mock-resolver.h
-
-test_programs += thumbnail-verification
-dist_test_data += $(thumbnail_data_files)
-thumbnail_data_files = $(addprefix thumbnails/,$(thumbnail_tests))
-thumbnail_tests = \
- bad-header.png \
- empty-key.png \
- header-and-chunk-size.png \
- header-only.png \
- huge-chunk-size.png \
- mtime-zero.png \
- no-text-data.png \
- overlong-value.png \
- uri-mismatch.png \
- valid.png \
- valid-no-size.png \
- $(NULL)
-
-test_programs += tls-certificate
-tls_certificate_SOURCES = \
- tls-certificate.c \
- gtesttlsbackend.c \
- gtesttlsbackend.h
-dist_test_data += $(cert_data_files)
-cert_data_files = $(addprefix cert-tests/,$(cert_tests))
-cert_tests = \
- cert1.pem \
- cert2.pem \
- cert3.pem \
- cert-crlf.pem \
- cert-key.pem \
- cert-list.pem \
- key8.pem \
- key8enc.pem \
- key-cert.pem \
- key.pem \
- key-crlf.pem \
- key_missing-footer.pem \
- key_missing-header.pem \
- nothing.pem \
- $(NULL)
-
-uninstalled_test_extra_programs += socket-client
-socket_client_SOURCES = \
- socket-client.c \
- gtlsconsoleinteraction.c \
- gtlsconsoleinteraction.h
-EXTRA_DIST += socket-common.c
-
-uninstalled_test_extra_programs += gdbus-daemon
-gdbus_daemon_SOURCES = gdbus-daemon.c
-nodist_gdbus_daemon_SOURCES = \
- gdbus-daemon-generated.c \
- gdbus-daemon-impl.c
-CLEANFILES += gdbus-daemon-impl.c gdbus-daemon-generated.c gdbus-daemon-generated.h
-
-# With subdir-objects we need to create a link to the original
-# file in the right directory, otherwise libtool will complain
-# that it cannot find the wrapper file
-gdbus-daemon-impl.c: $(top_srcdir)/gio/gdbusdaemon.c
- $(AM_V_GEN) $(LN_S) $^ $@
-
-# These files are only generated on Windows builds inside GIO,
-# but we want them on non-Windows builds for the tests
-gdbus-daemon-generated.h gdbus-daemon-generated.c: $(top_srcdir)/gio/dbus-daemon.xml $(GDBUS_PYTHON_DEPS)
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(top_srcdir)/gio/gdbus-2.0/codegen/gdbus-codegen.in \
- --interface-prefix org. \
- --generate-c-code gdbus-daemon-generated \
- --c-namespace _G \
- $(top_srcdir)/gio/dbus-daemon.xml \
- $(NULL)
-
-# -----------------------------------------------------------------------------
-# Test programs buildable on UNIX only
-
-if OS_UNIX
-test_programs += \
- file \
- gdbus-peer-object-manager \
- live-g-file \
- socket-address \
- stream-rw_all \
- unix-fd \
- unix-mounts \
- unix-streams \
- g-file-info-filesystem-readonly \
- trash \
- $(NULL)
-
-test_extra_programs += \
- basic-application \
- dbus-launch \
- $(NULL)
-
-if !OS_COCOA
-# Uninstalled because of the check-for-executable logic in DesktopAppInfo unable to find the installed executable
-uninstalled_test_programs += \
- appinfo \
- desktop-app-info \
- $(NULL)
-endif
-
-home_desktop_files = \
- epiphany-weather-for-toronto-island-9c6a4e022b17686306243dada811d550d25eb1fb.desktop \
- eog.desktop
-
-usr_desktop_files = \
- baobab.desktop \
- cheese.desktop \
- dconf-editor.desktop \
- eog.desktop \
- evince-previewer.desktop \
- evince.desktop \
- file-roller.desktop \
- frobnicator.desktop \
- gcr-prompter.desktop \
- gcr-viewer.desktop \
- gedit.desktop \
- glade.desktop \
- gnome-contacts.desktop \
- gnome-font-viewer.desktop \
- gnome-music.desktop \
- gnome-terminal.desktop \
- gucharmap.desktop \
- kde4/dolphin.desktop \
- kde4/kate.desktop \
- kde4/konqbrowser.desktop \
- kde4/okular.desktop \
- mimeinfo.cache \
- nautilus-autorun-software.desktop \
- nautilus-classic.desktop \
- nautilus-connect-server.desktop \
- nautilus.desktop \
- org.gnome.clocks.desktop \
- totem.desktop \
- yelp.desktop
-
-dist_test_data += \
- $(addprefix desktop-files/usr/applications/,$(usr_desktop_files)) \
- $(addprefix desktop-files/home/applications/,$(home_desktop_files))
-
-dist_test_data += \
- appinfo-test-actions.desktop \
- appinfo-test-static.desktop \
- file.c \
- org.gtk.test.dbusappinfo.desktop \
- x-content/image-dcf/DCIM/Camera/20130831_203925.jpg \
- x-content/image-dcf/DCIM/Camera/20130831_203928.jpg \
- x-content/unix-software/autorun.sh \
- x-content/win32-software/autorun.exe \
- $(NULL)
-
-test_extra_programs += \
- appinfo-test \
- $(NULL)
-
-uninstalled_test_extra_programs += \
- gdbus-example-unix-fd-client \
- $(NULL)
-
-if !OS_COCOA
-test_extra_programs += apps
-test_programs += mimeapps
-endif
-
-appinfo-test-gnome.desktop: appinfo-test-gnome.desktop.in Makefile
- $(AM_V_GEN)$(SED) \
- -e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
- $< > $@
-appinfo-test-notgnome.desktop: appinfo-test-notgnome.desktop.in Makefile
- $(AM_V_GEN)$(SED) \
- -e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
- $< > $@
-appinfo-test.desktop: appinfo-test.desktop.in Makefile
- $(AM_V_GEN)$(SED) \
- -e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
- $< > $@
-appinfo-test2.desktop: appinfo-test2.desktop.in Makefile
- $(AM_V_GEN)$(SED) \
- -e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
- $< > $@
-
-appinfo_desktop_templates = \
- appinfo-test-gnome.desktop.in \
- appinfo-test-notgnome.desktop.in \
- appinfo-test.desktop.in \
- appinfo-test2.desktop.in \
- $(NULL)
-appinfo_desktop_files = $(appinfo_desktop_templates:.in=)
-
-EXTRA_DIST += $(appinfo_desktop_templates)
-CLEANFILES += $(appinfo_desktop_files)
-test_data += $(appinfo_desktop_files)
-
-uninstalled_test_programs += gsettings gschema-compile
-gsettings_DEPENDENCIES = test.mo
-CLEANFILES += test.mo de/LC_MESSAGES/test.mo keyfile/gsettings.store
-gsettings_CFLAGS = $(AM_CFLAGS) -DSRCDIR=\"$(abs_srcdir)\"
-test.mo: de.po
- $(AM_V_GEN) $(MSGFMT) -o test.mo $(srcdir)/de.po; \
- $(MKDIR_P) de/LC_MESSAGES; \
- cp -f test.mo de/LC_MESSAGES
-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 \
- schema-source/gschemas.compiled \
- schema-source-corrupt/gschemas.compiled \
- schema-source-empty/gschemas.compiled \
- $(NULL)
-
-test_programs += gdbus-connection-flush
-gdbus_connection_flush_SOURCES = \
- gdbus-connection-flush.c \
- test-io-stream.c \
- test-io-stream.h \
- test-pipe-unix.c \
- test-pipe-unix.h
-
-test_programs += gdbus-non-socket
-gdbus_non_socket_SOURCES = \
- gdbus-non-socket.c \
- gdbus-tests.c \
- gdbus-tests.h \
- test-io-stream.c \
- test-io-stream.h \
- test-pipe-unix.c \
- test-pipe-unix.h
-
-# These three are manual-run tests because they need a session bus but don't bring one up themselves
-uninstalled_test_extra_programs += gdbus-example-objectmanager-client
-gdbus_example_objectmanager_client_LDADD = gdbus-object-manager-example/libgdbus-example-objectmanager.la $(LDADD)
-
-uninstalled_test_extra_programs += gdbus-example-objectmanager-server
-gdbus_example_objectmanager_server_LDADD = gdbus-object-manager-example/libgdbus-example-objectmanager.la $(LDADD)
-
-test_extra_programs += gsubprocess-testprog
-
-uninstalled_test_extra_programs += gdbus-test-fixture
-gdbus_test_fixture_LDADD = gdbus-object-manager-example/libgdbus-example-objectmanager.la $(LDADD)
-
-# This is peer to peer so it doesn't need a session bus (so we can run it normally)
-gdbus_peer_LDADD = gdbus-object-manager-example/libgdbus-example-objectmanager.la $(LDADD)
-
-# This test is currently unreliable
-test_extra_programs += gdbus-overflow
-
-# -----------------------------------------------------------------------------
-# Test programs that need to bring up a session bus (requires dbus-daemon)
-
-if HAVE_DBUS_DAEMON
-gdbus_sessionbus_sources = gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c
-
-test_programs += \
- actions \
- defaultvalue \
- gapplication \
- gdbus-auth \
- gdbus-bz627724 \
- gdbus-close-pending \
- gdbus-connection \
- gdbus-connection-loss \
- gdbus-connection-slow \
- gdbus-error \
- gdbus-exit-on-close \
- gdbus-export \
- gdbus-introspection \
- gdbus-names \
- gdbus-peer \
- gdbus-proxy \
- gdbus-proxy-threads \
- gdbus-proxy-unique-name \
- gdbus-proxy-well-known-name \
- gdbus-test-codegen \
- gdbus-test-codegen-old \
- gdbus-threading \
- gmenumodel \
- gnotification \
- $(NULL)
-
-if OS_UNIX
-test_programs += gdbus-unix-addresses
-
-if !OS_COCOA
-test_programs += dbus-appinfo
-endif
-
-endif
-
-gdbus_proxy_threads_CFLAGS = $(AM_CFLAGS) $(DBUS1_CFLAGS)
-actions_SOURCES = $(gdbus_sessionbus_sources) actions.c
-dbus_appinfo_SOURCES = $(gdbus_sessionbus_sources) dbus-appinfo.c
-gapplication_SOURCES = $(gdbus_sessionbus_sources) gapplication.c
-gdbus_auth_SOURCES = $(gdbus_sessionbus_sources) gdbus-auth.c
-gdbus_bz627724_SOURCES = $(gdbus_sessionbus_sources) gdbus-bz627724.c
-gdbus_close_pending_SOURCES = $(gdbus_sessionbus_sources) gdbus-close-pending.c
-gdbus_connection_SOURCES = $(gdbus_sessionbus_sources) gdbus-connection.c
-gdbus_connection_loss_SOURCES = $(gdbus_sessionbus_sources) gdbus-connection-loss.c
-gdbus_connection_slow_SOURCES = $(gdbus_sessionbus_sources) gdbus-connection-slow.c
-gdbus_error_SOURCES = $(gdbus_sessionbus_sources) gdbus-error.c
-gdbus_exit_on_close_SOURCES = $(gdbus_sessionbus_sources) gdbus-exit-on-close.c
-gdbus_export_SOURCES = $(gdbus_sessionbus_sources) gdbus-export.c
-gdbus_introspection_SOURCES = $(gdbus_sessionbus_sources) gdbus-introspection.c
-gdbus_names_SOURCES = $(gdbus_sessionbus_sources) gdbus-names.c
-gdbus_proxy_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy.c
-gdbus_proxy_threads_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-threads.c
-gdbus_proxy_unique_name_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-unique-name.c
-gdbus_proxy_well_known_name_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-well-known-name.c
-gdbus_test_codegen_SOURCES = $(gdbus_sessionbus_sources) gdbus-test-codegen.c
-nodist_gdbus_test_codegen_SOURCES = gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h gdbus-test-codegen-generated-interface-info.c gdbus-test-codegen-generated-interface-info.h
-gdbus_test_codegen_old_SOURCES = $(gdbus_sessionbus_sources) gdbus-test-codegen.c
-nodist_gdbus_test_codegen_old_SOURCES = gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h gdbus-test-codegen-generated-interface-info.c gdbus-test-codegen-generated-interface-info.h
-gdbus_test_codegen_old_CPPFLAGS = $(AM_CPPFLAGS) -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36 -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_36
-gdbus_threading_SOURCES = $(gdbus_sessionbus_sources) gdbus-threading.c
-gmenumodel_SOURCES = $(gdbus_sessionbus_sources) gmenumodel.c
-gnotification_SOURCES = $(gdbus_sessionbus_sources) gnotification.c gnotification-server.h gnotification-server.c
-
-BUILT_SOURCES += gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h gdbus-test-codegen-generated-interface-info.c gdbus-test-codegen-generated-interface-info.h
-gdbus-test-codegen.o: gdbus-test-codegen-generated.h gdbus-test-codegen-generated-interface-info.h
-gdbus-test-codegen-generated.h: test-codegen.xml Makefile $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen \
- --interface-prefix org.project. \
- --generate-c-code gdbus-test-codegen-generated \
- --c-generate-object-manager \
- --c-generate-autocleanup all \
- --c-namespace Foo_iGen \
- --generate-docbook gdbus-test-codegen-generated-doc \
- --annotate "org.project.Bar" Key1 Value1 \
- --annotate "org.project.Bar" org.gtk.GDBus.Internal Value2 \
- --annotate "org.project.Bar.HelloWorld()" Key3 Value3 \
- --annotate "org.project.Bar::TestSignal" Key4 Value4 \
- --annotate "org.project.Bar:ay" Key5 Value5 \
- --annotate "org.project.Bar.TestPrimitiveTypes()[val_int32]" Key6 Value6 \
- --annotate "org.project.Bar.TestPrimitiveTypes()[ret_uint32]" Key7 Value7 \
- --annotate "org.project.Bar::TestSignal[array_of_strings]" Key8 Value8 \
- $(srcdir)/test-codegen.xml \
- $(NULL)
-gdbus-test-codegen-generated.c: gdbus-test-codegen-generated.h
- @: # Generated as side-effect of .h
-gdbus-test-codegen-generated-interface-info.h: test-codegen.xml Makefile $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen \
- --interface-info-header \
- --annotate "org.project.Bar" Key1 Value1 \
- --annotate "org.project.Bar" org.gtk.GDBus.Internal Value2 \
- --annotate "org.project.Bar.HelloWorld()" Key3 Value3 \
- --annotate "org.project.Bar::TestSignal" Key4 Value4 \
- --annotate "org.project.Bar:ay" Key5 Value5 \
- --annotate "org.project.Bar.TestPrimitiveTypes()[val_int32]" Key6 Value6 \
- --annotate "org.project.Bar.TestPrimitiveTypes()[ret_uint32]" Key7 Value7 \
- --annotate "org.project.Bar::TestSignal[array_of_strings]" Key8 Value8 \
- --output $@ \
- $(srcdir)/test-codegen.xml \
- $(NULL)
-gdbus-test-codegen-generated-interface-info.c: test-codegen.xml Makefile $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen \
- --interface-info-body \
- --annotate "org.project.Bar" Key1 Value1 \
- --annotate "org.project.Bar" org.gtk.GDBus.Internal Value2 \
- --annotate "org.project.Bar.HelloWorld()" Key3 Value3 \
- --annotate "org.project.Bar::TestSignal" Key4 Value4 \
- --annotate "org.project.Bar:ay" Key5 Value5 \
- --annotate "org.project.Bar.TestPrimitiveTypes()[val_int32]" Key6 Value6 \
- --annotate "org.project.Bar.TestPrimitiveTypes()[ret_uint32]" Key7 Value7 \
- --annotate "org.project.Bar::TestSignal[array_of_strings]" Key8 Value8 \
- --output $@ \
- $(srcdir)/test-codegen.xml \
- $(NULL)
-
-EXTRA_DIST += test-codegen.xml
-CLEANFILES += gdbus-test-codegen-generated.[ch] gdbus-test-codegen-generated-doc-*.xml gdbus-test-codegen-generated-interface-info.[ch]
-endif # OS_UNIX
-endif # HAVE_DBUS_DAEMON
-
-tls_interaction_SOURCES = tls-interaction.c gtesttlsbackend.c gtesttlsbackend.h
-tls_database_SOURCES = tls-database.c gtesttlsbackend.c gtesttlsbackend.h
-
-# -----------------------------------------------------------------------------
-
-if OS_WIN32
-test_programs += win32-streams
-endif
-
-if PLATFORM_WIN32
-no_undefined = -no-undefined
-endif
-
-if HAVE_DBUS1
-test_programs += gdbus-serialization
-gdbus_serialization_CFLAGS = $(AM_CFLAGS) $(DBUS1_CFLAGS)
-gdbus_serialization_LDADD = $(LDADD) $(DBUS1_LIBS)
-gdbus_serialization_SOURCES = \
- gdbus-serialization.c \
- gdbus-tests.h \
- gdbus-tests.c
-endif
-
-if HAVE_GCC
-test_programs += \
- autoptr \
- $(NULL)
-endif
-
-# -----------------------------------------------------------------------------
-# The resources test is a bit more complicated, and we cannot build it when
-# cross-compiling GIO because it requires running a binary...
-
-if !CROSS_COMPILING
-test_programs += resources
-resources_SOURCES = resources.c
-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
-nodist_libresourceplugin_la_SOURCES = plugin_resources.c
-libresourceplugin_la_LDFLAGS = -avoid-version -module -export-dynamic $(no_undefined)
-libresourceplugin_la_LIBADD = $(LDADD)
-
-test_data += test.gresource
-
-# libtool contains a bug whereby the created .la file doesn't contain the correct dlname='' in the case that
-# you're building a library but not installing it. This is apparently because the only considered use for an
-# uninstalled library is as a convenience library for linking (despite the fact that we give -module). The lack
-# of dlname='' in the .la trips up libltdl and GModule as well. We can trick libtool into believing that we
-# will install the module by giving it a bogus -rpath for the uninstalled cases.
-#
-# See http://lists.gnu.org/archive/html/bug-libtool/2013-05/msg00009.html
-if !ENABLE_INSTALLED_TESTS
-libresourceplugin_la_LDFLAGS += -rpath /
-endif
-
-glib_compile_resources=$(top_builddir)/gio/glib-compile-resources
-
-test-generated.txt: test1.txt
- $(AM_V_GEN) echo "Generated" > $@ && \
- cat $< >> $@
-
-gresource-big-test.txt: gen-big-test-resource.py
- $(AM_V_GEN) $(PYTHON) $< $@
-
-resources.o: test_resources2.h
-test_resources.c: test2.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test2.gresource.xml)
- $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=. --sourcedir=$(srcdir) --generate-source --c-name _g_test1 $<
-
-test_resources2.h test_resources2.c: test3.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test3.gresource.xml)
- $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=$(srcdir) --generate --c-name _g_test2 --manual-register $<
-
-plugin_resources.c: test4.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test4.gresource.xml)
- $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=$(srcdir) --generate-source --c-name _g_plugin $<
-
-test.gresource: test.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=. --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test.gresource.xml)
- $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=. --sourcedir=$(srcdir) $<
-
-EXTRA_DIST += test.gresource.xml test1.txt test2.gresource.xml test2.txt test3.gresource.xml test3.txt test4.gresource.xml test5.gresource.xml gen-big-test-resource.py
-CLEANFILES += test-generated.txt test_resources.c test_resources2.[ch] plugin_resources.c test.gresource gresource-big-test.txt
-
-if OS_LINUX
-test5.gresource: test5.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=. --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test5.gresource.xml)
- $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=. --sourcedir=$(srcdir) $<
-test_resources_binary.c: test5.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=. --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test5.gresource.xml)
- $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=$(srcdir) --generate-source --c-name _g_binary_test1 $<
-test_resources_binary_data.o: test5.gresource
- $(AM_V_GEN) ld -r -b binary $< -o $@
-test_resources_binary_data2.o: test_resources_binary.o
- $(AM_V_GEN) objcopy --add-symbol _g_binary_test1_resource_data=.data:0 -N _binary_test5_gresource_start -N _binary_test5_gresource_size -N _binary_test5_gresource_end $< $@
-nodist_resources_SOURCES += test_resources_binary_data2.o test_resources_binary.c
-endif
-
-endif # !CROSS_COMPILING
-
-BUILT_SOURCES += giotypefuncs.inc
-
-giotypefuncs.inc: Makefile
- $(AM_V_GEN) echo '#include <gio/gio.h>' > xgen-giosrc.c && \
- echo "G_GNUC_BEGIN_IGNORE_DEPRECATIONS" > xgen-gio && \
- ${CPP} $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) xgen-giosrc.c | \
- $(GREP) -o '\bg_[A-Za-z0-9_]*_get_type\b' | \
- $(GREP) -v 'g_io_extension_get_type\|g_variant_get_type' | \
- LC_ALL=C sort | uniq | \
- $(SED) -e 's/^/*tp++ = /' -e 's/$$/ ();/' >> xgen-gio && \
- cp xgen-gio $@ # && rm -f xgen-gio xgen-giosrc.c
-
-CLEANFILES += xgen-giosrc.c xgen-gio giotypefuncs.inc
-
-if ENABLE_INSTALLED_TESTS
-if OS_UNIX
-install-data-hook:
- $(AM_V_at) chmod a+x $(DESTDIR)$(installed_testdir)/x-content/win32-software/autorun.exe
-endif
-endif
diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c
index dd41af842..ed2f89111 100644
--- a/gio/tests/desktop-app-info.c
+++ b/gio/tests/desktop-app-info.c
@@ -155,7 +155,7 @@ test_default (void)
static void
test_fallback (void)
{
- GAppInfo *info1, *info2, *app;
+ GAppInfo *info1, *info2, *app = NULL;
GList *apps, *recomm, *fallback, *list, *l, *m;
GError *error = NULL;
gint old_length;
@@ -188,6 +188,7 @@ test_fallback (void)
if (g_app_info_equal (info1, app))
break;
}
+ g_assert_nonnull (app);
g_assert_true (g_app_info_equal (info1, app));
/* and that Test2 is among the fallback apps */
diff --git a/gio/tests/file.c b/gio/tests/file.c
index d2f147419..658d17549 100644
--- a/gio/tests/file.c
+++ b/gio/tests/file.c
@@ -1162,6 +1162,561 @@ test_load_bytes_async (void)
g_main_loop_unref (data.main_loop);
}
+static void
+test_writev_helper (GOutputVector *vectors,
+ gsize n_vectors,
+ gboolean use_bytes_written,
+ const guint8 *expected_contents,
+ gsize expected_length)
+{
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gsize bytes_written = 0;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ res = g_output_stream_writev_all (ostream, vectors, n_vectors, use_bytes_written ? &bytes_written : NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ if (use_bytes_written)
+ g_assert_cmpuint (bytes_written, ==, expected_length);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_assert_cmpmem (contents, length, expected_contents, expected_length);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+/* Test that writev() on local file output streams works on a non-empty vector */
+static void
+test_writev (void)
+{
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + 5;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + 5 + 12;
+ vectors[2].size = 3;
+
+ test_writev_helper (vectors, G_N_ELEMENTS (vectors), TRUE, buffer, sizeof buffer);
+}
+
+/* Test that writev() on local file output streams works on a non-empty vector without returning bytes_written */
+static void
+test_writev_no_bytes_written (void)
+{
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + 5;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + 5 + 12;
+ vectors[2].size = 3;
+
+ test_writev_helper (vectors, G_N_ELEMENTS (vectors), FALSE, buffer, sizeof buffer);
+}
+
+/* Test that writev() on local file output streams works on 0 vectors */
+static void
+test_writev_no_vectors (void)
+{
+ test_writev_helper (NULL, 0, TRUE, NULL, 0);
+}
+
+/* Test that writev() on local file output streams works on empty vectors */
+static void
+test_writev_empty_vectors (void)
+{
+ GOutputVector vectors[3];
+
+ vectors[0].buffer = NULL;
+ vectors[0].size = 0;
+ vectors[1].buffer = NULL;
+ vectors[1].size = 0;
+ vectors[2].buffer = NULL;
+ vectors[2].size = 0;
+
+ test_writev_helper (vectors, G_N_ELEMENTS (vectors), TRUE, NULL, 0);
+}
+
+/* Test that writev() fails if the sum of sizes in the vector is too big */
+static void
+test_writev_too_big_vectors (void)
+{
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gsize bytes_written = 0;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+ GOutputVector vectors[3];
+
+ vectors[0].buffer = (void*) 1;
+ vectors[0].size = G_MAXSIZE / 2;
+
+ vectors[1].buffer = (void*) 1;
+ vectors[1].size = G_MAXSIZE / 2;
+
+ vectors[2].buffer = (void*) 1;
+ vectors[2].size = G_MAXSIZE / 2;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ res = g_output_stream_writev_all (ostream, vectors, G_N_ELEMENTS (vectors), &bytes_written, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
+ g_assert_cmpuint (bytes_written, ==, 0);
+ g_assert_false (res);
+ g_clear_error (&error);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_assert_cmpmem (contents, length, NULL, 0);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+typedef struct
+{
+ gsize bytes_written;
+ GOutputVector *vectors;
+ gsize n_vectors;
+ GError *error;
+ gboolean done;
+} WritevAsyncData;
+
+static void
+test_writev_async_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GOutputStream *ostream = G_OUTPUT_STREAM (object);
+ WritevAsyncData *data = user_data;
+ GError *error = NULL;
+ gsize bytes_written;
+ gboolean res;
+
+ res = g_output_stream_writev_finish (ostream, result, &bytes_written, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ data->bytes_written += bytes_written;
+
+ /* skip vectors that have been written in full */
+ while (data->n_vectors > 0 && bytes_written >= data->vectors[0].size)
+ {
+ bytes_written -= data->vectors[0].size;
+ ++data->vectors;
+ --data->n_vectors;
+ }
+ /* skip partially written vector data */
+ if (bytes_written > 0 && data->n_vectors > 0)
+ {
+ data->vectors[0].size -= bytes_written;
+ data->vectors[0].buffer = ((guint8 *) data->vectors[0].buffer) + bytes_written;
+ }
+
+ if (data->n_vectors > 0)
+ g_output_stream_writev_async (ostream, data->vectors, data->n_vectors, 0, NULL, test_writev_async_cb, &data);
+}
+
+/* Test that writev_async() on local file output streams works on a non-empty vector */
+static void
+test_writev_async (void)
+{
+ WritevAsyncData data = { 0 };
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + 5;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + 5 + 12;
+ vectors[2].size = 3;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ data.vectors = vectors;
+ data.n_vectors = G_N_ELEMENTS (vectors);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ g_output_stream_writev_async (ostream, data.vectors, data.n_vectors, 0, NULL, test_writev_async_cb, &data);
+
+ while (data.n_vectors > 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.bytes_written, ==, sizeof buffer);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_assert_cmpmem (contents, length, buffer, sizeof buffer);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+static void
+test_writev_all_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GOutputStream *ostream = G_OUTPUT_STREAM (object);
+ WritevAsyncData *data = user_data;
+
+ g_output_stream_writev_all_finish (ostream, result, &data->bytes_written, &data->error);
+ data->done = TRUE;
+}
+
+/* Test that writev_async_all() on local file output streams works on a non-empty vector */
+static void
+test_writev_async_all (void)
+{
+ WritevAsyncData data = { 0 };
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputStream *ostream;
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+ GError *error = NULL;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + 5;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + 5 + 12;
+ vectors[2].size = 3;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, NULL, test_writev_all_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.bytes_written, ==, sizeof buffer);
+ g_assert_no_error (data.error);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_assert_cmpmem (contents, length, buffer, sizeof buffer);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+/* Test that writev_async_all() on local file output streams handles cancellation correctly */
+static void
+test_writev_async_all_cancellation (void)
+{
+ WritevAsyncData data = { 0 };
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+ GCancellable *cancellable;
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + 5;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + 5 + 12;
+ vectors[2].size = 3;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ cancellable = g_cancellable_new ();
+ g_cancellable_cancel (cancellable);
+
+ g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, cancellable, test_writev_all_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.bytes_written, ==, 0);
+ g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&data.error);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (length, ==, 0);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+ g_object_unref (cancellable);
+}
+
+/* Test that writev_async_all() with empty vectors is handled correctly */
+static void
+test_writev_async_all_empty_vectors (void)
+{
+ WritevAsyncData data = { 0 };
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputVector vectors[3];
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+
+ vectors[0].buffer = NULL;
+ vectors[0].size = 0;
+
+ vectors[1].buffer = NULL;
+ vectors[1].size = 0;
+
+ vectors[2].buffer = NULL;
+ vectors[2].size = 0;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, NULL, test_writev_all_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.bytes_written, ==, 0);
+ g_assert_no_error (data.error);
+ g_clear_error (&data.error);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (length, ==, 0);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+/* Test that writev_async_all() with no vectors is handled correctly */
+static void
+test_writev_async_all_no_vectors (void)
+{
+ WritevAsyncData data = { 0 };
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ g_output_stream_writev_all_async (ostream, NULL, 0, 0, NULL, test_writev_all_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.bytes_written, ==, 0);
+ g_assert_no_error (data.error);
+ g_clear_error (&data.error);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (length, ==, 0);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+/* Test that writev_async_all() with too big vectors is handled correctly */
+static void
+test_writev_async_all_too_big_vectors (void)
+{
+ WritevAsyncData data = { 0 };
+ GFile *file;
+ GFileIOStream *iostream = NULL;
+ GOutputVector vectors[3];
+ GOutputStream *ostream;
+ GError *error = NULL;
+ gboolean res;
+ guint8 *contents;
+ gsize length;
+
+ vectors[0].buffer = (void*) 1;
+ vectors[0].size = G_MAXSIZE / 2;
+
+ vectors[1].buffer = (void*) 1;
+ vectors[1].size = G_MAXSIZE / 2;
+
+ vectors[2].buffer = (void*) 1;
+ vectors[2].size = G_MAXSIZE / 2;
+
+ file = g_file_new_tmp ("g_file_writev_XXXXXX",
+ &iostream, NULL);
+ g_assert_nonnull (file);
+ g_assert_nonnull (iostream);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+ g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, NULL, test_writev_all_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.bytes_written, ==, 0);
+ g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
+ g_clear_error (&data.error);
+
+ res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_object_unref (iostream);
+
+ res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (length, ==, 0);
+
+ g_free (contents);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
int
main (int argc, char *argv[])
{
@@ -1190,6 +1745,17 @@ main (int argc, char *argv[])
g_test_add_func ("/file/measure-async", test_measure_async);
g_test_add_func ("/file/load-bytes", test_load_bytes);
g_test_add_func ("/file/load-bytes-async", test_load_bytes_async);
+ g_test_add_func ("/file/writev", test_writev);
+ g_test_add_func ("/file/writev/no-bytes-written", test_writev_no_bytes_written);
+ g_test_add_func ("/file/writev/no-vectors", test_writev_no_vectors);
+ g_test_add_func ("/file/writev/empty-vectors", test_writev_empty_vectors);
+ g_test_add_func ("/file/writev/too-big-vectors", test_writev_too_big_vectors);
+ g_test_add_func ("/file/writev/async", test_writev_async);
+ g_test_add_func ("/file/writev/async_all", test_writev_async_all);
+ g_test_add_func ("/file/writev/async_all-empty-vectors", test_writev_async_all_empty_vectors);
+ g_test_add_func ("/file/writev/async_all-no-vectors", test_writev_async_all_no_vectors);
+ g_test_add_func ("/file/writev/async_all-to-big-vectors", test_writev_async_all_too_big_vectors);
+ g_test_add_func ("/file/writev/async_all-cancellation", test_writev_async_all_cancellation);
return g_test_run ();
}
diff --git a/gio/tests/gdbus-object-manager-example/Makefile.am b/gio/tests/gdbus-object-manager-example/Makefile.am
deleted file mode 100644
index 735fddcc6..000000000
--- a/gio/tests/gdbus-object-manager-example/Makefile.am
+++ /dev/null
@@ -1,49 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-AM_CPPFLAGS = -g $(gio_INCLUDES) $(GLIB_DEBUG_FLAGS) -I$(top_builddir)/gio -I$(top_srcdir)/gio
-
-# ------------------------------------------------------------------------
-
-GDBUS_GENERATED = \
- objectmanager-gen.h \
- objectmanager-gen.c \
- objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml \
- objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Cat.xml \
- $(NULL)
-
-$(GDBUS_GENERATED) : gdbus-example-objectmanager.xml Makefile $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen
- $(AM_V_GEN) UNINSTALLED_GLIB_SRCDIR=$(top_srcdir) \
- UNINSTALLED_GLIB_BUILDDIR=$(top_builddir) \
- $(PYTHON) $(top_builddir)/gio/gdbus-2.0/codegen/gdbus-codegen \
- --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
- --c-namespace Example \
- --c-generate-object-manager \
- --generate-c-code objectmanager-gen \
- --generate-docbook objectmanager-gen \
- $< \
- $(NULL)
-
-test_ltlibraries = libgdbus-example-objectmanager.la
-
-if ENABLE_GTK_DOC
-# The docs pull these in, so we need them even if not doing 'make check'
-BUILT_SOURCES += $(GDBUS_GENERATED)
-noinst_LTLIBRARIES += libgdbus-example-objectmanager.la
-endif
-
-nodist_libgdbus_example_objectmanager_la_SOURCES = \
- objectmanager-gen.h \
- objectmanager-gen.c
-
-libgdbus_example_objectmanager_la_LIBADD = \
- $(top_builddir)/glib/libglib-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/gio/libgio-2.0.la \
- $(NULL)
-
-EXTRA_DIST += gdbus-example-objectmanager.xml
-
-CLEANFILES += $(GDBUS_GENERATED)
-
-check-TESTS:
diff --git a/gio/tests/gdbus-proxy.c b/gio/tests/gdbus-proxy.c
index 8a2c324a2..6e092f42b 100644
--- a/gio/tests/gdbus-proxy.c
+++ b/gio/tests/gdbus-proxy.c
@@ -766,6 +766,7 @@ test_proxy (void)
GDBusProxy *proxy;
GDBusConnection *connection;
GError *error;
+ gchar *owner;
error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
@@ -783,7 +784,7 @@ test_proxy (void)
&error);
g_assert_no_error (error);
- /* this is safe; testserver will exit once the bus goes away */
+ /* this is safe; we explicitly kill the service later on */
g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
_g_assert_property_notify (proxy, "g-name-owner");
@@ -794,8 +795,15 @@ test_proxy (void)
test_signals (proxy);
test_expected_interface (proxy);
- g_object_unref (proxy);
kill_test_service (connection);
+
+ _g_assert_property_notify (proxy, "g-name-owner");
+
+ owner = g_dbus_proxy_get_name_owner (proxy);
+ g_assert_null (owner);
+ g_free (owner);
+
+ g_object_unref (proxy);
g_object_unref (connection);
}
@@ -808,11 +816,19 @@ proxy_ready (GObject *source,
{
GDBusProxy *proxy;
GError *error;
+ gchar *owner;
error = NULL;
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
g_assert_no_error (error);
+ owner = g_dbus_proxy_get_name_owner (proxy);
+ g_assert_null (owner);
+ g_free (owner);
+
+ /* this is safe; we explicitly kill the service later on */
+ g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
+
_g_assert_property_notify (proxy, "g-name-owner");
test_basic (proxy);
@@ -847,9 +863,6 @@ test_async (void)
proxy_ready,
NULL);
- /* this is safe; testserver will exit once the bus goes away */
- g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
-
id = g_timeout_add (10000, fail_test, NULL);
g_main_loop_run (loop);
diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c
index e212e98cc..8db555781 100644
--- a/gio/tests/gdbus-test-codegen.c
+++ b/gio/tests/gdbus-test-codegen.c
@@ -56,7 +56,7 @@ test_annotations (void)
iface = foo_igen_bar_interface_info ();
g_assert (iface != NULL);
- /* see Makefile.am for where these annotations are injected */
+ /* see meson.build for where these annotations are injected */
g_assert_cmpint (count_annotations (iface->annotations), ==, 1);
g_assert_cmpstr (g_dbus_annotation_info_lookup (iface->annotations, "Key1"), ==, "Value1");
diff --git a/gio/tests/glistmodel.c b/gio/tests/glistmodel.c
index 533e2e47d..2fef4ccbe 100644
--- a/gio/tests/glistmodel.c
+++ b/gio/tests/glistmodel.c
@@ -778,6 +778,34 @@ test_store_signal_items_changed (void)
g_object_unref (store);
}
+/* Due to an overflow in the list store last-iter optimization,
+ * the sequence 'lookup 0; lookup MAXUINT' was returning the
+ * same item twice, and not NULL for the second lookup.
+ * See #1639.
+ */
+static void
+test_store_past_end (void)
+{
+ GListStore *store;
+ GListModel *model;
+ GSimpleAction *item;
+
+ store = g_list_store_new (G_TYPE_SIMPLE_ACTION);
+ model = G_LIST_MODEL (store);
+
+ item = g_simple_action_new ("2", NULL);
+ g_list_store_append (store, item);
+ g_object_unref (item);
+
+ g_assert_cmpint (g_list_model_get_n_items (model), ==, 1);
+ item = g_list_model_get_item (model, 0);
+ g_assert_nonnull (item);
+ item = g_list_model_get_item (model, G_MAXUINT);
+ g_assert_null (item);
+
+ g_object_unref (store);
+}
+
int main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
@@ -809,6 +837,7 @@ int main (int argc, char *argv[])
test_store_get_item_cache);
g_test_add_func ("/glistmodel/store/items-changed",
test_store_signal_items_changed);
+ g_test_add_func ("/glistmodel/store/past-end", test_store_past_end);
return g_test_run ();
}
diff --git a/gio/tests/gschema-compile.c b/gio/tests/gschema-compile.c
index 81ded83fa..8dc4985b8 100644
--- a/gio/tests/gschema-compile.c
+++ b/gio/tests/gschema-compile.c
@@ -11,11 +11,6 @@ typedef struct {
const gchar *err;
} SchemaTest;
-/* Meson build defines this, autotools build does not */
-#ifndef GLIB_COMPILE_SCHEMAS
-#define GLIB_COMPILE_SCHEMAS "../glib-compile-schemas"
-#endif
-
static void
test_schema_do_compile (gpointer data)
{
@@ -23,7 +18,7 @@ test_schema_do_compile (gpointer data)
gchar *filename = g_strconcat (test->name, ".gschema.xml", NULL);
gchar *path = g_test_build_filename (G_TEST_DIST, "schema-tests", filename, NULL);
const gchar *argv[] = {
- GLIB_COMPILE_SCHEMAS,
+ GLIB_COMPILE_SCHEMAS, /* defined in meson.build */
"--strict",
"--dry-run",
"--schema-file", path,
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index 852a8b710..fb19e5156 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -1770,6 +1770,23 @@ test_keyfile (void)
g_assert_cmpstr (str, ==, "howdy");
g_free (str);
+ /* Now check setting a string without quotes */
+ called = FALSE;
+ g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
+
+ g_key_file_set_string (keyfile, "tests", "greeting", "he\"l🤗uń");
+ g_free (data);
+ data = g_key_file_to_data (keyfile, &len, NULL);
+ g_file_set_contents ("keyfile/gsettings.store", data, len, &error);
+ g_assert_no_error (error);
+ while (!called)
+ g_main_context_iteration (NULL, FALSE);
+ g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
+
+ str = g_settings_get_string (settings, "greeting");
+ g_assert_cmpstr (str, ==, "he\"l🤗uń");
+ g_free (str);
+
g_settings_set (settings, "farewell", "s", "cheerio");
called = FALSE;
@@ -2798,12 +2815,8 @@ main (int argc, char *argv[])
if (!backend_set)
g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
-/* Meson build defines this, autotools build does not */
-#ifndef GLIB_MKENUMS
-#define GLIB_MKENUMS "../../gobject/glib-mkenums"
-#endif
-
g_remove ("org.gtk.test.enums.xml");
+ /* #GLIB_MKENUMS is defined in meson.build */
g_assert (g_spawn_command_line_sync (GLIB_MKENUMS " "
"--template " SRCDIR "/enums.xml.template "
SRCDIR "/testenum.h",
@@ -2820,12 +2833,8 @@ main (int argc, char *argv[])
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"
-#endif
-
g_remove ("gschemas.compiled");
+ /* #GLIB_COMPILE_SCHEMAS is defined in meson.build */
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 "
diff --git a/gio/tests/memory-output-stream.c b/gio/tests/memory-output-stream.c
index 4c85993e4..72da6263d 100644
--- a/gio/tests/memory-output-stream.c
+++ b/gio/tests/memory-output-stream.c
@@ -300,6 +300,94 @@ test_write_bytes (void)
g_bytes_unref (bytes2);
}
+/* Test that writev() works on #GMemoryOutputStream with a non-empty set of vectors. This
+ * covers the default writev() implementation around write(). */
+static void
+test_writev (void)
+{
+ GOutputStream *mo;
+ GError *error = NULL;
+ gboolean res;
+ gsize bytes_written;
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+ guint8 *output_buffer;
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + vectors[0].size;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + vectors[0].size + vectors[1].size;
+ vectors[2].size = 3;
+
+ mo = (GOutputStream*) g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM,
+ "realloc-function", g_realloc,
+ "destroy-function", g_free,
+ NULL);
+ res = g_output_stream_writev_all (mo, vectors, G_N_ELEMENTS (vectors), &bytes_written, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (bytes_written, ==, sizeof buffer);
+
+ g_output_stream_close (mo, NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpuint (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo)), ==, sizeof buffer);
+ output_buffer = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mo));
+ g_assert_cmpmem (output_buffer, sizeof buffer, buffer, sizeof buffer);
+
+ g_object_unref (mo);
+}
+
+/* Test that writev_nonblocking() works on #GMemoryOutputStream with a non-empty set of vectors. This
+ * covers the default writev_nonblocking() implementation around write_nonblocking(). */
+static void
+test_writev_nonblocking (void)
+{
+ GOutputStream *mo;
+ GError *error = NULL;
+ gboolean res;
+ gsize bytes_written;
+ GOutputVector vectors[3];
+ const guint8 buffer[] = {1, 2, 3, 4, 5,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 2, 3};
+ guint8 *output_buffer;
+
+ vectors[0].buffer = buffer;
+ vectors[0].size = 5;
+
+ vectors[1].buffer = buffer + vectors[0].size;
+ vectors[1].size = 12;
+
+ vectors[2].buffer = buffer + vectors[0].size + vectors[1].size;
+ vectors[2].size = 3;
+
+ mo = (GOutputStream*) g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM,
+ "realloc-function", g_realloc,
+ "destroy-function", g_free,
+ NULL);
+ res = g_pollable_output_stream_writev_nonblocking (G_POLLABLE_OUTPUT_STREAM (mo),
+ vectors, G_N_ELEMENTS (vectors),
+ &bytes_written, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (res, ==, G_POLLABLE_RETURN_OK);
+ g_assert_cmpuint (bytes_written, ==, sizeof buffer);
+
+ g_output_stream_close (mo, NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpuint (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo)), ==, sizeof buffer);
+ output_buffer = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mo));
+ g_assert_cmpmem (output_buffer, sizeof buffer, buffer, sizeof buffer);
+
+ g_object_unref (mo);
+}
+
static void
test_steal_as_bytes (void)
{
@@ -350,6 +438,8 @@ main (int argc,
g_test_add_func ("/memory-output-stream/get-data-size", test_data_size);
g_test_add_func ("/memory-output-stream/properties", test_properties);
g_test_add_func ("/memory-output-stream/write-bytes", test_write_bytes);
+ g_test_add_func ("/memory-output-stream/writev", test_writev);
+ g_test_add_func ("/memory-output-stream/writev_nonblocking", test_writev_nonblocking);
g_test_add_func ("/memory-output-stream/steal_as_bytes", test_steal_as_bytes);
return g_test_run();
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 5bbc07176..8bf555cf2 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -55,7 +55,7 @@ gio_tests = {
'memory-output-stream' : {},
'monitor' : {},
'mount-operation' : {},
- 'network-address' : {'extra_sources': ['mock-resolver.c']},
+ 'network-address' : {'extra_sources': ['mock-resolver.c'], 'suite': ['flaky']},
'network-monitor' : {},
'network-monitor-race' : {},
'permission' : {},
@@ -73,7 +73,7 @@ gio_tests = {
'vfs' : {},
'volumemonitor' : {},
'glistmodel' : {},
- 'testfilemonitor' : {'suite' : ['slow']},
+ 'testfilemonitor' : {'suite' : ['slow', 'flaky']},
'thumbnail-verification' : {},
'tls-certificate' : {'extra_sources' : ['gtesttlsbackend.c']},
'tls-interaction' : {'extra_sources' : ['gtesttlsbackend.c']},
@@ -144,7 +144,8 @@ if host_machine.system() != 'windows'
],
'env' : {
'LD_PRELOAD': '@0@/slow-connect-preload.so'.format(meson.current_build_dir())
- }
+ },
+ 'suite': ['flaky'],
},
'gschema-compile' : {'install' : false},
'trash' : {},
@@ -236,10 +237,10 @@ if host_machine.system() != 'windows'
'extra_sources' : extra_sources,
'suite' : ['slow'],
},
- 'gdbus-auth' : {'extra_sources' : extra_sources},
- 'gdbus-bz627724' : {'extra_sources' : extra_sources},
+ 'gdbus-auth' : {'extra_sources' : extra_sources, 'suite': ['flaky']},
+ 'gdbus-bz627724' : {'extra_sources' : extra_sources, 'suite': ['flaky']},
'gdbus-close-pending' : {'extra_sources' : extra_sources},
- 'gdbus-connection' : {'extra_sources' : extra_sources},
+ 'gdbus-connection' : {'extra_sources' : extra_sources, 'suite': ['flaky']},
'gdbus-connection-loss' : {'extra_sources' : extra_sources},
'gdbus-connection-slow' : {'extra_sources' : extra_sources},
'gdbus-error' : {'extra_sources' : extra_sources},
@@ -262,7 +263,7 @@ if host_machine.system() != 'windows'
},
'gdbus-threading' : {
'extra_sources' : extra_sources,
- 'suite' : ['slow'],
+ 'suite' : ['slow', 'flaky'],
},
'gmenumodel' : {
'extra_sources' : extra_sources,
diff --git a/gio/tests/modules/Makefile.am b/gio/tests/modules/Makefile.am
deleted file mode 100644
index c301b6c47..000000000
--- a/gio/tests/modules/Makefile.am
+++ /dev/null
@@ -1,41 +0,0 @@
-NULL =
-
-LDADD = \
- $(top_builddir)/gio/libgio-2.0.la \
- $(top_builddir)/gobject/libgobject-2.0.la \
- $(top_builddir)/gmodule/libgmodule-2.0.la \
- $(top_builddir)/glib/libglib-2.0.la \
- $(NULL)
-
-AM_CPPFLAGS = \
- $(gio_INCLUDES) $(GLIB_DEBUG_FLAGS) \
- -I$(top_builddir)/gio \
- -I$(top_srcdir)/gio \
- $(NULL)
-
-modules = \
- libtestmodulea.la \
- libtestmoduleb.la \
- $(NULL)
-
-if ENABLE_ALWAYS_BUILD_TESTS
-noinst_LTLIBRARIES = $(modules)
-else
-check_LTLIBRARIES = $(modules)
-endif
-
-if ENABLE_INSTALLED_TESTS
-testmoduledir = $(installed_testdir)/modules
-testmodule_LTLIBRARIES = $(modules)
-else
-# See comment in Makefile.am one level up
-rpath_hack = -rpath /
-endif
-
-libtestmodulea_la_SOURCES = test-module-a.c symbol-visibility.h
-libtestmodulea_la_LIBADD = $(LDADD)
-libtestmodulea_la_LDFLAGS = $(LDFLAGS) -module -no-undefined -avoid-version $(rpath_hack)
-
-libtestmoduleb_la_SOURCES = test-module-b.c symbol-visibility.h
-libtestmoduleb_la_LIBADD = $(LDADD)
-libtestmoduleb_la_LDFLAGS =$(LDFLAGS) -module -no-undefined -avoid-version $(rpath_hack)
diff --git a/gio/tests/resources.c b/gio/tests/resources.c
index 719624514..6e9c7c5e6 100644
--- a/gio/tests/resources.c
+++ b/gio/tests/resources.c
@@ -679,7 +679,6 @@ test_uri_query_info (void)
g_resources_register (resource);
file = g_file_new_for_uri ("resource://" "/a_prefix/test2-alias.txt");
-
info = g_file_query_info (file, "*", 0, NULL, &error);
g_assert_no_error (error);
@@ -893,6 +892,37 @@ test_resource_64k (void)
g_bytes_unref (data);
}
+/* Check that g_resources_get_info() respects G_RESOURCE_OVERLAYS */
+static void
+test_overlay (void)
+{
+ if (g_test_subprocess ())
+ {
+ GError *error = NULL;
+ gboolean res;
+ gsize size;
+ char *overlay;
+ char *path;
+
+ path = g_test_build_filename (G_TEST_DIST, "test1.overlay", NULL);
+ overlay = g_strconcat ("/auto_loaded/test1.txt=", path, NULL);
+
+ g_setenv ("G_RESOURCE_OVERLAYS", overlay, TRUE);
+ res = g_resources_get_info ("/auto_loaded/test1.txt", 0, &size, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ /* test1.txt is 6 bytes, test1.overlay is 23 */
+ g_assert_cmpint (size, ==, 23);
+
+ g_free (overlay);
+ g_free (path);
+
+ return;
+ }
+ g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDERR);
+ g_test_trap_assert_passed ();
+}
+
int
main (int argc,
char *argv[])
@@ -919,6 +949,7 @@ main (int argc,
g_test_add_func ("/resource/uri/query-info", test_uri_query_info);
g_test_add_func ("/resource/uri/file", test_uri_file);
g_test_add_func ("/resource/64k", test_resource_64k);
+ g_test_add_func ("/resource/overlay", test_overlay);
return g_test_run();
}
diff --git a/gio/tests/services/Makefile.am b/gio/tests/services/Makefile.am
deleted file mode 100644
index 7ab7864c3..000000000
--- a/gio/tests/services/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-EXTRA_DIST = \
- org.gtk.GDBus.Examples.ObjectManager.service.in
diff --git a/gio/tests/socket-service.c b/gio/tests/socket-service.c
index 9ae76d082..5496b69c0 100644
--- a/gio/tests/socket-service.c
+++ b/gio/tests/socket-service.c
@@ -232,6 +232,316 @@ test_threaded_712570 (void)
g_mutex_unlock (&mutex_712570);
}
+static void
+closed_read_write_async_cb (GSocketConnection *conn,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ gboolean res;
+
+ res = g_io_stream_close_finish (G_IO_STREAM (conn), result, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+}
+
+typedef struct {
+ GSocketConnection *conn;
+ guint8 *data;
+} WriteAsyncData;
+
+static void
+written_read_write_async_cb (GOutputStream *ostream,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ WriteAsyncData *data = user_data;
+ GError *error = NULL;
+ gboolean res;
+ gsize bytes_written;
+ GSocketConnection *conn;
+
+ conn = data->conn;
+
+ g_free (data->data);
+ g_free (data);
+
+ res = g_output_stream_write_all_finish (ostream, result, &bytes_written, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (bytes_written, ==, 20);
+
+ g_io_stream_close_async (G_IO_STREAM (conn),
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) closed_read_write_async_cb,
+ NULL);
+ g_object_unref (conn);
+}
+
+static void
+connected_read_write_async_cb (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSocketConnection *conn;
+ GOutputStream *ostream;
+ GError *error = NULL;
+ WriteAsyncData *data;
+ gsize i;
+ GSocketConnection **sconn = user_data;
+
+ conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (conn);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (conn));
+
+ data = g_new0 (WriteAsyncData, 1);
+ data->conn = conn;
+ data->data = g_new0 (guint8, 20);
+ for (i = 0; i < 20; i++)
+ data->data[i] = i;
+
+ g_output_stream_write_all_async (ostream,
+ data->data,
+ 20,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) written_read_write_async_cb,
+ data /* stolen */);
+
+ *sconn = g_object_ref (conn);
+}
+
+typedef struct {
+ GSocketConnection *conn;
+ GOutputVector *vectors;
+ guint n_vectors;
+ guint8 *data;
+} WritevAsyncData;
+
+static void
+writtenv_read_write_async_cb (GOutputStream *ostream,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ WritevAsyncData *data = user_data;
+ GError *error = NULL;
+ gboolean res;
+ gsize bytes_written;
+ GSocketConnection *conn;
+
+ conn = data->conn;
+ g_free (data->data);
+ g_free (data);
+
+ res = g_output_stream_writev_all_finish (ostream, result, &bytes_written, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+ g_assert_cmpuint (bytes_written, ==, 20);
+
+ g_io_stream_close_async (G_IO_STREAM (conn),
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) closed_read_write_async_cb,
+ NULL);
+ g_object_unref (conn);
+}
+
+static void
+connected_read_writev_async_cb (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSocketConnection *conn;
+ GOutputStream *ostream;
+ GError *error = NULL;
+ WritevAsyncData *data;
+ gsize i;
+ GSocketConnection **sconn = user_data;
+
+ conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (conn);
+
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (conn));
+
+ data = g_new0 (WritevAsyncData, 1);
+ data->conn = conn;
+ data->vectors = g_new0 (GOutputVector, 3);
+ data->n_vectors = 3;
+ data->data = g_new0 (guint8, 20);
+ for (i = 0; i < 20; i++)
+ data->data[i] = i;
+
+ data->vectors[0].buffer = data->data;
+ data->vectors[0].size = 5;
+ data->vectors[1].buffer = data->data + 5;
+ data->vectors[1].size = 10;
+ data->vectors[2].buffer = data->data + 15;
+ data->vectors[2].size = 5;
+
+ g_output_stream_writev_all_async (ostream,
+ data->vectors,
+ data->n_vectors,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) writtenv_read_write_async_cb,
+ data /* stolen */);
+
+ *sconn = g_object_ref (conn);
+}
+
+typedef struct {
+ GSocketConnection *conn;
+ guint8 *data;
+} ReadAsyncData;
+
+static void
+read_read_write_async_cb (GInputStream *istream,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ReadAsyncData *data = user_data;
+ GError *error = NULL;
+ gboolean res;
+ gsize bytes_read;
+ GSocketConnection *conn;
+ const guint8 expected_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
+
+ res = g_input_stream_read_all_finish (istream, result, &bytes_read, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_assert_cmpmem (expected_data, sizeof expected_data, data->data, bytes_read);
+
+ conn = data->conn;
+ g_object_set_data (G_OBJECT (conn), "test-data-read", GINT_TO_POINTER (TRUE));
+
+ g_free (data->data);
+ g_free (data);
+
+ g_io_stream_close_async (G_IO_STREAM (conn),
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) closed_read_write_async_cb,
+ NULL);
+ g_object_unref (conn);
+}
+
+static void
+incoming_read_write_async_cb (GSocketService *service,
+ GSocketConnection *conn,
+ GObject *source_object,
+ gpointer user_data)
+{
+ ReadAsyncData *data;
+ GSocketConnection **cconn = user_data;
+ GInputStream *istream;
+
+ istream = g_io_stream_get_input_stream (G_IO_STREAM (conn));
+
+ data = g_new0 (ReadAsyncData, 1);
+ data->conn = g_object_ref (conn);
+ data->data = g_new0 (guint8, 20);
+
+ g_input_stream_read_all_async (istream,
+ data->data,
+ 20,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) read_read_write_async_cb,
+ data /* stolen */);
+
+ *cconn = g_object_ref (conn);
+}
+
+static void
+test_read_write_async_internal (gboolean writev)
+{
+ GInetAddress *iaddr;
+ GSocketAddress *saddr, *listening_addr;
+ GSocketService *service;
+ GError *error = NULL;
+ GSocketClient *client;
+ GSocketConnection *sconn = NULL, *cconn = NULL;
+
+ iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
+ saddr = g_inet_socket_address_new (iaddr, 0);
+ g_object_unref (iaddr);
+
+ service = g_socket_service_new ();
+
+ g_socket_listener_add_address (G_SOCKET_LISTENER (service),
+ saddr,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP,
+ NULL,
+ &listening_addr,
+ &error);
+ g_assert_no_error (error);
+ g_object_unref (saddr);
+
+ g_signal_connect (service, "incoming", G_CALLBACK (incoming_read_write_async_cb), &sconn);
+
+ client = g_socket_client_new ();
+
+ if (writev)
+ g_socket_client_connect_async (client,
+ G_SOCKET_CONNECTABLE (listening_addr),
+ NULL,
+ connected_read_writev_async_cb,
+ &cconn);
+ else
+ g_socket_client_connect_async (client,
+ G_SOCKET_CONNECTABLE (listening_addr),
+ NULL,
+ connected_read_write_async_cb,
+ &cconn);
+
+ g_object_unref (client);
+ g_object_unref (listening_addr);
+
+ g_socket_service_start (service);
+ g_assert_true (g_socket_service_is_active (service));
+
+ do
+ {
+ g_main_context_iteration (NULL, TRUE);
+ }
+ while (!sconn || !cconn ||
+ !g_io_stream_is_closed (G_IO_STREAM (sconn)) ||
+ !g_io_stream_is_closed (G_IO_STREAM (cconn)));
+
+ g_assert_true (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (sconn), "test-data-read")));
+
+ g_object_unref (sconn);
+ g_object_unref (cconn);
+ g_object_unref (service);
+}
+
+/* Test if connecting to a socket service and asynchronously writing data on
+ * one side followed by reading the same data on the other side of the
+ * connection works correctly
+ */
+static void
+test_read_write_async (void)
+{
+ test_read_write_async_internal (FALSE);
+}
+
+/* Test if connecting to a socket service and asynchronously writing data on
+ * one side followed by reading the same data on the other side of the
+ * connection works correctly. This uses writev() instead of normal write().
+ */
+static void
+test_read_writev_async (void)
+{
+ test_read_write_async_internal (TRUE);
+}
+
+
int
main (int argc,
char *argv[])
@@ -242,6 +552,8 @@ main (int argc,
g_test_add_func ("/socket-service/start-stop", test_start_stop);
g_test_add_func ("/socket-service/threaded/712570", test_threaded_712570);
+ g_test_add_func ("/socket-service/read_write_async", test_read_write_async);
+ g_test_add_func ("/socket-service/read_writev_async", test_read_writev_async);
return g_test_run();
}
diff --git a/gio/tests/socket.c b/gio/tests/socket.c
index 9b3adb4e4..8410a3e84 100644
--- a/gio/tests/socket.c
+++ b/gio/tests/socket.c
@@ -1709,6 +1709,154 @@ test_get_available (gconstpointer user_data)
g_object_unref (client);
}
+typedef struct {
+ GInputStream *is;
+ GOutputStream *os;
+ const guint8 *write_data;
+ guint8 *read_data;
+} TestReadWriteData;
+
+static gpointer
+test_read_write_write_thread (gpointer user_data)
+{
+ TestReadWriteData *data = user_data;
+ gsize bytes_written;
+ GError *error = NULL;
+ gboolean res;
+
+ res = g_output_stream_write_all (data->os, data->write_data, 1024, &bytes_written, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ g_assert_cmpint (bytes_written, ==, 1024);
+
+ return NULL;
+}
+
+static gpointer
+test_read_write_read_thread (gpointer user_data)
+{
+ TestReadWriteData *data = user_data;
+ gsize bytes_read;
+ GError *error = NULL;
+ gboolean res;
+
+ res = g_input_stream_read_all (data->is, data->read_data, 1024, &bytes_read, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ g_assert_cmpint (bytes_read, ==, 1024);
+
+ return NULL;
+}
+
+static gpointer
+test_read_write_writev_thread (gpointer user_data)
+{
+ TestReadWriteData *data = user_data;
+ gsize bytes_written;
+ GError *error = NULL;
+ gboolean res;
+ GOutputVector vectors[3];
+
+ vectors[0].buffer = data->write_data;
+ vectors[0].size = 256;
+ vectors[1].buffer = data->write_data + 256;
+ vectors[1].size = 256;
+ vectors[2].buffer = data->write_data + 512;
+ vectors[2].size = 512;
+
+ res = g_output_stream_writev_all (data->os, vectors, G_N_ELEMENTS (vectors), &bytes_written, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ g_assert_cmpint (bytes_written, ==, 1024);
+
+ return NULL;
+}
+
+/* test if normal read/write/writev via the GSocket*Streams works on TCP sockets */
+static void
+test_read_write (gconstpointer user_data)
+{
+ gboolean writev = GPOINTER_TO_INT (user_data);
+ GError *err = NULL;
+ GSocket *listener, *server, *client;
+ GInetAddress *addr;
+ GSocketAddress *saddr;
+ TestReadWriteData data;
+ guint8 data_write[1024], data_read[1024];
+ GSocketConnection *server_stream, *client_stream;
+ GThread *write_thread, *read_thread;
+ guint i;
+
+ listener = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &err);
+ g_assert_no_error (err);
+ g_assert (G_IS_SOCKET (listener));
+
+ client = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &err);
+ g_assert_no_error (err);
+ g_assert (G_IS_SOCKET (client));
+
+ addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
+ saddr = g_inet_socket_address_new (addr, 0);
+
+ g_socket_bind (listener, saddr, TRUE, &err);
+ g_assert_no_error (err);
+ g_object_unref (saddr);
+ g_object_unref (addr);
+
+ saddr = g_socket_get_local_address (listener, &err);
+ g_assert_no_error (err);
+
+ g_socket_listen (listener, &err);
+ g_assert_no_error (err);
+ g_socket_connect (client, saddr, NULL, &err);
+ g_assert_no_error (err);
+
+ server = g_socket_accept (listener, NULL, &err);
+ g_assert_no_error (err);
+ g_socket_set_blocking (server, FALSE);
+ g_object_unref (listener);
+
+ server_stream = g_socket_connection_factory_create_connection (server);
+ g_assert_nonnull (server_stream);
+ client_stream = g_socket_connection_factory_create_connection (client);
+ g_assert_nonnull (client_stream);
+
+ for (i = 0; i < sizeof (data_write); i++)
+ data_write[i] = i;
+
+ data.is = g_io_stream_get_input_stream (G_IO_STREAM (server_stream));
+ data.os = g_io_stream_get_output_stream (G_IO_STREAM (client_stream));
+ data.read_data = data_read;
+ data.write_data = data_write;
+
+ if (writev)
+ write_thread = g_thread_new ("writer", test_read_write_writev_thread, &data);
+ else
+ write_thread = g_thread_new ("writer", test_read_write_write_thread, &data);
+ read_thread = g_thread_new ("reader", test_read_write_read_thread, &data);
+
+ g_thread_join (write_thread);
+ g_thread_join (read_thread);
+
+ g_assert_cmpmem (data_write, sizeof data_write, data_read, sizeof data_read);
+
+ g_socket_close (server, &err);
+ g_assert_no_error (err);
+
+ g_object_unref (server_stream);
+ g_object_unref (client_stream);
+
+ g_object_unref (saddr);
+ g_object_unref (server);
+ g_object_unref (client);
+}
+
int
main (int argc,
char *argv[])
@@ -1761,6 +1909,10 @@ main (int argc,
test_get_available);
g_test_add_data_func ("/socket/get_available/stream", GUINT_TO_POINTER (G_SOCKET_TYPE_STREAM),
test_get_available);
+ g_test_add_data_func ("/socket/read_write", GUINT_TO_POINTER (FALSE),
+ test_read_write);
+ g_test_add_data_func ("/socket/read_writev", GUINT_TO_POINTER (TRUE),
+ test_read_write);
return g_test_run();
}
diff --git a/gio/tests/test1.overlay b/gio/tests/test1.overlay
new file mode 100644
index 000000000..687d69b2a
--- /dev/null
+++ b/gio/tests/test1.overlay
@@ -0,0 +1 @@
+It is a beautiful day!
diff --git a/gio/tests/unix-streams.c b/gio/tests/unix-streams.c
index 67a90d83d..65eedb368 100644
--- a/gio/tests/unix-streams.c
+++ b/gio/tests/unix-streams.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
#define DATA "abcdefghijklmnopqrstuvwxyz"
@@ -351,6 +352,476 @@ test_basic (void)
g_object_unref (os);
}
+typedef struct {
+ GInputStream *is;
+ GOutputStream *os;
+ const guint8 *write_data;
+ guint8 *read_data;
+} TestReadWriteData;
+
+static gpointer
+test_read_write_write_thread (gpointer user_data)
+{
+ TestReadWriteData *data = user_data;
+ gsize bytes_written;
+ GError *error = NULL;
+ gboolean res;
+
+ res = g_output_stream_write_all (data->os, data->write_data, 1024, &bytes_written, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ g_assert_cmpuint (bytes_written, ==, 1024);
+
+ return NULL;
+}
+
+static gpointer
+test_read_write_read_thread (gpointer user_data)
+{
+ TestReadWriteData *data = user_data;
+ gsize bytes_read;
+ GError *error = NULL;
+ gboolean res;
+
+ res = g_input_stream_read_all (data->is, data->read_data, 1024, &bytes_read, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ g_assert_cmpuint (bytes_read, ==, 1024);
+
+ return NULL;
+}
+
+static gpointer
+test_read_write_writev_thread (gpointer user_data)
+{
+ TestReadWriteData *data = user_data;
+ gsize bytes_written;
+ GError *error = NULL;
+ gboolean res;
+ GOutputVector vectors[3];
+
+ vectors[0].buffer = data->write_data;
+ vectors[0].size = 256;
+ vectors[1].buffer = data->write_data + 256;
+ vectors[1].size = 256;
+ vectors[2].buffer = data->write_data + 512;
+ vectors[2].size = 512;
+
+ res = g_output_stream_writev_all (data->os, vectors, G_N_ELEMENTS (vectors), &bytes_written, NULL, &error);
+ g_assert_true (res);
+ g_assert_no_error (error);
+ g_assert_cmpuint (bytes_written, ==, 1024);
+
+ return NULL;
+}
+
+/* test if normal writing/reading from a pipe works */
+static void
+test_read_write (gconstpointer user_data)
+{
+ gboolean writev = GPOINTER_TO_INT (user_data);
+ GUnixInputStream *is;
+ GUnixOutputStream *os;
+ gint fd[2];
+ guint8 data_write[1024], data_read[1024];
+ guint i;
+ GThread *write_thread, *read_thread;
+ TestReadWriteData data;
+
+ for (i = 0; i < sizeof (data_write); i++)
+ data_write[i] = i;
+
+ g_assert_cmpint (pipe (fd), ==, 0);
+
+ is = G_UNIX_INPUT_STREAM (g_unix_input_stream_new (fd[0], TRUE));
+ os = G_UNIX_OUTPUT_STREAM (g_unix_output_stream_new (fd[1], TRUE));
+
+ data.is = G_INPUT_STREAM (is);
+ data.os = G_OUTPUT_STREAM (os);
+ data.read_data = data_read;
+ data.write_data = data_write;
+
+ if (writev)
+ write_thread = g_thread_new ("writer", test_read_write_writev_thread, &data);
+ else
+ write_thread = g_thread_new ("writer", test_read_write_write_thread, &data);
+ read_thread = g_thread_new ("reader", test_read_write_read_thread, &data);
+
+ g_thread_join (write_thread);
+ g_thread_join (read_thread);
+
+ g_assert_cmpmem (data_write, sizeof data_write, data_read, sizeof data_read);
+
+ g_object_unref (os);
+ g_object_unref (is);
+}
+
+/* test if g_pollable_output_stream_write_nonblocking() and
+ * g_pollable_output_stream_read_nonblocking() correctly return WOULD_BLOCK
+ * and correctly reset their status afterwards again, and all data that is
+ * written can also be read again.
+ */
+static void
+test_write_wouldblock (void)
+{
+#ifndef F_GETPIPE_SZ
+ g_test_skip ("F_GETPIPE_SZ not defined");
+#else /* if F_GETPIPE_SZ */
+ GUnixInputStream *is;
+ GUnixOutputStream *os;
+ gint fd[2];
+ GError *err = NULL;
+ guint8 data_write[1024], data_read[1024];
+ guint i;
+ gint pipe_capacity;
+
+ for (i = 0; i < sizeof (data_write); i++)
+ data_write[i] = i;
+
+ g_assert_cmpint (pipe (fd), ==, 0);
+
+ g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0);
+ pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL);
+ g_assert_cmpint (pipe_capacity, >=, 4096);
+ g_assert_cmpint (pipe_capacity % 1024, >=, 0);
+
+ is = G_UNIX_INPUT_STREAM (g_unix_input_stream_new (fd[0], TRUE));
+ os = G_UNIX_OUTPUT_STREAM (g_unix_output_stream_new (fd[1], TRUE));
+
+ /* Run the whole thing three times to make sure that the streams
+ * reset the writability/readability state again */
+ for (i = 0; i < 3; i++) {
+ gssize written = 0, written_complete = 0;
+ gssize read = 0, read_complete = 0;
+
+ do
+ {
+ written_complete += written;
+ written = g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (os),
+ data_write,
+ sizeof (data_write),
+ NULL,
+ &err);
+ }
+ while (written > 0);
+
+ g_assert_cmpuint (written_complete, >, 0);
+ g_assert_nonnull (err);
+ g_assert_error (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_clear_error (&err);
+
+ do
+ {
+ read_complete += read;
+ read = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (is),
+ data_read,
+ sizeof (data_read),
+ NULL,
+ &err);
+ if (read > 0)
+ g_assert_cmpmem (data_read, read, data_write, sizeof (data_write));
+ }
+ while (read > 0);
+
+ g_assert_cmpuint (read_complete, ==, written_complete);
+ g_assert_nonnull (err);
+ g_assert_error (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_clear_error (&err);
+ }
+
+ g_object_unref (os);
+ g_object_unref (is);
+#endif /* if F_GETPIPE_SZ */
+}
+
+/* test if g_pollable_output_stream_writev_nonblocking() and
+ * g_pollable_output_stream_read_nonblocking() correctly return WOULD_BLOCK
+ * and correctly reset their status afterwards again, and all data that is
+ * written can also be read again.
+ */
+static void
+test_writev_wouldblock (void)
+{
+#ifndef F_GETPIPE_SZ
+ g_test_skip ("F_GETPIPE_SZ not defined");
+#else /* if F_GETPIPE_SZ */
+ GUnixInputStream *is;
+ GUnixOutputStream *os;
+ gint fd[2];
+ GError *err = NULL;
+ guint8 data_write[1024], data_read[1024];
+ guint i;
+ GOutputVector vectors[4];
+ GPollableReturn res;
+ gint pipe_capacity;
+
+ for (i = 0; i < sizeof (data_write); i++)
+ data_write[i] = i;
+
+ g_assert_cmpint (pipe (fd), ==, 0);
+
+ g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0);
+ pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL);
+ g_assert_cmpint (pipe_capacity, >=, 4096);
+ g_assert_cmpint (pipe_capacity % 1024, >=, 0);
+
+ is = G_UNIX_INPUT_STREAM (g_unix_input_stream_new (fd[0], TRUE));
+ os = G_UNIX_OUTPUT_STREAM (g_unix_output_stream_new (fd[1], TRUE));
+
+ /* Run the whole thing three times to make sure that the streams
+ * reset the writability/readability state again */
+ for (i = 0; i < 3; i++) {
+ gsize written = 0, written_complete = 0;
+ gssize read = 0, read_complete = 0;
+
+ do
+ {
+ written_complete += written;
+
+ vectors[0].buffer = data_write;
+ vectors[0].size = 256;
+ vectors[1].buffer = data_write + 256;
+ vectors[1].size = 256;
+ vectors[2].buffer = data_write + 512;
+ vectors[2].size = 256;
+ vectors[3].buffer = data_write + 768;
+ vectors[3].size = 256;
+
+ res = g_pollable_output_stream_writev_nonblocking (G_POLLABLE_OUTPUT_STREAM (os),
+ vectors,
+ G_N_ELEMENTS (vectors),
+ &written,
+ NULL,
+ &err);
+ }
+ while (res == G_POLLABLE_RETURN_OK);
+
+ g_assert_cmpuint (written_complete, >, 0);
+ g_assert_null (err);
+ g_assert_cmpint (res, ==, G_POLLABLE_RETURN_WOULD_BLOCK);
+ /* writev() on UNIX streams either succeeds fully or not at all */
+ g_assert_cmpuint (written, ==, 0);
+
+ do
+ {
+ read_complete += read;
+ read = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (is),
+ data_read,
+ sizeof (data_read),
+ NULL,
+ &err);
+ if (read > 0)
+ g_assert_cmpmem (data_read, read, data_write, sizeof (data_write));
+ }
+ while (read > 0);
+
+ g_assert_cmpuint (read_complete, ==, written_complete);
+ g_assert_nonnull (err);
+ g_assert_error (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_clear_error (&err);
+ }
+
+ g_object_unref (os);
+ g_object_unref (is);
+#endif /* if F_GETPIPE_SZ */
+}
+
+#ifdef F_GETPIPE_SZ
+static void
+write_async_wouldblock_cb (GUnixOutputStream *os,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ gsize *bytes_written = user_data;
+ GError *err = NULL;
+
+ g_output_stream_write_all_finish (G_OUTPUT_STREAM (os), result, bytes_written, &err);
+ g_assert_no_error (err);
+}
+
+static void
+read_async_wouldblock_cb (GUnixInputStream *is,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ gsize *bytes_read = user_data;
+ GError *err = NULL;
+
+ g_input_stream_read_all_finish (G_INPUT_STREAM (is), result, bytes_read, &err);
+ g_assert_no_error (err);
+}
+#endif /* if F_GETPIPE_SZ */
+
+/* test if the async implementation of write_all() and read_all() in G*Stream
+ * around the GPollable*Stream API is working correctly.
+ */
+static void
+test_write_async_wouldblock (void)
+{
+#ifndef F_GETPIPE_SZ
+ g_test_skip ("F_GETPIPE_SZ not defined");
+#else /* if F_GETPIPE_SZ */
+ GUnixInputStream *is;
+ GUnixOutputStream *os;
+ gint fd[2];
+ guint8 *data, *data_read;
+ guint i;
+ gint pipe_capacity;
+ gsize bytes_written = 0, bytes_read = 0;
+
+ g_assert_cmpint (pipe (fd), ==, 0);
+
+ /* FIXME: These should not be needed but otherwise
+ * g_unix_output_stream_write() will block because
+ * a) the fd is writable
+ * b) writing 4x capacity will block because writes are atomic
+ * c) the fd is blocking
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/issues/1654
+ */
+ g_unix_set_fd_nonblocking (fd[0], TRUE, NULL);
+ g_unix_set_fd_nonblocking (fd[1], TRUE, NULL);
+
+ g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0);
+ pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL);
+ g_assert_cmpint (pipe_capacity, >=, 4096);
+
+ data = g_new (guint8, 4 * pipe_capacity);
+ for (i = 0; i < 4 * pipe_capacity; i++)
+ data[i] = i;
+ data_read = g_new (guint8, 4 * pipe_capacity);
+
+ is = G_UNIX_INPUT_STREAM (g_unix_input_stream_new (fd[0], TRUE));
+ os = G_UNIX_OUTPUT_STREAM (g_unix_output_stream_new (fd[1], TRUE));
+
+ g_output_stream_write_all_async (G_OUTPUT_STREAM (os),
+ data,
+ 4 * pipe_capacity,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) write_async_wouldblock_cb,
+ &bytes_written);
+
+ g_input_stream_read_all_async (G_INPUT_STREAM (is),
+ data_read,
+ 4 * pipe_capacity,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) read_async_wouldblock_cb,
+ &bytes_read);
+
+ while (bytes_written == 0 && bytes_read == 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (bytes_written, ==, 4 * pipe_capacity);
+ g_assert_cmpuint (bytes_read, ==, 4 * pipe_capacity);
+ g_assert_cmpmem (data_read, bytes_read, data, bytes_written);
+
+ g_free (data);
+ g_free (data_read);
+
+ g_object_unref (os);
+ g_object_unref (is);
+#endif /* if F_GETPIPE_SZ */
+}
+
+#ifdef F_GETPIPE_SZ
+static void
+writev_async_wouldblock_cb (GUnixOutputStream *os,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ gsize *bytes_written = user_data;
+ GError *err = NULL;
+
+ g_output_stream_writev_all_finish (G_OUTPUT_STREAM (os), result, bytes_written, &err);
+ g_assert_no_error (err);
+}
+#endif /* if F_GETPIPE_SZ */
+
+/* test if the async implementation of writev_all() and read_all() in G*Stream
+ * around the GPollable*Stream API is working correctly.
+ */
+static void
+test_writev_async_wouldblock (void)
+{
+#ifndef F_GETPIPE_SZ
+ g_test_skip ("F_GETPIPE_SZ not defined");
+#else /* if F_GETPIPE_SZ */
+ GUnixInputStream *is;
+ GUnixOutputStream *os;
+ gint fd[2];
+ guint8 *data, *data_read;
+ guint i;
+ gint pipe_capacity;
+ gsize bytes_written = 0, bytes_read = 0;
+ GOutputVector vectors[4];
+
+ g_assert_cmpint (pipe (fd), ==, 0);
+
+ /* FIXME: These should not be needed but otherwise
+ * g_unix_output_stream_writev() will block because
+ * a) the fd is writable
+ * b) writing 4x capacity will block because writes are atomic
+ * c) the fd is blocking
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/issues/1654
+ */
+ g_unix_set_fd_nonblocking (fd[0], TRUE, NULL);
+ g_unix_set_fd_nonblocking (fd[1], TRUE, NULL);
+
+ g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0);
+ pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL);
+ g_assert_cmpint (pipe_capacity, >=, 4096);
+
+ data = g_new (guint8, 4 * pipe_capacity);
+ for (i = 0; i < 4 * pipe_capacity; i++)
+ data[i] = i;
+ data_read = g_new (guint8, 4 * pipe_capacity);
+
+ vectors[0].buffer = data;
+ vectors[0].size = 1024;
+ vectors[1].buffer = data + 1024;
+ vectors[1].size = 1024;
+ vectors[2].buffer = data + 2048;
+ vectors[2].size = 1024;
+ vectors[3].buffer = data + 3072;
+ vectors[3].size = 4 * pipe_capacity - 3072;
+
+ is = G_UNIX_INPUT_STREAM (g_unix_input_stream_new (fd[0], TRUE));
+ os = G_UNIX_OUTPUT_STREAM (g_unix_output_stream_new (fd[1], TRUE));
+
+ g_output_stream_writev_all_async (G_OUTPUT_STREAM (os),
+ vectors,
+ G_N_ELEMENTS (vectors),
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) writev_async_wouldblock_cb,
+ &bytes_written);
+
+ g_input_stream_read_all_async (G_INPUT_STREAM (is),
+ data_read,
+ 4 * pipe_capacity,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ (GAsyncReadyCallback) read_async_wouldblock_cb,
+ &bytes_read);
+
+ while (bytes_written == 0 && bytes_read == 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (bytes_written, ==, 4 * pipe_capacity);
+ g_assert_cmpuint (bytes_read, ==, 4 * pipe_capacity);
+ g_assert_cmpmem (data_read, bytes_read, data, bytes_written);
+
+ g_free (data);
+ g_free (data_read);
+
+ g_object_unref (os);
+ g_object_unref (is);
+#endif /* F_GETPIPE_SZ */
+}
+
int
main (int argc,
char *argv[])
@@ -365,5 +836,23 @@ main (int argc,
GINT_TO_POINTER (TRUE),
test_pipe_io);
+ g_test_add_data_func ("/unix-streams/read_write",
+ GINT_TO_POINTER (FALSE),
+ test_read_write);
+
+ g_test_add_data_func ("/unix-streams/read_writev",
+ GINT_TO_POINTER (TRUE),
+ test_read_write);
+
+ g_test_add_func ("/unix-streams/write-wouldblock",
+ test_write_wouldblock);
+ g_test_add_func ("/unix-streams/writev-wouldblock",
+ test_writev_wouldblock);
+
+ g_test_add_func ("/unix-streams/write-async-wouldblock",
+ test_write_async_wouldblock);
+ g_test_add_func ("/unix-streams/writev-async-wouldblock",
+ test_writev_async_wouldblock);
+
return g_test_run();
}
diff --git a/gio/win32/Makefile.am b/gio/win32/Makefile.am
deleted file mode 100644
index 2fc10f65e..000000000
--- a/gio/win32/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-noinst_LTLIBRARIES += libgiowin32.la
-
-libgiowin32_la_SOURCES = \
- gwin32fsmonitorutils.c \
- gwin32fsmonitorutils.h \
- gwin32filemonitor.c \
- gwin32filemonitor.h \
- gwinhttpvfs.c \
- gwinhttpvfs.h \
- gwinhttpfile.c \
- gwinhttpfile.h \
- gwinhttpfileinputstream.c \
- gwinhttpfileinputstream.h \
- gwinhttpfileoutputstream.c \
- gwinhttpfileoutputstream.h \
- winhttp.h \
- $(NULL)
-
-libgiowin32_la_CFLAGS = \
- $(GLIB_HIDDEN_VISIBILITY_CFLAGS) \
- -DG_LOG_DOMAIN=\"GLib-GIO\" \
- $(gio_INCLUDES) \
- $(GLIB_DEBUG_FLAGS) \
- -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
- -DGIO_COMPILATION \
- -DG_DISABLE_DEPRECATED
diff --git a/gio/xdgmime/Makefile.am b/gio/xdgmime/Makefile.am
deleted file mode 100644
index 42348a6ab..000000000
--- a/gio/xdgmime/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-include $(top_srcdir)/glib.mk
-
-AM_CPPFLAGS = -DXDG_PREFIX=_gio_xdg
-
-noinst_LTLIBRARIES += libxdgmime.la
-
-libxdgmime_la_CFLAGS = $(GLIB_HIDDEN_VISIBILITY_CFLAGS)
-libxdgmime_la_SOURCES = \
- xdgmime.c \
- xdgmime.h \
- xdgmimealias.c \
- xdgmimealias.h \
- xdgmimecache.c \
- xdgmimecache.h \
- xdgmimeglob.c \
- xdgmimeglob.h \
- xdgmimeicon.c \
- xdgmimeicon.h \
- xdgmimeint.c \
- xdgmimeint.h \
- xdgmimemagic.c \
- xdgmimemagic.h \
- xdgmimeparent.c \
- xdgmimeparent.h