<funcprototype>
<funcdef>int <function>sd_event_source_get_inotify_path</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
- <paramdef>char **<parameter>ret</parameter></paramdef>
+ <paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para><function>sd_event_source_get_inotify_path()</function> retrieves the target path of the configured
inotify watch of an event source created previously with <function>sd_event_add_inotify()</function>. It
takes the event source object as the <parameter>source</parameter> parameter and a pointer to a
- <type>char **</type> variable to return the path in. The caller needs to free the returned path.</para>
+ <type>const char **</type> variable to return the path in. The caller must not free the returned path.
+ </para>
</refsect1>
<refsect1>
<varlistentry>
<term><constant>-ENOSYS</constant></term>
- <listitem><para><function>sd_event_add_inotify_fd()</function> was called without
- <filename>/proc/</filename> mounted.</para></listitem>
+ <listitem>
+ <para><function>sd_event_add_inotify_fd()</function> or
+ <function>sd_event_source_get_inotify_path()</function> was called without
+ <filename>/proc/</filename> mounted.</para>
+ </listitem>
</varlistentry>
assert_se(hashmap_remove(d->inotify_data->inodes, d) == d);
}
+ free(d->path);
free(d);
}
}
LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data);
+
+ _cleanup_free_ char *path = NULL;
+ r = fd_get_path(inode_data->fd, &path);
+ if (r < 0 && r != -ENOSYS) { /* The path is optional, hence ignore -ENOSYS. */
+ event_gc_inode_data(e, inode_data);
+ return r;
+ }
+
+ free_and_replace(inode_data->path, path);
}
/* Link our event source to the inode data object */
}
LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data);
+
+ _cleanup_free_ char *path = NULL;
+ r = fd_get_path(new_inode_data->fd, &path);
+ if (r < 0 && r != -ENOSYS)
+ goto fail;
+
+ free_and_replace(new_inode_data->path, path);
}
/* Move the event source to the new inode data structure */
return 0;
}
-_public_ int sd_event_source_get_inotify_path(sd_event_source *s, char **ret) {
+_public_ int sd_event_source_get_inotify_path(sd_event_source *s, const char **ret) {
assert_return(s, -EINVAL);
assert_return(ret, -EINVAL);
assert_return(s->type == SOURCE_INOTIFY, -EDOM);
assert_return(!event_origin_changed(s->event), -ECHILD);
- if (!s->inotify.inode_data || s->inotify.inode_data->fd < 0)
- return -ESTALE;
+ if (!s->inotify.inode_data)
+ return -ESTALE; /* already disconnected. */
- return fd_get_path(s->inotify.inode_data->fd, ret);
+ if (!s->inotify.inode_data->path)
+ return -ENOSYS; /* /proc was not mounted? */
+
+ *ret = s->inotify.inode_data->path;
+ return 0;
}
_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
unsigned create_called[CREATE_EVENTS_MAX];
unsigned create_overflow;
unsigned n_create_events;
+ const char *path;
};
static void maybe_exit(sd_event_source *s, struct inotify_context *c) {
}
static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
- struct inotify_context *c = userdata;
- const char *description;
+ struct inotify_context *c = ASSERT_PTR(userdata);
+ const char *path, *description;
unsigned bit, n;
+ assert_se(sd_event_source_get_inotify_path(s, &path) >= 0);
+
assert_se(sd_event_source_get_description(s, &description) >= 0);
assert_se(safe_atou(description, &n) >= 0);
bit = 1U << n;
if (ev->mask & IN_Q_OVERFLOW) {
- log_info("inotify-handler <%s>: overflow", description);
+ log_info("inotify-handler for %s <%s>: overflow", path, description);
c->create_overflow |= bit;
} else if (ev->mask & IN_CREATE) {
+ assert_se(path_equal_or_inode_same(path, c->path, 0));
if (streq(ev->name, "sub"))
- log_debug("inotify-handler <%s>: create on %s", description, ev->name);
+ log_debug("inotify-handler for %s <%s>: create on %s", path, description, ev->name);
else {
unsigned i;
c->create_called[i] |= bit;
}
} else if (ev->mask & IN_DELETE) {
- log_info("inotify-handler <%s>: delete of %s", description, ev->name);
+ log_info("inotify-handler for %s <%s>: delete of %s", path, description, ev->name);
assert_se(streq(ev->name, "sub"));
} else
assert_not_reached();
}
static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
- struct inotify_context *c = userdata;
+ struct inotify_context *c = ASSERT_PTR(userdata);
+ const char *path;
+
+ assert_se(sd_event_source_get_inotify_path(s, &path) >= 0);
if (ev->mask & IN_Q_OVERFLOW) {
- log_info("delete-self-handler: overflow");
+ log_info("delete-self-handler for %s: overflow", path);
c->delete_self_handler_called = true;
} else if (ev->mask & IN_DELETE_SELF) {
- log_info("delete-self-handler: delete-self");
+ log_info("delete-self-handler for %s: delete-self", path);
c->delete_self_handler_called = true;
} else if (ev->mask & IN_IGNORED) {
- log_info("delete-self-handler: ignore");
+ log_info("delete-self-handler for %s: ignore", path);
} else
assert_not_reached();
static void test_inotify_one(unsigned n_create_events) {
_cleanup_(rm_rf_physical_and_freep) char *p = NULL;
- _cleanup_free_ char *pp = NULL;
sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL;
struct inotify_context context = {
.n_create_events = n_create_events,
};
sd_event *e = NULL;
- const char *q;
+ const char *q, *pp;
unsigned i;
log_info("/* %s(%u) */", __func__, n_create_events);
assert_se(sd_event_default(&e) >= 0);
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
+ context.path = p;
assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0);
assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0);
assert_se(sd_event_source_get_inotify_path(a, &pp) >= 0);
assert_se(path_equal_or_inode_same(pp, p, 0));
- pp = mfree(pp);
assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
assert_se(path_equal_or_inode_same(pp, p, 0));
- pp = mfree(pp);
assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
assert_se(path_equal_or_inode_same(pp, p, 0));
- pp = mfree(pp);
q = strjoina(p, "/sub");
assert_se(touch(q) >= 0);