1 /* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
2 /*======================================================================
3 Copyright (C) 2004,2005,2009,2013 Walter Doekes <walter+tthsum@wjd.nu>
4 This file is part of tthsum.
5
6 tthsum is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 tthsum is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with tthsum. If not, see <http://www.gnu.org/licenses/>.
18 ======================================================================*/
19 #include "texts.h"
20
21 #include <assert.h>
22
23 #ifdef _WIN32
24 # define WINDOWS_LEAN_AND_MEAN
25 # include <windows.h>
26 #else /* !_WIN32 */
27 # include <stdio.h>
28 # include <string.h>
29 # include <errno.h>
30 #endif /* !_WIN32 */
31
32
33 static int last_error = 0;
34 static int last_error_os = 0;
35 static const char* last_error_context = 0;
36 #define LAST_ERROR_SIZE 512
37 static char last_error_buf[LAST_ERROR_SIZE];
38
39 static const char* texts[] = {
40 /* ERROR_FIRST */
41 "No error yet",
42 /* BASE32_INVALID_CHARACTER */
43 "Invalid character encountered in BASE32 stream",
44 /* ESCAPE_INVALID_ESCAPE */
45 "Invalid escape sequence encountered",
46 /* TEXTS_UNKNOWN_ERROR */
47 "Unknown error",
48 /* THEX_INVALID_BLOCK_SIZE */
49 "The read operation isn't supplying multiples of 1024",
50 /* TTHSUM_FILENAME_TOO_LARGE */
51 "File name is too long",
52 /* TTHSUM_LINE_CORRUPT */
53 "Improperly formatted line",
54 /* TTHSUM_MISMATCHED_TTH */
55 "TTH check failed for",
56 /* UTF8_INVALID_UNICODE */
57 "Invalid character encountered in UNICODE stream",
58 /* UTF8_INVALID_UTF8 */
59 "Invalid character encountered in UTF8 stream",
60 /* UTF8_OVERLONG_UTF8 */
61 "Overlong character encountered in UTF8 stream"
62 /* ERROR_LAST */
63 };
64
set_error(const char * context,int error)65 void set_error(const char* context, int error) {
66 assert(strlen(context) < 32);
67 if (error == -1) {
68 #ifdef _WIN32
69 last_error = GetLastError();
70 #else /* !_WIN32 */
71 last_error = errno;
72 #endif /* !_WIN32 */
73 last_error_os = 1;
74 } else {
75 last_error = error;
76 last_error_os = 0;
77 }
78 last_error_context = context;
79 }
80
my_strcpy(char * dst,const char * src,int size)81 static int my_strcpy(char* dst, const char* src, int size) {
82 char *d = dst;
83
84 if (size <= 0)
85 return 0; /* no warning when truncating */
86
87 while (--size != 0 && *src != '\0') {
88 *d++ = *src++;
89 }
90 *d = '\0';
91
92 return d - dst; /* how many bytes we wrote excluding NUL */
93 }
94
get_error()95 const char* get_error() {
96 int i;
97 #ifdef _WIN32
98 DWORD w;
99 #endif /* !_WIN32 */
100
101 /* Avoid snprintf because it's not C90 */
102 if (!last_error_os) {
103 i = my_strcpy(last_error_buf, last_error_context, LAST_ERROR_SIZE);
104 i += my_strcpy(last_error_buf + i, ": ", LAST_ERROR_SIZE - i);
105 my_strcpy(last_error_buf + i, texts[last_error], LAST_ERROR_SIZE - i);
106 return last_error_buf;
107 }
108
109 i = my_strcpy(last_error_buf, last_error_context, LAST_ERROR_SIZE);
110 i += my_strcpy(last_error_buf + i, ": ", LAST_ERROR_SIZE - i);
111 #ifdef _WIN32
112 if ((w = FormatMessage(
113 FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
114 NULL, (DWORD)last_error, 0, last_error_buf + i,
115 LAST_ERROR_SIZE - 32 - i, NULL)) != 0) {
116 if (w >= 2) /* 32 is more than enough for " (0xINT)" */
117 sprintf(last_error_buf + i + w - 2, " (0x%x)", last_error);
118 } else {
119 i += my_strcpy(last_error_buf + i, get_text(TEXTS_UNKNOWN_ERROR),
120 LAST_ERROR_SIZE - i);
121 if (LAST_ERROR_SIZE - i >= 32) {
122 sprintf(last_error_buf + i, " (0x%x)", (unsigned)last_error);
123 }
124 }
125 #else /* !_WIN32 */
126 i += my_strcpy(last_error_buf + i, strerror(last_error),
127 LAST_ERROR_SIZE - i);
128 if (LAST_ERROR_SIZE - i >= 32) { /* 32 is more than enough */
129 sprintf(last_error_buf + i, " (%i)", last_error);
130 }
131 #endif /* !_WIN32 */
132 return last_error_buf;
133 }
134
get_text(enum text_id id)135 const char* get_text(enum text_id id) {
136 return texts[id];
137 }
138