]>
Dogcows Code - chaz/openbox/blob - obt/watch.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/watch.c for the Openbox window manager
4 Copyright (c) 2010 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 #include "obt/watch.h"
21 #ifdef HAVE_SYS_INOTIFY_H
22 # include <sys/inotify.h>
35 #ifdef HAVE_SYS_INOTIFY_H
36 GHashTable
*targets_by_wd
;
40 typedef struct _ObtWatchTarget
{
43 #ifdef HAVE_SYS_INOTIFY_H
52 static void init_inot(ObtWatch
*w
);
53 static gboolean
read_inot(GIOChannel
*s
, GIOCondition cond
, gpointer data
);
54 static gboolean
add_inot(ObtWatch
*w
, ObtWatchTarget
*t
, const char *path
,
56 static void rm_inot(ObtWatchTarget
*t
);
57 static ObtWatchTarget
* target_new(ObtWatch
*w
, const gchar
*path
,
58 ObtWatchFunc func
, gpointer data
);
59 static void target_free(ObtWatchTarget
*t
);
61 ObtWatch
* obt_watch_new()
65 w
= g_slice_new(ObtWatch
);
68 w
->targets
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
69 NULL
, (GDestroyNotify
)target_free
);
70 #ifdef HAVE_SYS_INOTIFY_H
71 w
->targets_by_wd
= g_hash_table_new(g_int_hash
, g_int_equal
);
78 void obt_watch_ref(ObtWatch
*w
)
83 void obt_watch_unref(ObtWatch
*w
)
86 if (w
->ino_fd
>= 0 && w
->ino_watch
)
87 g_source_remove(w
->ino_watch
);
89 g_hash_table_destroy(w
->targets
);
90 g_hash_table_destroy(w
->targets_by_wd
);
92 g_slice_free(ObtWatch
, w
);
96 static void init_inot(ObtWatch
*w
)
98 #ifdef HAVE_SYS_INOTIFY_H
99 if (w
->ino_fd
>= 0) return;
101 w
->ino_fd
= inotify_init();
102 if (w
->ino_fd
>= 0) {
105 ch
= g_io_channel_unix_new(w
->ino_fd
);
106 w
->ino_watch
= g_io_add_watch(ch
, G_IO_IN
| G_IO_HUP
| G_IO_ERR
,
108 g_io_channel_unref(ch
);
113 static gboolean
read_inot(GIOChannel
*src
, GIOCondition cond
, gpointer data
)
115 #ifdef HAVE_SYS_INOTIFY_H
118 struct inotify_event s
;
124 for (ilen
= 0; ilen
< sizeof(s
); ilen
+= len
) {
125 len
= read(w
->ino_fd
, ((char*)&s
)+ilen
, sizeof(s
)-ilen
);
126 if (len
< 0 && errno
!= EINTR
) return FALSE
; /* error, don't repeat */
127 if (!len
) return TRUE
; /* nothing there */
130 name
= g_new(char, s
.len
);
132 /* read the filename */
133 for (ilen
= 0; ilen
< s
.len
; ilen
+= len
) {
134 len
= read(w
->ino_fd
, name
+ilen
, s
.len
-ilen
);
135 if (len
< 0 && errno
!= EINTR
) return FALSE
; /* error, don't repeat */
136 if (!len
) return TRUE
; /* nothing there */
139 t
= g_hash_table_lookup(w
->targets
, &s
.wd
);
140 if (t
) t
->func(w
, name
, t
->data
);
144 return TRUE
; /* repeat */
147 static gboolean
add_inot(ObtWatch
*w
, ObtWatchTarget
*t
, const char *path
,
150 #ifndef HAVE_SYS_INOTIFY_H
154 if (w
->ino_fd
< 0) return FALSE
;
155 if (dir
) mask
= IN_MODIFY
| IN_CREATE
| IN_DELETE
| IN_MOVE
;
156 else g_assert_not_reached();
157 t
->wd
= inotify_add_watch(w
->ino_fd
, path
, mask
);
162 static void rm_inot(ObtWatchTarget
*t
)
164 #ifdef HAVE_SYS_INOTIFY_H
165 if (t
->w
->ino_fd
< 0) return;
166 if (t
->wd
< 0) return;
167 inotify_rm_watch(t
->w
->ino_fd
, t
->wd
);
171 static ObtWatchTarget
* target_new(ObtWatch
*w
, const gchar
*path
,
172 ObtWatchFunc func
, gpointer data
)
176 t
= g_slice_new0(ObtWatchTarget
);
179 t
->path
= g_strdup(path
);
183 if (!add_inot(w
, t
, path
, TRUE
)) {
184 g_assert_not_reached(); /* XXX do something */
187 #ifndef HAVE_SYS_INOTIFY_H
188 #error need inotify for now
194 static void target_free(ObtWatchTarget
*t
)
199 g_slice_free(ObtWatchTarget
, t
);
202 void obt_paths_watch_dir(ObtWatch
*w
, const gchar
*path
,
203 ObtWatchFunc func
, gpointer data
)
207 g_return_if_fail(w
!= NULL
);
208 g_return_if_fail(path
!= NULL
);
209 g_return_if_fail(data
!= NULL
);
211 t
= target_new(w
, path
, func
, data
);
212 g_hash_table_insert(w
->targets
, t
->path
, t
);
213 #ifdef HAVE_SYS_INOTIFY_H
214 g_hash_table_insert(w
->targets_by_wd
, &t
->wd
, t
);
218 void obt_paths_unwatch_dir(ObtWatch
*w
, const gchar
*path
)
222 g_return_if_fail(w
!= NULL
);
223 g_return_if_fail(path
!= NULL
);
225 t
= g_hash_table_lookup(w
->targets
, path
);
228 #ifdef HAVE_SYS_INOTIFY_H
229 g_hash_table_remove(w
->targets_by_wd
, &t
->wd
);
231 g_hash_table_remove(w
->targets
, path
);
This page took 0.043687 seconds and 4 git commands to generate.