root/lib-src/make-fingerprint.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. main

     1 /* Hash inputs and generate C file with the digest.
     2 
     3 Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016, 2018-2023 Free
     4 Software Foundation, Inc.
     5 
     6 This file is part of GNU Emacs.
     7 
     8 GNU Emacs is free software: you can redistribute it and/or modify
     9 it under the terms of the GNU General Public License as published by
    10 the Free Software Foundation, either version 3 of the License, or (at
    11 your option) any later version.
    12 
    13 GNU Emacs is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 
    22 /* The argument given to this program is the initial version of the
    23  temacs executable file used when building GNU Emacs.  This program computes
    24  a digest fingerprint for the executable, and modifies the binary in
    25  place, replacing all instances of the existing fingerprint (normally
    26  the default fingerprint from libgnu's lib/fingerprint.c) with the
    27  new value.  With option -r, it just prints the digest.   */
    28 
    29 #include <config.h>
    30 
    31 #include <limits.h>
    32 #include <stdarg.h>
    33 #include <stdint.h>
    34 #include <stdio.h>
    35 #include <stdlib.h>
    36 #include <string.h>
    37 #include <sys/stat.h>
    38 
    39 #include <sysstdio.h>
    40 
    41 #include <fingerprint.h>
    42 #include <getopt.h>
    43 #include <intprops.h>
    44 #include <min-max.h>
    45 #include <sha256.h>
    46 
    47 #ifndef SSIZE_MAX
    48 # define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
    49 #endif
    50 
    51 #ifdef WINDOWSNT
    52 /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
    53    is really just insurance.  */
    54 #undef fopen
    55 #include <direct.h>
    56 
    57 #ifndef MINGW_W64
    58 # undef fseeko
    59 # define fseeko fseeko64
    60 #endif
    61 #endif /* WINDOWSNT */
    62 
    63 /* Static (instead of being local to 'main') to pacify LeakSanitizer.  */
    64 static char *buf;
    65 
    66 int
    67 main (int argc, char **argv)
    68 {
    69   int c;
    70   bool raw = false;
    71   while (0 <= (c = getopt (argc, argv, "rh")))
    72     {
    73       switch (c)
    74         {
    75         case 'r':
    76           raw = true;
    77           break;
    78         case 'h':
    79           printf ("make-fingerprint [-r] FILE: replace or compute a hash\n");
    80           return EXIT_SUCCESS;
    81         default:
    82           return EXIT_FAILURE;
    83         }
    84     }
    85 
    86   struct sha256_ctx ctx;
    87   sha256_init_ctx (&ctx);
    88 
    89   char *prog = argv[0];
    90   char *file = argv[optind];
    91   if (argc - optind != 1)
    92     {
    93       fprintf (stderr, "%s: missing or extra file operand\n", prog);
    94       return EXIT_FAILURE;
    95     }
    96 
    97   FILE *f = fopen (file, raw ? "r" FOPEN_BINARY : "r+" FOPEN_BINARY);
    98   struct stat st;
    99   if (!f || fstat (fileno (f), &st) != 0)
   100     {
   101       perror (file);
   102       return EXIT_FAILURE;
   103     }
   104 
   105   if (!S_ISREG (st.st_mode))
   106     {
   107       fprintf (stderr, "%s: Error: %s is not a regular file\n",
   108                prog, file);
   109       return EXIT_FAILURE;
   110     }
   111 
   112   ptrdiff_t maxlen = min (min (TYPE_MAXIMUM (off_t), PTRDIFF_MAX),
   113                           min (SIZE_MAX, SSIZE_MAX));
   114   if (maxlen <= st.st_size)
   115     {
   116       fprintf (stderr, "%s: %s: file too big\n", prog, file);
   117       return EXIT_FAILURE;
   118     }
   119 
   120   buf = malloc (st.st_size + 1);
   121   if (!buf)
   122     {
   123       perror ("malloc");
   124       return EXIT_FAILURE;
   125     }
   126 
   127   size_t chunksz = fread (buf, 1, st.st_size + 1, f);
   128   if (ferror (f) || chunksz != st.st_size)
   129     {
   130       fprintf (stderr, "%s: Error: could not read %s\n", prog, file);
   131       return EXIT_FAILURE;
   132     }
   133 
   134   sha256_process_bytes (buf, chunksz, &ctx);
   135 
   136   unsigned char digest[32];
   137   sha256_finish_ctx (&ctx, digest);
   138 
   139   if (raw)
   140     {
   141       for (int i = 0; i < 32; ++i)
   142         printf ("%02X", digest[i]);
   143     }
   144   else
   145     {
   146       bool fingered = false;
   147 
   148       for (char *finger = buf;
   149            (finger = memmem (finger, buf + chunksz - finger,
   150                              (unsigned char *) fingerprint,
   151                              sizeof fingerprint));
   152            finger++)
   153         {
   154           if (! (fseeko (f, finger - buf, SEEK_SET) == 0
   155                  && fwrite (digest, 1, sizeof digest, f) == sizeof digest))
   156             {
   157               perror (file);
   158               return EXIT_FAILURE;
   159             }
   160           fingered = true;
   161         }
   162 
   163       if (!fingered)
   164         {
   165           fprintf (stderr, "%s: %s: missing fingerprint\n", prog, file);
   166           return EXIT_FAILURE;
   167         }
   168     }
   169 
   170   if (fclose (f) != 0)
   171     {
   172       perror (file);
   173       return EXIT_FAILURE;
   174     }
   175 
   176   return EXIT_SUCCESS;
   177 }
   178 
   179 /* make-fingerprint.c ends here */

/* [<][>][^][v][top][bottom][index][help] */