]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
hardlink: move global variables to a control structure
authorSami Kerola <kerolasa@iki.fi>
Sat, 27 Apr 2019 08:54:11 +0000 (09:54 +0100)
committerSami Kerola <kerolasa@iki.fi>
Wed, 1 May 2019 18:49:07 +0000 (19:49 +0100)
Well, sort of.  Due to use of ctl values in atexit() print_summary() there
is need for global control structure.

Secondly couple variables can be moved to more restricted scope, namely the
PCRE variables are now in main().

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
misc-utils/hardlink.c

index d64472e3fd3d8e5081756a244476ac677ff7f4a6..6a0d0c3615b9808ed95edbf73c095ce3860d4fea 100644 (file)
 #define NIOBUF  (1<<12)
 #define NBUF    64
 
-#ifdef HAVE_PCRE
-pcre2_code *re;
-PCRE2_SPTR exclude_pattern;
-pcre2_match_data *match_data;
-#endif
-
 struct hardlink_file;
 
 struct hardlink_hash {
@@ -78,20 +72,29 @@ struct hardlink_dynstr {
        size_t alloc;
 };
 
-static struct hardlink_dir *dirs;
-static struct hardlink_hash *hps[NHASH];
-
-static int no_link = 0;
-static int verbose = 0;
-static int content_only = 0;
-static int force = 0;
-static dev_t dev = 0;
-
-/* summary counters */
-static unsigned long long ndirs, nobjects, nregfiles, ncomp, nlinks, nsaved;
-
-static unsigned int buf[NBUF];
-static char iobuf1[NIOBUF], iobuf2[NIOBUF];
+struct hardlink_ctl {
+       struct hardlink_dir *dirs;
+       struct hardlink_hash *hps[NHASH];
+       char iobuf1[NIOBUF];
+       char iobuf2[NIOBUF];
+       /* summary counters */
+       unsigned long long ndirs;
+       unsigned long long nobjects;
+       unsigned long long nregfiles;
+       unsigned long long ncomp;
+       unsigned long long nlinks;
+       unsigned long long nsaved;
+       /* current device */
+       dev_t dev;
+       /* flags */
+       unsigned int verbose;
+       unsigned int
+               no_link:1,
+               content_only:1,
+               force:1;
+};
+/* ctl is in global scope due use in atexit() */
+struct hardlink_ctl global_ctl;
 
 __attribute__ ((always_inline))
 static inline unsigned int hash(off_t size, time_t mtime)
@@ -114,22 +117,24 @@ static inline int stcmp(struct stat *st1, struct stat *st2, int content_scope)
 
 static void print_summary(void)
 {
-       if (!verbose)
+       struct hardlink_ctl const *const ctl = &global_ctl;
+
+       if (!ctl->verbose)
                return;
 
-       if (verbose > 1 && nlinks)
+       if (ctl->verbose > 1 && ctl->nlinks)
                fputc('\n', stdout);
 
-       printf(_("Directories:   %9lld\n"), ndirs);
-       printf(_("Objects:       %9lld\n"), nobjects);
-       printf(_("Regular files: %9lld\n"), nregfiles);
-       printf(_("Comparisons:   %9lld\n"), ncomp);
-       printf("%s%9lld\n", (no_link ?
+       printf(_("Directories:   %9lld\n"), ctl->ndirs);
+       printf(_("Objects:       %9lld\n"), ctl->nobjects);
+       printf(_("Regular files: %9lld\n"), ctl->nregfiles);
+       printf(_("Comparisons:   %9lld\n"), ctl->ncomp);
+       printf(  "%s%9lld\n", (ctl->no_link ?
               _("Would link:    ") :
-              _("Linked:        ")), nlinks);
-       printf("%s %9lld\n", (no_link ?
-               _("Would save:   ") :
-               _("Saved:        ")), nsaved);
+              _("Linked:        ")), ctl->nlinks);
+       printf(  "%s %9lld\n", (ctl->no_link ?
+              _("Would save:   ") :
+              _("Saved:        ")), ctl->nsaved);
 }
 
 static void __attribute__((__noreturn__)) usage(void)
@@ -177,41 +182,42 @@ static void growstr(struct hardlink_dynstr *str, size_t newlen)
        str->buf = xrealloc(str->buf, str->alloc = add2(newlen, 1));
 }
 
-static void process_path(const char *name)
+static void process_path(struct hardlink_ctl *ctl, const char *name)
 {
        struct stat st, st2, st3;
        const size_t namelen = strlen(name);
 
-       nobjects++;
+       ctl->nobjects++;
        if (lstat(name, &st))
                return;
 
-       if (st.st_dev != dev && !force) {
-               if (dev)
+       if (st.st_dev != ctl->dev && !ctl->force) {
+               if (ctl->dev)
                        errx(EXIT_FAILURE,
                             _("%s is on different filesystem than the rest "
                               "(use -f option to override)."), name);
-               dev = st.st_dev;
+               ctl->dev = st.st_dev;
        }
        if (S_ISDIR(st.st_mode)) {
                struct hardlink_dir *dp = xmalloc(add3(sizeof(*dp), namelen, 1));
                memcpy(dp->name, name, namelen + 1);
-               dp->next = dirs;
-               dirs = dp;
+               dp->next = ctl->dirs;
+               ctl->dirs = dp;
 
        } else if (S_ISREG(st.st_mode)) {
                int fd, i;
                struct hardlink_file *fp, *fp2;
                struct hardlink_hash *hp;
                const char *n1, *n2;
+               unsigned int buf[NBUF];
                int cksumsize = sizeof(buf);
                unsigned int cksum;
-               time_t mtime = content_only ? 0 : st.st_mtime;
+               time_t mtime = ctl->content_only ? 0 : st.st_mtime;
                unsigned int hsh = hash(st.st_size, mtime);
                off_t fsize;
 
-               nregfiles++;
-               if (verbose > 1)
+               ctl->nregfiles++;
+               if (ctl->verbose > 1)
                        printf("%s\n", name);
 
                fd = open(name, O_RDONLY);
@@ -234,7 +240,7 @@ static void process_path(const char *name)
                        else
                                cksum += buf[i];
                }
-               for (hp = hps[hsh]; hp; hp = hp->next) {
+               for (hp = ctl->hps[hsh]; hp; hp = hp->next) {
                        if (hp->size == st.st_size && hp->mtime == mtime)
                                break;
                }
@@ -243,8 +249,8 @@ static void process_path(const char *name)
                        hp->size = st.st_size;
                        hp->mtime = mtime;
                        hp->chain = NULL;
-                       hp->next = hps[hsh];
-                       hps[hsh] = hp;
+                       hp->next = ctl->hps[hsh];
+                       ctl->hps[hsh] = hp;
                }
                for (fp = hp->chain; fp; fp = fp->next) {
                        if (fp->cksum == cksum)
@@ -259,7 +265,7 @@ static void process_path(const char *name)
                for (fp2 = fp; fp2 && fp2->cksum == cksum; fp2 = fp2->next) {
 
                        if (!lstat(fp2->name, &st2) && S_ISREG(st2.st_mode) &&
-                           !stcmp(&st, &st2, content_only) &&
+                           !stcmp(&st, &st2, ctl->content_only) &&
                            st2.st_ino != st.st_ino &&
                            st2.st_dev == st.st_dev) {
 
@@ -272,7 +278,7 @@ static void process_path(const char *name)
                                        close(fd2);
                                        continue;
                                }
-                               ncomp++;
+                               ctl->ncomp++;
                                lseek(fd, 0, SEEK_SET);
 
                                for (fsize = st.st_size; fsize > 0;
@@ -280,9 +286,9 @@ static void process_path(const char *name)
                                        ssize_t xsz;
                                        off_t rsize = fsize >= NIOBUF ? NIOBUF : fsize;
 
-                                       if ((xsz = read(fd, iobuf1, rsize)) != rsize)
+                                       if ((xsz = read(fd, ctl->iobuf1, rsize)) != rsize)
                                                warn(_("cannot read %s"), name);
-                                       else if ((xsz = read(fd2, iobuf2, rsize)) != rsize)
+                                       else if ((xsz = read(fd2, ctl->iobuf2, rsize)) != rsize)
                                                warn(_("cannot read %s"), fp2->name);
 
                                        if (xsz != rsize) {
@@ -290,7 +296,7 @@ static void process_path(const char *name)
                                                close(fd2);
                                                return;
                                        }
-                                       if (memcmp(iobuf1, iobuf2, rsize))
+                                       if (memcmp(ctl->iobuf1, ctl->iobuf2, rsize))
                                                break;
                                }
                                close(fd2);
@@ -310,7 +316,7 @@ static void process_path(const char *name)
                                n1 = fp2->name;
                                n2 = name;
 
-                               if (!no_link) {
+                               if (!ctl->no_link) {
                                        const char *suffix =
                                            ".$$$___cleanit___$$$";
                                        const size_t suffixlen = strlen(suffix);
@@ -340,21 +346,21 @@ static void process_path(const char *name)
                                        }
                                        free(nam2.buf);
                                }
-                               nlinks++;
+                               ctl->nlinks++;
                                if (st3.st_nlink > 1) {
                                        /* We actually did not save anything this time, since the link second argument
                                           had some other links as well.  */
-                                       if (verbose > 1)
+                                       if (ctl->verbose > 1)
                                                printf(_(" %s %s to %s\n"),
-                                                       (no_link ? _("Would link") : _("Linked")),
+                                                       (ctl->no_link ? _("Would link") : _("Linked")),
                                                        n1, n2);
                                } else {
-                                       nsaved += ((st.st_size + 4095) / 4096) * 4096;
-                                       if (verbose > 1)
+                                       ctl->nsaved += ((st.st_size + 4095) / 4096) * 4096;
+                                       if (ctl->verbose > 1)
                                                printf(_(" %s %s to %s, %s %jd\n"),
-                                                       (no_link ? _("Would link") : _("Linked")),
+                                                       (ctl->no_link ? _("Would link") : _("Linked")),
                                                        n1, n2,
-                                                       (no_link ? _("would save") : _("saved")),
+                                                       (ctl->no_link ? _("would save") : _("saved")),
                                                        (intmax_t)st.st_size);
                                }
                                close(fd);
@@ -386,8 +392,12 @@ int main(int argc, char **argv)
 #ifdef HAVE_PCRE
        int errornumber;
        PCRE2_SIZE erroroffset;
+       pcre2_code *re;
+       PCRE2_SPTR exclude_pattern;
+       pcre2_match_data *match_data;
 #endif
        struct hardlink_dynstr nam1 = { NULL, 0 };
+       struct hardlink_ctl *ctl = &global_ctl;
 
        static const struct option longopts[] = {
                { "content",    no_argument, NULL, 'c' },
@@ -408,16 +418,16 @@ int main(int argc, char **argv)
        while ((ch = getopt_long(argc, argv, "cnvfx:Vh", longopts, NULL)) != -1) {
                switch (ch) {
                case 'n':
-                       no_link++;
+                       ctl->no_link = 1;
                        break;
                case 'v':
-                       verbose++;
+                       ctl->verbose++;
                        break;
                case 'c':
-                       content_only++;
+                       ctl->content_only = 1;
                        break;
                case 'f':
-                       force = 1;
+                       ctl->force = 1;
                        break;
                case 'x':
 #ifdef HAVE_PCRE
@@ -460,15 +470,15 @@ int main(int argc, char **argv)
        atexit(print_summary);
 
        for (i = optind; i < argc; i++)
-               process_path(argv[i]);
+               process_path(ctl, argv[i]);
 
-       while (dirs) {
+       while (ctl->dirs) {
                DIR *dh;
                struct dirent *di;
-               struct hardlink_dir *dp = dirs;
+               struct hardlink_dir *dp = ctl->dirs;
                size_t nam1baselen = strlen(dp->name);
 
-               dirs = dp->next;
+               ctl->dirs = dp->next;
                growstr(&nam1, add2(nam1baselen, 1));
                memcpy(nam1.buf, dp->name, nam1baselen);
                free(dp);
@@ -478,7 +488,7 @@ int main(int argc, char **argv)
 
                if (dh == NULL)
                        continue;
-               ndirs++;
+               ctl->ndirs++;
 
                while ((di = readdir(dh)) != NULL) {
                        if (!di->d_name[0])
@@ -494,7 +504,7 @@ int main(int argc, char **argv)
                                              match_data, /* block for storing the result */
                                              NULL) /* use default match context */
                            >=0) {
-                               if (verbose) {
+                               if (ctl->verbose) {
                                        nam1.buf[nam1baselen] = 0;
                                        printf(_("Skipping %s%s\n"), nam1.buf, di->d_name);
                                }
@@ -509,7 +519,7 @@ int main(int argc, char **argv)
                                memcpy(&nam1.buf[nam1baselen], di->d_name,
                                       add2(subdirlen, 1));
                        }
-                       process_path(nam1.buf);
+                       process_path(ctl, nam1.buf);
                }
                closedir(dh);
        }