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