kgzip.c revision 330449
1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 448905Srnordier * Copyright (c) 1999 Global Technology Associates, Inc. 548905Srnordier * All rights reserved. 648905Srnordier * 748905Srnordier * Redistribution and use in source and binary forms, with or without 848905Srnordier * modification, are permitted provided that the following conditions 948905Srnordier * are met: 1048905Srnordier * 1. Redistributions of source code must retain the above copyright 1148905Srnordier * notice, this list of conditions and the following disclaimer. 1248905Srnordier * 2. Redistributions in binary form must reproduce the above copyright 1348905Srnordier * notice, this list of conditions and the following disclaimer in the 1448905Srnordier * documentation and/or other materials provided with the distribution. 1548905Srnordier * 1648905Srnordier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 1748905Srnordier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1848905Srnordier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1948905Srnordier * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 2048905Srnordier * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 2148905Srnordier * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 2248905Srnordier * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2348905Srnordier * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2448905Srnordier * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 2548905Srnordier * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 2648905Srnordier * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2748905Srnordier */ 2848905Srnordier 2948905Srnordier#ifndef lint 3048905Srnordierstatic const char rcsid[] = 3150479Speter "$FreeBSD: stable/11/usr.sbin/kgzip/kgzip.c 330449 2018-03-05 07:26:05Z eadler $"; 3248905Srnordier#endif /* not lint */ 3348905Srnordier 3448905Srnordier#include <sys/types.h> 3548905Srnordier#include <err.h> 3664214Skris#include <paths.h> 3748905Srnordier#include <stdio.h> 3848905Srnordier#include <stdlib.h> 3948905Srnordier#include <string.h> 4048905Srnordier#include <unistd.h> 4148905Srnordier 4248905Srnordier#include "kgzip.h" 4348905Srnordier 4448905Srnordier#define FN_SRC 0 /* Filename: source */ 4548905Srnordier#define FN_OBJ 1 /* Filename: relocatable */ 4648905Srnordier#define FN_KGZ 2 /* Filename: executable */ 4748905Srnordier#define FN_CNT 3 /* Number of filenames */ 4848905Srnordier 4948905Srnordier#define SFX_OBJ ".o" /* Filename suffix: relocatable */ 5048905Srnordier#define SFX_KGZ ".kgz" /* Filename suffix: executable */ 5148905Srnordier#define SFX_MAX 5 /* Size of larger filename suffix */ 5248905Srnordier 5348905Srnordierconst char *loader = "/usr/lib/kgzldr.o"; /* Default loader */ 5468313Srnordierint format; /* Output format */ 5548905Srnordier 5656128Skrischar *tname; /* Name of temporary file */ 5748905Srnordier 5848905Srnordierstatic void cleanup(void); 5948905Srnordierstatic void mk_fn(int, const char *, const char *, char *[]); 6048905Srnordierstatic void usage(void); 6148905Srnordier 6248905Srnordier/* 6348905Srnordier * Compress a kernel. 6448905Srnordier */ 6548905Srnordierint 6648905Srnordiermain(int argc, char *argv[]) 6748905Srnordier{ 6848905Srnordier static char *fn[FN_CNT]; 6948905Srnordier struct kgz_hdr kh; 7048905Srnordier const char *output; 7164214Skris char *tmpdir; 7248905Srnordier int cflag, vflag, c; 7348905Srnordier 7464214Skris tmpdir = getenv("TMPDIR"); 7568966Srnordier if (asprintf(&tname, "%s/kgzXXXXXXXXXX", 7668966Srnordier tmpdir == NULL ? _PATH_TMP : tmpdir) == -1) 7768313Srnordier errx(1, "Out of memory"); 7848905Srnordier output = NULL; 7948905Srnordier cflag = vflag = 0; 8068313Srnordier while ((c = getopt(argc, argv, "cvf:l:o:")) != -1) 8148905Srnordier switch (c) { 8248905Srnordier case 'c': 8348905Srnordier cflag = 1; 8448905Srnordier break; 8548905Srnordier case 'v': 8648905Srnordier vflag = 1; 8748905Srnordier break; 8868313Srnordier case 'f': 8968313Srnordier if (!strcmp(optarg, "aout")) 9068313Srnordier format = F_AOUT; 9168313Srnordier else if (!strcmp(optarg, "elf")) 9268313Srnordier format = F_ELF; 9368313Srnordier else 9468313Srnordier errx(1, "%s: Unknown format", optarg); 9568313Srnordier break; 9648905Srnordier case 'l': 9748905Srnordier loader = optarg; 9848905Srnordier break; 9948905Srnordier case 'o': 10048905Srnordier output = optarg; 10148905Srnordier break; 10248905Srnordier default: 10348905Srnordier usage(); 10448905Srnordier } 10548905Srnordier argc -= optind; 10648905Srnordier argv += optind; 10748905Srnordier if (argc != 1) 10848905Srnordier usage(); 10948905Srnordier atexit(cleanup); 11048905Srnordier mk_fn(cflag, *argv, output, fn); 11148905Srnordier memset(&kh, 0, sizeof(kh)); 11268313Srnordier if (fn[FN_SRC]) { 11368313Srnordier if (!format) 11468313Srnordier format = F_ELF; 11548905Srnordier kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]); 11668313Srnordier } 11748905Srnordier if (!cflag) 11848905Srnordier kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]); 11948905Srnordier if (vflag) 12048905Srnordier printf("dload=%#x dsize=%#x isize=%#x entry=%#x nsize=%#x\n", 12148905Srnordier kh.dload, kh.dsize, kh.isize, kh.entry, kh.nsize); 12248905Srnordier return 0; 12348905Srnordier} 12448905Srnordier 12548905Srnordier/* 12648905Srnordier * Clean up after processing. 12748905Srnordier */ 12848905Srnordierstatic void 12948905Srnordiercleanup(void) 13048905Srnordier{ 13148905Srnordier if (tname) 13248905Srnordier unlink(tname); 13348905Srnordier} 13448905Srnordier 13548905Srnordier/* 13648905Srnordier * Make the required filenames. 13748905Srnordier */ 13848905Srnordierstatic void 13948905Srnordiermk_fn(int cflag, const char *f1, const char *f2, char *fn[]) 14048905Srnordier{ 14148905Srnordier const char *p, *s; 14248905Srnordier size_t n; 14356128Skris int i, fd; 14448905Srnordier 14548905Srnordier i = 0; 14648905Srnordier s = strrchr(f1, 0); 14748905Srnordier n = sizeof(SFX_OBJ) - 1; 14848905Srnordier if ((size_t)(s - f1) > n && !memcmp(s - n, SFX_OBJ, n)) { 14948905Srnordier s -= n; 15048905Srnordier i++; 15148905Srnordier } 15248905Srnordier fn[i++] = (char *)f1; 15348905Srnordier if (i == FN_OBJ && !cflag) { 15456128Skris if ((fd = mkstemp(tname)) == -1) 15548905Srnordier err(1, NULL); 15656128Skris close(fd); 157116222Sobrien fn[i++] = tname; 15848905Srnordier } 15948905Srnordier if (!(fn[i] = (char *)f2)) { 16048905Srnordier p = (p = strrchr(f1, '/')) ? p + 1 : f1; 16148905Srnordier n = (size_t)(s - p); 16248905Srnordier if (!(fn[i] = malloc(n + SFX_MAX))) 16348905Srnordier err(1, NULL); 16448905Srnordier memcpy(fn[i], p, n); 16548905Srnordier strcpy(fn[i] + n, i == FN_OBJ ? SFX_OBJ : SFX_KGZ); 16648905Srnordier } 16748905Srnordier} 16848905Srnordier 16948905Srnordier/* 17048905Srnordier * Display usage information. 17148905Srnordier */ 17248905Srnordierstatic void 17348905Srnordierusage(void) 17448905Srnordier{ 17548905Srnordier fprintf(stderr, 176112048Sru "usage: kgzip [-cv] [-f format] [-l loader] [-o output] file\n"); 17748905Srnordier exit(1); 17848905Srnordier} 179