📄 jartool.c
字号:
/* jartool.c - main functions for fastjar utility Copyright (C) 1999 Bryan Burns This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* $Id: jartool.c,v 1.2 1999/12/06 07:38:28 toast Exp $ $Log: jartool.c,v $ Revision 1.2 1999/12/06 07:38:28 toast fixed recursive archiving bug Revision 1.1.1.1 1999/12/06 03:09:34 toast initial checkin.. Revision 1.22 1999/10/12 19:45:13 burnsbr adding patch to fix compat problem Revision 1.21 1999/05/10 09:15:49 burnsbr fixed manifest file version info Revision 1.20 1999/05/10 08:53:16 burnsbr *** empty log message *** Revision 1.19 1999/05/10 08:30:39 burnsbr added extract / listing code Revision 1.18 1999/04/28 04:24:29 burnsbr updated version Revision 1.17 1999/04/28 04:21:23 burnsbr added support for -C dir-changing flag.. Updated total compression display Revision 1.16 1999/04/27 10:28:22 burnsbr updated version string Revision 1.15 1999/04/27 10:04:06 burnsbr configure support Revision 1.14 1999/04/27 08:56:14 burnsbr added -V flag, better error messages Revision 1.13 1999/04/26 02:35:21 burnsbr changed all sorts of stuff.. compression now works 100% Revision 1.12 1999/04/23 12:00:45 burnsbr 90% done with compression code Revision 1.11 1999/04/22 04:12:57 burnsbr finished first round of Manifest file support.. might need to do more, digest etc.. Revision 1.10 1999/04/22 02:35:23 burnsbr added more manifest support, about 75% done now. Replaced all the redundant shifts and bit-logic with a macro or two, making the code easier to read. Revision 1.9 1999/04/21 09:55:16 burnsbr pulled out printfs Revision 1.8 1999/04/21 02:58:01 burnsbr started manifest code Revision 1.7 1999/04/20 23:15:28 burnsbr added patch sent by John Bley <jbb6@acpub.duke.edu> Revision 1.6 1999/04/20 08:56:02 burnsbr added GPL comment Revision 1.5 1999/04/20 08:16:09 burnsbr fixed verbose flag, did some optimization Revision 1.4 1999/04/20 05:09:59 burnsbr added rcsid variable Revision 1.3 1999/04/20 05:08:54 burnsbr fixed Log statement*/#include "config.h"#include <zlib.h>#ifdef STDC_HEADERS#include <stdlib.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdio.h>#include <sys/stat.h>#include <sys/types.h>#ifdef HAVE_DIRENT_H#include <dirent.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#include <string.h>#include <errno.h>#ifdef TM_IN_SYS_TIME#include <sys/time.h>#else#include <time.h>#endif#include "jartool.h"#include "zipfile.h"#include "dostime.h"#include "pushback.h"#include "compress.h"static char version_string[] = VERSION;static char rcsid[] = "$Id: jartool.c,v 1.2 1999/12/06 07:38:28 toast Exp $";extern int errno;void usage(char*);void add_entry(struct zipentry *);void init_headers();int consume(pb_file *, int);int list_jar(int, char**, int);int extract_jar(int, char**, int);int add_file_to_jar(int, int, char*, struct stat*);int add_to_jar(int, char*, char*);int create_central_header(int);int make_manifest(int, char*);/* global variables */ub1 file_header[30];ub1 data_descriptor[16];int do_compress;int seekable;int verbose;char jarfile[256];zipentry *ziplist; /* linked list of entries */zipentry *ziptail; /* tail of the linked list */int number_of_entries; /* number of entries in the linked list */int main(int argc, char **argv){ char mfile[256]; int action = ACTION_NONE; int manifest = TRUE; int manifest_file = FALSE; int file = FALSE; int file_first = FALSE; int i, j; int jarfd = -1; do_compress = TRUE; verbose = FALSE; ziplist = NULL; number_of_entries = 0; if(argc < 2) usage(argv[0]); j = strlen(argv[1]); for(i = 0; i < j; i++){ switch(argv[1][i]){ case 'c': action = ACTION_CREATE; break; case 't': action = ACTION_LIST; break; case 'x': action = ACTION_EXTRACT; break; case 'u': action = ACTION_UPDATE; break; case 'v': verbose = TRUE; break; case 'V': printf("%s\n", version_string); exit(0); case 'f': file = TRUE; if(!manifest_file) file_first = TRUE; else file_first = FALSE; break; case 'm': manifest_file = TRUE; break; case '0': do_compress = FALSE; break; case 'M': manifest = FALSE; break; case '-': break; default: fprintf(stderr, "Illegal option: %c\n", argv[1][i]); usage(argv[0]); } } if(action == ACTION_NONE){ fprintf(stderr, "One of options -{ctxu} must be specified.\n"); usage(argv[0]); } i = 2; /* get the jarfile and manifest file (if any) */ if(file && file_first){ if(i >= argc) usage(argv[0]); strncpy(jarfile, argv[i++], 256); } if(manifest_file){ if(i >= argc) usage(argv[0]); strncpy(mfile, argv[i++], 256); } if(file && !file_first){ if(i >= argc) usage(argv[0]); strncpy(jarfile, argv[i++], 256); } /* create the jarfile */ if(action == ACTION_CREATE){ if(file){ jarfd = creat(jarfile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(jarfd < 0){ fprintf(stderr, "Error opening %s for writing!\n", jarfile); perror(jarfile); exit(1); } /* We assume that the file is seekable */ seekable = TRUE; } else { jarfd = STDOUT_FILENO; /* jarfd is stdout otherwise */ /* standard out is not seekable */ seekable = FALSE; /* don't want our output to be part of the jar file.. figured this one out the hard way.. =P */ verbose = FALSE; } } else if(action == ACTION_LIST || action == ACTION_EXTRACT){ if(file){ jarfd = open(jarfile, O_RDONLY); if(jarfd < 0){ fprintf(stderr, "Error opening %s for reading!\n", jarfile); perror(jarfile); exit(1); } seekable = TRUE; } else { jarfd = STDIN_FILENO; /* jarfd is standard in */ /* we assume that the stream isn't seekable for safety */ seekable = FALSE; } } if(action == ACTION_CREATE || action == ACTION_UPDATE){ init_headers(); if(do_compress) init_compression(); /* Add the META-INF/ directory and the manifest */ if(manifest && manifest_file) make_manifest(jarfd, mfile); else if(manifest) make_manifest(jarfd, NULL); /* now we add the files to the archive */ for(; i < argc; i++){ /* i already is in the right location*/ if(!strcmp(argv[i], "-C")){ if(add_to_jar(jarfd, argv[i+1], argv[i+2])){ printf("Error adding %s to jar archive!\n", argv[i]); exit(1); } i += 2; } else { if(add_to_jar(jarfd, NULL, argv[i])){ printf("Error adding %s to jar archive!\n", argv[i]); exit(1); } } } /* de-initialize the compression DS */ if(do_compress) end_compression(); create_central_header(jarfd); if (close(jarfd) != 0) { fprintf(stderr, "Error closing jar archive!\n"); } } else if(action == ACTION_LIST){ list_jar(jarfd, &argv[i], (argc - i)); } else if(action == ACTION_EXTRACT){ extract_jar(jarfd, &argv[i], (argc - i)); } exit(0);}void init_headers(){ /* packing file header */ /* magic number */ file_header[0] = 0x50; file_header[1] = 0x4b; file_header[2] = 0x03; file_header[3] = 0x04; /* version number (Unix 1.0)*/ file_header[4] = 10; file_header[5] = 0; /* bit flag (normal deflation)*/ file_header[6] = 0x00; file_header[7] = 0x00; /* do_compression method (deflation) */ file_header[8] = 0; file_header[9] = 0; /* last mod file time (MS-DOS format) */ file_header[10] = 0; file_header[11] = 0; /* last mod file date (MS-DOS format) */ file_header[12] = 0; file_header[13] = 0; /* CRC 32 */ file_header[14] = 0; file_header[15] = 0; file_header[16] = 0; file_header[17] = 0; /* compressed size */ file_header[18] = 0; file_header[19] = 0; file_header[20] = 0; file_header[21] = 0; /* uncompressed size */ file_header[22] = 0; file_header[23] = 0; file_header[24] = 0; file_header[25] = 0; /* filename length */ file_header[26] = 0; file_header[27] = 0; /* extra field length */ file_header[28] = 0; file_header[29] = 0; /* Initialize the compression DS */ PACK_UB4(data_descriptor, 0, 0x08074b50); }void add_entry(struct zipentry *ze){ if(ziplist == NULL){ ziplist = ze; ziptail = ziplist; } else { ziplist->next_entry = ze; ziplist = ze; } number_of_entries++;}int make_manifest(int jfd, char *mf_name){ time_t current_time; int nlen; /* length of file name */ int mod_time; /* file modification time */ struct zipentry *ze; nlen = 9; /* trust me on this one */ memset((file_header + 12), '\0', 16); /*clear mod time, crc, size fields*/ current_time = time(NULL); if(current_time == (time_t)-1){ perror("time"); exit(1); } mod_time = unix2dostime(¤t_time); PACK_UB2(file_header, LOC_EXTRA, 0); PACK_UB2(file_header, LOC_COMP, 0); PACK_UB2(file_header, LOC_FNLEN, nlen); PACK_UB4(file_header, LOC_MODTIME, mod_time); if(verbose) printf("adding: META-INF/ (in=0) (out=0) (stored 0%%)\n"); ze = (zipentry*)malloc(sizeof(zipentry)); if(ze == NULL){ perror("malloc"); exit(1); } memset(ze, 0, sizeof(zipentry)); /* clear all the fields*/ ze->filename = (char*)malloc((nlen + 1) * sizeof(char) + 1); strcpy(ze->filename, "META-INF/"); ze->filename[nlen] = '\0'; ze->offset = lseek(jfd, 0, SEEK_CUR); ze->mod_time = (ub2)(mod_time & 0x0000ffff); ze->mod_date = (ub2)((mod_time & 0xffff0000) >> 16); ze->compressed = FALSE; add_entry(ze); write(jfd, file_header, 30); write(jfd, "META-INF/", nlen); /* if the user didn't specify an external manifest file... */ if(mf_name == NULL){ int mf_len = 37 + strlen(VERSION); uLong crc; char mf[mf_len + 1]; sprintf(mf, "Manifest-Version: 1.0\nCreated-By: %s\n\n", VERSION); crc = crc32(0L, Z_NULL, 0); crc = crc32(crc, mf, mf_len); nlen = 20; /* once again, trust me */ PACK_UB2(file_header, LOC_EXTRA, 0); PACK_UB2(file_header, LOC_COMP, 0); PACK_UB2(file_header, LOC_FNLEN, nlen); PACK_UB4(file_header, LOC_USIZE, mf_len); memcpy((file_header + LOC_CSIZE), (file_header + LOC_USIZE), 4); PACK_UB4(file_header, LOC_CRC, crc); if(verbose) printf("adding: META-INF/MANIFEST.MF (in=56) (out=56) (stored 0%%)\n"); ze = (zipentry*)malloc(sizeof(zipentry)); if(ze == NULL){ perror("malloc"); exit(1); } memset(ze, 0, sizeof(zipentry)); /* clear all the fields*/ ze->filename = (char*)malloc((nlen + 1) * sizeof(char) + 1); strcpy(ze->filename, "META-INF/MANIFEST.MF"); ze->filename[nlen] = '\0'; ze->offset = lseek(jfd, 0, SEEK_CUR); ze->mod_time = (ub2)(mod_time & 0x0000ffff); ze->mod_date = (ub2)((mod_time & 0xffff0000) >> 16); ze->crc = crc; ze->csize = mf_len; ze->usize = ze->csize; ze->compressed = FALSE; add_entry(ze); write(jfd, file_header, 30); write(jfd, "META-INF/MANIFEST.MF", nlen); write(jfd, mf, mf_len); } else { int mfd; struct stat statbuf; stat(mf_name, &statbuf); if(!S_ISREG(statbuf.st_mode)){ fprintf(stderr, "Invalid manifest file specified.\n"); exit(1); } mfd = open(mf_name, O_RDONLY); if(mfd < 0){ fprintf(stderr, "Error opening %s.\n", mf_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -