mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-15 09:47:20 +00:00
ebecafbd19
* lib-src/make-fingerprint.c (main): Don't consider multiple instances of the fingerprint to be an error, as this can happen with clang and -flto. Instead, replace all instances of the fingerprint. There is a tiny chance that this will silently corrupt the Emacs executable. This patch suggests that we should go back to fingerprinting the inputs to the linker instead of its output, as the new fingerprinting scheme is unnecessarily complicated and this complexity reduces reliability. The old scheme (i.e., before commit 2019-05-14T23:31:24Z!eggert@cs.ucla.edu) was simpler and more portable and good enough, and it's looking like it would be less trouble in practice than the new scheme.
176 lines
3.9 KiB
C
176 lines
3.9 KiB
C
/* Hash inputs and generate C file with the digest.
|
|
|
|
Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016, 2018-2019
|
|
Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Emacs.
|
|
|
|
GNU Emacs is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or (at
|
|
your option) any later version.
|
|
|
|
GNU Emacs is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
/* The arguments given to this program are all the object files that
|
|
go into building GNU Emacs. There is no special search logic to find
|
|
the files. */
|
|
|
|
#include <config.h>
|
|
|
|
#include <limits.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <sysstdio.h>
|
|
|
|
#include <fingerprint.h>
|
|
#include <getopt.h>
|
|
#include <intprops.h>
|
|
#include <min-max.h>
|
|
#include <sha256.h>
|
|
|
|
#ifndef SSIZE_MAX
|
|
# define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
|
|
#endif
|
|
|
|
#ifdef WINDOWSNT
|
|
/* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
|
|
is really just insurance. */
|
|
#undef fopen
|
|
#include <direct.h>
|
|
|
|
#ifndef MINGW_W64
|
|
# undef fseeko
|
|
# define fseeko fseeko64
|
|
#endif
|
|
#endif /* WINDOWSNT */
|
|
|
|
/* Static (instead of being local to 'main') to pacify LeakSanitizer. */
|
|
static char *buf;
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
int c;
|
|
bool raw = false;
|
|
while (0 <= (c = getopt (argc, argv, "rh")))
|
|
{
|
|
switch (c)
|
|
{
|
|
case 'r':
|
|
raw = true;
|
|
break;
|
|
case 'h':
|
|
printf ("make-fingerprint [-r] FILE: replace or compute a hash\n");
|
|
return EXIT_SUCCESS;
|
|
default:
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
struct sha256_ctx ctx;
|
|
sha256_init_ctx (&ctx);
|
|
|
|
char *prog = argv[0];
|
|
char *file = argv[optind];
|
|
if (argc - optind != 1)
|
|
{
|
|
fprintf (stderr, "%s: missing or extra file operand\n", prog);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
FILE *f = fopen (file, raw ? "r" FOPEN_BINARY : "r+" FOPEN_BINARY);
|
|
struct stat st;
|
|
if (!f || fstat (fileno (f), &st) != 0)
|
|
{
|
|
perror (file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (!S_ISREG (st.st_mode))
|
|
{
|
|
fprintf (stderr, "%s: Error: %s is not a regular file\n",
|
|
prog, file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
ptrdiff_t maxlen = min (min (TYPE_MAXIMUM (off_t), PTRDIFF_MAX),
|
|
min (SIZE_MAX, SSIZE_MAX));
|
|
if (maxlen <= st.st_size)
|
|
{
|
|
fprintf (stderr, "%s: %s: file too big\n", prog, file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
buf = malloc (st.st_size + 1);
|
|
if (!buf)
|
|
{
|
|
perror ("malloc");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
size_t chunksz = fread (buf, 1, st.st_size + 1, f);
|
|
if (ferror (f) || chunksz != st.st_size)
|
|
{
|
|
fprintf (stderr, "%s: Error: could not read %s\n", prog, file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
sha256_process_bytes (buf, chunksz, &ctx);
|
|
|
|
unsigned char digest[32];
|
|
sha256_finish_ctx (&ctx, digest);
|
|
|
|
if (raw)
|
|
{
|
|
for (int i = 0; i < 32; ++i)
|
|
printf ("%02X", digest[i]);
|
|
}
|
|
else
|
|
{
|
|
bool fingered = false;
|
|
|
|
for (char *finger = buf;
|
|
(finger = memmem (finger, buf + chunksz - finger,
|
|
fingerprint, sizeof fingerprint));
|
|
finger++)
|
|
{
|
|
if (! (fseeko (f, finger - buf, SEEK_SET) == 0
|
|
&& fwrite (digest, 1, sizeof digest, f) == sizeof digest))
|
|
{
|
|
perror (file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
fingered = true;
|
|
}
|
|
|
|
if (!fingered)
|
|
{
|
|
fprintf (stderr, "%s: %s: missing fingerprint\n", prog, file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (fclose (f) != 0)
|
|
{
|
|
perror (file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
/* make-fingerprint.c ends here */
|