diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-10 16:25:47 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-10 16:25:47 +0200 |
commit | 75703eb8d5bd0d8d9ef0a8abaf25b421ca668ab5 (patch) | |
tree | 75c79372e5def8a0feb93e48e0da72b1c2e112ba | |
parent | a48a29f921d9d50598784047b40c97c6850bb8ec (diff) | |
download | busybox-w32-75703eb8d5bd0d8d9ef0a8abaf25b421ca668ab5.tar.gz busybox-w32-75703eb8d5bd0d8d9ef0a8abaf25b421ca668ab5.tar.bz2 busybox-w32-75703eb8d5bd0d8d9ef0a8abaf25b421ca668ab5.zip |
diff: make diff -r much less eager to recurse into directories
function old new delta
skip_dir 44 120 +76
diff_main 1175 1185 +10
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/diff.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/editors/diff.c b/editors/diff.c index 3e2048330..a3ca2b660 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -121,6 +121,7 @@ typedef struct FILE_and_pos_t { | |||
121 | struct globals { | 121 | struct globals { |
122 | smallint exit_status; | 122 | smallint exit_status; |
123 | int opt_U_context; | 123 | int opt_U_context; |
124 | const char *other_dir; | ||
124 | char *label[2]; | 125 | char *label[2]; |
125 | struct stat stb[2]; | 126 | struct stat stb[2]; |
126 | }; | 127 | }; |
@@ -761,7 +762,7 @@ static int FAST_FUNC add_to_dirlist(const char *filename, | |||
761 | { | 762 | { |
762 | struct dlist *const l = userdata; | 763 | struct dlist *const l = userdata; |
763 | const char *file = filename + l->len; | 764 | const char *file = filename + l->len; |
764 | while(*file == '/') | 765 | while (*file == '/') |
765 | file++; | 766 | file++; |
766 | l->dl = xrealloc_vector(l->dl, 6, l->e); | 767 | l->dl = xrealloc_vector(l->dl, 6, l->e); |
767 | l->dl[l->e] = xstrdup(file); | 768 | l->dl[l->e] = xstrdup(file); |
@@ -780,6 +781,25 @@ static int FAST_FUNC skip_dir(const char *filename, | |||
780 | add_to_dirlist(filename, sb, userdata, depth); | 781 | add_to_dirlist(filename, sb, userdata, depth); |
781 | return SKIP; | 782 | return SKIP; |
782 | } | 783 | } |
784 | if (!(option_mask32 & FLAG(N))) { | ||
785 | /* -r without -N: no need to recurse into dirs | ||
786 | * which do not exist on the "other side". | ||
787 | * Testcase: diff -r /tmp / | ||
788 | * (it would recurse deep into /proc without this code) */ | ||
789 | struct dlist *const l = userdata; | ||
790 | filename += l->len; | ||
791 | if (filename[0]) { | ||
792 | struct stat osb; | ||
793 | char *othername = concat_path_file(G.other_dir, filename); | ||
794 | int r = stat(othername, &osb); | ||
795 | free(othername); | ||
796 | if (r != 0 || !S_ISDIR(osb.st_mode)) { | ||
797 | /* other dir doesn't have similarly named | ||
798 | * directory, don't recurse */ | ||
799 | return SKIP; | ||
800 | } | ||
801 | } | ||
802 | } | ||
783 | return TRUE; | 803 | return TRUE; |
784 | } | 804 | } |
785 | 805 | ||
@@ -793,6 +813,7 @@ static void diffdir(char *p[2], const char *s_start) | |||
793 | /*list[i].s = list[i].e = 0; - memset did it */ | 813 | /*list[i].s = list[i].e = 0; - memset did it */ |
794 | /*list[i].dl = NULL; */ | 814 | /*list[i].dl = NULL; */ |
795 | 815 | ||
816 | G.other_dir = p[1 - i]; | ||
796 | /* We need to trim root directory prefix. | 817 | /* We need to trim root directory prefix. |
797 | * Using list.len to specify its length, | 818 | * Using list.len to specify its length, |
798 | * add_to_dirlist will remove it. */ | 819 | * add_to_dirlist will remove it. */ |