hush: replace flag bytes in struct o_string with bit flags
[oweals/busybox.git] / editors / diff.c
index a8ffcdd8dc6368264da5a09dd678c9731aa45ea5..83de5275302d2f29e6e0010294fbc7e4513ec736 100644 (file)
@@ -10,7 +10,7 @@
  * Agency (DARPA) and Air Force Research Laboratory, Air Force
  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
  *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
 /*
@@ -121,6 +121,7 @@ typedef struct FILE_and_pos_t {
 struct globals {
        smallint exit_status;
        int opt_U_context;
+       const char *other_dir;
        char *label[2];
        struct stat stb[2];
 };
@@ -471,14 +472,14 @@ start:
                        ix[i][j] = nfile[i][j].offset;
        }
 
-       /* lenght of prefix and suffix is calculated */
+       /* length of prefix and suffix is calculated */
        for (; pref < nlen[0] && pref < nlen[1] &&
               nfile[0][pref + 1].value == nfile[1][pref + 1].value;
               pref++);
        for (; suff < nlen[0] - pref && suff < nlen[1] - pref &&
               nfile[0][nlen[0] - suff].value == nfile[1][nlen[1] - suff].value;
               suff++);
-       /* Arrays are pruned by the suffix and prefix lenght,
+       /* Arrays are pruned by the suffix and prefix length,
         * the result being sorted and stored in sfile[fileno],
         * and their sizes are stored in slen[fileno]
         */
@@ -501,7 +502,7 @@ start:
        free(nfile[1]);
 
        class = xmalloc((slen[0] + 1) * sizeof(class[0]));
-       for (int i = 1; i <= slen[0]; i++) /* Unsorting */
+       for (i = 1; i <= slen[0]; i++) /* Unsorting */
                class[sfile[0][i].serial] = sfile[0][i].value;
        free(nfile[0]);
 #else
@@ -565,7 +566,7 @@ static bool diff(FILE* fp[2], char *file[2])
        FILE_and_pos_t ft[2];
        typedef struct { int a, b; } vec_t[2];
        vec_t *vec = NULL;
-       int i = 1, idx = -1;
+       int i = 1, j, k, idx = -1;
        bool anychange = false;
        int *J;
 
@@ -608,8 +609,8 @@ static bool diff(FILE* fp[2], char *file[2])
                                        break;
                                }
 
-                               for (int j = 0; j < 2; j++)
-                                       for (int k = v[j].a; k < v[j].b; k++)
+                               for (j = 0; j < 2; j++)
+                                       for (k = v[j].a; k < v[j].b; k++)
                                                nonempty |= (ix[j][k+1] - ix[j][k] != 1);
 
                                vec = xrealloc_vector(vec, 6, ++idx);
@@ -624,6 +625,7 @@ static bool diff(FILE* fp[2], char *file[2])
                if (idx < 0 || ((option_mask32 & FLAG(B)) && !nonempty))
                        goto cont;
                if (!(option_mask32 & FLAG(q))) {
+                       int lowa;
                        vec_t span, *cvp = vec;
 
                        if (!anychange) {
@@ -633,7 +635,7 @@ static bool diff(FILE* fp[2], char *file[2])
                        }
 
                        printf("@@");
-                       for (int j = 0; j < 2; j++) {
+                       for (j = 0; j < 2; j++) {
                                int a = span[j].a = MAX(1, (*cvp)[j].a - opt_U_context);
                                int b = span[j].b = MIN(nlen[j], vec[idx][j].b + opt_U_context);
 
@@ -647,12 +649,12 @@ static bool diff(FILE* fp[2], char *file[2])
                         * Output changes in "unified" diff format--the old and new lines
                         * are printed together.
                         */
-                       for (int lowa = span[0].a; ; lowa = (*cvp++)[0].b + 1) {
+                       for (lowa = span[0].a; ; lowa = (*cvp++)[0].b + 1) {
                                bool end = cvp > &vec[idx];
                                fetch(&ft[0], ix[0], lowa, end ? span[0].b : (*cvp)[0].a - 1, ' ');
                                if (end)
                                        break;
-                               for (int j = 0; j < 2; j++)
+                               for (j = 0; j < 2; j++)
                                        fetch(&ft[j], ix[j], (*cvp)[j].a, (*cvp)[j].b, j ? '+' : '-');
                        }
                }
@@ -759,9 +761,11 @@ static int FAST_FUNC add_to_dirlist(const char *filename,
                void *userdata, int depth UNUSED_PARAM)
 {
        struct dlist *const l = userdata;
+       const char *file = filename + l->len;
+       while (*file == '/')
+               file++;
        l->dl = xrealloc_vector(l->dl, 6, l->e);
-       /* + 1 skips "/" after dirname */
-       l->dl[l->e] = xstrdup(filename + l->len + 1);
+       l->dl[l->e] = xstrdup(file);
        l->e++;
        return TRUE;
 }
@@ -777,6 +781,25 @@ static int FAST_FUNC skip_dir(const char *filename,
                add_to_dirlist(filename, sb, userdata, depth);
                return SKIP;
        }
+       if (!(option_mask32 & FLAG(N))) {
+               /* -r without -N: no need to recurse into dirs
+                * which do not exist on the "other side".
+                * Testcase: diff -r /tmp /
+                * (it would recurse deep into /proc without this code) */
+               struct dlist *const l = userdata;
+               filename += l->len;
+               if (filename[0]) {
+                       struct stat osb;
+                       char *othername = concat_path_file(G.other_dir, filename);
+                       int r = stat(othername, &osb);
+                       free(othername);
+                       if (r != 0 || !S_ISDIR(osb.st_mode)) {
+                               /* other dir doesn't have similarly named
+                                * directory, don't recurse */
+                               return SKIP;
+                       }
+               }
+       }
        return TRUE;
 }
 
@@ -790,6 +813,7 @@ static void diffdir(char *p[2], const char *s_start)
                /*list[i].s = list[i].e = 0; - memset did it */
                /*list[i].dl = NULL; */
 
+               G.other_dir = p[1 - i];
                /* We need to trim root directory prefix.
                 * Using list.len to specify its length,
                 * add_to_dirlist will remove it. */