@@ -617,6 +617,52 @@ static int property_get_set_callbacks_run(
617617 return 1 ;
618618}
619619
620+ static int vtable_append_one_property (
621+ sd_bus * bus ,
622+ sd_bus_message * reply ,
623+ const char * path ,
624+ struct node_vtable * c ,
625+ const sd_bus_vtable * v ,
626+ void * userdata ,
627+ sd_bus_error * error ) {
628+
629+ int r ;
630+
631+ assert (bus );
632+ assert (reply );
633+ assert (path );
634+ assert (c );
635+ assert (v );
636+
637+ r = sd_bus_message_open_container (reply , 'e' , "sv" );
638+ if (r < 0 )
639+ return r ;
640+
641+ r = sd_bus_message_append (reply , "s" , v -> x .property .member );
642+ if (r < 0 )
643+ return r ;
644+
645+ r = sd_bus_message_open_container (reply , 'v' , v -> x .property .signature );
646+ if (r < 0 )
647+ return r ;
648+
649+ r = invoke_property_get (bus , v , path , c -> interface , v -> x .property .member , reply , vtable_property_convert_userdata (v , userdata ), error );
650+ if (r < 0 )
651+ return r ;
652+ if (bus -> nodes_modified )
653+ return 0 ;
654+
655+ r = sd_bus_message_close_container (reply );
656+ if (r < 0 )
657+ return r ;
658+
659+ r = sd_bus_message_close_container (reply );
660+ if (r < 0 )
661+ return r ;
662+
663+ return 0 ;
664+ }
665+
620666static int vtable_append_all_properties (
621667 sd_bus * bus ,
622668 sd_bus_message * reply ,
@@ -643,31 +689,11 @@ static int vtable_append_all_properties(
643689 if (v -> flags & SD_BUS_VTABLE_HIDDEN )
644690 continue ;
645691
646- r = sd_bus_message_open_container (reply , 'e' , "sv" );
647- if (r < 0 )
648- return r ;
649-
650- r = sd_bus_message_append (reply , "s" , v -> x .property .member );
651- if (r < 0 )
652- return r ;
653-
654- r = sd_bus_message_open_container (reply , 'v' , v -> x .property .signature );
655- if (r < 0 )
656- return r ;
657-
658- r = invoke_property_get (bus , v , path , c -> interface , v -> x .property .member , reply , vtable_property_convert_userdata (v , userdata ), error );
692+ r = vtable_append_one_property (bus , reply , path , c , v , userdata , error );
659693 if (r < 0 )
660694 return r ;
661695 if (bus -> nodes_modified )
662696 return 0 ;
663-
664- r = sd_bus_message_close_container (reply );
665- if (r < 0 )
666- return r ;
667-
668- r = sd_bus_message_close_container (reply );
669- if (r < 0 )
670- return r ;
671697 }
672698
673699 return 1 ;
@@ -1996,57 +2022,75 @@ static int emit_properties_changed_on_interface(
19962022 if (r == 0 )
19972023 continue ;
19982024
1999- STRV_FOREACH (property , names ) {
2000- struct vtable_member * v ;
2025+ if (names ) {
2026+ /* If the caller specified a list of
2027+ * properties we include exactly those in the
2028+ * PropertiesChanged message */
20012029
2002- assert_return (member_name_is_valid (* property ), - EINVAL );
2030+ STRV_FOREACH (property , names ) {
2031+ struct vtable_member * v ;
20032032
2004- key .member = * property ;
2005- v = hashmap_get (bus -> vtable_properties , & key );
2006- if (!v )
2007- return - ENOENT ;
2033+ assert_return (member_name_is_valid (* property ), - EINVAL );
20082034
2009- /* If there are two vtables for the same
2010- * interface, let's handle this property when
2011- * we come to that vtable. */
2012- if (c != v -> parent )
2013- continue ;
2035+ key .member = * property ;
2036+ v = hashmap_get (bus -> vtable_properties , & key );
2037+ if (!v )
2038+ return - ENOENT ;
2039+
2040+ /* If there are two vtables for the same
2041+ * interface, let's handle this property when
2042+ * we come to that vtable. */
2043+ if (c != v -> parent )
2044+ continue ;
20142045
2015- assert_return (v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ||
2016- v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION , - EDOM );
2046+ assert_return (v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ||
2047+ v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION , - EDOM );
20172048
2018- if (v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION ) {
2019- has_invalidating = true;
2020- continue ;
2049+ assert_return (!(v -> vtable -> flags & SD_BUS_VTABLE_HIDDEN ), - EDOM );
2050+
2051+ if (v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION ) {
2052+ has_invalidating = true;
2053+ continue ;
2054+ }
2055+
2056+ has_changing = true;
2057+
2058+ r = vtable_append_one_property (bus , m , m -> path , c , v -> vtable , u , & error );
2059+ if (r < 0 )
2060+ return r ;
2061+ if (bus -> nodes_modified )
2062+ return 0 ;
20212063 }
2064+ } else {
2065+ const sd_bus_vtable * v ;
20222066
2023- has_changing = true;
2067+ /* If the caller specified no properties list
2068+ * we include all properties that are marked
2069+ * as changing in the message. */
20242070
2025- r = sd_bus_message_open_container ( m , 'e' , "sv" );
2026- if (r < 0 )
2027- return r ;
2071+ for ( v = c -> vtable + 1 ; v -> type != _SD_BUS_VTABLE_END ; v ++ ) {
2072+ if (v -> type != _SD_BUS_VTABLE_PROPERTY && v -> type != _SD_BUS_VTABLE_WRITABLE_PROPERTY )
2073+ continue ;
20282074
2029- r = sd_bus_message_append (m , "s" , * property );
2030- if (r < 0 )
2031- return r ;
2075+ if (v -> flags & SD_BUS_VTABLE_HIDDEN )
2076+ continue ;
20322077
2033- r = sd_bus_message_open_container (m , 'v' , v -> vtable -> x .property .signature );
2034- if (r < 0 )
2035- return r ;
2078+ if (v -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION ) {
2079+ has_invalidating = true;
2080+ continue ;
2081+ }
20362082
2037- r = invoke_property_get (bus , v -> vtable , m -> path , interface , * property , m , vtable_property_convert_userdata (v -> vtable , u ), & error );
2038- if (r < 0 )
2039- return r ;
2040- if (bus -> nodes_modified )
2041- return 0 ;
2083+ if (!(v -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ))
2084+ continue ;
20422085
2043- r = sd_bus_message_close_container (m );
2044- if (r < 0 )
2045- return r ;
2086+ has_changing = true;
20462087
2047- r = sd_bus_message_close_container (m );
2048- if (r < 0 )
2049- return r ;
2088+ r = vtable_append_one_property (bus , m , m -> path , c , v , u , & error );
2089+ if (r < 0 )
2090+ return r ;
2091+ if (bus -> nodes_modified )
2092+ return 0 ;
2093+ }
20502094 }
20512095 }
20522096
@@ -2077,19 +2121,38 @@ static int emit_properties_changed_on_interface(
20772121 if (r == 0 )
20782122 continue ;
20792123
2080- STRV_FOREACH (property , names ) {
2081- struct vtable_member * v ;
2124+ if (names ) {
2125+ STRV_FOREACH (property , names ) {
2126+ struct vtable_member * v ;
20822127
2083- key .member = * property ;
2084- assert_se (v = hashmap_get (bus -> vtable_properties , & key ));
2085- assert (c == v -> parent );
2128+ key .member = * property ;
2129+ assert_se (v = hashmap_get (bus -> vtable_properties , & key ));
2130+ assert (c == v -> parent );
20862131
2087- if (!(v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION ))
2088- continue ;
2132+ if (!(v -> vtable -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION ))
2133+ continue ;
20892134
2090- r = sd_bus_message_append (m , "s" , * property );
2091- if (r < 0 )
2092- return r ;
2135+ r = sd_bus_message_append (m , "s" , * property );
2136+ if (r < 0 )
2137+ return r ;
2138+ }
2139+ } else {
2140+ const sd_bus_vtable * v ;
2141+
2142+ for (v = c -> vtable + 1 ; v -> type != _SD_BUS_VTABLE_END ; v ++ ) {
2143+ if (v -> type != _SD_BUS_VTABLE_PROPERTY && v -> type != _SD_BUS_VTABLE_WRITABLE_PROPERTY )
2144+ continue ;
2145+
2146+ if (v -> flags & SD_BUS_VTABLE_HIDDEN )
2147+ continue ;
2148+
2149+ if (!(v -> flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION ))
2150+ continue ;
2151+
2152+ r = sd_bus_message_append (m , "s" , v -> x .property .member );
2153+ if (r < 0 )
2154+ return r ;
2155+ }
20932156 }
20942157 }
20952158 }
@@ -2121,7 +2184,12 @@ _public_ int sd_bus_emit_properties_changed_strv(
21212184 assert_return (BUS_IS_OPEN (bus -> state ), - ENOTCONN );
21222185 assert_return (!bus_pid_changed (bus ), - ECHILD );
21232186
2124- if (strv_isempty (names ))
2187+
2188+ /* A non-NULL but empty names list means nothing needs to be
2189+ generated. A NULL list OTOH indicates that all properties
2190+ that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be
2191+ included in the PropertiesChanged message. */
2192+ if (names && names [0 ] == NULL )
21252193 return 0 ;
21262194
21272195 do {
0 commit comments