Logo Search packages:      
Sourcecode: afflib version File versions  Download package

afsegment.cpp

/*
 * afsegment.cpp
 *
 * segment manipulation tool
 */

/*
 * Copyright (c) 2006
 *    Simson L. Garfinkel and Basis Technology, Inc. 
 *      All rights reserved.
 *
 * This code is derrived from software contributed by
 * Simson L. Garfinkel
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Simson L. Garfinkel
 *    and Basis Technology Corp.
 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
 *    contributors to this program may be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.  
 */


#include "afflib.h"
#include "afflib_i.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <zlib.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <assert.h>
#include <regex.h>

#include <algorithm>
#include <cstdlib>
#include <vector>
#include <string>

using namespace std;


char *progname = "afsegment";

#define xstr(s) str(s)
#define str(s) #s

vector<string>del_segs;
vector<string>new_segs;

int opt_create = 0;

void usage()
{
    printf("afsegment version %s\n",xstr(AFFLIB_VERSION));
    printf("usage: afcat [options] file1.aff [file2.aff ...]\n");
    printf("options:\n");
    printf("    -c              Create AFF files if they do not exist\n");
    printf("    -s segval       Sets the value of a segment; may be repeated\n");
    printf("    -v              Just print the version number and exit.\n");    printf("\n");
    printf("Values for segval:\n");
    printf("\n");
    printf("Setting the segment values:\n");
    printf("    -s name=-       Take the new value of segment 'name' from stdin\n");
    printf("    -s name=val     Sets segment 'name' to be 'val'  \n");
    printf("    -s name=<val    Sets segment 'name' to be contents of file 'val'\n");
    printf("\n");
    printf("Setting the segment args:\n");
    printf("    -s name/arg     Sets segment 'name' arg to be 'arg'  (may be repeated)\n");
    printf("\n");
    printf("Setting both the segment value and the arg:\n");
    printf("    -s name/arg=val   Sets both arg and val for segment 'name'\n");
    printf("    -s name/arg=<file Sets the arg and take contents from file 'file'\n");
    printf("    -s name/arg=-     Sets the arg of segment 'name' and take the contents from stdin\n");
    printf("\n");
    printf("    -d name         Delete segment 'name'\n");
    printf("    -h, -?          Print this message\n");
    printf("\n");
    printf("Note: All deletions are done first, then all updates. Don't specify the\n");
    printf("same segment twice on one command line.\n");
    exit(0);
}

int get_segment_from_file(AFFILE *af,const char *segname,unsigned long arg,FILE *in)
{
    char *value = (char *)malloc(0);
    int  value_len = 0;

    while(!feof(in)){
      char buf[4096];
      int  count;
      count = fread(buf,1,sizeof(buf),in);
      if(count>0){
          value = (char *)realloc(value,value_len+count);
          memcpy(value+value_len,buf,count);
          value_len += count;
      }
    }
    int r = af_update_seg(af,segname,arg,value,value_len,1);
    free(value);
    return r;
}


void update_segment(AFFILE *af,const char *segname,
                const char *argstr,const char *segval)
{
    unsigned long arg = 0;

    if(strlen(argstr)>1) arg = atoi(argstr+1);

    if(!strcmp(segval,"=-")){
      get_segment_from_file(af,segname,arg,stdin);
      return;
    }
    if(!strncmp(segval,"=<",2)){
      FILE *f = fopen(segval+2,"rb");
      if(!f) err(1,"fopen(%s)",segval+2);
      get_segment_from_file(af,segname,arg,f);
      fclose(f);
      return;
    }
    segval++;                       // skip past the "="
    int r = af_update_seg(af,segname,arg,segval,strlen(segval),1);
    if(r) warn("af_update(%s,%s) ",af_filename(af),segname);
}


char *make_re_string(const char *buf,regmatch_t *match,int num)
{
    int len = match[num].rm_eo - match[num].rm_so;
    char *ret = (char *)malloc(len+1);
    memcpy(ret,buf+match[num].rm_so,len);
    ret[len] = '\000';
    return ret;
}


int main(int argc,char **argv)
{
    int ch;
    int flags = O_RDWR;
    while ((ch = getopt(argc, argv, "cdvs::h?")) != -1) {
      switch (ch) {
      case 'c':
          flags |= O_CREAT;
          break;
      case 'd':
          del_segs.push_back(optarg);
          break;
      case 's':
          new_segs.push_back(optarg);
          break;
      case 'h':
      case '?':
      default:
          usage();
          exit(0);
      case 'v':
          printf("%s version %s\n",progname,xstr(AFFLIB_VERSION));
          exit(0);
          
      }
    }
    argc -= optind;
    argv += optind;

    if(argc<1){
      usage();
    }

    regex_t re;
    if(regcomp(&re,"([^/=]*)(/[0-9]+)?(=.*)?",REG_EXTENDED|REG_ICASE)){
      err(1,"regcomp");
    }

    while(*argv){
      AFFILE *af = af_open(*argv,flags,0666);
      if(af){
          vector<string>::iterator i;

          for(i=del_segs.begin();i!=del_segs.end();i++){
            if(af_del_seg(af,i->c_str())){
                warn("af_del_seg(%s,%s) ",*argv,i->c_str());
            }
          }
          for(i=new_segs.begin();i!=new_segs.end();i++){
            regmatch_t match[10];
            memset(match,0,sizeof(match));
            if(regexec(&re,i->c_str(),10,match,0)==0){
                char *segname = make_re_string(i->c_str(),match,1);
                char *argstr  = make_re_string(i->c_str(),match,2);
                char *segval  = make_re_string(i->c_str(),match,3);
                update_segment(af,segname,argstr,segval);
                free(segname);
                free(argstr);
                free(segval);
            }
          }
          af_close(af);
      }
      else {
          warn("af_open(%s) ",*argv);
      }
      argv++;
      argc--;
    }
}

Generated by  Doxygen 1.6.0   Back to index