| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | /* GIO - GLib Input, Output and Streaming Library
 | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * Copyright (C) 2006-2007 Red Hat, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General | 
					
						
							|  |  |  |  * Public License along with this library; if not, write to the | 
					
						
							|  |  |  |  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, | 
					
						
							|  |  |  |  * Boston, MA 02111-1307, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Author: Alexander Larsson <alexl@redhat.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-22 15:10:51 +00:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gpollfilemonitor.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-01 06:32:35 +00:00
										 |  |  | #include "gfile.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | #include "gfilemonitor.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-01 06:32:35 +00:00
										 |  |  | #include "gfileinfo.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-28 12:39:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | static gboolean g_poll_file_monitor_cancel (GFileMonitor* monitor); | 
					
						
							|  |  |  | static void schedule_poll_timeout (GPollFileMonitor* poll_monitor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _GPollFileMonitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GFileMonitor parent_instance; | 
					
						
							|  |  |  |   GFile *file; | 
					
						
							|  |  |  |   GFileInfo *last_info; | 
					
						
							|  |  |  |   guint timeout; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define POLL_TIME_SECS 5
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-28 16:01:59 +00:00
										 |  |  | #define g_poll_file_monitor_get_type _g_poll_file_monitor_get_type
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | G_DEFINE_TYPE (GPollFileMonitor, g_poll_file_monitor, G_TYPE_FILE_MONITOR) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_poll_file_monitor_finalize (GObject* object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GPollFileMonitor* poll_monitor; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   poll_monitor = G_POLL_FILE_MONITOR (object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_object_unref (poll_monitor->file); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 09:54:04 +00:00
										 |  |  |   G_OBJECT_CLASS (g_poll_file_monitor_parent_class)->finalize (object); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_poll_file_monitor_class_init (GPollFileMonitorClass* klass) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GObjectClass* gobject_class = G_OBJECT_CLASS (klass); | 
					
						
							|  |  |  |   GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   gobject_class->finalize = g_poll_file_monitor_finalize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   file_monitor_class->cancel = g_poll_file_monitor_cancel; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_poll_file_monitor_init (GPollFileMonitor* poll_monitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							| 
									
										
										
										
											2007-11-30 05:11:25 +00:00
										 |  |  | safe_strcmp (const char *a,  | 
					
						
							|  |  |  |              const char *b) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   if (a == NULL && b == NULL) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   if (a == NULL) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   if (b == NULL) | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   return strcmp (a, b); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | calc_event_type (GFileInfo *last, | 
					
						
							|  |  |  | 		 GFileInfo *new) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (last == NULL && new == NULL) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (last == NULL && new != NULL) | 
					
						
							|  |  |  |     return G_FILE_MONITOR_EVENT_CREATED; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   if (last != NULL && new == NULL) | 
					
						
							|  |  |  |     return G_FILE_MONITOR_EVENT_DELETED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (safe_strcmp (g_file_info_get_etag (last), | 
					
						
							|  |  |  | 		   g_file_info_get_etag (new))) | 
					
						
							|  |  |  |     return G_FILE_MONITOR_EVENT_CHANGED; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   if (g_file_info_get_size (last) != | 
					
						
							|  |  |  |       g_file_info_get_size (new)) | 
					
						
							|  |  |  |     return G_FILE_MONITOR_EVENT_CHANGED; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2007-11-30 05:11:25 +00:00
										 |  |  | got_new_info (GObject      *source_object, | 
					
						
							|  |  |  |               GAsyncResult *res, | 
					
						
							|  |  |  |               gpointer      user_data) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   GPollFileMonitor* poll_monitor = user_data; | 
					
						
							|  |  |  |   GFileInfo *info; | 
					
						
							|  |  |  |   int event; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   info = g_file_query_info_finish (poll_monitor->file, res, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!g_file_monitor_is_cancelled (G_FILE_MONITOR (poll_monitor))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       event = calc_event_type (poll_monitor->last_info, info); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (event != -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  g_file_monitor_emit_event (G_FILE_MONITOR (poll_monitor), | 
					
						
							|  |  |  | 				     poll_monitor->file, | 
					
						
							|  |  |  | 				     NULL, event); | 
					
						
							|  |  |  | 	  /* We're polling so slowly anyway, so always emit the done hint */ | 
					
						
							|  |  |  | 	  if (event == G_FILE_MONITOR_EVENT_CHANGED) | 
					
						
							|  |  |  | 	    g_file_monitor_emit_event (G_FILE_MONITOR (poll_monitor), | 
					
						
							|  |  |  | 				       poll_monitor->file, | 
					
						
							|  |  |  | 				       NULL, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       if (poll_monitor->last_info) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  g_object_unref (poll_monitor->last_info); | 
					
						
							|  |  |  | 	  poll_monitor->last_info = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       if (info) | 
					
						
							|  |  |  | 	poll_monitor->last_info = g_object_ref (info); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       schedule_poll_timeout (poll_monitor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (info) | 
					
						
							|  |  |  |     g_object_unref (info); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   g_object_unref (poll_monitor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | poll_file_timeout (gpointer data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GPollFileMonitor* poll_monitor = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   poll_monitor->timeout = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-20 13:30:47 +00:00
										 |  |  |   g_file_query_info_async (poll_monitor->file, G_FILE_ATTRIBUTE_ETAG_VALUE "," G_FILE_ATTRIBUTE_STANDARD_SIZE, | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 			 0, 0, NULL, got_new_info, g_object_ref (poll_monitor)); | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2012-01-25 14:18:34 -05:00
										 |  |  |   return G_SOURCE_REMOVE; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | schedule_poll_timeout (GPollFileMonitor* poll_monitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   poll_monitor->timeout = g_timeout_add_seconds (POLL_TIME_SECS, poll_file_timeout, poll_monitor); | 
					
						
							|  |  |  |  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2007-11-30 05:11:25 +00:00
										 |  |  | got_initial_info (GObject      *source_object, | 
					
						
							|  |  |  |                   GAsyncResult *res, | 
					
						
							|  |  |  |                   gpointer      user_data) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   GPollFileMonitor* poll_monitor = user_data; | 
					
						
							|  |  |  |   GFileInfo *info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   info = g_file_query_info_finish (poll_monitor->file, res, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   poll_monitor->last_info = info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!g_file_monitor_is_cancelled (G_FILE_MONITOR (poll_monitor))) | 
					
						
							|  |  |  |     schedule_poll_timeout (poll_monitor); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   g_object_unref (poll_monitor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_poll_file_monitor_new: | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  |  * @file: a #GFile. | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * Polls @file for changes. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2007-11-28 04:29:02 +00:00
										 |  |  |  * Returns: a new #GFileMonitor for the given #GFile.  | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  **/ | 
					
						
							|  |  |  | GFileMonitor* | 
					
						
							| 
									
										
										
										
											2007-11-28 16:01:59 +00:00
										 |  |  | _g_poll_file_monitor_new (GFile *file) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   GPollFileMonitor* poll_monitor; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   poll_monitor = g_object_new (G_TYPE_POLL_FILE_MONITOR, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   poll_monitor->file = g_object_ref (file); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-20 13:30:47 +00:00
										 |  |  |   g_file_query_info_async (file, G_FILE_ATTRIBUTE_ETAG_VALUE "," G_FILE_ATTRIBUTE_STANDARD_SIZE, | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 			   0, 0, NULL, got_initial_info, g_object_ref (poll_monitor)); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   return G_FILE_MONITOR (poll_monitor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_poll_file_monitor_cancel (GFileMonitor* monitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GPollFileMonitor *poll_monitor = G_POLL_FILE_MONITOR (monitor); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   if (poll_monitor->timeout) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_source_remove (poll_monitor->timeout); | 
					
						
							|  |  |  |       poll_monitor->timeout = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } |