Merge from vendor branch BIND:
[dragonfly.git] / usr.sbin / kgzip / kgzip.c
1 /*
2  * Copyright (c) 1999 Global Technology Associates, Inc.
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, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD: src/usr.sbin/kgzip/kgzip.c,v 1.3.2.3 2001/07/19 04:42:38 kris Exp $
27  * $DragonFly: src/usr.sbin/kgzip/kgzip.c,v 1.3 2004/08/19 21:36:46 joerg Exp $
28  */
29
30 #include <sys/types.h>
31 #include <err.h>
32 #include <paths.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include "kgzip.h"
39
40 #define FN_SRC          0       /* Filename: source */
41 #define FN_OBJ          1       /* Filename: relocatable */
42 #define FN_KGZ          2       /* Filename: executable */
43 #define FN_CNT          3       /* Number of filenames */
44
45 #define SFX_OBJ         ".o"    /* Filename suffix: relocatable */
46 #define SFX_KGZ         ".kgz"  /* Filename suffix: executable */
47 #define SFX_MAX         5       /* Size of larger filename suffix */
48
49 const char *loader = "/usr/lib/kgzldr.o";  /* Default loader */
50 int format;                     /* Output format */
51
52 char *tname;                    /* Name of temporary file */
53
54 static void cleanup(void);
55 static void mk_fn(int, const char *, const char *, const char *[]);
56 static void usage(void);
57
58 /*
59  * Compress a kernel.
60  */
61 int
62 main(int argc, char *argv[])
63 {
64     static const char *fn[FN_CNT];
65     struct kgz_hdr kh;
66     const char *output;
67     char *tmpdir;
68     int cflag, vflag, c;
69
70     tmpdir = getenv("TMPDIR");
71     if (asprintf(&tname, "%s/kgzXXXXXXXXXX",
72                  tmpdir == NULL ? _PATH_TMP : tmpdir) == -1)
73         errx(1, "Out of memory");
74     output = NULL;
75     cflag = vflag = 0;
76     while ((c = getopt(argc, argv, "cvf:l:o:")) != -1)
77         switch (c) {
78         case 'c':
79             cflag = 1;
80             break;
81         case 'v':
82             vflag = 1;
83             break;
84         case 'f':
85             if (!strcmp(optarg, "aout"))
86                 format = F_AOUT;
87             else if (!strcmp(optarg, "elf"))
88                 format = F_ELF;
89             else
90                 errx(1, "%s: Unknown format", optarg);
91             break;
92         case 'l':
93             loader = optarg;
94             break;
95         case 'o':
96             output = optarg;
97             break;
98         default:
99             usage();
100         }
101     argc -= optind;
102     argv += optind;
103     if (argc != 1)
104         usage();
105     atexit(cleanup);
106     mk_fn(cflag, *argv, output, fn);
107     memset(&kh, 0, sizeof(kh));
108     if (fn[FN_SRC]) {
109         if (!format)
110             format = F_ELF;
111         kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]);
112     }
113     if (!cflag)
114         kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]);
115     if (vflag)
116         printf("dload=%#x dsize=%#x isize=%#x entry=%#x nsize=%#x\n",
117                kh.dload, kh.dsize, kh.isize, kh.entry, kh.nsize);
118     return 0;
119 }
120
121 /*
122  * Clean up after processing.
123  */
124 static void
125 cleanup(void)
126 {
127     if (tname)
128         unlink(tname);
129 }
130
131 /*
132  * Make the required filenames.
133  */
134 static void
135 mk_fn(int cflag, const char *f1, const char *f2, const char *fn[])
136 {
137     const char *p, *s;
138     char *sfx;
139     size_t n;
140     int i, fd;
141
142     i = 0;
143     s = strrchr(f1, 0);
144     n = sizeof(SFX_OBJ) - 1;
145     if ((size_t)(s - f1) > n && !memcmp(s - n, SFX_OBJ, n)) {
146         s -= n;
147         i++;
148     }
149     fn[i++] = f1;
150     if (i == FN_OBJ && !cflag) {
151         if ((fd = mkstemp(tname)) == -1)
152             err(1, NULL);
153         close(fd);
154         fn[i++] = tname;
155     }
156     fn[i] = f2;
157     if (fn[i] == NULL) {
158         p = (p = strrchr(f1, '/')) ? p + 1 : f1;
159         n = (size_t)(s - p);
160         sfx = malloc(n + SFX_MAX);
161         if (sfx == NULL)
162             err(1, NULL);
163         memcpy(sfx, p, n);
164         strcpy(sfx + n, i == FN_OBJ ? SFX_OBJ : SFX_KGZ);
165         fn[i] = sfx;
166     }
167 }
168
169 /*
170  * Display usage information.
171  */
172 static void
173 usage(void)
174 {
175     fprintf(stderr,
176       "usage: kgzip [-cv] [-f format] [-l file] [-o filename] file\n");
177     exit(1);
178 }