128a8b562SDavid E. O'Brien /*
228a8b562SDavid E. O'Brien * Copyright (c) Christos Zoulas 2003.
328a8b562SDavid E. O'Brien * All Rights Reserved.
428a8b562SDavid E. O'Brien *
528a8b562SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
628a8b562SDavid E. O'Brien * modification, are permitted provided that the following conditions
728a8b562SDavid E. O'Brien * are met:
828a8b562SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
928a8b562SDavid E. O'Brien * notice immediately at the beginning of the file, without modification,
1028a8b562SDavid E. O'Brien * this list of conditions, and the following disclaimer.
1128a8b562SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
1228a8b562SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
1328a8b562SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1428a8b562SDavid E. O'Brien *
1528a8b562SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1628a8b562SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1728a8b562SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1828a8b562SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
1928a8b562SDavid E. O'Brien * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2028a8b562SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2128a8b562SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2228a8b562SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2328a8b562SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2428a8b562SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2528a8b562SDavid E. O'Brien * SUCH DAMAGE.
2628a8b562SDavid E. O'Brien */
2728a8b562SDavid E. O'Brien
2828a8b562SDavid E. O'Brien #include <stdio.h>
2928a8b562SDavid E. O'Brien #include <stdlib.h>
30*898496eeSXin LI #include <unistd.h>
3128a8b562SDavid E. O'Brien #include <string.h>
3243a5ec4eSXin LI #include <errno.h>
33*898496eeSXin LI #include <time.h>
3443a5ec4eSXin LI
3528a8b562SDavid E. O'Brien #include "magic.h"
3628a8b562SDavid E. O'Brien
3743a5ec4eSXin LI static const char *prog;
3843a5ec4eSXin LI
3928a8b562SDavid E. O'Brien static void *
xrealloc(void * p,size_t n)4028a8b562SDavid E. O'Brien xrealloc(void *p, size_t n)
4128a8b562SDavid E. O'Brien {
4228a8b562SDavid E. O'Brien p = realloc(p, n);
4328a8b562SDavid E. O'Brien if (p == NULL) {
4443a5ec4eSXin LI (void)fprintf(stderr, "%s ERROR slurping file: %s\n",
4543a5ec4eSXin LI prog, strerror(errno));
4628a8b562SDavid E. O'Brien exit(10);
4728a8b562SDavid E. O'Brien }
4828a8b562SDavid E. O'Brien return p;
4928a8b562SDavid E. O'Brien }
5028a8b562SDavid E. O'Brien
5128a8b562SDavid E. O'Brien static char *
slurp(FILE * fp,size_t * final_len)5228a8b562SDavid E. O'Brien slurp(FILE *fp, size_t *final_len)
5328a8b562SDavid E. O'Brien {
5428a8b562SDavid E. O'Brien size_t len = 256;
5528a8b562SDavid E. O'Brien int c;
56*898496eeSXin LI char *l = xrealloc(NULL, len), *s = l;
5728a8b562SDavid E. O'Brien
5828a8b562SDavid E. O'Brien for (c = getc(fp); c != EOF; c = getc(fp)) {
5928a8b562SDavid E. O'Brien if (s == l + len) {
60*898496eeSXin LI s = l + len;
6128a8b562SDavid E. O'Brien len *= 2;
62*898496eeSXin LI l = xrealloc(l, len);
6328a8b562SDavid E. O'Brien }
6428a8b562SDavid E. O'Brien *s++ = c;
6528a8b562SDavid E. O'Brien }
66a2dfb722SXin LI if (s != l && s[-1] == '\n')
67a2dfb722SXin LI s--;
68*898496eeSXin LI if (s == l + len) {
69*898496eeSXin LI l = xrealloc(l, len + 1);
70*898496eeSXin LI s = l + len;
71*898496eeSXin LI }
7228a8b562SDavid E. O'Brien *s++ = '\0';
7328a8b562SDavid E. O'Brien
7428a8b562SDavid E. O'Brien *final_len = s - l;
75*898496eeSXin LI return xrealloc(l, s - l);
7628a8b562SDavid E. O'Brien }
7728a8b562SDavid E. O'Brien
7828a8b562SDavid E. O'Brien int
main(int argc,char ** argv)7928a8b562SDavid E. O'Brien main(int argc, char **argv)
8028a8b562SDavid E. O'Brien {
81*898496eeSXin LI struct magic_set *ms = NULL;
8228a8b562SDavid E. O'Brien const char *result;
8343a5ec4eSXin LI size_t result_len, desired_len;
8443a5ec4eSXin LI char *desired = NULL;
85*898496eeSXin LI int e = EXIT_FAILURE, flags, c;
8628a8b562SDavid E. O'Brien FILE *fp;
8728a8b562SDavid E. O'Brien
88*898496eeSXin LI setenv("TZ", "UTC", 1);
89*898496eeSXin LI tzset();
90*898496eeSXin LI
9143a5ec4eSXin LI
9243a5ec4eSXin LI prog = strrchr(argv[0], '/');
9343a5ec4eSXin LI if (prog)
9443a5ec4eSXin LI prog++;
9543a5ec4eSXin LI else
9643a5ec4eSXin LI prog = argv[0];
9743a5ec4eSXin LI
98*898496eeSXin LI if (argc == 1)
99*898496eeSXin LI return 0;
100*898496eeSXin LI
101*898496eeSXin LI flags = 0;
102*898496eeSXin LI while ((c = getopt(argc, argv, "ek")) != -1)
103*898496eeSXin LI switch (c) {
104*898496eeSXin LI case 'e':
105*898496eeSXin LI flags |= MAGIC_ERROR;
106*898496eeSXin LI break;
107*898496eeSXin LI case 'k':
108*898496eeSXin LI flags |= MAGIC_CONTINUE;
109*898496eeSXin LI break;
110*898496eeSXin LI default:
111*898496eeSXin LI goto usage;
112*898496eeSXin LI }
113*898496eeSXin LI
114*898496eeSXin LI argc -= optind;
115*898496eeSXin LI argv += optind;
116*898496eeSXin LI if (argc != 2) {
117*898496eeSXin LI usage:
118*898496eeSXin LI (void)fprintf(stderr,
119*898496eeSXin LI "Usage: %s [-ek] TEST-FILE RESULT\n", prog);
120*898496eeSXin LI goto bad;
121*898496eeSXin LI }
122*898496eeSXin LI
123*898496eeSXin LI ms = magic_open(flags);
12428a8b562SDavid E. O'Brien if (ms == NULL) {
12543a5ec4eSXin LI (void)fprintf(stderr, "%s: ERROR opening MAGIC_NONE: %s\n",
12643a5ec4eSXin LI prog, strerror(errno));
12743a5ec4eSXin LI return e;
12828a8b562SDavid E. O'Brien }
12928a8b562SDavid E. O'Brien if (magic_load(ms, NULL) == -1) {
13043a5ec4eSXin LI (void)fprintf(stderr, "%s: ERROR loading with NULL file: %s\n",
13143a5ec4eSXin LI prog, magic_error(ms));
13243a5ec4eSXin LI goto bad;
13328a8b562SDavid E. O'Brien }
13428a8b562SDavid E. O'Brien
135*898496eeSXin LI if ((result = magic_file(ms, argv[0])) == NULL) {
13643a5ec4eSXin LI (void)fprintf(stderr, "%s: ERROR loading file %s: %s\n",
13743a5ec4eSXin LI prog, argv[1], magic_error(ms));
13843a5ec4eSXin LI goto bad;
13943a5ec4eSXin LI }
140*898496eeSXin LI fp = fopen(argv[1], "r");
14128a8b562SDavid E. O'Brien if (fp == NULL) {
14243a5ec4eSXin LI (void)fprintf(stderr, "%s: ERROR opening `%s': %s",
143*898496eeSXin LI prog, argv[1], strerror(errno));
14443a5ec4eSXin LI goto bad;
14528a8b562SDavid E. O'Brien }
14628a8b562SDavid E. O'Brien desired = slurp(fp, &desired_len);
14728a8b562SDavid E. O'Brien fclose(fp);
148*898496eeSXin LI (void)printf("%s: %s\n", argv[0], result);
14928a8b562SDavid E. O'Brien if (strcmp(result, desired) != 0) {
15043a5ec4eSXin LI result_len = strlen(result);
15143a5ec4eSXin LI (void)fprintf(stderr, "%s: ERROR: result was (len %zu)\n%s\n"
15243a5ec4eSXin LI "expected (len %zu)\n%s\n", prog, result_len, result,
15343a5ec4eSXin LI desired_len, desired);
15443a5ec4eSXin LI goto bad;
15528a8b562SDavid E. O'Brien }
15643a5ec4eSXin LI e = 0;
15743a5ec4eSXin LI bad:
15843a5ec4eSXin LI free(desired);
159*898496eeSXin LI if (ms)
16028a8b562SDavid E. O'Brien magic_close(ms);
16143a5ec4eSXin LI return e;
16228a8b562SDavid E. O'Brien }
163