1 /*
2 * $Id: exe_sear.c,v 1.3 2003/10/16 10:32:46 andrew_belov Exp $
3 * ---------------------------------------------------------------------------
4 * Routines that fetch overlay data are located in this file.
5 *
6 */
7
8 #include "arj.h"
9
10 #ifdef ELF_EXECUTABLES
11 #ifdef __QNXNTO__
12 #include <libelf.h>
13 #else
14 #include <elf.h>
15 #endif /* __QNXNTO__ */
16 #endif
17
18 DEBUGHDR(__FILE__) /* Debug information block */
19
20 /* ARJSFX module order */
21
22 #define MN_SFXJR 1
23 #define MN_SFX 2
24 #define MN_SFXV 3
25 #define MN_SFXSTUB 4
26
27 /* Define the ELF magic numbers if not defined yet */
28
29 #if defined(ELF_EXECUTABLES)&&!defined(ELFMAG)
30 static char elfmag[4]={'E', 'L', 'F', 0x7F};
31 #define ELFMAG elfmag
32 #define SELFMAG 4
33 #endif
34
35 #if SFX_LEVEL>=ARJ
36
37 /* Local variables */
38
39 static char overlay_sig[]="RJ_SFX";
40
41 /* Looks for ARJ_SFX signature */
42
browse(FILE * stream)43 static void browse(FILE *stream)
44 {
45 char buf[256];
46 unsigned long cur_pos, sig_pos;
47 int bytes_read;
48 int i;
49 char *buf_ptr;
50
51 while(1)
52 {
53 cur_pos=ftell(stream);
54 bytes_read=fread(buf, 1, sizeof(buf), stream);
55 if(bytes_read<=0)
56 error(M_CANTREAD);
57 buf_ptr=buf;
58 i=0;
59 while(i<bytes_read)
60 {
61 if(*buf_ptr=='A'&&!strcmp(buf_ptr+1, overlay_sig))
62 {
63 sig_pos=cur_pos+(unsigned long)i;
64 if(mget_dword(buf_ptr+8)==sig_pos)
65 goto loc_hdr;
66 }
67 i++;
68 buf_ptr++;
69 }
70 if(bytes_read==sizeof(buf))
71 fseek(stream, -16L, SEEK_CUR);
72 }
73 loc_hdr:
74 cur_pos+=(unsigned long)i+12L;
75 fseek(stream, cur_pos, SEEK_SET);
76 }
77
78 /* Writes the contents of a FAR block to the output stream */
79
farblock_output(FILE * stream,char FAR * block,unsigned long len)80 static void farblock_output(FILE *stream, char FAR *block, unsigned long len)
81 {
82 #ifdef TILED
83 while(len-->0)
84 {
85 if(fputc((int)*(block++), stream)==EOF)
86 error(M_DISK_FULL);
87 }
88 #else
89 file_write(block, 1, len, stream);
90 #endif
91 }
92
93 #endif
94
95 /* Reads the EXE size from the header */
96
get_exe_size(FILE * stream)97 static unsigned long get_exe_size(FILE *stream)
98 {
99 #if SFX_LEVEL>=ARJ
100 unsigned long result=EXESIZE_ARJ;
101 #elif SFX_LEVEL==ARJSFXV
102 unsigned long result=EXESIZE_ARJSFXV;
103 #else
104 unsigned long result=EXESIZE_ARJSFX;
105 #endif
106 #ifndef ELF_EXECUTABLES
107 unsigned int remainder, blocks;
108 #else
109 Elf32_Ehdr ehdr;
110 Elf32_Shdr shdr;
111 unsigned long ref_point;
112 unsigned long cur_pos;
113 unsigned int i;
114 #endif
115
116 #ifndef ELF_EXECUTABLES /* Presume standard DOS or OS/2 EXE */
117 fseek(stream, 2L, SEEK_SET);
118 remainder=fget_word(stream);
119 blocks=fget_word(stream);
120 result=(unsigned long)(blocks-1)*512L+(unsigned long)remainder;
121 return(result);
122 #else /* ELF (Linux, OS/2 PPC, Solaris...) */
123 fread(&ehdr, 1, sizeof(ehdr), stream);
124 if(memcmp(ehdr.e_ident, ELFMAG, SELFMAG))
125 return(0);
126 result=ehdr.e_shoff+(unsigned long)ehdr.e_shentsize*ehdr.e_shnum;
127 fseek(stream, ehdr.e_shoff, SEEK_SET);
128 for(i=0; i<ehdr.e_shnum; i++)
129 {
130 fseek(stream, ehdr.e_shoff+(unsigned long)i*ehdr.e_shentsize, SEEK_SET);
131 cur_pos=ftell(stream);
132 fread(&shdr, 1, sizeof(shdr), stream);
133 ref_point=shdr.sh_offset+shdr.sh_size;
134 /* Ignore uninitialized sections (BSS) */
135 if(ref_point>result&&shdr.sh_type!=SHT_NOBITS)
136 result=ref_point;
137 }
138 return(result);
139 #endif
140 }
141
142 #if SFX_LEVEL>=ARJ
143
144 /* Performs all actions related to picking a block */
145
fetch_block(int num)146 static void fetch_block(int num)
147 {
148 FILE *stream;
149 unsigned long exe_size;
150 int t_num;
151 unsigned long t_pos;
152 char buf[256];
153 int block_len;
154 int bytes_read;
155 unsigned int desc_word;
156
157 stream=file_open_noarch(exe_name, m_rb);
158 exe_size=get_exe_size(stream);
159 fseek(stream, exe_size, SEEK_SET);
160 t_pos=0L;
161 for(t_num=0; t_num<num; t_num++)
162 {
163 fseek(stream, t_pos, SEEK_CUR);
164 browse(stream);
165 t_pos=fget_longword(stream);
166 }
167 crc32term=CRC_MASK;
168 block_len=(int)min(sizeof(buf), t_pos);
169 while(t_pos>0)
170 {
171 bytes_read=fread(buf, 1, block_len, stream);
172 if(bytes_read<=0)
173 break;
174 crc32_for_block(buf, bytes_read);
175 farblock_output(aostream, (char FAR *)buf, (unsigned long)bytes_read);
176 t_pos-=(unsigned long)bytes_read;
177 block_len=(int)min(sizeof(buf), t_pos);
178 }
179 fclose(stream);
180 desc_word=SFXDESC_NONSFX;
181 if(create_sfx==SFXCRT_SFX&&multivolume_option)
182 desc_word=SFXDESC_SFXV;
183 else if(create_sfx==SFXCRT_SFX)
184 desc_word=SFXDESC_SFX;
185 else if(create_sfx==SFXCRT_SFXJR)
186 desc_word=SFXDESC_SFXJR;
187 fput_word(desc_word, aostream);
188 if(is_registered)
189 desc_word=REG_ID;
190 fput_word(desc_word, aostream);
191 crc32term^=CRC_MASK;
192 fput_dword(crc32term, aostream);
193 }
194
195 /* Picks the ARJSFX and stores ARJSFX run-time data */
196
fetch_sfx()197 void fetch_sfx()
198 {
199 fetch_block(MN_SFX);
200 }
201
202 /* Picks the ARJSFXJR and stores ARJSFXJR run-time data */
203
fetch_sfxjr()204 void fetch_sfxjr()
205 {
206 fetch_block(MN_SFXJR);
207 }
208
209 /* Picks the ARJSFXV and stores ARJSFXV run-time data */
210
fetch_sfxv()211 void fetch_sfxv()
212 {
213 fetch_block(MN_SFXV);
214 }
215
216 /* Picks the SFXSTUB */
217
fetch_sfxstub()218 void fetch_sfxstub()
219 {
220 fetch_block(MN_SFXSTUB);
221 }
222
223 #endif
224
225 #if SFX_LEVEL<=ARJSFXV
226
227 /* SFX seek routine */
228
sfx_seek()229 void sfx_seek()
230 {
231 unsigned long exe_size;
232 unsigned long fcrc;
233 unsigned int block_size, bytes_read;
234 char buf[256];
235
236 exe_size=get_exe_size(aistream);
237 fseek(aistream, exe_size, SEEK_SET);
238 main_hdr_offset=find_header(0, aistream);
239 fseek(aistream, -8L, SEEK_CUR);
240 exe_size=ftell(aistream);
241 reg_id=fget_word(aistream); /* Descriptive word */
242 reg_id=fget_word(aistream);
243 fcrc=fget_longword(aistream);
244 if(reg_id!=REG_ID)
245 reg_id=0;
246 fseek(aistream, 0L, SEEK_SET);
247 crc32term=CRC_MASK;
248 block_size=min((unsigned long)sizeof(buf), exe_size);
249 while(exe_size>0L)
250 {
251 bytes_read=fread(buf, 1, block_size, aistream);
252 if(bytes_read==0)
253 break;
254 crc32_for_block(buf, bytes_read);
255 exe_size-=(unsigned long)bytes_read;
256 block_size=min((unsigned long)block_size, exe_size);
257 }
258 if((crc32term^CRC_MASK)!=fcrc&&!skip_integrity_test)
259 error(M_DAMAGED_SFX);
260 fseek(aistream, main_hdr_offset, SEEK_SET);
261 }
262
263 #endif
264