mirror of
https://github.com/git/git
synced 2024-10-30 14:03:28 +00:00
c20181e3a3
Callers of start_command() can set the members .in and .out of struct child_process to a value > 0 to specify that this descriptor is used as the stdin or stdout of the child process. Previously, if start_command() was successful, this descriptor was closed upon return. Here we now make sure that the descriptor is also closed in case of failures. All callers are updated not to close the file descriptor themselves after start_command() was called. Note that earlier run_gpg_verify() of git-verify-tag set .out = 1, which worked because start_command() treated this as a special case, but now this is incorrect because it closes the descriptor. The intent here is to inherit stdout to the child, which is achieved by .out = 0. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>
108 lines
2.4 KiB
C
108 lines
2.4 KiB
C
/*
|
|
* Builtin "git verify-tag"
|
|
*
|
|
* Copyright (c) 2007 Carlos Rica <jasampler@gmail.com>
|
|
*
|
|
* Based on git-verify-tag.sh
|
|
*/
|
|
#include "cache.h"
|
|
#include "builtin.h"
|
|
#include "tag.h"
|
|
#include "run-command.h"
|
|
#include <signal.h>
|
|
|
|
static const char builtin_verify_tag_usage[] =
|
|
"git-verify-tag [-v|--verbose] <tag>...";
|
|
|
|
#define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
|
|
|
|
static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
|
|
{
|
|
struct child_process gpg;
|
|
const char *args_gpg[] = {"gpg", "--verify", "FILE", "-", NULL};
|
|
char path[PATH_MAX], *eol;
|
|
size_t len;
|
|
int fd, ret;
|
|
|
|
fd = git_mkstemp(path, PATH_MAX, ".git_vtag_tmpXXXXXX");
|
|
if (fd < 0)
|
|
return error("could not create temporary file '%s': %s",
|
|
path, strerror(errno));
|
|
if (write_in_full(fd, buf, size) < 0)
|
|
return error("failed writing temporary file '%s': %s",
|
|
path, strerror(errno));
|
|
close(fd);
|
|
|
|
/* find the length without signature */
|
|
len = 0;
|
|
while (len < size && prefixcmp(buf + len, PGP_SIGNATURE)) {
|
|
eol = memchr(buf + len, '\n', size - len);
|
|
len += eol ? eol - (buf + len) + 1 : size - len;
|
|
}
|
|
if (verbose)
|
|
write_in_full(1, buf, len);
|
|
|
|
memset(&gpg, 0, sizeof(gpg));
|
|
gpg.argv = args_gpg;
|
|
gpg.in = -1;
|
|
args_gpg[2] = path;
|
|
if (start_command(&gpg))
|
|
return error("could not run gpg.");
|
|
|
|
write_in_full(gpg.in, buf, len);
|
|
close(gpg.in);
|
|
ret = finish_command(&gpg);
|
|
|
|
unlink(path);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int verify_tag(const char *name, int verbose)
|
|
{
|
|
enum object_type type;
|
|
unsigned char sha1[20];
|
|
char *buf;
|
|
unsigned long size;
|
|
int ret;
|
|
|
|
if (get_sha1(name, sha1))
|
|
return error("tag '%s' not found.", name);
|
|
|
|
type = sha1_object_info(sha1, NULL);
|
|
if (type != OBJ_TAG)
|
|
return error("%s: cannot verify a non-tag object of type %s.",
|
|
name, typename(type));
|
|
|
|
buf = read_sha1_file(sha1, &type, &size);
|
|
if (!buf)
|
|
return error("%s: unable to read file.", name);
|
|
|
|
ret = run_gpg_verify(buf, size, verbose);
|
|
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
int cmd_verify_tag(int argc, const char **argv, const char *prefix)
|
|
{
|
|
int i = 1, verbose = 0, had_error = 0;
|
|
|
|
git_config(git_default_config);
|
|
|
|
if (argc == 1)
|
|
usage(builtin_verify_tag_usage);
|
|
|
|
if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) {
|
|
verbose = 1;
|
|
i++;
|
|
}
|
|
|
|
/* sometimes the program was terminated because this signal
|
|
* was received in the process of writing the gpg input: */
|
|
signal(SIGPIPE, SIG_IGN);
|
|
while (i < argc)
|
|
if (verify_tag(argv[i++], verbose))
|
|
had_error = 1;
|
|
return had_error;
|
|
}
|