]> granicus.if.org Git - file/commitdiff
From: Denys Vlasenko
authorChristos Zoulas <christos@zoulas.com>
Tue, 7 May 2019 02:27:11 +0000 (02:27 +0000)
committerChristos Zoulas <christos@zoulas.com>
Tue, 7 May 2019 02:27:11 +0000 (02:27 +0000)
Reduce amount of stat(2) calls when processing elf files;
propagate fstat result deeper into callees.

src/ascmagic.c
src/buffer.c
src/compress.c
src/file.h
src/funcs.c
src/magic.c
src/readelf.c
src/softmagic.c

index ea69f7846d066e088fbfd1c7f15834ecf496917d..624ac90b1f1c2dfdcf648d584a350f4d8788ce99 100644 (file)
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: ascmagic.c,v 1.103 2019/05/06 21:23:38 christos Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.104 2019/05/07 02:27:11 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -151,7 +151,7 @@ file_ascmagic_with_encoding(struct magic_set *ms,
                if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen))
                    == NULL)
                        goto done;
-               buffer_init(&bb, b->fd, utf8_buf,
+               buffer_init(&bb, b->fd, &b->st, utf8_buf,
                    CAST(size_t, utf8_end - utf8_buf));
 
                if ((rv = file_softmagic(ms, &bb, NULL, NULL,
index fd40416ae42d94fbe405d0a2ee4d2ee5b5b351e2..6d8967d2fa73de66f48b94b141d699d9ffb3c962 100644 (file)
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: buffer.c,v 1.5 2019/02/20 02:35:27 christos Exp $")
+FILE_RCSID("@(#)$File: buffer.c,v 1.6 2019/05/07 02:27:11 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -37,10 +37,13 @@ FILE_RCSID("@(#)$File: buffer.c,v 1.5 2019/02/20 02:35:27 christos Exp $")
 #include <sys/stat.h>
 
 void
-buffer_init(struct buffer *b, int fd, const void *data, size_t len)
+buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data,
+    size_t len)
 {
        b->fd = fd;
-       if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
+       if (st)
+               memcpy(&b->st, st, sizeof(b->st));
+       else if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
                memset(&b->st, 0, sizeof(b->st));
        b->fbuf = data;
        b->flen = len;
index 6ae0c59dae31250ced33097e5db84fb0cbe79804..95e42a24dd5229af8ae50b77a1d7258e9a7648ab 100644 (file)
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.120 2019/05/07 02:20:27 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.121 2019/05/07 02:27:11 christos Exp $")
 #endif
 
 #include "magic.h"
@@ -267,7 +267,7 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
                        if (urv == ERRDATA)
                                prv = format_decompression_error(ms, i, newbuf);
                        else
-                               prv = file_buffer(ms, -1, name, newbuf, nsz);
+                               prv = file_buffer(ms, -1, NULL, name, newbuf, nsz);
                        if (prv == -1)
                                goto error;
                        rv = 1;
@@ -284,7 +284,7 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
                         * XXX: If file_buffer fails here, we overwrite
                         * the compressed text. FIXME.
                         */
-                       if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) {
+                       if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1) {
                                if (file_pop_buffer(ms, pb) != NULL)
                                        abort();
                                goto error;
index d96be4f99d1663ae37f643b453e430dce9def859..69a586ab73238e6dccb7e5d14f09ee0020ccf3f5 100644 (file)
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.205 2019/05/06 21:22:13 christos Exp $
+ * @(#)$File: file.h,v 1.206 2019/05/07 02:27:11 christos Exp $
  */
 
 #ifndef __file_h__
@@ -454,8 +454,8 @@ protected const char *file_fmttime(uint64_t, int, char *);
 protected struct magic_set *file_ms_alloc(int);
 protected void file_ms_free(struct magic_set *);
 protected int file_default(struct magic_set *, size_t);
-protected int file_buffer(struct magic_set *, int, const char *, const void *,
-    size_t);
+protected int file_buffer(struct magic_set *, int, struct stat *, const char *,
+    const void *, size_t);
 protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
 protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
 protected int file_vprintf(struct magic_set *, const char *, va_list)
@@ -513,7 +513,8 @@ protected int file_os2_apptype(struct magic_set *, const char *, const void *,
     size_t);
 #endif /* __EMX__ */
 
-protected void buffer_init(struct buffer *, int, const void *, size_t);
+protected void buffer_init(struct buffer *, int, const struct stat *,
+    const void *, size_t);
 protected void buffer_fini(struct buffer *);
 protected int buffer_fill(const struct buffer *);
 
index 0fc53ad75a362e411536c30aa9b022eb0bf9f4b9..23e7f32e63d26bfa4e13ac4fa55f94198fe788d5 100644 (file)
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.103 2019/05/06 21:22:13 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.104 2019/05/07 02:27:11 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -207,7 +207,8 @@ file_default(struct magic_set *ms, size_t nb)
  */
 /*ARGSUSED*/
 protected int
-file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__unused__)),
+file_buffer(struct magic_set *ms, int fd, struct stat *st,
+    const char *inname __attribute__ ((__unused__)),
     const void *buf, size_t nb)
 {
        int m = 0, rv = 0, looks_text = 0;
@@ -218,7 +219,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
        char *rbuf = NULL;
        struct buffer b;
 
-       buffer_init(&b, fd, buf, nb);
+       buffer_init(&b, fd, st, buf, nb);
        ms->mode = b.st.st_mode;
 
        if (nb == 0) {
index 0796a753a819491091e9d0a9cb1c8f007833132a..da5baf108e5d9bfeec10329888ba00014be66c50 100644 (file)
@@ -33,7 +33,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: magic.c,v 1.110 2019/04/15 16:49:29 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.111 2019/05/07 02:27:11 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -406,6 +406,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
        struct stat     sb;
        ssize_t nbytes = 0;     /* number of bytes read from a datafile */
        int     ispipe = 0;
+       int     okstat = 0;
        off_t   pos = CAST(off_t, -1);
 
        if (file_reset(ms, 1) == -1)
@@ -438,7 +439,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
                int flags = O_RDONLY|O_BINARY|O_NONBLOCK;
                errno = 0;
                if ((fd = open(inname, flags)) < 0) {
-                       int okstat = stat(inname, &sb) == 0;
+                       okstat = stat(inname, &sb) == 0;
                        if (okstat && S_ISFIFO(sb.st_mode))
                                ispipe = 1;
 #ifdef WIN32
@@ -462,7 +463,9 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
        }
 
        if (fd != -1) {
-               if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
+               if (!okstat)
+                       okstat = fstat(fd, &sb) == 0;
+               if (okstat && S_ISFIFO(sb.st_mode))
                        ispipe = 1;
                if (inname == NULL)
                        pos = lseek(fd, CAST(off_t, 0), SEEK_CUR);
@@ -508,7 +511,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
        }
 
        (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
-       if (file_buffer(ms, fd, inname, buf, CAST(size_t, nbytes)) == -1)
+       if (file_buffer(ms, fd, okstat ? &sb : NULL, inname, buf, CAST(size_t, nbytes)) == -1)
                goto done;
        rv = 0;
 done:
@@ -534,7 +537,7 @@ magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
         * The main work is done here!
         * We have the file name and/or the data buffer to be identified.
         */
-       if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
+       if (file_buffer(ms, -1, NULL, NULL, buf, nb) == -1) {
                return NULL;
        }
        return file_getbuffer(ms);
index 5d97dd024430c2dcfda2200eeb1e5f97bfb13ee6..ef61d4cd600fe29a8f85771cf39daf9ed3bccc44 100644 (file)
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.164 2019/04/15 16:49:53 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.165 2019/05/07 02:27:11 christos Exp $")
 #endif
 
 #ifdef BUILTIN_ELF
@@ -1734,6 +1734,7 @@ file_tryelf(struct magic_set *ms, const struct buffer *b)
        int clazz;
        int swap;
        struct stat st;
+       const struct stat *stp;
        off_t fsize;
        int flags = 0;
        Elf32_Ehdr elf32hdr;
@@ -1762,12 +1763,25 @@ file_tryelf(struct magic_set *ms, const struct buffer *b)
            && (errno == ESPIPE))
                fd = file_pipe2file(ms, fd, buf, nbytes);
 
-       if (fd == -1 || fstat(fd, &st) == -1) {
-               file_badread(ms);
+       if (fd == -1) {
+               file_badread(ms);
                return -1;
        }
-       if (S_ISREG(st.st_mode) || st.st_size != 0)
-               fsize = st.st_size;
+
+       stp = &b->st;
+       /*
+        * b->st.st_size != 0 if previous fstat() succeeded,
+        * which is likely, we can avoid extra stat() call.
+        */
+       if (b->st.st_size == 0) {
+               stp = &st;
+               if (fstat(fd, &st) == -1) {
+                       file_badread(ms);
+                       return -1;
+               }
+       }
+       if (S_ISREG(stp->st_mode) || stp->st_size != 0)
+               fsize = stp->st_size;
        else
                fsize = SIZE_UNKNOWN;
 
index 542f6c5a7730671b4353d6fa5dbf62606c8b6779..e1495a4acccef63cbb6c514839002d760974021a 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.283 2019/05/06 21:22:40 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.284 2019/05/07 02:27:11 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -1487,13 +1487,13 @@ msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
                }
                if (CAST(size_t, -m->offset) > b->elen)
                        return -1;
-               buffer_init(bb, -1, b->ebuf, b->elen);
+               buffer_init(bb, -1, NULL, b->ebuf, b->elen);
                ms->eoffset = ms->offset = CAST(int32_t, b->elen + m->offset);
        } else {
                if (cont_level == 0) {
 normal:
                        // XXX: Pass real fd, then who frees bb?
-                       buffer_init(bb, -1, b->fbuf, b->flen);
+                       buffer_init(bb, -1, NULL, b->fbuf, b->flen);
                        ms->offset = m->offset;
                        ms->eoffset = 0;
                } else {