]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
more: use libmagic to identify binary files
authorSami Kerola <kerolasa@iki.fi>
Wed, 6 May 2020 19:19:22 +0000 (20:19 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 12 May 2020 08:22:09 +0000 (10:22 +0200)
As the old commend said: 'This code would best be shared with the file(1)
program or, perhaps, more should not try to be so smart'.  Now at configure
time one can choose whether more(1) is sharing code with file(1), or not.

Addresses: http://bugs.debian.org/139205
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
configure.ac
text-utils/Makemodule.am
text-utils/more.c

index 1428dc893e273ad8980ce4df5dd5b708dafb0049..8f50e8102b06ff736fa63f1e8dc66967812b03e8 100644 (file)
@@ -1501,6 +1501,18 @@ AS_IF([test "x$with_libz" = xno], [have_z=no], [
   AC_CHECK_LIB([z], [crc32], [have_z=yes], [have_z=no])
 ])
 
+AC_ARG_WITH([libmagic],
+  AS_HELP_STRING([--without-libmagic], [compile without libmagic]),
+  [], [with_libmagic=auto]
+)
+AS_IF([test "x$with_libmagic" = xno], [have_magic=no], [
+  AC_CHECK_LIB([magic], [magic_open], [
+    AC_DEFINE([HAVE_MAGIC], [1], [Define to 1 if you have the libmagic present.])
+    MAGIC_LIBS="-lmagic"
+  ])
+])
+AC_SUBST([MAGIC_LIBS])
+
 
 AC_ARG_ENABLE([cramfs],
   AS_HELP_STRING([--disable-cramfs], [do not build fsck.cramfs, mkfs.cramfs]),
index 3f10934e9f79036d44cd49dbc2618b8fa89fad53..6c4b5208260d2fff5af3fdebc3fc66e7a265243f 100644 (file)
@@ -80,7 +80,7 @@ bin_PROGRAMS += more
 dist_man_MANS += text-utils/more.1
 more_SOURCES = text-utils/more.c
 more_CFLAGS = $(AM_CFLAGS) $(BSD_WARN_CFLAGS)
-more_LDADD = $(LDADD) libcommon.la
+more_LDADD = $(LDADD) $(MAGIC_LIBS) libcommon.la
 if HAVE_TINFO
 more_LDADD += $(TINFO_LIBS)
 more_LDADD += $(TINFO_CFLAGS)
index 69a0b89f6aec6540371eee0262a6a3709f2ff3b8..014b40a6cc0f079682453764c0ca0261820f726a 100644 (file)
 # include <term.h>
 #endif
 
-#include "env.h"
+#ifdef HAVE_MAGIC
+# include <magic.h>
+#endif
+
 #include "strutils.h"
 #include "nls.h"
 #include "xalloc.h"
 #include "widechar.h"
 #include "closestream.h"
 #include "rpmatch.h"
+#include "env.h"
 
 #ifdef TEST_PROGRAM
 # define NON_INTERACTIVE_MORE 1
@@ -157,6 +161,9 @@ struct more_control {
        int last_key_arg;               /* previous key command argument */
        int last_colon_command;         /* is a colon-prefixed key command */
        char *shell_line;               /* line to execute in subshell */
+#ifdef HAVE_MAGIC
+       magic_t magic;                  /* libmagic database entries */
+#endif
        unsigned int
                bad_stdout:1,           /* true if overwriting does not turn off standout */
                catch_suspend:1,        /* we should catch the SIGTSTP signal */
@@ -350,19 +357,24 @@ static void print_separator(const int c, int n)
        putchar('\n');
 }
 
-/* magic --
- *     check for file magic numbers.  This code would best be shared
- *     with the file(1) program or, perhaps, more should not try to be
- *     so smart. */
-static int check_magic(FILE *f, char *fs)
+/* check_magic -- check for file magic numbers. */
+static int check_magic(struct more_control *ctl, char *fs)
 {
+#ifdef HAVE_MAGIC
+       const char *mime_encoding = magic_descriptor(ctl->magic, fileno(ctl->current_file));
+
+       if (!mime_encoding || !(strcmp("binary", mime_encoding))) {
+               printf(_("\n******** %s: Not a text file ********\n\n"), fs);
+               return 1;
+       }
+#else
        signed char twobytes[2];
 
        /* don't try to look ahead if the input is unseekable */
-       if (fseek(f, 0L, SEEK_SET))
+       if (fseek(ctl->current_file, 0L, SEEK_SET))
                return 0;
 
-       if (fread(twobytes, 2, 1, f) == 1) {
+       if (fread(twobytes, 2, 1, ctl->current_file) == 1) {
                switch (twobytes[0] + (twobytes[1] << 8)) {
                case 0407:      /* a.out obj */
                case 0410:      /* a.out exec */
@@ -376,7 +388,8 @@ static int check_magic(FILE *f, char *fs)
                        return 1;
                }
        }
-       fseek(f, 0L, SEEK_SET); /* rewind() not necessary */
+       fseek(ctl->current_file, 0L, SEEK_SET); /* rewind() not necessary */
+#endif
        return 0;
 }
 
@@ -394,23 +407,17 @@ static void checkf(struct more_control *ctl, char *fs)
            (fstat(fileno(ctl->current_file), &st) != 0)) {
                if (ctl->clear_line_ends)
                        putp(ctl->erase_line);
-               warn(_("stat of %s failed"), fs);
-               ctl->current_file = NULL;
+               warn(_("cannot open %s"), fs);
                return;
        }
+#ifndef HAVE_MAGIC
        if ((st.st_mode & S_IFMT) == S_IFDIR) {
                printf(_("\n*** %s: directory ***\n\n"), fs);
                ctl->current_file = NULL;
                return;
        }
-       ctl->current_line = 0;
-       ctl->file_position = 0;
-       if ((ctl->current_file = fopen(fs, "r")) == NULL) {
-               fflush(stdout);
-               warn(_("cannot open %s"), fs);
-               return;
-       }
-       if (check_magic(ctl->current_file, fs)) {
+#endif
+       if (check_magic(ctl, fs)) {
                fclose(ctl->current_file);
                ctl->current_file = NULL;
                return;
@@ -704,6 +711,9 @@ static void reset_tty(struct more_control *ctl)
 /* Clean up terminal state and exit. Also come here if interrupt signal received */
 static void __attribute__((__noreturn__)) more_exit(struct more_control *ctl)
 {
+#ifdef HAVE_MAGIC
+       magic_close(ctl->magic);
+#endif
        reset_tty(ctl);
        if (ctl->clear_line_ends) {
                putchar('\r');
@@ -1906,6 +1916,10 @@ int main(int argc, char **argv)
 
        initterm(&ctl);
 
+#ifdef HAVE_MAGIC
+       ctl.magic = magic_open(MAGIC_MIME_ENCODING | MAGIC_SYMLINK);
+       magic_load(ctl.magic, NULL);
+#endif
        prepare_line_buffer(&ctl);
 
        ctl.d_scroll_len = ctl.lines_per_page / 2 - 1;