1 /* Copyright (C) 2008 Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 gboolean inotify_enabled
= FALSE
, debug_inotify
= FALSE
;
22 GHashTable
*watches_table
;
23 int inotify_descriptor
;
24 char events_buffer
[BUFFER_LENGTH
];
26 void init_inotify(GNode
*tree_root
)
28 if ((inotify_descriptor
= inotify_init()) == -1) {
32 watches_table
= g_hash_table_new(g_int_hash
, g_int_equal
);
33 inotify_enabled
= TRUE
;
36 void stop_inotify(void)
38 CHECK_INOTIFY_ENABLED();
39 g_hash_table_destroy(watches_table
);
40 close(inotify_descriptor
);
41 inotify_enabled
= FALSE
;
44 void add_watch_directory(GNode
*directory
)
49 CHECK_INOTIFY_ENABLED();
50 path
= get_path(directory
);
51 if ((watch
= inotify_add_watch(inotify_descriptor
, path
, IN_CREATE
| IN_MOVED_FROM
|
52 IN_MOVED_TO
| IN_DELETE
)) == -1)
55 FILE(directory
)->watch
= watch
;
56 g_hash_table_insert(watches_table
, &(FILE(directory
)->watch
), directory
);
61 void remove_watch_directory(GNode
*directory
, gboolean remove_watch
)
63 CHECK_INOTIFY_ENABLED();
64 if (FILE(directory
)->watch
== -1)
65 PRINT_ERROR_INFO("Directory doesn't have a watch associated");
66 else if (remove_watch
&& inotify_rm_watch(inotify_descriptor
, FILE(directory
)->watch
) == -1)
68 else if (g_hash_table_remove(watches_table
, &(FILE(directory
)->watch
)) == FALSE
)
69 PRINT_ERROR_INFO("Element removal failed in watches_table");
72 void watch_events(void)
74 GNode
*modified_directory
, *removed_file
;
76 gboolean refresh_request
= FALSE
;
78 struct inotify_event
*event
;
82 CHECK_INOTIFY_ENABLED();
83 again
: time
.tv_sec
= 0;
86 FD_SET(inotify_descriptor
, &fds
);
87 while ((n
= select(inotify_descriptor
+ 1, &fds
, NULL
, NULL
, &time
)) == 1) {
88 again2
: if ((n
= read(inotify_descriptor
, events_buffer
, BUFFER_LENGTH
)) > 0) {
89 for (i
= 0; i
< n
; i
+= sizeof(struct inotify_event
) + event
->len
) {
90 event
= (struct inotify_event
*) (events_buffer
+ i
);
91 if (debug_inotify
== TRUE
)
93 modified_directory
= (GNode
*) g_hash_table_lookup(
94 watches_table
, &(event
->wd
));
96 if (event
->mask
& IN_CREATE
|| event
->mask
& IN_MOVED_TO
) {
97 if ((new_file
= create_new_file(event
->name
,
98 get_path(modified_directory
), FALSE
)) != NULL
)
99 refresh_request
|= insert_in_tree(modified_directory
, new_file
);
100 } else if (event
->mask
& IN_DELETE
|| event
->mask
& IN_MOVED_FROM
) {
101 if ((removed_file
= search_node_by_name(modified_directory
,
102 event
->name
)) != NULL
)
103 refresh_request
|= remove_from_tree(removed_file
, FALSE
);
104 } else if (event
->mask
& IN_UNMOUNT
) {
105 refresh_request
|= remove_from_tree(modified_directory
, TRUE
);
108 } else if (n
== -1) {
112 PRINT_ERRNO_AND_EXIT();
119 PRINT_ERRNO_AND_EXIT();
121 if (refresh_request
== TRUE
)
125 gboolean
insert_in_tree(GNode
*directory
, File
*file
)
127 GNode
*new_file
, *file_ptr
;
130 if (file
->name
[0] == '.' && FILE(directory
)->show_dotfiles
== FALSE
) {
131 insert_sorted_in_dotfiles(directory
, file
);
135 new_file
= insert_sorted_in_tree(directory
, file
);
136 file_ptr
= get_previous_file(new_file
);
137 position
= g_list_position(lines
, FILE(file_ptr
)->line
);
138 lines
= g_list_insert(lines
, new_file
, position
+ 1);
139 file
->line
= g_list_nth(lines
, position
+ 1);
141 if (g_list_length(first_line
) - g_list_length(last_line
) + 1) {
142 if (g_list_previous(first_line
) == file
->line
)
143 first_line
= file
->line
;
144 else if (g_list_next(last_line
) == file
->line
)
145 last_line
= file
->line
;
147 if (g_list_position(lines
, first_line
) <= position
+ 1 &&
148 position
+ 1 <= g_list_position(lines
, last_line
)) {
149 if (position
+ 1 < g_list_position(lines
, selected_line
)) {
150 if (g_list_length(first_line
) <= getmaxy(tree_window
))
151 print_lines(first_line
, last_line
, FALSE
);
153 first_line
= g_list_next(first_line
);
154 print_lines(first_line
, file
->line
, FALSE
);
157 if (g_list_length(first_line
) > getmaxy(tree_window
))
158 last_line
= g_list_previous(last_line
);
160 if (g_node_last_sibling(new_file
) == new_file
)
161 print_lines(g_list_previous(file
->line
), last_line
, FALSE
);
163 print_lines(file
->line
, last_line
, FALSE
);
172 gboolean
remove_from_tree(GNode
*file
, gboolean unmount
)
174 int position
= g_list_position(lines
, FILE(file
)->line
);
175 gboolean refresh_needed
= FALSE
;
176 GList
*line_ptr
, *line_ptr2
;
178 if (G_NODE_IS_ROOT(file
)) {
181 printf("The tree root was removed\n");
184 if (g_node_is_ancestor(file
, NODE(selected_line
)))
186 if (FILE(file
)->type
== directory_type
) {
187 close_directory(file
);
188 destroy_directory_content_real(file
, FALSE
);
194 if (g_list_position(lines
, first_line
) <= position
&&
195 position
<= g_list_position(lines
, last_line
)) {
196 if (first_line
== FILE(file
)->line
&& selected_line
== FILE(file
)->line
) {
197 selected_line
= first_line
= g_list_previous(first_line
);
198 lines
= g_list_delete_link(lines
, FILE(file
)->line
);
199 print_lines(first_line
, first_line
, FALSE
);
200 } else if (position
< g_list_position(lines
, selected_line
)) {
201 if (first_line
== FILE(file
)->line
)
202 first_line
= g_list_next(first_line
);
203 line_ptr
= g_list_previous(FILE(file
)->line
);
204 lines
= g_list_delete_link(lines
, FILE(file
)->line
);
205 if ((line_ptr2
= g_list_previous(first_line
)) != NULL
) {
206 first_line
= line_ptr2
;
207 print_lines(first_line
, line_ptr
, FALSE
);
208 } else if ((line_ptr2
= g_list_next(last_line
)) != NULL
) {
209 last_line
= line_ptr2
;
210 print_lines(line_ptr
, last_line
, FALSE
);
212 print_lines(line_ptr
, last_line
, TRUE
);
214 if (FILE(file
)->line
== selected_line
)
215 selected_line
= g_list_previous(selected_line
);
216 if (last_line
== FILE(file
)->line
)
217 last_line
= g_list_previous(last_line
);
218 line_ptr
= g_list_previous(FILE(file
)->line
);
219 lines
= g_list_delete_link(lines
, FILE(file
)->line
);
220 if ((line_ptr2
= g_list_next(last_line
)) != NULL
) {
221 last_line
= line_ptr2
;
222 print_lines(line_ptr
, last_line
, FALSE
);
224 print_lines(line_ptr
, last_line
, TRUE
);
226 refresh_needed
= TRUE
;
228 if (last_line
== g_list_previous(FILE(file
)->line
)) {
229 lines
= g_list_delete_link(lines
, FILE(file
)->line
);
230 print_lines(last_line
, last_line
, FALSE
);
231 refresh_needed
= TRUE
;
233 lines
= g_list_delete_link(lines
, FILE(file
)->line
);
235 free_node_data(file
, NULL
);
236 g_node_destroy(file
);
238 return refresh_needed
;
241 GNode
*search_node_by_name(GNode
*directory
, char *name
)
245 for (file_ptr
= g_node_first_child(directory
); file_ptr
!= NULL
;
246 file_ptr
= g_node_next_sibling(file_ptr
)) {
247 if (!strcmp(FILE(file_ptr
)->name
, name
))
254 void dump_event(struct inotify_event
*event
)
256 static int first
= 0;
259 fprintf(stderr
, "================================\n");
260 if (event
->len
> 0) {
261 fprintf(stderr
, "wd = %i\ncookie = %i\nlen = %i\nname = %s\nmask = ",
262 event
->wd
, event
->cookie
, event
->len
, event
->name
);
264 fprintf(stderr
, "wd = %i\ncookie = %i\nlen = %i\nname =\nmask = ",
265 event
->wd
, event
->cookie
, event
->len
);
267 dump_mask(event
->mask
);
271 void dump_mask(int mask
)
273 if (mask
& IN_ACCESS
)
274 fprintf(stderr
, " IN_ACCESS ");
275 if (mask
& IN_ATTRIB
)
276 fprintf(stderr
, " IN_ATTRIB ");
277 if (mask
& IN_CLOSE_WRITE
)
278 fprintf(stderr
, " IN_CLOSE_WRITE ");
279 if (mask
& IN_CLOSE_NOWRITE
)
280 fprintf(stderr
, " IN_CLOSE_NOWRITE ");
281 if (mask
& IN_CREATE
)
282 fprintf(stderr
, " IN_CREATE ");
283 if (mask
& IN_DELETE
)
284 fprintf(stderr
, " IN_DELETE ");
285 if (mask
& IN_DELETE_SELF
)
286 fprintf(stderr
, " IN_DELETE_SELF ");
287 if (mask
& IN_MODIFY
)
288 fprintf(stderr
, " IN_MODIFY ");
289 if (mask
& IN_MOVE_SELF
)
290 fprintf(stderr
, " IN_MOVE_SELF ");
291 if (mask
& IN_MOVED_FROM
)
292 fprintf(stderr
, " IN_MOVED_FROM ");
293 if (mask
& IN_MOVED_TO
)
294 fprintf(stderr
, " IN_MOVED_TO ");
296 fprintf(stderr
, " IN_OPEN ");
297 if (mask
& IN_IGNORED
)
298 fprintf(stderr
, " IN_IGNORED ");
300 fprintf(stderr
, " IN_ISDIR ");
301 if (mask
& IN_Q_OVERFLOW
)
302 fprintf(stderr
, " IN_Q_OVERFLOW ");
303 if (mask
& IN_UNMOUNT
)
304 fprintf(stderr
, " IN_UNMOUNT ");
305 fprintf(stderr
, "\n");
This page took 0.399701 seconds and 4 git commands to generate.