2 * Copyright (c) 1999 Global Technology Associates, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 * $FreeBSD: src/usr.sbin/kgzip/kgzcmp.c,v 1.2.2.3 2001/07/19 04:37:24 kris Exp $
27 * $DragonFly: src/usr.sbin/kgzip/kgzcmp.c,v 1.4 2004/08/19 21:36:46 joerg Exp $
30 #include <sys/param.h>
33 #include <machine/elf.h>
47 static void mk_data(const struct iodesc
*i
, const struct iodesc
*,
48 struct kgz_hdr
*, size_t);
49 static int ld_elf(const struct iodesc
*, const struct iodesc
*,
50 struct kgz_hdr
*, const Elf32_Ehdr
*);
51 static int ld_aout(const struct iodesc
*, const struct iodesc
*,
52 struct kgz_hdr
*, const struct exec
*);
55 * Compress executable and output it in relocatable object format.
58 kgzcmp(struct kgz_hdr
*kh
, const char *f1
, const char *f2
)
60 struct iodesc idi
, ido
;
62 if ((idi
.fd
= open(idi
.fname
= f1
, O_RDONLY
)) == -1)
63 err(1, "%s", idi
.fname
);
64 if ((ido
.fd
= open(ido
.fname
= f2
, O_CREAT
| O_TRUNC
| O_WRONLY
,
66 err(1, "%s", ido
.fname
);
67 kh
->ident
[0] = KGZ_ID0
;
68 kh
->ident
[1] = KGZ_ID1
;
69 kh
->ident
[2] = KGZ_ID2
;
70 kh
->ident
[3] = KGZ_ID3
;
71 mk_data(&idi
, &ido
, kh
,
72 (format
== F_AOUT
? sizeof(struct kgz_aouthdr0
) :
73 sizeof(struct kgz_elfhdr
)) +
74 sizeof(struct kgz_hdr
));
75 kh
->dload
&= 0xffffff;
76 kh
->entry
&= 0xffffff;
77 if (format
== F_AOUT
) {
78 struct kgz_aouthdr0 ahdr0
= aouthdr0
;
79 struct kgz_aouthdr1 ahdr1
= aouthdr1
;
80 unsigned x
= (sizeof(struct kgz_hdr
) + kh
->nsize
) & (16 - 1);
85 xwrite(&ido
, &ahdr1
, sizeof(ahdr1
));
86 ahdr0
.a
.a_data
+= kh
->nsize
+ x
;
88 xwrite(&ido
, &ahdr0
, sizeof(ahdr0
));
90 struct kgz_elfhdr ehdr
= elfhdr
;
91 ehdr
.st
[KGZ_ST_KGZ_NDATA
].st_size
= kh
->nsize
;
92 ehdr
.sh
[KGZ_SH_DATA
].sh_size
+= kh
->nsize
;
94 xwrite(&ido
, &ehdr
, sizeof(ehdr
));
96 xwrite(&ido
, kh
, sizeof(*kh
));
102 * Make encoded (compressed) data.
105 mk_data(const struct iodesc
* idi
, const struct iodesc
* ido
,
106 struct kgz_hdr
* kh
, size_t off
)
119 n
= xread(idi
, &hdr
, sizeof(hdr
), 0);
121 if (n
>= sizeof(hdr
.ee
) && IS_ELF(hdr
.ee
))
123 else if (n
>= sizeof(hdr
.ex
) && N_GETMAGIC(hdr
.ex
) == ZMAGIC
)
126 errx(1, "%s: Format not supported", idi
->fname
);
130 switch (pid
= fork()) {
135 dup2(fd
[0], STDIN_FILENO
);
138 dup2(ido
->fd
, STDOUT_FILENO
);
140 execlp("gzip", "gzip", "-9", NULL
);
145 idp
.fname
= "(pipe)";
147 e
= fmt
== F_ELF
? ld_elf(idi
, &idp
, kh
, &hdr
.ee
) :
148 fmt
== F_AOUT
? ld_aout(idi
, &idp
, kh
, &hdr
.ex
) : -1;
150 if ((pid
= waitpid(pid
, &status
, 0)) == -1)
152 if (WIFSIGNALED(status
) || WEXITSTATUS(status
))
156 errx(1, "%s: Invalid format", idi
->fname
);
157 if (fstat(ido
->fd
, &sb
))
158 err(1, "%s", ido
->fname
);
159 kh
->nsize
= sb
.st_size
- off
;
163 * "Load" an ELF-format executable.
166 ld_elf(const struct iodesc
* idi
, const struct iodesc
* ido
,
167 struct kgz_hdr
* kh
, const Elf32_Ehdr
* e
)
170 size_t load
, addr
, n
;
174 for (x
= i
= 0; i
< e
->e_phnum
; i
++) {
175 if (xread(idi
, &p
, sizeof(p
),
176 e
->e_phoff
+ i
* e
->e_phentsize
) != e
->e_phentsize
)
178 if (p
.p_type
!= PT_LOAD
)
181 load
= addr
= p
.p_vaddr
;
183 if (p
.p_vaddr
< addr
)
185 n
= p
.p_vaddr
- addr
;
191 if (p
.p_memsz
< p
.p_filesz
)
193 n
= p
.p_memsz
- p
.p_filesz
;
194 xcopy(idi
, ido
, p
.p_filesz
, p
.p_offset
);
201 kh
->dsize
= addr
- load
;
202 kh
->isize
= kh
->dsize
+ n
;
203 kh
->entry
= e
->e_entry
;
208 * "Load" an a.out-format executable.
211 ld_aout(const struct iodesc
* idi
, const struct iodesc
* ido
,
212 struct kgz_hdr
* kh
, const struct exec
* a
)
216 load
= addr
= N_TXTADDR(*a
);
217 xcopy(idi
, ido
, a
->a_text
, N_TXTOFF(*a
));
219 if (N_DATADDR(*a
) != addr
)
221 xcopy(idi
, ido
, a
->a_data
, N_DATOFF(*a
));
224 kh
->dsize
= addr
- load
;
225 kh
->isize
= kh
->dsize
+ a
->a_bss
;
226 kh
->entry
= a
->a_entry
;