aboutsummaryrefslogtreecommitdiff
path: root/src/lzma/error.c
blob: a83de27a7761fec72e6b009aade729e0882030ab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
///////////////////////////////////////////////////////////////////////////////
//
/// \file       error.c
/// \brief      Error message printing
//
//  Copyright (C) 2007 Lasse Collin
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This program 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
//  Lesser General Public License for more details.
//
///////////////////////////////////////////////////////////////////////////////

#include "private.h"
#include <stdarg.h>


exit_status_type exit_status = SUCCESS;
verbosity_type verbosity = V_WARNING;
char *argv0 = NULL;
volatile sig_atomic_t user_abort = 0;


extern const char *
str_strm_error(lzma_ret code)
{
	switch (code) {
	case LZMA_OK:
		return _("Operation successful");

	case LZMA_STREAM_END:
		return _("Operation finished successfully");

	case LZMA_PROG_ERROR:
		return _("Internal error (bug)");

	case LZMA_DATA_ERROR:
		return _("Compressed data is corrupt");

	case LZMA_MEM_ERROR:
		return strerror(ENOMEM);

	case LZMA_BUF_ERROR:
		return _("Unexpected end of input");

	case LZMA_HEADER_ERROR:
		return _("Unsupported options");

	case LZMA_UNSUPPORTED_CHECK:
		return _("Unsupported integrity check type");

	default:
		return NULL;
	}
}


extern void
set_exit_status(exit_status_type new_status)
{
	static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_lock(&mutex);

	if (new_status != WARNING || exit_status == SUCCESS)
		exit_status = new_status;

	pthread_mutex_unlock(&mutex);
	return;
}


extern void lzma_attribute((noreturn))
my_exit(int status)
{
	// Close stdout. If something goes wrong, print an error message
	// to stderr.
	{
		const int ferror_err = ferror(stdout);
		const int fclose_err = fclose(stdout);
		if (fclose_err) {
			errmsg(V_ERROR, _("Writing to standard output "
					"failed: %s"), strerror(errno));
			status = ERROR;
		} else if (ferror_err) {
			// Some error has occurred but we have no clue about
			// the reason since fclose() succeeded.
			errmsg(V_ERROR, _("Writing to standard output "
					"failed: %s"), "Unknown error");
			status = ERROR;
		}
	}

	// Close stderr. If something goes wrong, there's nothing where we
	// could print an error message. Just set the exit status.
	{
		const int ferror_err = ferror(stderr);
		const int fclose_err = fclose(stderr);
		if (fclose_err || ferror_err)
			status = ERROR;
	}

	exit(status);
}


extern void lzma_attribute((format(printf, 2, 3)))
errmsg(verbosity_type v, const char *fmt, ...)
{
	va_list ap;

	if (v <= verbosity) {
		va_start(ap, fmt);

		static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
		pthread_mutex_lock(&mutex);

		fprintf(stderr, "%s: ", argv0);
		vfprintf(stderr, fmt, ap);
		fprintf(stderr, "\n");

		pthread_mutex_unlock(&mutex);

		va_end(ap);
	}

	if (v == V_ERROR)
		set_exit_status(ERROR);
	else if (v == V_WARNING)
		set_exit_status(WARNING);

	return;
}


extern void
out_of_memory(void)
{
	errmsg(V_ERROR, "%s", strerror(ENOMEM));
	user_abort = 1;
	return;
}


extern void
internal_error(void)
{
	errmsg(V_ERROR, _("Internal error (bug)"));
	user_abort = 1;
	return;
}