diff options
author | Todd Lewis | 2017-03-28 21:16:56 +0200 |
---|---|---|
committer | Ruediger Meier | 2018-06-12 14:24:02 +0200 |
commit | 551e8963f4ca7850a2d91bcb5ffb6032a690e93f (patch) | |
tree | fbd3b4113c8ac5b785e2e3690e5992ce10fccffe /misc-utils | |
parent | Fixed 32 bit build with gcc7 (RH Bugzilla ID 1422989) (diff) | |
download | kernel-qcow2-util-linux-551e8963f4ca7850a2d91bcb5ffb6032a690e93f.tar.gz kernel-qcow2-util-linux-551e8963f4ca7850a2d91bcb5ffb6032a690e93f.tar.xz kernel-qcow2-util-linux-551e8963f4ca7850a2d91bcb5ffb6032a690e93f.zip |
exclude files via pcre
Diffstat (limited to 'misc-utils')
-rw-r--r-- | misc-utils/hardlink.1 | 14 | ||||
-rw-r--r-- | misc-utils/hardlink.c | 53 |
2 files changed, 57 insertions, 10 deletions
diff --git a/misc-utils/hardlink.1 b/misc-utils/hardlink.1 index 04228f4bb..b8bfe9d22 100644 --- a/misc-utils/hardlink.1 +++ b/misc-utils/hardlink.1 @@ -3,7 +3,7 @@ hardlink \- Consolidate duplicate files via hardlinks .SH "SYNOPSIS" .PP -\fBhardlink\fP [\fB-c\fP] [\fB-n\fP] [\fB-v\fP] [\fB-vv\fP] [\fB-h\fP] directory1 [ directory2 ... ] +\fBhardlink\fP [\fB-c\fP] [\fB-n\fP] [\fB-v\fP] [\fB-vv\fP] [\fB-x pattern\fP] [\fB-h\fP] directory1 [ directory2 ... ] .SH "DESCRIPTION" .PP This manual page documents \fBhardlink\fP, a @@ -32,8 +32,14 @@ Do not perform the consolidation; only print what would be changed. Print summary after hardlinking. .IP "\fB-vv\fP" 10 Print every hardlinked file and bytes saved. Also print summary after hardlinking. +.IP "\fB-x pattern\fP" 10 +Exclude files and directories matching pattern from hardlinking. .IP "\fB-h\fP" 10 Show help. +.PP +The optional pattern for excluding files and directories must be a PCRE2 +compatible regular expression. Only the basename of the file or directory +is checked, not its path. Excluded directories' contents will not be examined. .SH "AUTHOR" .PP \fBhardlink\fP was written by Jakub Jelinek <jakub@redhat.com>. @@ -48,3 +54,9 @@ it. If a directory tree does change, this may result in \fBhardlink\fP accessing files and/or directories outside of the intended directory tree. Thus, you must avoid running \fBhardlink\fP on potentially changing directory trees, and especially on directory trees under control of another user. +.PP +Historically \fBhardlink\fP silently excluded any names beginning with +".in.", as well as any names beginning with "." followed by exactly 6 +other characters. That prior behavior can be achieved by specifying +.br +-x '^(\.in\.|\.[^.]{6}$)' diff --git a/misc-utils/hardlink.c b/misc-utils/hardlink.c index 16d8163e2..69f6a464c 100644 --- a/misc-utils/hardlink.c +++ b/misc-utils/hardlink.c @@ -21,6 +21,7 @@ /* Changes by Travers Carter to make atomic hardlinking */ #define _GNU_SOURCE +#define PCRE2_CODE_UNIT_WIDTH 8 #include <sys/types.h> #include <stdlib.h> #include <stdio.h> @@ -31,12 +32,17 @@ #include <dirent.h> #include <fcntl.h> #include <errno.h> +#include <pcre2.h> #define NHASH (1<<17) /* Must be a power of 2! */ #define NIOBUF (1<<12) #define NAMELEN 4096 #define NBUF 64 +pcre2_code *re; +PCRE2_SPTR exclude_pattern; +pcre2_match_data *match_data; + struct _f; typedef struct _h { struct _h *next; @@ -99,12 +105,13 @@ void doexit(int i) void usage(char *prog) { - fprintf (stderr, "Usage: %s [-cnvhf] directories...\n", prog); + fprintf (stderr, "Usage: %s [-cnvhf] [-x pat] directories...\n", prog); fprintf (stderr, " -c When finding candidates for linking, compare only file contents.\n"); fprintf (stderr, " -n Don't actually link anything, just report what would be done.\n"); fprintf (stderr, " -v Print summary after hardlinking.\n"); fprintf (stderr, " -vv Print every hardlinked file and bytes saved + summary.\n"); fprintf (stderr, " -f Force hardlinking across filesystems.\n"); + fprintf (stderr, " -x pat Exclude files matching pattern.\n"); fprintf (stderr, " -h Show help.\n"); exit(255); } @@ -328,8 +335,10 @@ int main(int argc, char **argv) { int ch; int i; + int errornumber; + PCRE2_SIZE erroroffset; dynstr nam1 = {NULL, 0}; - while ((ch = getopt (argc, argv, "cnvhf")) != -1) { + while ((ch = getopt (argc, argv, "cnvhfx:")) != -1) { switch (ch) { case 'n': no_link++; @@ -343,6 +352,9 @@ int main(int argc, char **argv) case 'f': force=1; break; + case 'x': + exclude_pattern = (PCRE2_SPTR)optarg; + break; case 'h': default: usage(argv[0]); @@ -350,6 +362,22 @@ int main(int argc, char **argv) } if (optind >= argc) usage(argv[0]); + if (exclude_pattern) { + re = pcre2_compile( + exclude_pattern, /* the pattern */ + PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminate */ + 0, /* default options */ + &errornumber, + &erroroffset, + NULL); /* use default compile context */ + if (!re) { + PCRE2_UCHAR buffer[256]; + pcre2_get_error_message(errornumber, buffer, sizeof(buffer)); + fprintf(stderr, "pattern error at offset %d: %s\n", (int)erroroffset, buffer); + usage(argv[0]); + } + match_data = pcre2_match_data_create_from_pattern(re, NULL); + } for (i = optind; i < argc; i++) rf(argv[i]); while (dirs) { @@ -371,16 +399,23 @@ int main(int argc, char **argv) if (!di->d_name[0]) continue; if (di->d_name[0] == '.') { - char *q; - if (!di->d_name[1] || !strcmp (di->d_name, "..") || !strncmp (di->d_name, ".in.", 4)) + if (!di->d_name[1] || !strcmp(di->d_name, "..")) continue; - q = strrchr (di->d_name, '.'); - if (q && strlen (q) == 7 && q != di->d_name) { + } + if (re && pcre2_match( + re, /* compiled regex */ + (PCRE2_SPTR)di->d_name, + strlen(di->d_name), + 0, /* start at offset 0 */ + 0, /* default options */ + match_data, /* block for storing the result */ + NULL) /* use default match context */ + >= 0) { + if (verbose) { nam1.buf[nam1baselen] = 0; - if (verbose) - fprintf(stderr, "Skipping %s%s\n", nam1.buf, di->d_name); - continue; + fprintf(stderr,"Skipping %s%s\n", nam1.buf, di->d_name); } + continue; } { size_t subdirlen; |