"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* binary.c - The binary-related code for the replace program.
2 (C) Richard K. Lloyd 2001-2004
3 */
4
5 #define Extern extern
6 #include "replace.h"
7
8 static int maxtimeswarn;
9 static size_t minloop,totbuff;
10 static LONG_LONG outpos;
11
12 #ifdef __STDC__
13 char *alloc_mem(char *theptr,size_t *cursize,size_t newsize)
14 #else
15 char *alloc_mem(theptr,cursize,newsize)
16 char *theptr;
17 size_t *cursize;
18 size_t newsize;
19 #endif
20 {
21 /* Allocate newsize bytes of memory to a pointer that's already
22 had cursize bytes allocated */
23 if (*cursize<newsize)
24 {
25 if ((theptr=(char *)realloc((MALLOCPTR)theptr,newsize))==(char *)NULL)
26 leave("Can't allocate memory for replacement operations");
27 *cursize=newsize;
28 }
29 return(theptr);
30 }
31
32 #ifdef __STDC__
33 static char *out_string(char *thestr,size_t stlen)
34 #else
35 static char *out_string(thestr,stlen)
36 char *thestr;
37 size_t stlen;
38 #endif
39 {
40 /* Return string (doesn't necessarily have a zero terminator)
41 in either hex or ASCII */
42 size_t hl;
43 static char ostr[BUFSIZ];
44 char hstr[4];
45 if (hex)
46 {
47 ostr[0]='\0';
48 for (hl=0;hl<stlen;hl++)
49 {
50 (void)snprintf(hstr,3,"%02x",(unsigned int)thestr[hl]);
51 (void)strcat(ostr,hstr);
52 }
53 (void)strcat(ostr," hex");
54 }
55 else
56 {
57 (void)strcpy(ostr,"\""); hstr[1]='\0';
58 for (hl=0;hl<stlen;hl++)
59 if (thestr[hl]=='\0')
60 (void)strcat(ostr,"\\0");
61 else
62 {
63 hstr[0]=thestr[hl];
64 (void)strcat(ostr,hstr);
65 }
66 (void)strcat(ostr,"\"");
67 }
68 return(ostr);
69 }
70
71 /*
72 The algorithm for binary replacement is tricky because different
73 length strings could straddle the binary chunk boundary of course.
74 Here's the psuedo-code (something I hardly ever write
75 because it's usually a waste of time, but this is quite complex
76 and worth working out):
77
78 B = binary buffer
79 C = binary chunk size
80 L = Chunk loading offset
81 X = Old string array
82 Y = New string array
83
84 Alloc C bytes of RAM at &B[0]
85 L=0
86 repeat
87 fread() in C-L bytes at &B[L]
88 A = num bytes actually read in
89 T = L+A # i.e. total number of bytes in buffer
90 if T>0 then
91 minloop=C+1
92 for eachstr in 1..numstrs
93 do
94 O=length of X[eachstr]
95 if T>=O then
96 loop=0
97 while loop<=T-O
98 do
99 if B[loop...loop+O-1]==X[eachstr]
100 then
101 replace string at B[loop] with Y[eachstr]
102 loop+=O
103 else
104 loop++
105 fi
106 done
107 if (loop<minloop) minloop=loop
108 fi
109 done
110 if (minloop==C+1 && T<C)
111 L=T
112 else
113 if (minloop<T)
114 then
115 fwrite() minloop bytes at &B[0]
116 for copy in 0..T-minloop-1
117 do
118 B[copy]=B[minloop+copy]
119 done
120 L=T-minloop
121 else
122 fwrite() T bytes at &B[0]
123 L=0
124 fi
125 fi
126 fi
127 until A==0
128 if (L>0) fwrite L bytes at &B[0]
129 */
130
131 #ifdef __STDC__
132 static void replace_chunk(size_t eachstr)
133 #else
134 static void replace_chunk(eachstr)
135 size_t eachstr;
136 #endif
137 {
138 /* Replace string number "eachstr" in the current binary chunk */
139 size_t olen=oldstrlen[eachstr],nlen=newstrlen[eachstr];
140 /* Note that we have to check the new string's len versus the
141 old one here, cos auto-detect code may be calling the
142 binary replace code without having compared the new length
143 vs. the old length beforehand. Old string must also be >0 in length
144 (auto-detect lets zero-length old strings through cos it's allowed for
145 text files now) */
146 if (totbuff>=olen && nlen<=olen && olen>0)
147 {
148 size_t loop=0;
149 while (loop<=totbuff-olen)
150 {
151 int binmatch;
152 size_t bl;
153 if (sensitive)
154 binmatch=!memcmp(&binchunkptr[loop],oldstr[eachstr],olen);
155 else
156 {
157 binmatch=1;
158 for (bl=0;bl<olen && binmatch;bl++)
159 binmatch=(tolower(binchunkptr[loop+bl])==tolower(oldstr[eachstr][bl]));
160 }
161
162 if (binmatch)
163 {
164 if (maxtimes && repcount==maxtimes)
165 {
166 if (!maxtimeswarn)
167 {
168 (void)fprintf(stderr,"WARNING: Attempt to exceed ");
169 plural("replacement",(LONG_LONG)maxtimes);
170 (void)fprintf(stderr," in binary file ignored\n");
171 maxtimeswarn=1;
172 }
173 loop++;
174 }
175 else
176 {
177 char oldtmp[BUFSIZ],obuf[BUFSIZ];
178 LONG_LONG coffset=outpos+(LONG_LONG)loop;
179 (void)snprintf(oldtmp,BUFSIZ,"%s with ",out_string(&binchunkptr[loop],olen));
180 (void)strcat(oldtmp,out_string(newstr[eachstr],nlen));
181 (void)snprintf(obuf,BUFSIZ," at offset " LONG_LONG_FORMAT,coffset);
182 (void)strcat(oldtmp,obuf);
183 if (ask_user(2,oldtmp))
184 {
185 (void)memcpy(oldtmp,&binchunkptr[loop],olen);
186 if (sensitive)
187 (void)memcpy(&binchunkptr[loop],newstr[eachstr],nlen);
188 else
189 for (bl=0;bl<nlen;bl++)
190 {
191 char newchar=newstr[eachstr][bl];
192 if (isupper((int)binchunkptr[loop+bl]))
193 newchar=(char)toupper(newchar);
194 else newchar=(char)tolower(newchar);
195 binchunkptr[loop+bl]=newchar;
196 }
197
198 if (verbose==2)
199 {
200 (void)fprintf(stderr,"%s -> ",out_string(oldtmp,olen));
201 (void)fprintf(stderr,
202 " %s (offset: " LONG_LONG_FORMAT ")\n",
203 out_string(&binchunkptr[loop],nlen),coffset);
204 }
205 repcount++;
206 loop+=olen;
207 } else loop++;
208 }
209 } else loop++;
210 }
211 if (loop<minloop) minloop=loop;
212 }
213 }
214
215 #ifdef __STDC__
216 int binary_io(FILE *fd,FILE *fdout)
217 #else
218 int binary_io(fd,fdout)
219 FILE *fd,*fdout;
220 #endif
221 {
222 /* Read/write from/to a binary file. Returns 0 for success, != 0 fails */
223 int gotfail=0;
224 size_t numread=1,loadoff=autobinsize;
225
226 binchunkptr=alloc_mem(binchunkptr,&binchunksize,BIN_CHUNK);
227 maxtimeswarn=0; outpos=0;
228
229 while (numread>0 && !gotfail)
230 {
231 numread=fread((void *)&binchunkptr[loadoff],1,BIN_CHUNK-loadoff,fd);
232 gotfail=ferror(fd);
233 if (!gotfail && (totbuff=numread+loadoff)>0)
234 {
235 size_t estr;
236 minloop=BIN_CHUNK+1;
237 for (estr=1;estr<=numstrs;estr++) replace_chunk(estr);
238 if (minloop==BIN_CHUNK+1 && totbuff<BIN_CHUNK)
239 loadoff=totbuff;
240 else
241 if (minloop<totbuff)
242 {
243 outpos+=(LONG_LONG)minloop;
244 if (!fake) (void)fwrite((void *)binchunkptr,minloop,1,fdout);
245 for (estr=0;estr<=totbuff-minloop-1;estr++)
246 binchunkptr[estr]=binchunkptr[minloop+estr];
247 loadoff=totbuff-minloop;
248 }
249 else
250 {
251 outpos+=(LONG_LONG)totbuff;
252 if (!fake) (void)fwrite((void *)binchunkptr,totbuff,1,fdout);
253 loadoff=0;
254 }
255 if (!fake) gotfail=ferror(fdout);
256 }
257 }
258 if (loadoff>0 && !gotfail)
259 {
260 outpos+=(LONG_LONG)loadoff;
261 if (!fake)
262 {
263 (void)fwrite((void *)binchunkptr,loadoff,1,fdout);
264 gotfail=ferror(fdout);
265 }
266 }
267 return(gotfail);
268 }