Annotation of src/usr.bin/file/funcs.c, Revision 1.4
1.4 ! dim 1: /* $OpenBSD: funcs.c,v 1.3 2005/04/11 16:31:35 deraadt Exp $ */
1.1 tedu 2: /*
3: * Copyright (c) Christos Zoulas 2003.
4: * All Rights Reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice immediately at the beginning of the file, without modification,
11: * this list of conditions, and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
30: #include "file.h"
31: #include "magic.h"
1.4 ! dim 32: #include <limits.h>
1.1 tedu 33: #include <stdarg.h>
1.4 ! dim 34: #include <stddef.h>
1.1 tedu 35: #include <stdlib.h>
36: #include <string.h>
37: #include <ctype.h>
38:
39: #ifndef lint
1.4 ! dim 40: FILE_RCSID("@(#)$Id: funcs.c,v 1.3 2005/04/11 16:31:35 deraadt Exp $")
1.1 tedu 41: #endif /* lint */
42: /*
43: * Like printf, only we print to a buffer and advance it.
44: */
45: protected int
46: file_printf(struct magic_set *ms, const char *fmt, ...)
47: {
48: va_list ap;
1.4 ! dim 49: int len;
! 50: size_t size;
1.1 tedu 51: char *buf;
1.4 ! dim 52: ptrdiff_t diff;
1.1 tedu 53:
54: va_start(ap, fmt);
55:
1.4 ! dim 56: len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap);
! 57: if (len == -1) {
! 58: file_error(ms, errno, "vsnprintf failed");
! 59: return -1;
! 60: } else if (len >= ms->o.left) {
1.1 tedu 61: va_end(ap);
1.4 ! dim 62: size = (ms->o.size - ms->o.left) + len + 1024;
! 63: if ((buf = realloc(ms->o.buf, size)) == NULL) {
1.1 tedu 64: file_oomem(ms);
65: return -1;
66: }
1.4 ! dim 67: diff = ms->o.ptr - ms->o.buf;
! 68: ms->o.ptr = buf + diff;
1.1 tedu 69: ms->o.buf = buf;
1.4 ! dim 70: ms->o.left = size - diff;
! 71: ms->o.size = size;
1.1 tedu 72:
73: va_start(ap, fmt);
1.4 ! dim 74: len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap);
! 75: if (len == -1) {
! 76: file_error(ms, errno, "vsnprintf failed");
! 77: return -1;
! 78: }
1.1 tedu 79: }
80: ms->o.ptr += len;
1.4 ! dim 81: ms->o.left -= len;
1.1 tedu 82: va_end(ap);
83: return 0;
84: }
85:
86: /*
87: * error - print best error message possible
88: */
89: /*VARARGS*/
90: protected void
91: file_error(struct magic_set *ms, int error, const char *f, ...)
92: {
93: va_list va;
94: /* Only the first error is ok */
95: if (ms->haderr)
96: return;
97: va_start(va, f);
98: (void)vsnprintf(ms->o.buf, ms->o.size, f, va);
99: va_end(va);
100: if (error > 0) {
101: size_t len = strlen(ms->o.buf);
102: (void)snprintf(ms->o.buf + len, ms->o.size - len, " (%s)",
103: strerror(error));
104: }
105: ms->haderr++;
106: ms->error = error;
107: }
108:
109:
110: protected void
111: file_oomem(struct magic_set *ms)
112: {
113: file_error(ms, errno, "cannot allocate memory");
114: }
115:
116: protected void
117: file_badseek(struct magic_set *ms)
118: {
119: file_error(ms, errno, "error seeking");
120: }
121:
122: protected void
123: file_badread(struct magic_set *ms)
124: {
125: file_error(ms, errno, "error reading");
126: }
127:
128: protected int
129: file_buffer(struct magic_set *ms, const void *buf, size_t nb)
130: {
131: int m;
132: /* try compression stuff */
133: if ((m = file_zmagic(ms, buf, nb)) == 0) {
134: /* Check if we have a tar file */
135: if ((m = file_is_tar(ms, buf, nb)) == 0) {
136: /* try tests in /etc/magic (or surrogate magic file) */
137: if ((m = file_softmagic(ms, buf, nb)) == 0) {
138: /* try known keywords, check whether it is ASCII */
139: if ((m = file_ascmagic(ms, buf, nb)) == 0) {
140: /* abandon hope, all ye who remain here */
141: if (file_printf(ms, ms->flags & MAGIC_MIME ?
142: "application/octet-stream" : "data") == -1)
143: return -1;
144: m = 1;
145: }
146: }
147: }
148: }
149: return m;
150: }
151:
152: protected int
153: file_reset(struct magic_set *ms)
154: {
155: if (ms->mlist == NULL) {
156: file_error(ms, 0, "no magic files loaded");
157: return -1;
158: }
159: ms->o.ptr = ms->o.buf;
160: ms->haderr = 0;
161: ms->error = -1;
162: return 0;
163: }
164:
165: protected const char *
166: file_getbuffer(struct magic_set *ms)
167: {
1.4 ! dim 168: char *pbuf, *op, *np;
! 169: size_t psize, len;
1.1 tedu 170:
171: if (ms->haderr)
172: return NULL;
173:
174: if (ms->flags & MAGIC_RAW)
175: return ms->o.buf;
176:
1.4 ! dim 177: len = ms->o.size - ms->o.left;
! 178: if (len > (SIZE_T_MAX - 1) / 4) {
! 179: file_oomem(ms);
! 180: return NULL;
! 181: }
! 182: /* * 4 is for octal representation, + 1 is for NUL */
! 183: psize = len * 4 + 1;
! 184: if (ms->o.psize < psize) {
! 185: if ((pbuf = realloc(ms->o.pbuf, psize)) == NULL) {
1.1 tedu 186: file_oomem(ms);
187: return NULL;
188: }
1.4 ! dim 189: ms->o.psize = psize;
! 190: ms->o.pbuf = pbuf;
1.1 tedu 191: }
192:
193: for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) {
194: if (isprint((unsigned char)*op)) {
195: *np++ = *op;
196: } else {
197: *np++ = '\\';
198: *np++ = ((*op >> 6) & 3) + '0';
199: *np++ = ((*op >> 3) & 7) + '0';
200: *np++ = ((*op >> 0) & 7) + '0';
201: }
202: }
203: *np = '\0';
204: return ms->o.pbuf;
205: }