nautilus-3.6.3/libnautilus-private/nautilus-vfs-file.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
  2 
  3    nautilus-vfs-file.c: Subclass of NautilusFile to help implement the
  4    virtual trash directory.
  5  
  6    Copyright (C) 1999, 2000, 2001 Eazel, Inc.
  7   
  8    This program is free software; you can redistribute it and/or
  9    modify it under the terms of the GNU General Public License as
 10    published by the Free Software Foundation; either version 2 of the
 11    License, or (at your option) any later version.
 12   
 13    This program is distributed in the hope that it will be useful,
 14    but WITHOUT ANY WARRANTY; without even the implied warranty of
 15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16    General Public License for more details.
 17   
 18    You should have received a copy of the GNU General Public
 19    License along with this program; if not, write to the
 20    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 21    Boston, MA 02111-1307, USA.
 22   
 23    Author: Darin Adler <darin@bentspoon.com>
 24 */
 25 
 26 #include <config.h>
 27 #include "nautilus-vfs-file.h"
 28 
 29 #include "nautilus-directory-notify.h"
 30 #include "nautilus-directory-private.h"
 31 #include "nautilus-file-private.h"
 32 #include <glib/gi18n.h>
 33 
 34 G_DEFINE_TYPE (NautilusVFSFile, nautilus_vfs_file, NAUTILUS_TYPE_FILE);
 35 
 36 static void             
 37 vfs_file_monitor_add (NautilusFile *file,
 38 		      gconstpointer client,
 39 		      NautilusFileAttributes attributes)
 40 {
 41 	nautilus_directory_monitor_add_internal
 42 		(file->details->directory, file,
 43 		 client, TRUE, attributes, NULL, NULL);
 44 }   
 45 			   
 46 static void
 47 vfs_file_monitor_remove (NautilusFile *file,
 48 			 gconstpointer client)
 49 {
 50 	nautilus_directory_monitor_remove_internal
 51 		(file->details->directory, file, client);
 52 }			      
 53 
 54 static void
 55 vfs_file_call_when_ready (NautilusFile *file,
 56 			  NautilusFileAttributes file_attributes,
 57 			  NautilusFileCallback callback,
 58 			  gpointer callback_data)
 59 
 60 {
 61 	nautilus_directory_call_when_ready_internal
 62 		(file->details->directory, file,
 63 		 file_attributes, FALSE, NULL, callback, callback_data);
 64 }
 65 
 66 static void
 67 vfs_file_cancel_call_when_ready (NautilusFile *file,
 68 				 NautilusFileCallback callback,
 69 				 gpointer callback_data)
 70 {
 71 	nautilus_directory_cancel_callback_internal
 72 		(file->details->directory, file,
 73 		 NULL, callback, callback_data);
 74 }
 75 
 76 static gboolean
 77 vfs_file_check_if_ready (NautilusFile *file,
 78 			 NautilusFileAttributes file_attributes)
 79 {
 80 	return nautilus_directory_check_if_ready_internal
 81 		(file->details->directory, file,
 82 		 file_attributes);
 83 }
 84 
 85 static void
 86 set_metadata_get_info_callback (GObject *source_object,
 87 				GAsyncResult *res,
 88 				gpointer callback_data)
 89 {
 90 	NautilusFile *file;
 91 	GFileInfo *new_info;
 92 	GError *error;
 93 
 94 	file = callback_data;
 95 
 96 	error = NULL;
 97 	new_info = g_file_query_info_finish (G_FILE (source_object), res, &error);
 98 	if (new_info != NULL) {
 99 		if (nautilus_file_update_info (file, new_info)) {
100 			nautilus_file_changed (file);
101 		}
102 		g_object_unref (new_info);
103 	}
104 	nautilus_file_unref (file);
105 	if (error) {
106 		g_error_free (error);
107 	}
108 }
109 
110 static void
111 set_metadata_callback (GObject *source_object,
112 		       GAsyncResult *result,
113 		       gpointer callback_data)
114 {
115 	NautilusFile *file;
116 	GError *error;
117 	gboolean res;
118 
119 	file = callback_data;
120 
121 	error = NULL;
122 	res = g_file_set_attributes_finish (G_FILE (source_object),
123 					    result,
124 					    NULL,
125 					    &error);
126 
127 	if (res) {
128 		g_file_query_info_async (G_FILE (source_object),
129 					 NAUTILUS_FILE_DEFAULT_ATTRIBUTES,
130 					 0,
131 					 G_PRIORITY_DEFAULT,
132 					 NULL,
133 					 set_metadata_get_info_callback, file);
134 	} else {
135 		nautilus_file_unref (file);
136 		g_error_free (error);
137 	}
138 }
139 
140 static void
141 vfs_file_set_metadata (NautilusFile           *file,
142 		       const char             *key,
143 		       const char             *value)
144 {
145 	GFileInfo *info;
146 	GFile *location;
147 	char *gio_key;
148 
149 	info = g_file_info_new ();
150 	
151 	gio_key = g_strconcat ("metadata::", key, NULL);
152 	if (value != NULL) {
153 		g_file_info_set_attribute_string (info, gio_key, value);
154 	} else {
155 		/* Unset the key */
156 		g_file_info_set_attribute (info, gio_key,
157 					   G_FILE_ATTRIBUTE_TYPE_INVALID,
158 					   NULL);
159 	}
160 	g_free (gio_key);
161 
162 	location = nautilus_file_get_location (file);
163 	g_file_set_attributes_async (location,
164 				     info,
165 				     0,
166 				     G_PRIORITY_DEFAULT,
167 				     NULL,
168 				     set_metadata_callback,
169 				     nautilus_file_ref (file));
170 	g_object_unref (location);
171 	g_object_unref (info);
172 }
173 
174 static void
175 vfs_file_set_metadata_as_list (NautilusFile           *file,
176 			       const char             *key,
177 			       char                  **value)
178 {
179 	GFile *location;
180 	GFileInfo *info;
181 	char *gio_key;
182 
183 	info = g_file_info_new ();
184 
185 	gio_key = g_strconcat ("metadata::", key, NULL);
186 	g_file_info_set_attribute_stringv (info, gio_key, value);
187 	g_free (gio_key);
188 
189 	location = nautilus_file_get_location (file);
190 	g_file_set_attributes_async (location,
191 				     info,
192 				     0,
193 				     G_PRIORITY_DEFAULT,
194 				     NULL,
195 				     set_metadata_callback,
196 				     nautilus_file_ref (file));
197 	g_object_unref (info);
198 	g_object_unref (location);
199 }
200 
201 static gboolean
202 vfs_file_get_item_count (NautilusFile *file, 
203 			 guint *count,
204 			 gboolean *count_unreadable)
205 {
206 	if (count_unreadable != NULL) {
207 		*count_unreadable = file->details->directory_count_failed;
208 	}
209 	if (!file->details->got_directory_count) {
210 		if (count != NULL) {
211 			*count = 0;
212 		}
213 		return FALSE;
214 	}
215 	if (count != NULL) {
216 		*count = file->details->directory_count;
217 	}
218 	return TRUE;
219 }
220 
221 static NautilusRequestStatus
222 vfs_file_get_deep_counts (NautilusFile *file,
223 			  guint *directory_count,
224 			  guint *file_count,
225 			  guint *unreadable_directory_count,
226 			  goffset *total_size)
227 {
228 	GFileType type;
229 
230 	if (directory_count != NULL) {
231 		*directory_count = 0;
232 	}
233 	if (file_count != NULL) {
234 		*file_count = 0;
235 	}
236 	if (unreadable_directory_count != NULL) {
237 		*unreadable_directory_count = 0;
238 	}
239 	if (total_size != NULL) {
240 		*total_size = 0;
241 	}
242 
243 	if (!nautilus_file_is_directory (file)) {
244 		return NAUTILUS_REQUEST_DONE;
245 	}
246 
247 	if (file->details->deep_counts_status != NAUTILUS_REQUEST_NOT_STARTED) {
248 		if (directory_count != NULL) {
249 			*directory_count = file->details->deep_directory_count;
250 		}
251 		if (file_count != NULL) {
252 			*file_count = file->details->deep_file_count;
253 		}
254 		if (unreadable_directory_count != NULL) {
255 			*unreadable_directory_count = file->details->deep_unreadable_count;
256 		}
257 		if (total_size != NULL) {
258 			*total_size = file->details->deep_size;
259 		}
260 		return file->details->deep_counts_status;
261 	}
262 
263 	/* For directories, or before we know the type, we haven't started. */
264 	type = nautilus_file_get_file_type (file);
265 	if (type == G_FILE_TYPE_UNKNOWN
266 	    || type == G_FILE_TYPE_DIRECTORY) {
267 		return NAUTILUS_REQUEST_NOT_STARTED;
268 	}
269 
270 	/* For other types, we are done, and the zeros are permanent. */
271 	return NAUTILUS_REQUEST_DONE;
272 }
273 
274 static gboolean
275 vfs_file_get_date (NautilusFile *file,
276 		   NautilusDateType date_type,
277 		   time_t *date)
278 {
279 	switch (date_type) {
280 	case NAUTILUS_DATE_TYPE_ACCESSED:
281 		/* Before we have info on a file, the date is unknown. */
282 		if (file->details->atime == 0) {
283 			return FALSE;
284 		}
285 		if (date != NULL) {
286 			*date = file->details->atime;
287 		}
288 		return TRUE;
289 	case NAUTILUS_DATE_TYPE_MODIFIED:
290 		/* Before we have info on a file, the date is unknown. */
291 		if (file->details->mtime == 0) {
292 			return FALSE;
293 		}
294 		if (date != NULL) {
295 			*date = file->details->mtime;
296 		}
297 		return TRUE;
298 	case NAUTILUS_DATE_TYPE_TRASHED:
299 		/* Before we have info on a file, the date is unknown. */
300 		if (file->details->trash_time == 0) {
301 			return FALSE;
302 		}
303 		if (date != NULL) {
304 			*date = file->details->trash_time;
305 		}
306 		return TRUE;
307 	}
308 	return FALSE;
309 }
310 
311 static char *
312 vfs_file_get_where_string (NautilusFile *file)
313 {
314 	return nautilus_file_get_parent_uri_for_display (file);
315 }
316 
317 static void
318 vfs_file_mount_callback (GObject *source_object,
319 			 GAsyncResult *res,
320 			 gpointer callback_data)
321 {
322 	NautilusFileOperation *op;
323 	GFile *mounted_on;
324 	GError *error;
325 
326 	op = callback_data;
327 
328 	error = NULL;
329 	mounted_on = g_file_mount_mountable_finish (G_FILE (source_object),
330 						    res, &error);
331 	nautilus_file_operation_complete (op, mounted_on, error);
332 	if (mounted_on) {
333 		g_object_unref (mounted_on);
334 	}
335 	if (error) {
336 		g_error_free (error);
337 	}
338 }
339 
340 
341 static void
342 vfs_file_mount (NautilusFile                   *file,
343 		GMountOperation                *mount_op,
344 		GCancellable                   *cancellable,
345 		NautilusFileOperationCallback   callback,
346 		gpointer                        callback_data)
347 {
348 	NautilusFileOperation *op;
349 	GError *error;
350 	GFile *location;
351 	
352 	if (file->details->type != G_FILE_TYPE_MOUNTABLE) {
353 		if (callback) {
354 			error = NULL;
355 			g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
356                                              _("This file cannot be mounted"));
357 			callback (file, NULL, error, callback_data);
358 			g_error_free (error);
359 		}
360 		return;
361 	}
362 
363 	op = nautilus_file_operation_new (file, callback, callback_data);
364 	if (cancellable) {
365 		g_object_unref (op->cancellable);
366 		op->cancellable = g_object_ref (cancellable);
367 	}
368 
369 	location = nautilus_file_get_location (file);
370 	g_file_mount_mountable (location,
371 				0,
372 				mount_op,
373 				op->cancellable,
374 				vfs_file_mount_callback,
375 				op);
376 	g_object_unref (location);
377 }
378 
379 static void
380 vfs_file_unmount_callback (GObject *source_object,
381 			 GAsyncResult *res,
382 			 gpointer callback_data)
383 {
384 	NautilusFileOperation *op;
385 	gboolean unmounted;
386 	GError *error;
387 
388 	op = callback_data;
389 
390 	error = NULL;
391 	unmounted = g_file_unmount_mountable_with_operation_finish (G_FILE (source_object),
392 								    res, &error);
393 	
394     if (!unmounted &&
395 	error->domain == G_IO_ERROR && 
396 	(error->code == G_IO_ERROR_FAILED_HANDLED ||
397 	 error->code == G_IO_ERROR_CANCELLED)) {
398 	    g_error_free (error);
399 	    error = NULL;
400     }
401 
402     nautilus_file_operation_complete (op, G_FILE (source_object), error);
403 	if (error) {
404 		g_error_free (error);
405 	}
406 }
407 
408 static void
409 vfs_file_unmount (NautilusFile                   *file,
410 		  GMountOperation                *mount_op,
411 		  GCancellable                   *cancellable,
412 		  NautilusFileOperationCallback   callback,
413 		  gpointer                        callback_data)
414 {
415 	NautilusFileOperation *op;
416 	GFile *location;
417 	
418 	op = nautilus_file_operation_new (file, callback, callback_data);
419 	if (cancellable) {
420 		g_object_unref (op->cancellable);
421 		op->cancellable = g_object_ref (cancellable);
422 	}
423 
424 	location = nautilus_file_get_location (file);
425 	g_file_unmount_mountable_with_operation (location,
426 						 G_MOUNT_UNMOUNT_NONE,
427 						 mount_op,
428 						 op->cancellable,
429 						 vfs_file_unmount_callback,
430 						 op);
431 	g_object_unref (location);
432 }
433 
434 static void
435 vfs_file_eject_callback (GObject *source_object,
436 			 GAsyncResult *res,
437 			 gpointer callback_data)
438 {
439 	NautilusFileOperation *op;
440 	gboolean ejected;
441 	GError *error;
442 
443 	op = callback_data;
444 
445 	error = NULL;
446 	ejected = g_file_eject_mountable_with_operation_finish (G_FILE (source_object),
447 								res, &error);
448 
449 	if (!ejected &&
450 	    error->domain == G_IO_ERROR &&
451 	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
452 	     error->code == G_IO_ERROR_CANCELLED)) {
453 		g_error_free (error);
454 		error = NULL;
455 	}
456 	
457 	nautilus_file_operation_complete (op, G_FILE (source_object), error);
458 	if (error) {
459 		g_error_free (error);
460 	}
461 }
462 
463 static void
464 vfs_file_eject (NautilusFile                   *file,
465 		GMountOperation                *mount_op,
466 		GCancellable                   *cancellable,
467 		NautilusFileOperationCallback   callback,
468 		gpointer                        callback_data)
469 {
470 	NautilusFileOperation *op;
471 	GFile *location;
472 	
473 	op = nautilus_file_operation_new (file, callback, callback_data);
474 	if (cancellable) {
475 		g_object_unref (op->cancellable);
476 		op->cancellable = g_object_ref (cancellable);
477 	}
478 
479 	location = nautilus_file_get_location (file);
480 	g_file_eject_mountable_with_operation (location,
481 					       G_MOUNT_UNMOUNT_NONE,
482 					       mount_op,
483 					       op->cancellable,
484 					       vfs_file_eject_callback,
485 					       op);
486 	g_object_unref (location);
487 }
488 
489 static void
490 vfs_file_start_callback (GObject *source_object,
491 			 GAsyncResult *res,
492 			 gpointer callback_data)
493 {
494 	NautilusFileOperation *op;
495 	gboolean started;
496 	GError *error;
497 
498 	op = callback_data;
499 
500 	error = NULL;
501 	started = g_file_start_mountable_finish (G_FILE (source_object),
502 						 res, &error);
503 
504 	if (!started &&
505 	    error->domain == G_IO_ERROR &&
506 	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
507 	     error->code == G_IO_ERROR_CANCELLED)) {
508 		g_error_free (error);
509 		error = NULL;
510 	}
511 
512 	nautilus_file_operation_complete (op, G_FILE (source_object), error);
513 	if (error) {
514 		g_error_free (error);
515 	}
516 }
517 
518 
519 static void
520 vfs_file_start (NautilusFile                   *file,
521 		GMountOperation                *mount_op,
522 		GCancellable                   *cancellable,
523 		NautilusFileOperationCallback   callback,
524 		gpointer                        callback_data)
525 {
526 	NautilusFileOperation *op;
527 	GError *error;
528 	GFile *location;
529 
530 	if (file->details->type != G_FILE_TYPE_MOUNTABLE) {
531 		if (callback) {
532 			error = NULL;
533 			g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
534                                              _("This file cannot be started"));
535 			callback (file, NULL, error, callback_data);
536 			g_error_free (error);
537 		}
538 		return;
539 	}
540 
541 	op = nautilus_file_operation_new (file, callback, callback_data);
542 	if (cancellable) {
543 		g_object_unref (op->cancellable);
544 		op->cancellable = g_object_ref (cancellable);
545 	}
546 
547 	location = nautilus_file_get_location (file);
548 	g_file_start_mountable (location,
549 				0,
550 				mount_op,
551 				op->cancellable,
552 				vfs_file_start_callback,
553 				op);
554 	g_object_unref (location);
555 }
556 
557 static void
558 vfs_file_stop_callback (GObject *source_object,
559 			GAsyncResult *res,
560 			gpointer callback_data)
561 {
562 	NautilusFileOperation *op;
563 	gboolean stopped;
564 	GError *error;
565 
566 	op = callback_data;
567 
568 	error = NULL;
569 	stopped = g_file_stop_mountable_finish (G_FILE (source_object),
570 						res, &error);
571 
572 	if (!stopped &&
573 	    error->domain == G_IO_ERROR &&
574 	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
575 	     error->code == G_IO_ERROR_CANCELLED)) {
576 		g_error_free (error);
577 		error = NULL;
578 	}
579 
580 	nautilus_file_operation_complete (op, G_FILE (source_object), error);
581 	if (error) {
582 		g_error_free (error);
583 	}
584 }
585 
586 static void
587 vfs_file_stop (NautilusFile                   *file,
588 	       GMountOperation                *mount_op,
589 	       GCancellable                   *cancellable,
590 	       NautilusFileOperationCallback   callback,
591 	       gpointer                        callback_data)
592 {
593 	NautilusFileOperation *op;
594 	GFile *location;
595 
596 	op = nautilus_file_operation_new (file, callback, callback_data);
597 	if (cancellable) {
598 		g_object_unref (op->cancellable);
599 		op->cancellable = g_object_ref (cancellable);
600 	}
601 
602 	location = nautilus_file_get_location (file);
603 	g_file_stop_mountable (location,
604 			       G_MOUNT_UNMOUNT_NONE,
605 			       mount_op,
606 			       op->cancellable,
607 			       vfs_file_stop_callback,
608 			       op);
609 	g_object_unref (location);
610 }
611 
612 static void
613 vfs_file_poll_callback (GObject *source_object,
614 			GAsyncResult *res,
615 			gpointer callback_data)
616 {
617 	NautilusFileOperation *op;
618 	gboolean stopped;
619 	GError *error;
620 
621 	op = callback_data;
622 
623 	error = NULL;
624 	stopped = g_file_poll_mountable_finish (G_FILE (source_object),
625 						res, &error);
626 
627 	if (!stopped &&
628 	    error->domain == G_IO_ERROR &&
629 	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
630 	     error->code == G_IO_ERROR_CANCELLED)) {
631 		g_error_free (error);
632 		error = NULL;
633 	}
634 
635 	nautilus_file_operation_complete (op, G_FILE (source_object), error);
636 	if (error) {
637 		g_error_free (error);
638 	}
639 }
640 
641 static void
642 vfs_file_poll_for_media (NautilusFile *file)
643 {
644 	NautilusFileOperation *op;
645 	GFile *location;
646 
647 	op = nautilus_file_operation_new (file, NULL, NULL);
648 
649 	location = nautilus_file_get_location (file);
650 	g_file_poll_mountable (location,
651 			       op->cancellable,
652 			       vfs_file_poll_callback,
653 			       op);
654 	g_object_unref (location);
655 }
656 
657 static void
658 nautilus_vfs_file_init (NautilusVFSFile *file)
659 {
660 }
661 
662 static void
663 nautilus_vfs_file_class_init (NautilusVFSFileClass *klass)
664 {
665 	NautilusFileClass *file_class = NAUTILUS_FILE_CLASS (klass);
666 
667 	file_class->monitor_add = vfs_file_monitor_add;
668 	file_class->monitor_remove = vfs_file_monitor_remove;
669 	file_class->call_when_ready = vfs_file_call_when_ready;
670 	file_class->cancel_call_when_ready = vfs_file_cancel_call_when_ready;
671 	file_class->check_if_ready = vfs_file_check_if_ready;
672 	file_class->get_item_count = vfs_file_get_item_count;
673 	file_class->get_deep_counts = vfs_file_get_deep_counts;
674 	file_class->get_date = vfs_file_get_date;
675 	file_class->get_where_string = vfs_file_get_where_string;
676 	file_class->set_metadata = vfs_file_set_metadata;
677 	file_class->set_metadata_as_list = vfs_file_set_metadata_as_list;
678 	file_class->mount = vfs_file_mount;
679 	file_class->unmount = vfs_file_unmount;
680 	file_class->eject = vfs_file_eject;
681 	file_class->start = vfs_file_start;
682 	file_class->stop = vfs_file_stop;
683 	file_class->poll_for_media = vfs_file_poll_for_media;
684 }