grep: Add optargs to grep API and deprecate fgrep etc.

This commit makes grep into an optargs API, with flags for extended,
fixed, [case-]insensitive and compressed.

At the same time it deprecates: egrep, fgrep, grepi, egrepi, fgrepi,
zgrep, zegrep, zfgrep, zgrepi, zegrepi and zfgrepi.
This commit is contained in:
Richard W.M. Jones
2012-08-02 14:05:54 +01:00
parent d40b502876
commit b3d0cc0588
6 changed files with 146 additions and 27 deletions

View File

@@ -28,13 +28,40 @@
#include "daemon.h"
#include "actions.h"
#define MAX_ARGS 64
static char **
grep (const char *prog, const char *flag, const char *regex, const char *path)
grep (const char *regex, const char *path,
int extended, int fixed, int insensitive, int compressed)
{
const char *argv[MAX_ARGS];
size_t i = 0;
char *out, *err;
int fd, flags, r;
char **lines;
if (extended && fixed) {
reply_with_error ("can't use 'extended' and 'fixed' flags at the same time");
return NULL;
}
if (!compressed)
ADD_ARG (argv, i, "grep");
else
ADD_ARG (argv, i, "zgrep");
if (extended)
ADD_ARG (argv, i, "-E");
if (fixed)
ADD_ARG (argv, i, "-F");
if (insensitive)
ADD_ARG (argv, i, "-i");
ADD_ARG (argv, i, regex);
ADD_ARG (argv, i, NULL);
CHROOT_IN;
fd = open (path, O_RDONLY|O_CLOEXEC);
CHROOT_OUT;
@@ -48,9 +75,9 @@ grep (const char *prog, const char *flag, const char *regex, const char *path)
* suppress this error and return an empty list.
*/
flags = COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN | fd;
r = commandrf (&out, &err, flags, prog, flag, regex, NULL);
r = commandrvf (&out, &err, flags, argv);
if (r == -1 || r > 1) {
reply_with_error ("%s %s %s: %s", prog, flag, regex, err);
reply_with_error ("%s: %s", regex, err);
free (out);
free (err);
return NULL;
@@ -65,75 +92,85 @@ grep (const char *prog, const char *flag, const char *regex, const char *path)
return lines;
}
/* Takes optional arguments, consult optargs_bitmask. */
char **
do_grep (const char *regex, const char *path)
do_grep (const char *regex, const char *path,
int extended, int fixed, int insensitive, int compressed)
{
/* The "--" is not really needed, but it helps when we don't need a flag. */
return grep ("grep", "--", regex, path);
if (!(optargs_bitmask & GUESTFS_GREP_EXTENDED_BITMASK))
extended = 0;
if (!(optargs_bitmask & GUESTFS_GREP_FIXED_BITMASK))
fixed = 0;
if (!(optargs_bitmask & GUESTFS_GREP_INSENSITIVE_BITMASK))
insensitive = 0;
if (!(optargs_bitmask & GUESTFS_GREP_COMPRESSED_BITMASK))
compressed = 0;
return grep (regex, path, extended, fixed, insensitive, compressed);
}
char **
do_egrep (const char *regex, const char *path)
{
return grep ("egrep", "--", regex, path);
return grep (regex, path, 1, 0, 0, 0);
}
char **
do_fgrep (const char *regex, const char *path)
{
return grep ("fgrep", "--", regex, path);
return grep (regex, path, 0, 1, 0, 0);
}
char **
do_grepi (const char *regex, const char *path)
{
return grep ("grep", "-i", regex, path);
return grep (regex, path, 0, 0, 1, 0);
}
char **
do_egrepi (const char *regex, const char *path)
{
return grep ("egrep", "-i", regex, path);
return grep (regex, path, 1, 0, 1, 0);
}
char **
do_fgrepi (const char *regex, const char *path)
{
return grep ("fgrep", "-i", regex, path);
return grep (regex, path, 0, 1, 1, 0);
}
char **
do_zgrep (const char *regex, const char *path)
{
return grep ("zgrep", "--", regex, path);
return grep (regex, path, 0, 0, 0, 1);
}
char **
do_zegrep (const char *regex, const char *path)
{
return grep ("zegrep", "--", regex, path);
return grep (regex, path, 1, 0, 0, 1);
}
char **
do_zfgrep (const char *regex, const char *path)
{
return grep ("zfgrep", "--", regex, path);
return grep (regex, path, 0, 1, 0, 1);
}
char **
do_zgrepi (const char *regex, const char *path)
{
return grep ("zgrep", "-i", regex, path);
return grep (regex, path, 0, 0, 1, 1);
}
char **
do_zegrepi (const char *regex, const char *path)
{
return grep ("zegrep", "-i", regex, path);
return grep (regex, path, 1, 0, 1, 1);
}
char **
do_zfgrepi (const char *regex, const char *path)
{
return grep ("zfgrep", "-i", regex, path);
return grep (regex, path, 0, 1, 1, 1);
}

View File

@@ -169,7 +169,9 @@ print_dhcp_address_linux (guestfs_h *g, char *root, const char *logfile)
char **lines, *p;
size_t len;
lines = guestfs_egrep (g, "dhclient.*: bound to ", logfile);
lines = guestfs_grep_opts (g, "dhclient.*: bound to ", logfile,
GUESTFS_GREP_OPTS_EXTENDED, 1,
-1);
if (lines == NULL)
exit (EXIT_FAILURE);

View File

@@ -5131,28 +5131,88 @@ in the total size of file that can be handled." };
{ defaults with
name = "grep";
style = RStringList "lines", [String "regex"; Pathname "path"], [];
style = RStringList "lines", [String "regex"; Pathname "path"], [OBool "extended"; OBool "fixed"; OBool "insensitive"; OBool "compressed"];
proc_nr = Some 151;
protocol_limit_warning = true;
protocol_limit_warning = true; once_had_no_optargs = true;
tests = [
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
[["grep"; "abc"; "/test-grep.txt"; ""; ""; ""; ""]],
["abc"; "abc123"]);
InitISOFS, Always, TestOutputList (
[["grep"; "nomatch"; "/test-grep.txt"]], []);
[["grep"; "nomatch"; "/test-grep.txt"; ""; ""; ""; ""]], []);
(* Test for RHBZ#579608, absolute symbolic links. *)
InitISOFS, Always, TestOutputList (
[["grep"; "nomatch"; "/abssymlink"]], [])
[["grep"; "nomatch"; "/abssymlink"; ""; ""; ""; ""]], []);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"; "true"; ""; ""; ""]],
["abc"; "abc123"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"; ""; "true"; ""; ""]],
["abc"; "abc123"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"; ""; ""; "true"; ""]],
["abc"; "abc123"; "ABC"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"; "true"; ""; "true"; ""]],
["abc"; "abc123"; "ABC"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt"; ""; "true"; "true"; ""]],
["abc"; "abc123"; "ABC"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt.gz"; ""; ""; ""; "true"]],
["abc"; "abc123"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt.gz"; "true"; ""; ""; "true"]],
["abc"; "abc123"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt.gz"; ""; "true"; ""; "true"]],
["abc"; "abc123"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt.gz"; ""; ""; "true"; "true"]],
["abc"; "abc123"; "ABC"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt.gz"; "true"; ""; "true"; "true"]],
["abc"; "abc123"; "ABC"]);
InitISOFS, Always, TestOutputList (
[["grep"; "abc"; "/test-grep.txt.gz"; ""; "true"; "true"; "true"]],
["abc"; "abc123"; "ABC"])
];
shortdesc = "return lines matching a pattern";
longdesc = "\
This calls the external C<grep> program and returns the
matching lines." };
matching lines.
The optional flags are:
=over 4
=item C<extended>
Use extended regular expressions.
This is the same as using the I<-E> flag.
=item C<fixed>
Match fixed (don't use regular expressions).
This is the same as using the I<-F> flag.
=item C<insensitive>
Match case-insensitive. This is the same as using the I<-i> flag.
=item C<compressed>
Use C<zgrep> instead of C<grep>. This allows the input to be
compress- or gzip-compressed.
=back" };
{ defaults with
name = "egrep";
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 152;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])
@@ -5167,6 +5227,7 @@ matching lines." };
style = RStringList "lines", [String "pattern"; Pathname "path"], [];
proc_nr = Some 153;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])
@@ -5181,6 +5242,7 @@ matching lines." };
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 154;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])
@@ -5195,6 +5257,7 @@ matching lines." };
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 155;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])
@@ -5209,6 +5272,7 @@ matching lines." };
style = RStringList "lines", [String "pattern"; Pathname "path"], [];
proc_nr = Some 156;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])
@@ -5223,6 +5287,7 @@ matching lines." };
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 157;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])
@@ -5237,6 +5302,7 @@ matching lines." };
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 158;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])
@@ -5251,6 +5317,7 @@ matching lines." };
style = RStringList "lines", [String "pattern"; Pathname "path"], [];
proc_nr = Some 159;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])
@@ -5265,6 +5332,7 @@ matching lines." };
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 160;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])
@@ -5279,6 +5347,7 @@ matching lines." };
style = RStringList "lines", [String "regex"; Pathname "path"], [];
proc_nr = Some 161;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])
@@ -5293,6 +5362,7 @@ matching lines." };
style = RStringList "lines", [String "pattern"; Pathname "path"], [];
proc_nr = Some 162;
protocol_limit_warning = true;
deprecated_by = Some "grep";
tests = [
InitISOFS, Always, TestOutputList (
[["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])

View File

@@ -47,6 +47,7 @@ guestfs_gobject_headers= \
include/guestfs-gobject/optargs-mount_local.h \
include/guestfs-gobject/optargs-umount_local.h \
include/guestfs-gobject/optargs-umount.h \
include/guestfs-gobject/optargs-grep.h \
include/guestfs-gobject/optargs-mkfs.h \
include/guestfs-gobject/optargs-mount_9p.h \
include/guestfs-gobject/optargs-ntfsresize.h \
@@ -95,6 +96,7 @@ guestfs_gobject_sources= \
src/optargs-mount_local.c \
src/optargs-umount_local.c \
src/optargs-umount.c \
src/optargs-grep.c \
src/optargs-mkfs.c \
src/optargs-mount_9p.c \
src/optargs-ntfsresize.c \

View File

@@ -146,6 +146,7 @@ gobject/src/optargs-copy_file_to_device.c
gobject/src/optargs-copy_file_to_file.c
gobject/src/optargs-e2fsck.c
gobject/src/optargs-fstrim.c
gobject/src/optargs-grep.c
gobject/src/optargs-inspect_get_icon.c
gobject/src/optargs-internal_test.c
gobject/src/optargs-md_create.c

View File

@@ -551,7 +551,7 @@ guestfs___first_line_of_file (guestfs_h *g, const char *filename)
return ret;
}
/* Get the first matching line (using guestfs_egrep{,i}) of a small file,
/* Get the first matching line (using egrep [-i]) of a small file,
* without any trailing newline character.
*
* Returns: 1 = returned a line (in *ret)
@@ -565,8 +565,9 @@ guestfs___first_egrep_of_file (guestfs_h *g, const char *filename,
char **lines;
int64_t size;
size_t i;
struct guestfs_grep_opts_argv optargs;
/* Don't trust guestfs_egrep not to break with very large files.
/* Don't trust guestfs_grep not to break with very large files.
* Check the file size is something reasonable first.
*/
size = guestfs_filesize (g, filename);
@@ -579,7 +580,13 @@ guestfs___first_egrep_of_file (guestfs_h *g, const char *filename,
return -1;
}
lines = (!iflag ? guestfs_egrep : guestfs_egrepi) (g, eregex, filename);
optargs.bitmask = GUESTFS_GREP_OPTS_EXTENDED_BITMASK;
optargs.extended = 1;
if (iflag) {
optargs.bitmask |= GUESTFS_GREP_OPTS_INSENSITIVE_BITMASK;
optargs.insensitive = 1;
}
lines = guestfs_grep_opts_argv (g, eregex, filename, &optargs);
if (lines == NULL)
return -1;
if (lines[0] == NULL) {