⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jartool.c

📁 jar文件处理原程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif    flags = UNPACK_UB2(file_header, LOC_EXTRA);#ifdef DEBUG        printf("Flags are %#hx\n", flags);#endif    method = UNPACK_UB2(file_header, LOC_COMP);#ifdef DEBUG    printf("Compression method is %#hx\n", method);#endif    /* if there isn't a data descriptor */    if(!(flags & 0x0008)){      crc = UNPACK_UB4(file_header, LOC_CRC);#ifdef DEBUG          printf("CRC is %x\n", crc);#endif    }    if(filename_len < fnlen){      if(filename != NULL)        free(filename);            filename = malloc(sizeof(ub1) * (fnlen + 1));      filename_len = fnlen + 1;    }    pb_read(&pbf, filename, fnlen);    filename[fnlen] = '\0';#ifdef DEBUG        printf("filename is %s\n", filename);#endif    if(file_num > 0){      handle = FALSE;            for(j = 0; j < file_num; j++)        if(strcmp(files[j], filename) == 0){          handle = TRUE;          break;        }    }    if(!handle)      f_fd = -1;    /* OK, there is some directory information in the file.  Nothing to do       but ensure the directory(s) exist, and create them if they don't.       What a pain! */    if(index(filename, '/') != NULL && handle){      /* Loop through all the directories in the path, (everything w/ a '/') */      ub1 *start = filename;      char *tmp_buff;      struct stat sbuf;      tmp_buff = malloc(sizeof(char) * strlen(filename));      for(;;){        ub1 *idx = index(start, '/');        if(idx == NULL)          break;        else if(idx == start){          start++;          continue;        }        start = idx + 1;        strncpy(tmp_buff, filename, (idx - filename));        tmp_buff[(idx - filename)] = '\0';#ifdef DEBUG            printf("checking the existance of %s\n", tmp_buff);#endif        if(stat(tmp_buff, &sbuf) < 0){          if(errno != ENOENT){            perror("stat");            exit(1);          }        } else if(S_ISDIR(sbuf.st_mode)){#ifdef DEBUG              printf("Directory exists\n");#endif          continue;        }else {          fprintf(stderr, "Hmmm.. %s exists but isn't a directory!\n",                  tmp_buff);          exit(1);        }        #ifdef DEBUG            printf("Making directory..\n");#endif        if(mkdir(tmp_buff, 0755) < 0){          perror("mkdir");          exit(1);        }        if(verbose && handle)          printf("%10s: %s/\n", "created", tmp_buff);      }      /* only a directory */      if(strlen(start) == 0)        dir = TRUE;#ifdef DEBUG          printf("Leftovers are \"%s\" (%d)\n", start, strlen(start));#endif      /* If the entry was just a directory, don't write to file, etc */      if(strlen(start) == 0)        f_fd = -1;      free(tmp_buff);    }    if(f_fd != -1 && handle){      f_fd = creat(filename, 00644);      if(f_fd < 0){        fprintf(stderr, "Error extracting JAR archive!\n");        perror(filename);        exit(1);      }    }    if(method != 8 && flags & 0x0008){      fprintf(stderr, "Error in JAR file! (not compressed but data desc.)\n");      exit(1);    }    if(method == 8 || flags & 0x0008){      if(seekable)        lseek(fd, eflen, SEEK_CUR);      else        consume(&pbf, eflen);            inflate_file(&pbf, f_fd, &ze);    } else {#ifdef DEBUG          printf("writing stored data.. (%d bytes)\n", csize);#endif      out_a = 0;      in_a = csize;      ze.crc = crc32(ze.crc, NULL, 0); /* initialize the crc */      while(out_a < csize){        rdamt = (in_a > RDSZ ? RDSZ : in_a);        if(pb_read(&pbf, rd_buff, rdamt) != rdamt){          perror("read");          exit(1);        }                ze.crc = crc32(ze.crc, (Bytef*)rd_buff, rdamt);        if(f_fd >= 0)          write(f_fd, rd_buff, rdamt);        out_a += rdamt;        in_a -= rdamt;#ifdef DEBUG            printf("%d bytes written\n", out_a);#endif      }      if(seekable)        lseek(fd, eflen, SEEK_CUR);      else        consume(&pbf, eflen);    }    /* if there is a data descriptor left, compare the CRC */    if(flags & 0x0008){      if(pb_read(&pbf, scratch, 16) != 16){        perror("read");        exit(1);      }      signature = UNPACK_UB4(scratch, 0);      if(signature != 0x08074b50){        fprintf(stderr, "Error! Missing data descriptor!\n");        exit(1);      }      crc = UNPACK_UB4(scratch, 4);    }    if(crc != ze.crc){      fprintf(stderr, "Error! CRCs do not match! Got %x, expected %x\n",              ze.crc, crc);      exit(1);    }    close(f_fd);    if(verbose && dir == FALSE && handle)      printf("%10s: %s\n",             (method == 8 ? "inflated" : "extracted"),             filename);  }  return 0;}int list_jar(int fd, char **files, int file_num){  int rdamt;  ub4 signature;  ub4 csize;  ub4 usize;  ub4 mdate;  ub4 tmp;  ub2 fnlen;  ub2 eflen;  ub2 clen;  ub2 flags;  ub2 method;  ub2 cen_size;  ub1 *filename = NULL;  ub1 scratch[16];  ub1 cen_header[46];  int filename_len = 0;  off_t size;  int i, j;  time_t tdate;  struct tm *s_tm;  char ascii_date[30];  zipentry ze;#ifdef DEBUG  printf("Listing jar file, looking for %d files\n", file_num);#endif  /* This should be the start of the central-header-end section */  if(seekable){    if(lseek(fd, -22, SEEK_END) == (off_t)-1){      perror("lseek");      exit(1);    }        if(read(fd, &tmp, sizeof(ub4)) != 4){      perror("read");      exit(1);    }        if(tmp != 0x06054b50){      fprintf(stderr, "Error in JAR file format. zip-style comment?\n");      exit(1);    }    if(lseek(fd, 6, SEEK_CUR) == (off_t)-1){      perror("lseek");      exit(1);    }      if(read(fd, &cen_size, 2) != 2){      perror("read");      exit(1);    }    /*   printf("%hu entries in central header\n", cen_size); */    if(lseek(fd, 4, SEEK_CUR) == (off_t)-1){      perror("lseek");      exit(1);    }    if(read(fd, &tmp, 4) != 4){      perror("read");      exit(1);    }    /*   printf("Central header offset = %d\n", tmp); */    if(lseek(fd, tmp, SEEK_SET) != tmp){      perror("lseek");      exit(1);    }    /* Loop through the entries in the central header */    for(i = 0; i < cen_size; i++){          if(read(fd, &cen_header, 46) != 46){        perror("read");        exit(1);      }      signature = UNPACK_UB4(cen_header, 0);      if(signature != 0x02014b50){        fprintf(stderr, "Error in JAR file! Cannot locate central header!\n");        exit(1);      }      usize = UNPACK_UB4(cen_header, CEN_USIZE);      fnlen = UNPACK_UB2(cen_header, CEN_FNLEN);      eflen = UNPACK_UB2(cen_header, CEN_EFLEN);      clen = UNPACK_UB2(cen_header, CEN_COMLEN);      /* If we're providing verbose output, we need to make an ASCII       * formatted version of the date. */      if(verbose){        mdate = UNPACK_UB4(cen_header, CEN_MODTIME);        tdate = dos2unixtime(mdate);        s_tm = localtime(&tdate);        strftime(ascii_date, 30, "%a %b %d %H:%M:%S %Z %Y", s_tm);      }      if(filename_len < fnlen){        if(filename != NULL)          free(filename);              filename = malloc(sizeof(ub1) * (fnlen + 1));        filename_len = fnlen + 1;      }          if(read(fd, filename, fnlen) != fnlen){        perror("read");        exit(1);      }      filename[fnlen] = '\0';          /* if the user specified a list of files on the command line,         we'll only display those, otherwise we'll display everything */      if(file_num > 0){        for(j = 0; j < file_num; j++)          if(strcmp(files[j], filename) == 0){            if(verbose)              printf("%6d %s %s\n", usize, ascii_date, filename);            else              printf("%s\n", filename);            break;          }      } else {        if(verbose)          printf("%6d %s %s\n", usize, ascii_date, filename);        else          printf("%s\n", filename);      }                        size = eflen + clen;      if(size > 0){        if(lseek(fd, size, SEEK_CUR) == (off_t)-1){          perror("lseek");          exit(1);        }      }    }  } else {    /* the file isn't seekable.. evil! */    pb_file pbf;    pb_init(&pbf, fd);    init_inflation();    for(;;){      if((rdamt = pb_read(&pbf, scratch, 4)) != 4){        perror("read");        break;      }            signature = UNPACK_UB4(scratch, 0);      #ifdef DEBUG      printf("signature is %x\n", signature);#endif            if(signature == 0x08074b50){#ifdef DEBUG        printf("skipping data descriptor\n");#endif        pb_read(&pbf, scratch, 12);        continue;      } else if(signature == 0x02014b50){#ifdef DEBUG        printf("Central header reached.. we're all done!\n");#endif        break;      }else if(signature != 0x04034b50){#ifdef DEBUG        printf("Ick! %#x\n", signature);#endif        break;      }            if((rdamt = pb_read(&pbf, (file_header + 4), 26)) != 26){        perror("read");        break;      }            csize = UNPACK_UB4(file_header, LOC_CSIZE);#ifdef DEBUG      printf("Compressed size is %u\n", csize);#endif            fnlen = UNPACK_UB2(file_header, LOC_FNLEN);#ifdef DEBUG      printf("Filename length is %hu\n", fnlen);#endif            eflen = UNPACK_UB2(file_header, LOC_EFLEN);#ifdef DEBUG      printf("Extra field length is %hu\n", eflen);#endif            method = UNPACK_UB2(file_header, LOC_COMP);#ifdef DEBUG      printf("Compression method is %#hx\n", method);#endif      flags = UNPACK_UB2(file_header, LOC_EXTRA);#ifdef DEBUG      printf("Flags are %#hx\n", flags);#endif            usize = UNPACK_UB4(file_header, LOC_USIZE);      /* If we're providing verbose output, we need to make an ASCII       * formatted version of the date. */      if(verbose){        mdate = UNPACK_UB4(file_header, LOC_MODTIME);        tdate = dos2unixtime(mdate);        s_tm = localtime(&tdate);        strftime(ascii_date, 30, "%a %b %d %H:%M:%S %Z %Y", s_tm);      }      if(filename_len < fnlen){        if(filename != NULL)          free(filename);                filename = malloc(sizeof(ub1) * (fnlen + 1));        filename_len = fnlen + 1;      }            pb_read(&pbf, filename, fnlen);      filename[fnlen] = '\0';            /* the header is at the end.  In a JAR file, this means that the data         happens to be compressed.  We have no choice but to inflate the         data */      if(flags & 0x0008){        size = eflen;        if(size > 0)          consume(&pbf, size);                if(method == 8){#ifdef DEBUG          printf("inflating %s\n", filename);#endif          inflate_file(&pbf, -1, &ze);          usize = ze.usize;        } else           printf("We're shit outta luck!\n");                } else {        size = csize + (eflen > 0 ? eflen : 0);        #ifdef DEBUG        printf("Skipping %d bytes\n", size);#endif        consume(&pbf, size);      }      /* print out the listing */      if(file_num > 0){        for(j = 0; j < file_num; j++)          if(strcmp(files[j], filename) == 0){            if(verbose)              printf("%6d %s %s\n", usize, ascii_date, filename);            else              printf("%s\n", filename);            break;          }      } else {        if(verbose)          printf("%6d %s %s\n", usize, ascii_date, filename);        else          printf("%s\n", filename);      }            }  }  return 0;}int consume(pb_file *pbf, int amt){  int tc = 0; /* total amount consumed */  ub1 buff[RDSZ];  int rdamt;#ifdef DEBUG  printf("Consuming %d bytes\n", amt);#endif  while(tc < amt){    rdamt = pb_read(pbf, buff, ((amt - tc) < RDSZ ? (amt - tc) : RDSZ));#ifdef DEBUG    printf("got %d bytes\n", rdamt);#endif    tc += rdamt;  }#ifdef DEBUG  printf("%d bytes consumed\n", tc);#endif  return 0;}void usage(char *filename){  fprintf(stderr, "Usage: %s {ctxuV}[vfm0M] [jar-file] [manifest-file] [-C dir] files ...\nOptions\n -c  create new archive\n -t  list table of contents for archive\n -x  extract named (or all) files from archive\n -u  update existing archive\n -V  display version information\n -v  generate verbose output on standard output\n -f  specify archive file name\n -m  include manifest information from specified manifest file\n -0  store only; use no ZIP compression\n -M  Do not create a manifest file for the entries\n -C  change to the specified directory and include the following file\nIf any file is a directory then it is processed recursively.\nThe manifest file name and the archive file name needs to be specified\nin the same order the 'm' and 'f' flags are specified.\n\nExample 1: to archive two class files into an archive called classes.jar: \n     jar cvf classes.jar Foo.class Bar.class \nExample 2: use an existing manifest file 'mymanifest' and archive all the\n     files in the foo/ directory into 'classes.jar': \n     jar cvfm classes.jar mymanifest -C foo/ .\n", filename);  exit(1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -