tracker-file-data-provider.c 6.81 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
/*
 * Copyright (C) 2014, Softathome <contact@softathome.com>
 *
 * 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.1 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 * Author: Martyn Russell <martyn@lanedo.com>
 */

#include "config.h"

#include "tracker-file-data-provider.h"

static void tracker_file_data_provider_file_iface_init (TrackerDataProviderIface *iface);

struct _TrackerFileDataProvider {
	GObject parent_instance;
};

/**
 * SECTION:tracker-file-data-provider
 * @short_description: File based data provider for file:// descendant URIs
 * @include: libtracker-miner/miner.h
 *
 * #TrackerFileDataProvider is a local file implementation of the
 * #TrackerDataProvider interface, charged with handling all file:// type URIs.
 *
40 41
 * Underneath it all, this implementation makes use of GIO-based
 * #GFileEnumerator<!-- -->s.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
 *
 * Since: 1.2
 **/

G_DEFINE_TYPE_WITH_CODE (TrackerFileDataProvider, tracker_file_data_provider, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (TRACKER_TYPE_DATA_PROVIDER,
                                                tracker_file_data_provider_file_iface_init))

static void
tracker_file_data_provider_finalize (GObject *object)
{
	G_OBJECT_CLASS (tracker_file_data_provider_parent_class)->finalize (object);
}

static void
tracker_file_data_provider_class_init (TrackerFileDataProviderClass *klass)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

	gobject_class->finalize = tracker_file_data_provider_finalize;
}

static void
tracker_file_data_provider_init (TrackerFileDataProvider *fe)
{
}

69
static GFileEnumerator *
70 71 72 73 74 75
file_data_provider_begin (TrackerDataProvider    *data_provider,
                          GFile                  *url,
                          const gchar            *attributes,
                          TrackerDirectoryFlags   flags,
                          GCancellable           *cancellable,
                          GError                **error)
76
{
77
	GFileQueryInfoFlags file_flags;
78 79 80 81 82 83 84
	GFileEnumerator *fe;
	GError *local_error = NULL;

	if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
		return NULL;
	}

85 86 87 88 89 90 91 92 93 94 95 96
	/* We ignore the TRACKER_DIRECTORY_FLAG_NO_STAT here, it makes
	 * no sense to be at this point with that flag. So we warn
	 * about it...
	 */
	if ((flags & TRACKER_DIRECTORY_FLAG_NO_STAT) != 0) {
		g_warning ("Did not expect to have TRACKER_DIRECTORY_FLAG_NO_STAT "
		           "flag in %s(), continuing anyway...",
		           __FUNCTION__);
	}

	file_flags = G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS;

97 98
	fe = g_file_enumerate_children (url,
	                                attributes,
99
	                                file_flags,
100 101 102 103 104 105 106 107 108 109 110 111 112
	                                cancellable,
	                                &local_error);

	if (local_error) {
		gchar *uri;

		uri = g_file_get_uri (url);

		g_warning ("Could not open directory '%s': %s",
		           uri, local_error->message);

		g_propagate_error (error, local_error);
		g_free (uri);
113 114

		return NULL;
115 116
	}

117
	return fe;
118 119 120
}

static void
121 122 123
enumerate_children_cb (GObject       *source_object,
                       GAsyncResult  *res,
                       gpointer       user_data)
124
{
125
	GFile *url = G_FILE (source_object);
126
	GFileEnumerator *enumerator = NULL;
127
	GTask *task = G_TASK (user_data);
128 129
	GError *error = NULL;

130
	enumerator = g_file_enumerate_children_finish (url, res, &error);
131
	if (error) {
132 133 134 135 136 137 138 139 140
		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
			gchar *uri;

			uri = g_file_get_uri (url);
			g_warning ("Could not open directory '%s': %s",
			           uri, error->message);
			g_free (uri);
		}

141 142 143 144
		g_task_return_error (task, error);
	} else {
		g_task_return_pointer (task, enumerator, (GDestroyNotify) g_object_unref);
	}
145 146

	g_object_unref (task);
147 148 149
}

static void
150
file_data_provider_begin_async (TrackerDataProvider   *data_provider,
151
                                GFile                 *url,
152 153 154 155 156 157
                                const gchar           *attributes,
                                TrackerDirectoryFlags  flags,
                                int                    io_priority,
                                GCancellable          *cancellable,
                                GAsyncReadyCallback    callback,
                                gpointer               user_data)
158
{
159
	GFileQueryInfoFlags file_flags;
160 161 162
	GTask *task;

	task = g_task_new (data_provider, cancellable, callback, user_data);
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

	/* We ignore the TRACKER_DIRECTORY_FLAG_NO_STAT here, it makes
	 * no sense to be at this point with that flag. So we warn
	 * about it...
	 */
	if ((flags & TRACKER_DIRECTORY_FLAG_NO_STAT) != 0) {
		g_warning ("Did not expect to have TRACKER_DIRECTORY_FLAG_NO_STAT "
		           "flag in %s(), continuing anyway...",
		           __FUNCTION__);
	}

	file_flags = G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS;

	g_file_enumerate_children_async (url,
	                                 attributes,
	                                 file_flags,
	                                 io_priority,
	                                 cancellable,
	                                 enumerate_children_cb,
	                                 g_object_ref (task));

184 185 186
	g_object_unref (task);
}

187
static GFileEnumerator *
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
file_data_provider_begin_finish (TrackerDataProvider  *data_provider,
                                 GAsyncResult         *result,
                                 GError              **error)
{
	g_return_val_if_fail (g_task_is_valid (result, data_provider), NULL);

	return g_task_propagate_pointer (G_TASK (result), error);
}

static void
tracker_file_data_provider_file_iface_init (TrackerDataProviderIface *iface)
{
	iface->begin = file_data_provider_begin;
	iface->begin_async = file_data_provider_begin_async;
	iface->begin_finish = file_data_provider_begin_finish;
}

/**
 * tracker_file_data_provider_new:
 *
 * Creates a new TrackerDataProvider which can be used to create new
 * #TrackerMinerFS classes. See #TrackerMinerFS for an example of how
 * to use your #TrackerDataProvider.
 *
 * Returns: (transfer full): a #TrackerDataProvider which must be
 * unreferenced with g_object_unref().
 *
215
 * Since: 1.2
216 217 218 219 220 221 222 223 224 225
 **/
TrackerDataProvider *
tracker_file_data_provider_new (void)
{
	TrackerFileDataProvider *tfdp;

	tfdp = g_object_new (TRACKER_TYPE_FILE_DATA_PROVIDER, NULL);

	return TRACKER_DATA_PROVIDER (tfdp);
}