configure.ac: Move OggVorbis Encoder to Encoder Plugins.
[mpd-mk.git] / src / inotify_source.c
blobd4b047fe18f5104336dc38753fec1cbf130ed15e
1 /*
2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
21 #include "inotify_source.h"
22 #include "fifo_buffer.h"
23 #include "fd_util.h"
25 #include <sys/inotify.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <stdbool.h>
30 #undef G_LOG_DOMAIN
31 #define G_LOG_DOMAIN "inotify"
33 struct mpd_inotify_source {
34 int fd;
36 GIOChannel *channel;
38 /**
39 * The channel's source id in the GLib main loop.
41 guint id;
43 struct fifo_buffer *buffer;
45 mpd_inotify_callback_t callback;
46 void *callback_ctx;
49 /**
50 * A GQuark for GError instances.
52 static inline GQuark
53 mpd_inotify_quark(void)
55 return g_quark_from_static_string("inotify");
58 static gboolean
59 mpd_inotify_in_event(G_GNUC_UNUSED GIOChannel *_source,
60 G_GNUC_UNUSED GIOCondition condition,
61 gpointer data)
63 struct mpd_inotify_source *source = data;
64 void *dest;
65 size_t length;
66 ssize_t nbytes;
67 const struct inotify_event *event;
69 dest = fifo_buffer_write(source->buffer, &length);
70 if (dest == NULL)
71 g_error("buffer full");
73 nbytes = read(source->fd, dest, length);
74 if (nbytes < 0)
75 g_error("failed to read from inotify: %s", g_strerror(errno));
76 if (nbytes == 0)
77 g_error("end of file from inotify");
79 fifo_buffer_append(source->buffer, nbytes);
81 while (true) {
82 const char *name;
84 event = fifo_buffer_read(source->buffer, &length);
85 if (event == NULL || length < sizeof(*event) ||
86 length < sizeof(*event) + event->len)
87 break;
89 if (event->len > 0 && event->name[event->len - 1] == 0)
90 name = event->name;
91 else
92 name = NULL;
94 source->callback(event->wd, event->mask, name,
95 source->callback_ctx);
96 fifo_buffer_consume(source->buffer,
97 sizeof(*event) + event->len);
100 return true;
103 struct mpd_inotify_source *
104 mpd_inotify_source_new(mpd_inotify_callback_t callback, void *callback_ctx,
105 GError **error_r)
107 struct mpd_inotify_source *source =
108 g_new(struct mpd_inotify_source, 1);
110 source->fd = inotify_init_cloexec();
111 if (source->fd < 0) {
112 g_set_error(error_r, mpd_inotify_quark(), errno,
113 "inotify_init() has failed: %s",
114 g_strerror(errno));
115 g_free(source);
116 return NULL;
119 source->buffer = fifo_buffer_new(4096);
121 source->channel = g_io_channel_unix_new(source->fd);
122 source->id = g_io_add_watch(source->channel, G_IO_IN,
123 mpd_inotify_in_event, source);
125 source->callback = callback;
126 source->callback_ctx = callback_ctx;
128 return source;
131 void
132 mpd_inotify_source_free(struct mpd_inotify_source *source)
134 g_source_remove(source->id);
135 g_io_channel_unref(source->channel);
136 fifo_buffer_free(source->buffer);
137 close(source->fd);
138 g_free(source);
142 mpd_inotify_source_add(struct mpd_inotify_source *source,
143 const char *path_fs, unsigned mask,
144 GError **error_r)
146 int wd = inotify_add_watch(source->fd, path_fs, mask);
147 if (wd < 0)
148 g_set_error(error_r, mpd_inotify_quark(), errno,
149 "inotify_add_watch() has failed: %s",
150 g_strerror(errno));
152 return wd;
155 void
156 mpd_inotify_source_rm(struct mpd_inotify_source *source, unsigned wd)
158 int ret = inotify_rm_watch(source->fd, wd);
159 if (ret < 0 && errno != EINVAL)
160 g_warning("inotify_rm_watch() has failed: %s",
161 g_strerror(errno));
163 /* EINVAL may happen here when the file has been deleted; the
164 kernel seems to auto-unregister deleted files */