1/*
2 * Copyright (c) Christos Zoulas 2021.
3 * All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice immediately at the beginning of the file, without modification,
10 *    this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27#include "file.h"
28
29#ifndef lint
30FILE_RCSID("@(#)$File: memtest.c,v 1.6 2022/09/24 20:30:13 christos Exp $")
31#endif
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/mman.h>
36#include <stdio.h>
37#include <stdbool.h>
38#include <string.h>
39#include <stdlib.h>
40#include <err.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <dlfcn.h>
44#include <magic.h>
45
46void *
47malloc(size_t len)
48{
49	char buf[512];
50	void *(*orig)(size_t) = dlsym(RTLD_NEXT, "malloc");
51	void *p = (*orig)(len);
52	int l = snprintf(buf, sizeof(buf), "malloc %zu %p\n", len, p);
53	write(2, buf, l);
54	return p;
55}
56
57void
58free(void *p)
59{
60	char buf[512];
61	void (*orig)(void *) = dlsym(RTLD_NEXT, "free");
62	(*orig)(p);
63	int l = snprintf(buf, sizeof(buf), "free %p\n", p);
64	write(2, buf, l);
65}
66
67void *
68calloc(size_t len, size_t nitems)
69{
70	char buf[512];
71	void *(*orig)(size_t, size_t) = dlsym(RTLD_NEXT, "calloc");
72	void *p = (*orig)(len, nitems);
73	size_t tot = len * nitems;
74	int l = snprintf(buf, sizeof(buf), "calloc %zu %p\n", tot, p);
75	write(2, buf, l);
76	return p;
77}
78void *
79realloc(void *q, size_t len)
80{
81	char buf[512];
82	void *(*orig)(void *, size_t) = dlsym(RTLD_NEXT, "realloc");
83	void *p = (*orig)(q, len);
84	int l = snprintf(buf, sizeof(buf), "realloc %zu %p\n", len, p);
85	write(2, buf, l);
86	return p;
87}
88
89static void
90usage(void)
91{
92	fprintf(stderr, "Usage: test [-b] <filename>\n");
93	exit(EXIT_FAILURE);
94}
95
96int
97main(int argc, char *argv[])
98{
99	bool buf = false;
100	int c;
101
102	while ((c = getopt(argc, argv, "b")) != -1)
103		switch (c) {
104		case 'b':
105			buf = true;
106			break;
107		default:
108			usage();
109		}
110
111	argc -= optind;
112	argv += optind;
113
114	if (argc == 0)
115		usage();
116
117	magic_t m = magic_open(0);
118	if (m == NULL)
119		err(EXIT_FAILURE, "magic_open");
120
121	magic_load(m, NULL);
122
123	const char *r;
124	if (buf) {
125		int fd = open(argv[0], O_RDONLY);
126		if (fd == -1)
127			err(EXIT_FAILURE, "Cannot open `%s'", argv[0]);
128
129		struct stat st;
130		if (fstat(fd, &st) == -1)
131			err(EXIT_FAILURE, "Cannot stat `%s'", argv[0]);
132		size_t l = (size_t)st.st_size;
133		void *p = mmap(NULL, l, PROT_READ, MAP_FILE | MAP_PRIVATE, fd,
134		    (off_t)0);
135		if (p == MAP_FAILED)
136			err(EXIT_FAILURE, "Cannot map `%s'", argv[0]);
137		close(fd);
138		r = magic_buffer(m, p, l);
139		munmap(p, l);
140	} else {
141		r = magic_file(m, argv[0]);
142	}
143	magic_close(m);
144
145	printf("%s\n", r ? r : "(null)");
146
147	return 0;
148}
149