]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-event: add sd_event_add_inotify_fd() call
authorLennart Poettering <lennart@poettering.net>
Mon, 8 Nov 2021 23:10:58 +0000 (00:10 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 9 Nov 2021 12:02:13 +0000 (13:02 +0100)
sd_event_add_inotify_fd() is like sd_event_add_inotify(), but takes an
fd to an inode instead of a path, and is hence a ton nicer.

man/rules/meson.build
man/sd_event_add_inotify.xml
src/libsystemd/libsystemd.sym
src/libsystemd/sd-event/sd-event.c
src/systemd/sd-event.h

index ad7cc41c98347a62a2c55c3304b3485faa26ac60..7bf93fc16b66b40e6b4687e4ced90bed365a1cf8 100644 (file)
@@ -518,7 +518,9 @@ manpages = [
   ''],
  ['sd_event_add_inotify',
   '3',
-  ['sd_event_inotify_handler_t', 'sd_event_source_get_inotify_mask'],
+  ['sd_event_add_inotify_fd',
+   'sd_event_inotify_handler_t',
+   'sd_event_source_get_inotify_mask'],
   ''],
  ['sd_event_add_io',
   '3',
index 1681143eb15d4855298054f007df6b0943306897..d632bf7282ef9e021e2e440f470f1ebe231dc649 100644 (file)
@@ -17,6 +17,7 @@
 
   <refnamediv>
     <refname>sd_event_add_inotify</refname>
+    <refname>sd_event_add_inotify_fd</refname>
     <refname>sd_event_source_get_inotify_mask</refname>
     <refname>sd_event_inotify_handler_t</refname>
 
         <paramdef>void *<parameter>userdata</parameter></paramdef>
       </funcprototype>
 
+      <funcprototype>
+        <funcdef>int <function>sd_event_add_inotify_fd</function></funcdef>
+        <paramdef>sd_event *<parameter>event</parameter></paramdef>
+        <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+        <paramdef>int <parameter>fd</parameter></paramdef>
+        <paramdef>uint32_t <parameter>mask</parameter></paramdef>
+        <paramdef>sd_event_inotify_handler_t <parameter>handler</parameter></paramdef>
+        <paramdef>void *<parameter>userdata</parameter></paramdef>
+      </funcprototype>
+
       <funcprototype>
         <funcdef>int <function>sd_event_source_get_inotify_mask</function></funcdef>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
     <citerefentry project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
     further information.</para>
 
+    <para><function>sd_event_add_inotify_fd()</function> is identical to
+    <function>sd_event_add_inotify()</function>, except that it takes a file descriptor to an inode (possibly
+    an <constant>O_PATH</constant> one, but any other will do too) instead of a path in the file
+    system.</para>
+
     <para>If multiple event sources are installed for the same inode the backing inotify watch descriptor is
     automatically shared. The mask parameter may contain any flag defined by the inotify API, with the exception of
     <constant>IN_MASK_ADD</constant>.</para>
           <listitem><para>The passed event source is not an inotify process event source.</para></listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><constant>-EBADF</constant></term>
+
+          <listitem><para>The passed file descriptor is not valid.</para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>-ENOSYS</constant></term>
+
+          <listitem><para><function>sd_event_add_inotify_fd()</function> was called without
+          <filename>/proc/</filename> mounted.</para></listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect2>
   </refsect1>
index 04db791f644c4f2c00586c40568e36114823aec2..5e2fc9e2319eec847e28854b7b9e3144036ec6ff 100644 (file)
@@ -766,4 +766,5 @@ global:
 LIBSYSTEMD_250 {
 global:
         sd_device_get_diskseq;
+        sd_event_add_inotify_fd;
 } LIBSYSTEMD_249;
index 2a15e686d4531c9eb8997dfbe3fe1476a6370606..0ca02485108ee1628692f71e206175852658fb13 100644 (file)
@@ -1989,24 +1989,25 @@ static int inotify_exit_callback(sd_event_source *s, const struct inotify_event
         return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
 }
 
-_public_ int sd_event_add_inotify(
+static int event_add_inotify_fd_internal(
                 sd_event *e,
                 sd_event_source **ret,
-                const char *path,
+                int fd,
+                bool donate,
                 uint32_t mask,
                 sd_event_inotify_handler_t callback,
                 void *userdata) {
 
+        _cleanup_close_ int donated_fd = donate ? fd : -1;
+        _cleanup_(source_freep) sd_event_source *s = NULL;
         struct inotify_data *inotify_data = NULL;
         struct inode_data *inode_data = NULL;
-        _cleanup_close_ int fd = -1;
-        _cleanup_(source_freep) sd_event_source *s = NULL;
         struct stat st;
         int r;
 
         assert_return(e, -EINVAL);
         assert_return(e = event_resolve(e), -ENOPKG);
-        assert_return(path, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
@@ -2019,12 +2020,6 @@ _public_ int sd_event_add_inotify(
         if (mask & IN_MASK_ADD)
                 return -EINVAL;
 
-        fd = open(path, O_PATH|O_CLOEXEC|
-                  (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
-                  (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
-        if (fd < 0)
-                return -errno;
-
         if (fstat(fd, &st) < 0)
                 return -errno;
 
@@ -2044,14 +2039,24 @@ _public_ int sd_event_add_inotify(
 
         r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data);
         if (r < 0) {
-                event_free_inotify_data(e, inotify_data);
+                event_gc_inotify_data(e, inotify_data);
                 return r;
         }
 
         /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of
          * the event source, until then, for which we need the original inode. */
         if (inode_data->fd < 0) {
-                inode_data->fd = TAKE_FD(fd);
+                if (donated_fd >= 0)
+                        inode_data->fd = TAKE_FD(donated_fd);
+                else {
+                        inode_data->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+                        if (inode_data->fd < 0) {
+                                r = -errno;
+                                event_gc_inode_data(e, inode_data);
+                                return r;
+                        }
+                }
+
                 LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
         }
 
@@ -2064,8 +2069,6 @@ _public_ int sd_event_add_inotify(
         if (r < 0)
                 return r;
 
-        (void) sd_event_source_set_description(s, path);
-
         if (ret)
                 *ret = s;
         TAKE_PTR(s);
@@ -2073,6 +2076,48 @@ _public_ int sd_event_add_inotify(
         return 0;
 }
 
+_public_ int sd_event_add_inotify_fd(
+                sd_event *e,
+                sd_event_source **ret,
+                int fd,
+                uint32_t mask,
+                sd_event_inotify_handler_t callback,
+                void *userdata) {
+
+        return event_add_inotify_fd_internal(e, ret, fd, /* donate= */ false, mask, callback, userdata);
+}
+
+_public_ int sd_event_add_inotify(
+                sd_event *e,
+                sd_event_source **ret,
+                const char *path,
+                uint32_t mask,
+                sd_event_inotify_handler_t callback,
+                void *userdata) {
+
+        sd_event_source *s;
+        int fd, r;
+
+        assert_return(path, -EINVAL);
+
+        fd = open(path, O_PATH|O_CLOEXEC|
+                  (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
+                  (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
+        if (fd < 0)
+                return -errno;
+
+        r = event_add_inotify_fd_internal(e, &s, fd, /* donate= */ true, mask, callback, userdata);
+        if (r < 0)
+                return r;
+
+        (void) sd_event_source_set_description(s, path);
+
+        if (ret)
+                *ret = s;
+
+        return r;
+}
+
 static sd_event_source* event_source_free(sd_event_source *s) {
         if (!s)
                 return NULL;
index 2ae2a0da48a2ac180ad6504e5fee92ce4d6e0f5f..f4357aa59306775b691ce6f8d7530a91a19f33f4 100644 (file)
@@ -93,6 +93,7 @@ int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_sign
 int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
 int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata);
 int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
+int sd_event_add_inotify_fd(sd_event *e, sd_event_source **s, int fd, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
 int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
 int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
 int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);