"Fossies" - the Fresh Open Source Software Archive

Member "replace-2.24/binary.c" (20 Jun 2004, 7736 Bytes) of package /linux/privat/old/replace-2.24-src-11.11.tar.gz:


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 }