brandelf.c revision 55377
1193323Sed/*-
2193323Sed * Copyright (c) 1996 S�ren Schmidt
3193323Sed * All rights reserved.
4193323Sed *
5193323Sed * Redistribution and use in source and binary forms, with or without
6193323Sed * modification, are permitted provided that the following conditions
7193323Sed * are met:
8193323Sed * 1. Redistributions of source code must retain the above copyright
9193323Sed *    notice, this list of conditions and the following disclaimer
10193323Sed *    in this position and unchanged.
11193323Sed * 2. Redistributions in binary form must reproduce the above copyright
12193323Sed *    notice, this list of conditions and the following disclaimer in the
13193323Sed *    documentation and/or other materials provided with the distribution.
14193323Sed * 3. The name of the author may not be used to endorse or promote products
15193323Sed *    derived from this software withough specific prior written permission
16252723Sdim *
17218893Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18263509Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19252723Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20252723Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21252723Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22252723Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23252723Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24252723Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25252723Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26252723Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27252723Sdim *
28235633Sdim * $FreeBSD: head/usr.bin/brandelf/brandelf.c 55377 2000-01-04 02:33:54Z wes $
29193323Sed */
30193323Sed
31218893Sdim#include <elf.h>
32193323Sed#include <fcntl.h>
33193323Sed#include <stdio.h>
34218893Sdim#include <stdlib.h>
35193323Sed#include <string.h>
36218893Sdim#include <unistd.h>
37218893Sdim#include <err.h>
38218893Sdim
39218893Sdimstatic int iselftype(const char *);
40245431Sdimstatic void printelftypes(void);
41218893Sdimstatic void usage __P((void));
42218893Sdim
43263509Sdimint
44263509Sdimmain(int argc, char **argv)
45218893Sdim{
46218893Sdim
47235633Sdim	const char *type = "FreeBSD";
48235633Sdim	int retval = 0;
49235633Sdim	int ch, change = 0, verbose = 0, force = 0, listed = 0;
50245431Sdim
51235633Sdim	while ((ch = getopt(argc, argv, "flt:v")) != -1)
52235633Sdim		switch (ch) {
53235633Sdim		case 'f':
54235633Sdim			force = 1;
55235633Sdim			break;
56235633Sdim		case 'l':
57235633Sdim			printelftypes();
58235633Sdim			listed = 1;
59235633Sdim			break;
60235633Sdim		case 'v':
61235633Sdim			verbose = 1;
62252723Sdim			break;
63235633Sdim		case 't':
64235633Sdim			change = 1;
65235633Sdim			type = optarg;
66235633Sdim			break;
67235633Sdim		default:
68235633Sdim			usage();
69235633Sdim	}
70235633Sdim	argc -= optind;
71235633Sdim	argv += optind;
72235633Sdim	if (!argc) {
73235633Sdim		if (listed)
74235633Sdim			exit(0);
75235633Sdim		else {
76235633Sdim			warnx("no file(s) specified");
77235633Sdim			usage();
78235633Sdim		}
79235633Sdim	}
80235633Sdim
81235633Sdim	if (!force && !iselftype(type)) {
82235633Sdim		warnx("invalid ELF type '%s'", type);
83235633Sdim		printelftypes();
84235633Sdim		usage();
85235633Sdim	}
86235633Sdim
87235633Sdim	while (argc) {
88252723Sdim		int fd;
89235633Sdim		char buffer[EI_NIDENT];
90235633Sdim		char string[(EI_NIDENT-EI_BRAND)+1];
91235633Sdim
92235633Sdim		if ((fd = open(argv[0], change? O_RDWR: O_RDONLY, 0)) < 0) {
93235633Sdim			warn("error opening file %s", argv[0]);
94235633Sdim			retval = 1;
95235633Sdim			goto fail;
96235633Sdim		}
97235633Sdim		if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
98235633Sdim			warnx("file '%s' too short", argv[0]);
99235633Sdim			retval = 1;
100235633Sdim			goto fail;
101235633Sdim		}
102235633Sdim		if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
103235633Sdim		    buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
104235633Sdim			warnx("file '%s' is not ELF format", argv[0]);
105235633Sdim			retval = 1;
106235633Sdim			goto fail;
107235633Sdim		}
108235633Sdim		if (!change) {
109235633Sdim			bzero(string, sizeof(string));
110235633Sdim			strncpy(string, &buffer[EI_BRAND], EI_NIDENT-EI_BRAND);
111235633Sdim			if (strlen(string)) {
112235633Sdim				fprintf(stdout,
113235633Sdim					"File '%s' is of brand '%s'.\n",
114235633Sdim					argv[0], string);
115235633Sdim				if (!force && !iselftype(string)) {
116235633Sdim					warnx("Brand '%s' is unknown",
117235633Sdim					      string);
118235633Sdim					printelftypes();
119235633Sdim				}
120235633Sdim			}
121235633Sdim			else
122235633Sdim				fprintf(stdout, "File '%s' has no branding.\n",
123235633Sdim					argv[0]);
124235633Sdim		}
125235633Sdim		else {
126235633Sdim			strncpy(&buffer[EI_BRAND], type, EI_NIDENT-EI_BRAND);
127235633Sdim			lseek(fd, 0, SEEK_SET);
128235633Sdim			if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
129235633Sdim				warnx("error writing %s", argv[0]);
130235633Sdim				retval = 1;
131235633Sdim				goto fail;
132235633Sdim			}
133235633Sdim		}
134235633Sdimfail:
135235633Sdim		argc--;
136245431Sdim		argv++;
137235633Sdim	}
138235633Sdim
139235633Sdim	return retval;
140235633Sdim}
141235633Sdim
142235633Sdimstatic void
143235633Sdimusage()
144235633Sdim{
145235633Sdim	fprintf(stderr, "usage: brandelf [-f] [-v] [-l] [-t string] file ...\n");
146235633Sdim	exit(1);
147235633Sdim}
148235633Sdim
149235633Sdim/* XXX - any more types? */
150235633Sdimstatic const char *elftypes[] = { "FreeBSD", "Linux", "SVR4" };
151235633Sdim
152235633Sdimstatic int
153235633Sdimiselftype(const char *elftype)
154235633Sdim{
155235633Sdim	int elfwalk;
156235633Sdim
157235633Sdim	for (elfwalk = 0;
158235633Sdim	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
159235633Sdim	     elfwalk++)
160235633Sdim		if (strcmp(elftype, elftypes[elfwalk]) == 0)
161235633Sdim			return 1;
162235633Sdim	return 0;
163235633Sdim}
164235633Sdim
165235633Sdimstatic void
166235633Sdimprintelftypes()
167235633Sdim{
168235633Sdim	int elfwalk;
169235633Sdim
170235633Sdim	fprintf(stderr, "known ELF types are: ");
171235633Sdim	for (elfwalk = 0;
172235633Sdim	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
173235633Sdim	     elfwalk++)
174235633Sdim		fprintf(stderr, "%s ", elftypes[elfwalk]);
175235633Sdim	fprintf(stderr, "\n");
176235633Sdim}
177235633Sdim