summaryrefslogtreecommitdiff
path: root/programs
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2008-02-25 11:17:08 +0000
committerAlexander Larsson <alexl@src.gnome.org>2008-02-25 11:17:08 +0000
commitfd09daa489fbf2158472c4a7f3b4e92bf8f4ec0c (patch)
treeacfdb20f29bf00584ade92c855d65c7dec241264 /programs
parent08ef6a83f785d5ac1eb423f8253c6455ad596232 (diff)
downloadgvfs-fd09daa489fbf2158472c4a7f3b4e92bf8f4ec0c.tar.gz
Prefer to return a GDaemonMount from an existing GDaemonVolumeMonitor
2008-02-24 David Zeuthen <davidz@redhat.com> * client/gdaemonfile.c: * client/gdaemonvolumemonitor.c: * client/gdaemonvolumemonitor.h: Prefer to return a GDaemonMount from an existing GDaemonVolumeMonitor rather than rolling our own for GDaemonFile's g_file_find_enclosing_mount() implementation. This is to ensure that g_mount_get_volume() will work properly with mounts that are adopted by GVolume objects from other volume monitors. * configure.ac: Check for libgphoto2 * daemon/Makefile.am: * daemon/gvfsbackendcdda.c: Use HAL to detect when the disc is removed and then forcibly unmount the mount. Report size of disc. Hint the file manager to preview files. * hal/ghaldrive.c: * hal/ghalmount.c: * hal/ghalvolume.c: * hal/ghalvolumemonitor.c: * hal/ghalvolumemonitor.h: * hal/hal-pool.c: Ensure that audio and blank CD's are displayed (#514139). Read info.desktop.[icon|name] properties from hal and use these if found. Use proper icon for audio players and make the gphoto2 detection support it as well. Also check for subsystem when filtering on hal capabilities. Also revert the commit to ignore NFS mounts as gio will now only report an user visible mount if it's in /media or $HOME. Make LUKS encrypted volumes work. * daemon/Makefile.am: * daemon/gphoto2.mount.in: * daemon/gvfsbackendgphoto2.c: Land the gphoto2 backend. * programs/Makefile.am: * programs/gvfs-ls.c: Make the --hidden option work. Default to short listing and add a --long option. Implement new options --show-completions and --show-mounts that can be used for shell completions. * programs/gvfs-tree.c: New program * programs/gvfs-bash-completion.sh: Bash completion for gvfs; uses the new --show-completions and --show-mounts options in gvfs-ls. svn path=/trunk/; revision=1359
Diffstat (limited to 'programs')
-rw-r--r--programs/Makefile.am7
-rwxr-xr-xprograms/gvfs-bash-completion.sh56
-rw-r--r--programs/gvfs-ls.c183
-rw-r--r--programs/gvfs-tree.c270
4 files changed, 509 insertions, 7 deletions
diff --git a/programs/Makefile.am b/programs/Makefile.am
index b104c355..766bfa2b 100644
--- a/programs/Makefile.am
+++ b/programs/Makefile.am
@@ -16,6 +16,7 @@ bin_PROGRAMS = \
gvfs-open \
gvfs-save \
gvfs-ls \
+ gvfs-tree \
gvfs-info \
gvfs-trash \
gvfs-rm \
@@ -30,6 +31,9 @@ bin_SCRIPTS = \
gvfs-less \
$(NULL)
+profiledir = $(sysconfdir)/profile.d
+profile_SCRIPTS = gvfs-bash-completion.sh
+
gvfs_cat_SOURCES = gvfs-cat.c
gvfs_cat_LDADD = $(libraries)
@@ -54,6 +58,9 @@ gvfs_rm_LDADD = $(libraries)
gvfs_ls_SOURCES = gvfs-ls.c
gvfs_ls_LDADD = $(libraries)
+gvfs_tree_SOURCES = gvfs-tree.c
+gvfs_tree_LDADD = $(libraries)
+
gvfs_move_SOURCES = gvfs-move.c
gvfs_move_LDADD = $(libraries)
diff --git a/programs/gvfs-bash-completion.sh b/programs/gvfs-bash-completion.sh
new file mode 100755
index 00000000..1854663f
--- /dev/null
+++ b/programs/gvfs-bash-completion.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# 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: David Zeuthen <davidz@redhat.com>
+
+# Check for bash
+[ -z "$BASH_VERSION" ] && return
+
+####################################################################################################
+
+# don't misbehave on colons; See item E13 at http://tiswww.case.edu/php/chet/bash/FAQ
+COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
+
+__gvfs_multiple_uris() {
+ local IFS=$'\n'
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+
+ if [ "$cur" = "" ] ; then
+ COMPREPLY=($(compgen -W "$(gvfs-ls --show-mounts)" -- $cur))
+ else
+ COMPREPLY=($(compgen -W "$(gvfs-ls --show-completions $cur)" -- $cur))
+ fi
+}
+
+####################################################################################################
+
+complete -o nospace -F __gvfs_multiple_uris gvfs-ls
+complete -o nospace -F __gvfs_multiple_uris gvfs-info
+complete -o nospace -F __gvfs_multiple_uris gvfs-cat
+complete -o nospace -F __gvfs_multiple_uris gvfs-less
+complete -o nospace -F __gvfs_multiple_uris gvfs-copy
+complete -o nospace -F __gvfs_multiple_uris gvfs-mkdir
+complete -o nospace -F __gvfs_multiple_uris gvfs-monitor-dir
+complete -o nospace -F __gvfs_multiple_uris gvfs-monitor-file
+complete -o nospace -F __gvfs_multiple_uris gvfs-move
+complete -o nospace -F __gvfs_multiple_uris gvfs-open
+complete -o nospace -F __gvfs_multiple_uris gvfs-rm
+complete -o nospace -F __gvfs_multiple_uris gvfs-save
+complete -o nospace -F __gvfs_multiple_uris gvfs-trash
+complete -o nospace -F __gvfs_multiple_uris gvfs-tree
diff --git a/programs/gvfs-ls.c b/programs/gvfs-ls.c
index be202a7b..fb726b5d 100644
--- a/programs/gvfs-ls.c
+++ b/programs/gvfs-ls.c
@@ -1,3 +1,5 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
@@ -29,11 +31,17 @@
static char *attributes = NULL;
static gboolean show_hidden = FALSE;
+static gboolean show_mounts = FALSE;
+static gboolean show_long = FALSE;
+static char *show_completions = NULL;
static GOptionEntry entries[] =
{
{ "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, "The attributes to get", NULL },
{ "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, "Show hidden files", NULL },
+ { "long", 'l', 0, G_OPTION_ARG_NONE, &show_long, "Use a long listing format", NULL },
+ { "show-completions", 'c', 0, G_OPTION_ARG_STRING, &show_completions, "Show completions", NULL},
+ { "show-mounts", 'm', 0, G_OPTION_ARG_NONE, &show_mounts, "Show mounts", NULL },
{ NULL }
};
@@ -86,7 +94,10 @@ show_info (GFileInfo *info)
size = g_file_info_get_size (info);
type = type_to_string (g_file_info_get_file_type (info));
- g_print ("%s\t%"G_GUINT64_FORMAT"\t(%s)", name, (guint64)size, type);
+ if (show_long)
+ g_print ("%s\t%"G_GUINT64_FORMAT"\t(%s)", name, (guint64)size, type);
+ else
+ g_print ("%s", name);
first_attr = TRUE;
attributes = g_file_info_list_attributes (info, NULL);
@@ -94,9 +105,11 @@ show_info (GFileInfo *info)
{
char *val_as_string;
- if (strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0 ||
+ if (!show_long ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0 ||
strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_SIZE) == 0 ||
- strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0)
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0 ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) == 0)
continue;
if (first_attr)
@@ -130,7 +143,7 @@ list (GFile *file)
enumerator = g_file_enumerate_children (file, attributes, 0, NULL, &error);
if (enumerator == NULL)
{
- g_print ("Error: %s\n", error->message);
+ g_printerr ("Error: %s\n", error->message);
g_error_free (error);
error = NULL;
return;
@@ -145,19 +158,157 @@ list (GFile *file)
if (error)
{
- g_print ("Error: %s\n", error->message);
+ g_printerr ("Error: %s\n", error->message);
g_error_free (error);
error = NULL;
}
if (!g_file_enumerator_close (enumerator, NULL, &error))
{
- g_print ("Error closing enumerator: %s\n", error->message);
+ g_printerr ("Error closing enumerator: %s\n", error->message);
g_error_free (error);
error = NULL;
}
}
+static void
+print_mounts (const char *prefix)
+{
+ GList *l;
+ GList *mounts;
+ GVolumeMonitor *volume_monitor;
+
+ volume_monitor = g_volume_monitor_get ();
+
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ if (mounts != NULL)
+ {
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = l->data;
+ GFile *mount_root;
+ char *uri;
+
+ mount_root = g_mount_get_root (mount);
+ uri = g_file_get_uri (mount_root);
+ if (prefix == NULL ||
+ g_str_has_prefix (uri, prefix))
+ g_print ("%s\n", uri);
+ g_free (uri);
+ g_object_unref (mount_root);
+ g_object_unref (mount);
+ }
+ g_list_free (mounts);
+ }
+ g_object_unref (volume_monitor);
+
+ if (prefix == NULL || g_str_has_prefix ("file:///", prefix))
+ g_print ("file:///\n");
+}
+
+static void
+show_completed_file (GFile *hit,
+ gboolean is_dir,
+ const char *arg)
+{
+ char *display, *cwd;
+ GFile *cwd_f;
+
+ if (g_file_is_native (hit))
+ {
+ cwd = g_get_current_dir ();
+ cwd_f = g_file_new_for_path (cwd);
+ g_free (cwd);
+
+ if (g_file_has_prefix (hit, cwd_f) &&
+ !g_path_is_absolute (arg))
+ display = g_file_get_relative_path (cwd_f, hit);
+ else
+ display = g_file_get_path (hit);
+ g_object_unref (cwd_f);
+ }
+ else
+ display = g_file_get_uri (hit);
+
+ g_print ("%s%s\n", display, (is_dir)?"/":"");
+ g_free (display);
+}
+
+static void
+print_completions (const char *arg)
+{
+ GFile *f;
+ GFile *parent;
+ char *basename;
+
+ f = g_file_new_for_commandline_arg (arg);
+
+ if (g_str_has_suffix (arg, "/") ||
+ *arg == 0)
+ {
+ parent = g_object_ref (f);
+ basename = g_strdup ("");
+ }
+ else
+ {
+ parent = g_file_get_parent (f);
+ basename = g_file_get_basename (f);
+ }
+
+ if (parent == NULL ||
+ !g_file_query_exists (parent, NULL))
+ {
+ GMount *mount;
+ mount = g_file_find_enclosing_mount (f, NULL, NULL);
+ if (mount == NULL)
+ {
+ print_mounts (arg);
+ goto out;
+ }
+ g_object_unref (mount);
+ }
+
+ if (parent != NULL)
+ {
+ GFileEnumerator *enumerator;
+ enumerator = g_file_enumerate_children (parent,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ 0,
+ NULL,
+ NULL);
+ if (enumerator != NULL)
+ {
+ GFileInfo *info;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
+ {
+ const char *name;
+ GFileType type;
+
+ name = g_file_info_get_name (info);
+ type = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
+ if (name != NULL && g_str_has_prefix (name, basename))
+ {
+ GFile *entry;
+ char *entry_uri;
+
+ entry = g_file_get_child (parent, name);
+ show_completed_file (entry, type == G_FILE_TYPE_DIRECTORY, arg);
+ g_object_unref (entry);
+ }
+ g_object_unref (info);
+ }
+ g_file_enumerator_close (enumerator, NULL, NULL);
+ }
+ g_object_unref (parent);
+ }
+
+ out:
+ g_object_unref (f);
+ g_free (basename);
+}
+
int
main (int argc, char *argv[])
{
@@ -175,12 +326,30 @@ main (int argc, char *argv[])
g_option_context_parse (context, &argc, &argv, &error);
g_option_context_free (context);
+ if (attributes != NULL)
+ {
+ /* asking for attributes implies -l; otherwise it won't get shown */
+ show_long = TRUE;
+ }
+
attributes = g_strconcat (G_FILE_ATTRIBUTE_STANDARD_NAME ","
G_FILE_ATTRIBUTE_STANDARD_TYPE ","
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
attributes != NULL ? "," : "",
attributes,
NULL);
+
+ if (show_mounts)
+ {
+ print_mounts (NULL);
+ return 0;
+ }
+ else if (show_completions != NULL)
+ {
+ print_completions (show_completions);
+ return 0;
+ }
if (argc > 1)
{
diff --git a/programs/gvfs-tree.c b/programs/gvfs-tree.c
new file mode 100644
index 00000000..c55b6621
--- /dev/null
+++ b/programs/gvfs-tree.c
@@ -0,0 +1,270 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* 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: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <string.h>
+#include <gio/gio.h>
+
+static gboolean show_hidden = FALSE;
+static gboolean follow_symlinks = FALSE;
+
+static GOptionEntry entries[] =
+{
+ { "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, "Show hidden files", NULL },
+ { "follow-symlinks", 'l', 0, G_OPTION_ARG_NONE, &follow_symlinks, "Follow symlinks, mounts and shortcuts like dirs", NULL },
+};
+
+static gint
+sort_info_by_name (GFileInfo *a, GFileInfo *b)
+{
+ const char *na;
+ const char *nb;
+
+ na = g_file_info_get_name (a);
+ nb = g_file_info_get_name (b);
+
+ if (na == NULL)
+ na = "";
+ if (nb == NULL)
+ nb = "";
+
+ return strcmp (na, nb);
+}
+
+static void
+do_tree (GFile *f, int level, guint64 pattern)
+{
+ GFileEnumerator *enumerator;
+ GError *error = NULL;
+ unsigned int n;
+ GFileInfo *info;
+
+ info = g_file_query_info (f,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ 0,
+ NULL, NULL);
+ if (info != NULL)
+ {
+ if (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) == G_FILE_TYPE_MOUNTABLE)
+ {
+ /* don't process mountables; we avoid these by getting the target_uri below */
+ g_object_unref (info);
+ return;
+ }
+ g_object_unref (info);
+ }
+
+ enumerator = g_file_enumerate_children (f,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET ","
+ G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ 0,
+ NULL,
+ &error);
+ if (enumerator != NULL)
+ {
+ GList *l;
+ GList *info_list;
+
+ info_list = NULL;
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
+ {
+ if (g_file_info_get_is_hidden (info) && !show_hidden)
+ {
+ g_object_unref (info);
+ }
+ else
+ {
+ info_list = g_list_prepend (info_list, info);
+ }
+ }
+ g_file_enumerator_close (enumerator, NULL, NULL);
+
+ info_list = g_list_sort (info_list, (GCompareFunc) sort_info_by_name);
+
+ for (l = info_list; l != NULL; l = l->next)
+ {
+ const char *name;
+ const char *target_uri;
+ GFileType type;
+ gboolean is_last_item;
+
+ info = l->data;
+ is_last_item = (l->next == NULL);
+
+ name = g_file_info_get_name (info);
+ type = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
+ if (name != NULL)
+ {
+
+ for (n = 0; n < level; n++)
+ {
+ if (pattern & (1<<n))
+ {
+ g_print ("| ");
+ }
+ else
+ {
+ g_print (" ");
+ }
+ }
+
+ if (is_last_item)
+ {
+ g_print ("`-- %s", name);
+ }
+ else
+ {
+ g_print ("|-- %s", name);
+ }
+
+ target_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
+ if (target_uri != NULL)
+ {
+ g_print (" -> %s", target_uri);
+ }
+ else
+ {
+ if (g_file_info_get_is_symlink (info))
+ {
+ const char *target;
+ target = g_file_info_get_symlink_target (info);
+ g_print (" -> %s", target);
+ }
+ }
+
+ g_print ("\n");
+
+ if ((type & G_FILE_TYPE_DIRECTORY) &&
+ (follow_symlinks || !g_file_info_get_is_symlink (info)))
+ {
+ guint64 new_pattern;
+ GFile *child;
+
+ if (is_last_item)
+ new_pattern = pattern;
+ else
+ new_pattern = pattern | (1<<level);
+
+ child = NULL;
+ if (target_uri != NULL)
+ {
+ if (follow_symlinks)
+ child = g_file_new_for_uri (target_uri);
+ }
+ else
+ {
+ child = g_file_get_child (f, name);
+ }
+
+ if (child != NULL)
+ {
+ do_tree (child, level + 1, new_pattern);
+ g_object_unref (child);
+ }
+ }
+ }
+ g_object_unref (info);
+ }
+ g_list_free (info_list);
+ }
+ else
+ {
+ for (n = 0; n < level; n++)
+ {
+ if (pattern & (1<<n))
+ {
+ g_print ("| ");
+ }
+ else
+ {
+ g_print (" ");
+ }
+ }
+
+ g_print (" [%s]\n", error->message);
+
+ g_error_free (error);
+ }
+}
+
+static void
+tree (GFile *f)
+{
+ char *uri;
+
+ uri = g_file_get_uri (f);
+ g_print ("%s\n", uri);
+ g_free (uri);
+
+ do_tree (f, 0, 0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- list contents of directories in a tree-like format");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ tree (file);
+ g_object_unref (file);
+ }
+ }
+ else
+ {
+ char *cwd;
+
+ cwd = g_get_current_dir ();
+ file = g_file_new_for_path (cwd);
+ g_free (cwd);
+ tree (file);
+ g_object_unref (file);
+ }
+
+ return 0;
+}