2 * Copyright 2015 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Author: Matthias Clasen <mclasen@redhat.com>
27 static gchar
**watch_dirs
;
28 static gchar
**watch_files
;
29 static gchar
**watch_direct
;
30 static gchar
**watch_silent
;
31 static gchar
**watch_default
;
32 static gboolean no_moves
;
33 static gboolean mounts
;
35 static const GOptionEntry entries
[] = {
36 { "dir", 'd', 0, G_OPTION_ARG_FILENAME_ARRAY
, &watch_dirs
,
37 N_("Monitor a directory (default: depends on type)"), N_("LOCATION") },
38 { "file", 'f', 0, G_OPTION_ARG_FILENAME_ARRAY
, &watch_files
,
39 N_("Monitor a file (default: depends on type)"), N_("LOCATION") },
40 { "direct", 'D', 0, G_OPTION_ARG_FILENAME_ARRAY
, &watch_direct
,
41 N_("Monitor a file directly (notices changes made via hardlinks)"), N_("LOCATION") },
42 { "silent", 's', 0, G_OPTION_ARG_FILENAME_ARRAY
, &watch_silent
,
43 N_("Monitors a file directly, but doesn’t report changes"), N_("LOCATION") },
44 { "no-moves", 'n', 0, G_OPTION_ARG_NONE
, &no_moves
,
45 N_("Report moves and renames as simple deleted/created events"), NULL
},
46 { "mounts", 'm', 0, G_OPTION_ARG_NONE
, &mounts
,
47 N_("Watch for mount events"), NULL
},
48 { G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_FILENAME_ARRAY
, &watch_default
},
53 watch_callback (GFileMonitor
*monitor
,
56 GFileMonitorEvent event_type
,
64 if (g_file_is_native (child
))
65 child_str
= g_file_get_path (child
);
67 child_str
= g_file_get_uri (child
);
71 if (g_file_is_native (other
))
72 other_str
= g_file_get_path (other
);
74 other_str
= g_file_get_uri (other
);
77 other_str
= g_strdup ("(none)");
79 g_print ("%s: ", (gchar
*) user_data
);
82 case G_FILE_MONITOR_EVENT_CHANGED
:
84 g_print ("%s: changed", child_str
);
86 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
:
88 g_print ("%s: changes done", child_str
);
90 case G_FILE_MONITOR_EVENT_DELETED
:
92 g_print ("%s: deleted", child_str
);
94 case G_FILE_MONITOR_EVENT_CREATED
:
96 g_print ("%s: created", child_str
);
98 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED
:
100 g_print ("%s: attributes changed", child_str
);
102 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT
:
104 g_print ("%s: pre-unmount", child_str
);
106 case G_FILE_MONITOR_EVENT_UNMOUNTED
:
108 g_print ("%s: unmounted", child_str
);
110 case G_FILE_MONITOR_EVENT_MOVED_IN
:
111 g_print ("%s: moved in", child_str
);
113 g_print (" (from %s)", other_str
);
115 case G_FILE_MONITOR_EVENT_MOVED_OUT
:
116 g_print ("%s: moved out", child_str
);
118 g_print (" (to %s)", other_str
);
120 case G_FILE_MONITOR_EVENT_RENAMED
:
122 g_print ("%s: renamed to %s\n", child_str
, other_str
);
125 case G_FILE_MONITOR_EVENT_MOVED
:
127 g_assert_not_reached ();
143 add_watch (const gchar
*cmdline
,
144 WatchType watch_type
,
145 GFileMonitorFlags flags
,
146 gboolean connect_handler
)
148 GFileMonitor
*monitor
= NULL
;
149 GError
*error
= NULL
;
152 file
= g_file_new_for_commandline_arg (cmdline
);
154 if (watch_type
== WATCH_AUTO
)
159 info
= g_file_query_info (file
, G_FILE_ATTRIBUTE_STANDARD_TYPE
, G_FILE_QUERY_INFO_NONE
, NULL
, &error
);
163 type
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_STANDARD_TYPE
);
164 watch_type
= (type
== G_FILE_TYPE_DIRECTORY
) ? WATCH_DIR
: WATCH_FILE
;
167 if (watch_type
== WATCH_DIR
)
168 monitor
= g_file_monitor_directory (file
, flags
, NULL
, &error
);
170 monitor
= g_file_monitor (file
, flags
, NULL
, &error
);
176 g_signal_connect (monitor
, "changed", G_CALLBACK (watch_callback
), g_strdup (cmdline
));
178 monitor
= NULL
; /* leak */
179 g_object_unref (file
);
184 print_file_error (file
, error
->message
);
185 g_error_free (error
);
186 g_object_unref (file
);
192 handle_monitor (int argc
, gchar
*argv
[], gboolean do_help
)
194 GOptionContext
*context
;
196 GError
*error
= NULL
;
197 GFileMonitorFlags flags
;
200 g_set_prgname ("gio monitor");
202 /* Translators: commandline placeholder */
203 param
= g_strdup_printf ("%s…", _("LOCATION"));
204 context
= g_option_context_new (param
);
206 g_option_context_set_help_enabled (context
, FALSE
);
207 g_option_context_set_summary (context
,
208 _("Monitor files or directories for changes."));
209 g_option_context_add_main_entries (context
, entries
, GETTEXT_PACKAGE
);
213 show_help (context
, NULL
);
214 g_option_context_free (context
);
218 if (!g_option_context_parse (context
, &argc
, &argv
, &error
))
220 show_help (context
, error
->message
);
221 g_error_free (error
);
222 g_option_context_free (context
);
226 if (!watch_dirs
&& !watch_files
&& !watch_direct
&& !watch_silent
&& !watch_default
)
228 show_help (context
, _("No locations given"));
229 g_option_context_free (context
);
233 g_option_context_free (context
);
235 flags
= (no_moves
? 0 : G_FILE_MONITOR_WATCH_MOVES
) |
236 (mounts
? G_FILE_MONITOR_WATCH_MOUNTS
: 0);
240 for (i
= 0; watch_dirs
[i
]; i
++)
241 if (!add_watch (watch_dirs
[i
], WATCH_DIR
, flags
, TRUE
))
247 for (i
= 0; watch_files
[i
]; i
++)
248 if (!add_watch (watch_files
[i
], WATCH_FILE
, flags
, TRUE
))
254 for (i
= 0; watch_direct
[i
]; i
++)
255 if (!add_watch (watch_direct
[i
], WATCH_FILE
, flags
| G_FILE_MONITOR_WATCH_HARD_LINKS
, TRUE
))
261 for (i
= 0; watch_silent
[i
]; i
++)
262 if (!add_watch (watch_silent
[i
], WATCH_FILE
, flags
| G_FILE_MONITOR_WATCH_HARD_LINKS
, FALSE
))
268 for (i
= 0; watch_default
[i
]; i
++)
269 if (!add_watch (watch_default
[i
], WATCH_AUTO
, flags
, TRUE
))
274 g_main_context_iteration (NULL
, TRUE
);