common: Rename log and gcc attribute macros (jnlib merge).
[gnupg.git] / common / miscellaneous.c
1 /* miscellaneous.c - Stuff not fitting elsewhere
2  *      Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <http://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31 #include <stdlib.h>
32 #include <errno.h>
33
34 #include "util.h"
35 #include "iobuf.h"
36 #include "i18n.h"
37
38 /* Used by libgcrypt for logging.  */
39 static void
40 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
41 {
42   (void)dummy;
43
44   /* Map the log levels.  */
45   switch (level)
46     {
47     case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
48     case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
49     case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
50     case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
51     case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
52     case GCRY_LOG_BUG:  level = GPGRT_LOG_BUG; break;
53     case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
54     default:            level = GPGRT_LOG_ERROR; break;
55     }
56   log_logv (level, fmt, arg_ptr);
57 }
58
59
60 /* This function is called by libgcrypt on a fatal error.  */
61 static void
62 my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
63 {
64   (void)opaque;
65
66   log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc));
67   abort ();
68 }
69
70
71 /* This function is called by libgcrypt if it ran out of core and
72    there is no way to return that error to the caller.  We do our own
73    function here to make use of our logging functions. */
74 static int
75 my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
76 {
77   static int been_here;  /* Used to protect against recursive calls. */
78
79   (void)opaque;
80
81   if (!been_here)
82     {
83       been_here = 1;
84       if ( (flags & 1) )
85         log_fatal (_("out of core in secure memory "
86                      "while allocating %lu bytes"), (unsigned long)req_n);
87       else
88         log_fatal (_("out of core while allocating %lu bytes"),
89                    (unsigned long)req_n);
90     }
91   return 0; /* Let libgcrypt call its own fatal error handler.
92                Actually this will turn out to be
93                my_gcry_fatalerror_handler. */
94 }
95
96
97 /* Setup libgcrypt to use our own logging functions.  Should be used
98    early at startup. */
99 void
100 setup_libgcrypt_logging (void)
101 {
102   gcry_set_log_handler (my_gcry_logger, NULL);
103   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
104   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
105 }
106
107 /* A wrapper around gcry_cipher_algo_name to return the string
108    "AES-128" instead of "AES".  Given that we have an alias in
109    libgcrypt for it, it does not harm to too much to return this other
110    string.  Some users complained that we print "AES" but "AES192"
111    and "AES256".  We can't fix that in libgcrypt but it is pretty
112    safe to do it in an application. */
113 const char *
114 gnupg_cipher_algo_name (int algo)
115 {
116   const char *s;
117
118   s = gcry_cipher_algo_name (algo);
119   if (!strcmp (s, "AES"))
120     s = "AES128";
121   return s;
122 }
123
124
125 /* Decide whether the filename is stdout or a real filename and return
126  * an appropriate string.  */
127 const char *
128 print_fname_stdout (const char *s)
129 {
130     if( !s || (*s == '-' && !s[1]) )
131         return "[stdout]";
132     return s;
133 }
134
135
136 /* Decide whether the filename is stdin or a real filename and return
137  * an appropriate string.  */
138 const char *
139 print_fname_stdin (const char *s)
140 {
141     if( !s || (*s == '-' && !s[1]) )
142         return "[stdin]";
143     return s;
144 }
145
146
147 static int
148 do_print_utf8_buffer (estream_t stream,
149                       const void *buffer, size_t length,
150                       const char *delimiters, size_t *bytes_written)
151 {
152   const char *p = buffer;
153   size_t i;
154
155   /* We can handle plain ascii simpler, so check for it first. */
156   for (i=0; i < length; i++ )
157     {
158       if ( (p[i] & 0x80) )
159         break;
160     }
161   if (i < length)
162     {
163       int delim = delimiters? *delimiters : 0;
164       char *buf;
165       int ret;
166
167       /*(utf8 conversion already does the control character quoting). */
168       buf = utf8_to_native (p, length, delim);
169       if (bytes_written)
170         *bytes_written = strlen (buf);
171       ret = es_fputs (buf, stream);
172       xfree (buf);
173       return ret == EOF? ret : (int)i;
174     }
175   else
176     return es_write_sanitized (stream, p, length, delimiters, bytes_written);
177 }
178
179
180 void
181 print_utf8_buffer3 (estream_t stream, const void *p, size_t n,
182                     const char *delim)
183 {
184   do_print_utf8_buffer (stream, p, n, delim, NULL);
185 }
186
187
188 void
189 print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim)
190 {
191   char tmp[2];
192
193   tmp[0] = delim;
194   tmp[1] = 0;
195   do_print_utf8_buffer (stream, p, n, tmp, NULL);
196 }
197
198
199 void
200 print_utf8_buffer (estream_t stream, const void *p, size_t n)
201 {
202   do_print_utf8_buffer (stream, p, n, NULL, NULL);
203 }
204
205 /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
206    RESERVED must be 0. */
207 void
208 print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
209 {
210 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
211   const unsigned char *s;
212
213   (void)reserved;
214
215   for (s = buffer; length; s++, length--)
216     {
217       putc ( tohex ((*s>>4)&15), fp);
218       putc ( tohex (*s&15), fp);
219     }
220 #undef tohex
221 }
222
223 char *
224 make_printable_string (const void *p, size_t n, int delim )
225 {
226   return sanitize_buffer (p, n, delim);
227 }
228
229
230
231 /*
232  * Check if the file is compressed.
233  */
234 int
235 is_file_compressed (const char *s, int *ret_rc)
236 {
237     iobuf_t a;
238     byte buf[4];
239     int i, rc = 0;
240     int overflow;
241
242     struct magic_compress_s {
243         size_t len;
244         byte magic[4];
245     } magic[] = {
246         { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
247         { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
248         { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
249     };
250
251     if ( iobuf_is_pipe_filename (s) || !ret_rc )
252         return 0; /* We can't check stdin or no file was given */
253
254     a = iobuf_open( s );
255     if ( a == NULL ) {
256         *ret_rc = gpg_error_from_syserror ();
257         return 0;
258     }
259
260     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
261         *ret_rc = 0;
262         goto leave;
263     }
264
265     if ( iobuf_read( a, buf, 4 ) == -1 ) {
266         *ret_rc = a->error;
267         goto leave;
268     }
269
270     for ( i = 0; i < DIM( magic ); i++ ) {
271         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
272             *ret_rc = 0;
273             rc = 1;
274             break;
275         }
276     }
277
278 leave:
279     iobuf_close( a );
280     return rc;
281 }
282
283
284 /* Try match against each substring of multistr, delimited by | */
285 int
286 match_multistr (const char *multistr,const char *match)
287 {
288   do
289     {
290       size_t seglen = strcspn (multistr,"|");
291       if (!seglen)
292         break;
293       /* Using the localized strncasecmp! */
294       if (strncasecmp(multistr,match,seglen)==0)
295         return 1;
296       multistr += seglen;
297       if (*multistr == '|')
298         multistr++;
299     }
300   while (*multistr);
301
302   return 0;
303 }
304
305
306 \f
307 /* Parse the first portion of the version number S and store it at
308    NUMBER.  On success, the function returns a pointer into S starting
309    with the first character, which is not part of the initial number
310    portion; on failure, NULL is returned.  */
311 static const char*
312 parse_version_number (const char *s, int *number)
313 {
314   int val = 0;
315
316   if (*s == '0' && digitp (s+1))
317     return NULL; /* Leading zeros are not allowed.  */
318   for (; digitp (s); s++ )
319     {
320       val *= 10;
321       val += *s - '0';
322     }
323   *number = val;
324   return val < 0? NULL : s;
325 }
326
327 /* Break up the complete string representation of the version number S,
328    which is expected to have this format:
329
330       <major number>.<minor number>.<micro number><patch level>.
331
332    The major, minor and micro number components will be stored at
333    MAJOR, MINOR and MICRO. On success, a pointer to the last
334    component, the patch level, will be returned; on failure, NULL will
335    be returned.  */
336 static const char *
337 parse_version_string (const char *s, int *major, int *minor, int *micro)
338 {
339   s = parse_version_number (s, major);
340   if (!s || *s != '.')
341     return NULL;
342   s++;
343   s = parse_version_number (s, minor);
344   if (!s || *s != '.')
345     return NULL;
346   s++;
347   s = parse_version_number (s, micro);
348   if (!s)
349     return NULL;
350   return s; /* Patchlevel.  */
351 }
352
353 /* Return true if version string is at least version B. */
354 int
355 gnupg_compare_version (const char *a, const char *b)
356 {
357   int a_major, a_minor, a_micro;
358   int b_major, b_minor, b_micro;
359   const char *a_plvl, *b_plvl;
360
361   if (!a || !b)
362     return 0;
363
364   /* Parse version A.  */
365   a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
366   if (!a_plvl )
367     return 0; /* Invalid version number.  */
368
369   /* Parse version B.  */
370   b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
371   if (!b_plvl )
372     return 0; /* Invalid version number.  */
373
374   /* Compare version numbers.  */
375   return (a_major > b_major
376           || (a_major == b_major && a_minor > b_minor)
377           || (a_major == b_major && a_minor == b_minor
378               && a_micro > b_micro)
379           || (a_major == b_major && a_minor == b_minor
380               && a_micro == b_micro
381               && strcmp (a_plvl, b_plvl) >= 0));
382 }