1 /* guestfish - the filesystem interactive shell
2 * Copyright (C) 2009 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program 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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #define _GNU_SOURCE // for strndup, asprintf
27 #ifdef HAVE_LIBREADLINE
28 #include <readline/readline.h>
35 /* Readline completion for paths on the guest filesystem, also for
36 * devices and LVM names.
39 int complete_dest_paths = 0; /* SEE NOTE */
41 /* NOTE: This is currently disabled by default (with no way to
42 * enable it). That's because it's not particularly natural.
44 * Also there is a quite serious performance problem. When listing
45 * even moderately long directories, this takes many seconds. The
46 * reason is because it calls guestfs_is_dir on each directory
47 * entry, thus lots of round trips to the server. We could have
48 * a "readdir and stat each entry" call to ease this.
52 complete_dest_paths_generator (const char *text, int state)
54 #ifdef HAVE_LIBREADLINE
56 static int len, index;
57 static char **words = NULL;
58 static int nr_words = 0;
60 guestfs_error_handler_cb old_error_cb;
61 void *old_error_cb_data;
63 /* Temporarily replace the error handler so that messages don't
64 * get printed to stderr while we are issuing commands.
66 #define SAVE_ERROR_CB \
67 old_error_cb = guestfs_get_error_handler (g, &old_error_cb_data); \
68 guestfs_set_error_handler (g, NULL, NULL);
70 /* Restore error handler. */
71 #define RESTORE_ERROR_CB \
72 guestfs_set_error_handler (g, old_error_cb, old_error_cb_data);
82 /* NB. 'words' array is NOT NULL-terminated. */
83 for (i = 0; i < nr_words; ++i)
93 #define APPEND_STRS_AND_FREE \
95 n = count_strings (strs); \
96 words = realloc (words, sizeof (char *) * (nr_words + n)); \
97 for (i = 0; i < n; ++i) \
98 words[nr_words++] = strs[i]; \
102 /* Is it a device? */
103 if (len < 5 || strncmp (text, "/dev/", 5) == 0) {
104 /* Get a list of everything that can possibly begin with /dev/ */
105 strs = guestfs_list_devices (g);
108 strs = guestfs_list_partitions (g);
111 strs = guestfs_lvs (g);
115 if (len < 1 || text[0] == '/') {
116 /* If we've got a partial path already, we need to list everything
117 * in that directory, otherwise list everything in /
121 p = strrchr (text, '/');
122 dir = p && p > text ? strndup (text, p - text) : strdup ("/");
124 strs = guestfs_ls (g, dir);
126 /* Prepend directory to names. */
128 for (i = 0; strs[i]; ++i) {
130 if (strcmp (dir, "/") == 0)
131 asprintf (&p, "/%s", strs[i]);
133 asprintf (&p, "%s/%s", dir, strs[i]);
143 /* else ... In theory we could complete other things here such as VG
144 * names. At the moment we don't do that.
150 /* This inhibits ordinary (local filename) completion. */
151 rl_attempted_completion_over = 1;
153 /* Complete the string. */
154 while (index < nr_words) {
157 if (strncasecmp (word, text, len) == 0) {
158 /* Is it a directory? */
159 if (strncmp (word, "/dev/", 5) != 0) {
161 if (guestfs_is_dir (g, word) > 0)
162 rl_completion_append_character = '/';
166 return strdup (word);
170 #endif /* HAVE_LIBREADLINE */