</tgroup>
</table>
- <para>For types "s" and "g" (unicode string or signature), the pointer may be
- <constant>NULL</constant>, which is equivalent to an empty string. See
+ <para>For types <literal>s</literal> and <literal>g</literal> (unicode string or signature), the pointer
+ may be <constant>NULL</constant>, which is equivalent to an empty string. For <literal>h</literal> (UNIX
+ file descriptor), the descriptor is duplicated by this call and the passed descriptor stays in possession
+ of the caller. See
<citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for the precise interpretation of those and other types.</para>
</refsect1>
should be read. See the table below for a complete list of allowed arguments and their types. Note that,
if the basic type is a pointer (e.g., <type>const char *</type> in the case of a string), the argument is
a pointer to a pointer, and also the pointer value that is written is only borrowed and the contents must
- be copied if they are to be used after the end of the messages lifetime.</para>
+ be copied if they are to be used after the end of the messages lifetime. If the type is
+ <literal>h</literal> (UNIX file descriptor), the descriptor is not duplicated by this call and the
+ returned descriptor remains in possession of the message object, and needs to be duplicated by the caller
+ in order to keep an open reference to it after the message object is freed.</para>
<para>Each argument may also be <constant>NULL</constant>, in which case the value is read and ignored.
</para>
sd_bus_message_read(m, "a{is}", 3, &i, &s, &j, &t, &k, &u);
</programlisting>
+
+ <para>Read a single file descriptor, and duplicate it in order to keep it open after the message is
+ freed.</para>
+
+ <programlisting>sd_bus_message *m;
+int fd, fd_copy;
+
+sd_bus_message_read(m, "h", &fd);
+fd_copy = fcntl(fd, FD_DUPFD_CLOEXEC, 3);</programlisting>
</refsect1>
<refsect1>
</para>
<para>
- If <parameter>p</parameter> is not <constant>NULL</constant>, it should contain
- a pointer to an appropriate object. For example, if <parameter>type</parameter>
- is <constant>'y'</constant>, the object passed in <parameter>p</parameter>
- should have type <type>uint8_t *</type>. If <parameter>type</parameter> is
- <constant>'s'</constant>, the object passed in <parameter>p</parameter> should
- have type <type>const char **</type>. Note that, if the basic type is a pointer
- (e.g., <type>const char *</type> in the case of a string), the pointer is only
- borrowed and the contents must be copied if they are to be used after the end
- of the messages lifetime. Similarly, during the lifetime of such a pointer, the
- message must not be modified. See the table below for a complete list of allowed
- types.
+ If <parameter>p</parameter> is not <constant>NULL</constant>, it should contain a pointer to an
+ appropriate object. For example, if <parameter>type</parameter> is <constant>'y'</constant>, the object
+ passed in <parameter>p</parameter> should have type <type>uint8_t *</type>. If
+ <parameter>type</parameter> is <constant>'s'</constant>, the object passed in <parameter>p</parameter>
+ should have type <type>const char **</type>. Note that, if the basic type is a pointer (e.g.,
+ <type>const char *</type> in the case of a string), the pointer is only borrowed and the contents must
+ be copied if they are to be used after the end of the messages lifetime. Similarly, during the lifetime
+ of such a pointer, the message must not be modified. If <parameter>type</parameter> is
+ <constant>'h'</constant> (UNIX file descriptor), the descriptor is not duplicated by this call and the
+ returned descriptor remains in possession of the message object, and needs to be duplicated by the caller
+ in order to keep an open reference to it after the message object is freed (for example by calling
+ <literal>fcntl(fd, FD_DUPFD_CLOEXEC, 3)</literal>). See the table below for a complete list of
+ allowed types.
</para>
<table id='format-specifiers'>