X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=fastjar%2Fjartool.c;h=0a1694eebb9b5ce99957693fecfe92b000755a08;hb=78e1dded8bd3a5379fdc6c17814ade1f4e21afd8;hp=cd2efcb109f3e300f4600a2db642c1f67bada775;hpb=d36bda007ad84778419c06c811063e4a72e2b6f0;p=pf3gnuchains%2Fgcc-fork.git diff --git a/fastjar/jartool.c b/fastjar/jartool.c index cd2efcb109f..0a1694eebb9 100644 --- a/fastjar/jartool.c +++ b/fastjar/jartool.c @@ -1,6 +1,6 @@ /* jartool.c - main functions for fastjar utility - Copyright (C) 2002 Free Software Foundation + Copyright (C) 2002, 2004, 2005 Free Software Foundation Copyright (C) 1999, 2000, 2001 Bryan Burns This program is free software; you can redistribute it and/or @@ -15,7 +15,7 @@ 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. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* @@ -238,6 +238,7 @@ #include "dostime.h" #include "pushback.h" #include "compress.h" +#include "shift.h" /* Some systems have mkdir that takes a single argument. */ #ifdef MKDIR_TAKES_ONE_ARG @@ -273,14 +274,18 @@ void init_headers(void); int consume(pb_file *, int); int list_jar(int, char**, int); int extract_jar(int, char**, int); -int add_file_to_jar(int, int, const char*, struct stat*); -int add_to_jar(int, const char*, const char*); +int add_file_to_jar(int, int, const char*, struct stat*, int); +int add_to_jar(int, const char*, int); +int add_to_jar_with_dir(int, const char*, const char*, int); int create_central_header(int); -int make_manifest(int, const char*); +int make_manifest(int, const char*, int); +int read_entries (int); static void init_args(char **, int); static char *get_next_arg (void); static char *jt_strdup (char*); static void expand_options (int *argcp, char ***argvp); +static struct zipentry *find_entry (const char *); +static int looks_like_dir (const char *); /* global variables */ ub1 file_header[30]; @@ -304,6 +309,12 @@ zipentry *ziptail; /* tail of the linked list */ int number_of_entries; /* number of entries in the linked list */ +/* What we go by. */ +const char *progname; + +/* The offset of the end of the last zip entry. */ +ub4 end_of_entries; + /* This is used to mark options with no short value. */ #define LONG_OPT(Num) ((Num) + 128) @@ -312,6 +323,11 @@ int number_of_entries; /* number of entries in the linked list */ /* This holds all options. */ #define OPTION_STRING "-ctxuvVf:m:C:0ME@" +/* Define the MANIFEST content here to have it easier with calculations + below. This is for the case we create an empty MANIFEST.MF. */ +#define MANIFEST_STR "Manifest-Version: 1.0\nCreated-By: " +#define MANIFEST_END "\n\n" + static const struct option options[] = { { "help", no_argument, NULL, OPT_HELP }, @@ -319,7 +335,8 @@ static const struct option options[] = { NULL, no_argument, NULL, 0 } }; -int main(int argc, char **argv){ +int main(int argc, char **argv) +{ char *mfile = NULL; @@ -327,7 +344,6 @@ int main(int argc, char **argv){ int manifest = TRUE; int opt; - int j; int jarfd = -1; /* These are used to collect file names and `-C' options for the @@ -335,6 +351,8 @@ int main(int argc, char **argv){ int new_argc; char **new_argv; + progname = argv[0]; + do_compress = TRUE; verbose = FALSE; @@ -345,8 +363,6 @@ int main(int argc, char **argv){ if(argc < 2) usage(argv[0]); - j = strlen(argv[1]); - new_argc = 0; new_argv = (char **) malloc (argc * sizeof (char *)); @@ -415,15 +431,11 @@ int main(int argc, char **argv){ new_argv[new_argc] = NULL; if(action == ACTION_NONE){ - fprintf(stderr, "One of options -{ctxu} must be specified.\n"); + fprintf(stderr, "%s: one of options -{ctxu} must be specified.\n", + progname); usage(argv[0]); } - if(action == ACTION_UPDATE){ - fprintf(stderr, "%s: `-u' mode unimplemented.\n", argv[0]); - exit(1); - } - /* Verify unsupported combinations and warn of the use of non standard features */ if(verbose && use_explicit_list_only) @@ -432,7 +444,8 @@ int main(int argc, char **argv){ fprintf (stderr, "Warning: using non standard '-@' option\n"); if(read_names_from_stdin && (action != ACTION_CREATE && action != ACTION_UPDATE)){ - fprintf(stderr, "Option '-@' is supported only with '-c' or '-u'.\n"); + fprintf(stderr, "%s: option '-@' is supported only with '-c' or '-u'.\n", + progname); usage(argv[0]); } @@ -442,8 +455,8 @@ int main(int argc, char **argv){ jarfd = open(jarfile, O_CREAT | O_BINARY | O_WRONLY | O_TRUNC, 0666); if(jarfd < 0){ - fprintf(stderr, "Error opening %s for writing!\n", jarfile); - perror(jarfile); + fprintf(stderr, "%s: error opening %s for writing: %s\n", progname, + jarfile, strerror (errno)); exit(1); } @@ -467,8 +480,8 @@ int main(int argc, char **argv){ jarfd = open(jarfile, O_RDONLY | O_BINARY); if(jarfd < 0){ - fprintf(stderr, "Error opening %s for reading!\n", jarfile); - perror(jarfile); + fprintf(stderr, "%s: error opening %s for reading: %s\n", progname, + jarfile, strerror (errno)); exit(1); } @@ -481,28 +494,51 @@ int main(int argc, char **argv){ } } + if (action == ACTION_UPDATE) + { + if (!jarfile) + { + fprintf (stderr, "%s: `-u' mode requires a file name\n", + argv[0]); + exit (1); + } + + if ((jarfd = open (jarfile, O_RDWR | O_BINARY)) < 0) + { + fprintf (stderr, "Error opening %s for reading!\n", jarfile); + perror (jarfile); + exit (1); + } + + /* Assert that jarfd is seekable. */ + if (lseek (jarfd, 0, SEEK_CUR) == -1) + { + fprintf (stderr, "%s: %s is not seekable\n", argv[0], jarfile); + exit (1); + } + + seekable = TRUE; + } + if(action == ACTION_CREATE || action == ACTION_UPDATE){ const char *arg; init_headers(); - if((action == ACTION_UPDATE) && jarfile) { - if((jarfd = open(jarfile, O_RDWR | O_BINARY)) < 0) { - fprintf(stderr, "Error opening %s for reading!\n", jarfile); - perror(jarfile); - exit(1); - } - } - if(do_compress) init_compression(); - + + if (action == ACTION_UPDATE) + { + if (read_entries (jarfd)) + exit (1); + } /* Add the META-INF/ directory and the manifest */ if(manifest && mfile) - make_manifest(jarfd, mfile); - else if(manifest) - make_manifest(jarfd, NULL); - + make_manifest(jarfd, mfile, action == ACTION_UPDATE); + else if(manifest && action == ACTION_CREATE) + make_manifest(jarfd, NULL, FALSE); + init_args (new_argv, 0); /* now we add the files to the archive */ while ((arg = get_next_arg ())){ @@ -510,15 +546,21 @@ int main(int argc, char **argv){ if(!strcmp(arg, "-C")){ const char *dir_to_change = get_next_arg (); const char *file_to_add = get_next_arg (); - if(!dir_to_change - || !file_to_add - || add_to_jar(jarfd, dir_to_change, file_to_add)){ - printf("Error adding %s to jar archive!\n", arg); + if (!dir_to_change || !file_to_add) { + fprintf(stderr, "%s: error: missing argument for -C.\n", progname); exit(1); } + if (add_to_jar_with_dir(jarfd, dir_to_change, file_to_add, + action == ACTION_UPDATE)) + { + fprintf(stderr, + "Error adding %s (in directory %s) to jar archive!\n", + file_to_add, dir_to_change); + exit(1); + } } else { - if(add_to_jar(jarfd, NULL, arg)){ - printf("Error adding %s to jar archive!\n", arg); + if(add_to_jar(jarfd, arg, action == ACTION_UPDATE)){ + fprintf(stderr, "Error adding %s to jar archive!\n", arg); exit(1); } } @@ -526,11 +568,27 @@ int main(int argc, char **argv){ /* de-initialize the compression DS */ if(do_compress) end_compression(); + + if (action == ACTION_UPDATE) + lseek (jarfd, end_of_entries, SEEK_SET); create_central_header(jarfd); - - if (close(jarfd) != 0) { - fprintf(stderr, "Error closing jar archive!\n"); + +#if ! (HAVE_FTRUNCATE || HAVE__CHSIZE) + #error neither ftruncate() or _chsize() available +#endif + /* Check if the file shrunk when we updated it. */ + if (action == ACTION_UPDATE) +#if HAVE_FTRUNCATE + ftruncate (jarfd, lseek (jarfd, 0, SEEK_CUR)); +#else + _chsize (jarfd, lseek (jarfd, 0, SEEK_CUR)); +#endif + + if (jarfd != STDIN_FILENO && close(jarfd) != 0) { + fprintf(stderr, "%s: error closing jar archive: %s\n", + progname, strerror (errno)); + exit (1); } } else if(action == ACTION_LIST){ list_jar(jarfd, &new_argv[0], new_argc); @@ -545,9 +603,7 @@ static int args_current_g; static char **args_g; static void -init_args(args, current) - char **args; - int current; +init_args(char **args, int current) { if(!read_names_from_stdin) { @@ -557,7 +613,7 @@ init_args(args, current) } static char * -get_next_arg () +get_next_arg (void) { static int reached_end = 0; @@ -617,7 +673,8 @@ get_next_arg () } } -void init_headers(){ +void init_headers(void) +{ /* packing file header */ /* magic number */ file_header[0] = 0x50; @@ -668,7 +725,8 @@ void init_headers(){ } -void add_entry(struct zipentry *ze){ +void add_entry(struct zipentry *ze) +{ if(ziplist == NULL){ ziplist = ze; @@ -681,7 +739,176 @@ void add_entry(struct zipentry *ze){ number_of_entries++; } -int make_manifest(int jfd, const char *mf_name){ +static struct zipentry * +find_entry (const char *fname) +{ + struct zipentry *ze; + + for (ze = ziptail; ze; ze = ze->next_entry) + { + if (!strcmp (ze->filename, fname)) + return ze; + } + return NULL; +} + + +static int +looks_like_dir (const char *fname) +{ + struct zipentry *ze; + size_t len = strlen (fname); + + for (ze = ziptail; ze; ze = ze->next_entry) + { + if (strlen (ze->filename) > len + && !strncmp (fname, ze->filename, len) + && ze->filename[len] == '/') + return 1; + } + return 0; +} + + +/* + * Read the zip entries of an existing file, building `ziplist' as we go. + */ +int read_entries (int fd) +{ + struct zipentry *ze; + ub1 intbuf[4]; + ub1 header[46]; + ub2 len; + ub2 count, i; + off_t offset; + + if (lseek (fd, -22, SEEK_END) == -1) + { + fprintf (stderr, "%s: %s: can't seek file\n", progname, jarfile); + return 1; + } + + if (read (fd, intbuf, 4) < 4) + { + perror (progname); + return 1; + } + /* Is there a zipfile comment? */ + while (UNPACK_UB4(intbuf, 0) != 0x06054b50) + { + if (lseek (fd, -5, SEEK_CUR) == -1 || + read (fd, intbuf, 4) != 4) + { + fprintf (stderr, "%s: can't find end of central directory: %s\n", + progname, strerror (errno)); + return 1; + } + } + + /* Skip disk numbers. */ + if (lseek (fd, 6, SEEK_CUR) == -1) + { + perror (progname); + return 1; + } + + /* Number of entries in the central directory. */ + if (read (fd, intbuf, 2) != 2) + { + perror (progname); + return 1; + } + count = UNPACK_UB2(intbuf, 0); + + if (lseek (fd, 4, SEEK_CUR) == -1) + { + perror (progname); + return 1; + } + + /* Offset where the central directory begins. */ + if (read (fd, intbuf, 4) != 4) + { + perror (progname); + return 1; + } + offset = UNPACK_UB4(intbuf, 0); + end_of_entries = offset; + + if (lseek (fd, offset, SEEK_SET) != offset) + { + perror (progname); + return 1; + } + + if (read (fd, header, 46) != 46) + { + fprintf (stderr, "%s: %s: unexpected end of file\n", + progname, jarfile); + return 1; + } + + for (i = 0; i < count; i++) + { + if (UNPACK_UB4(header, 0) != 0x02014b50) + { + fprintf (stderr, "%s: can't find central directory header\n", + progname); + return 1; + } + ze = (struct zipentry *) malloc (sizeof (struct zipentry)); + if (!ze) + { + perror (progname); + return 1; + } + memset (ze, 0, sizeof (struct zipentry)); + ze->flags = UNPACK_UB2(header, CEN_FLAGS); + ze->mod_time = UNPACK_UB2(header, CEN_MODTIME); + ze->mod_date = UNPACK_UB2(header, CEN_MODDATE); + ze->crc = UNPACK_UB4(header, CEN_CRC); + ze->usize = UNPACK_UB4(header, CEN_USIZE); + ze->csize = UNPACK_UB4(header, CEN_CSIZE); + ze->offset = UNPACK_UB4(header, CEN_OFFSET); + ze->compressed = (header[CEN_COMP] || header[CEN_COMP+1]); + len = UNPACK_UB2(header, CEN_FNLEN); + ze->filename = (char *) malloc ((len+1) * sizeof (char)); + if (!ze->filename) + { + perror (progname); + return 1; + } + if (read (fd, ze->filename, len) != len) + { + fprintf (stderr, "%s: %s: unexpected end of file\n", + progname, jarfile); + return 1; + } + len = UNPACK_UB4(header, CEN_EFLEN); + len += UNPACK_UB4(header, CEN_COMLEN); + if (lseek (fd, len, SEEK_CUR) == -1) + { + perror (progname); + return 1; + } + add_entry (ze); + if (i < count - 1) + { + if (read (fd, header, 46) != 46) + { + fprintf (stderr, "%s: %s: unexpected end of file\n", + progname, jarfile); + return 1; + } + } + } + + lseek (fd, 0, SEEK_SET); + return 0; +} + +int make_manifest(int jfd, const char *mf_name, int updating) +{ time_t current_time; int nlen; /* length of file name */ int mod_time; /* file modification time */ @@ -730,13 +957,14 @@ int make_manifest(int jfd, const char *mf_name){ /* if the user didn't specify an external manifest file... */ if(mf_name == NULL){ - int mf_len = 37 + strlen(VERSION); + + int mf_len = strlen(MANIFEST_STR) + strlen(VERSION) + strlen(MANIFEST_END); char *mf; if((mf = (char *) malloc(mf_len + 1))) { uLong crc; - sprintf(mf, "Manifest-Version: 1.0\nCreated-By: %s\n\n", VERSION); + sprintf(mf, "%s%s%s", MANIFEST_STR, VERSION, MANIFEST_END); crc = crc32(0L, Z_NULL, 0); @@ -804,7 +1032,7 @@ int make_manifest(int jfd, const char *mf_name){ exit(1); } - if(add_file_to_jar(jfd, mfd, "META-INF/MANIFEST.MF", &statbuf)){ + if(add_file_to_jar(jfd, mfd, "META-INF/MANIFEST.MF", &statbuf, updating)){ perror("error writing to jar"); exit(1); } @@ -814,14 +1042,46 @@ int make_manifest(int jfd, const char *mf_name){ return 0; } -int add_to_jar(int fd, const char *new_dir, const char *file){ +/* Implements -C by wrapping add_to_jar. new_dir is the directory + to switch to. + + `updating', if nonzero, will indicate that we are updating an + existing file, and will need to take special care. If set, we will + also expect that the linked list of zip entries will be filled in + with the jar file's current contents. + */ +int +add_to_jar_with_dir (int fd, const char* new_dir, const char* file, + const int updating) +{ + int retval; + char old_dir[MAXPATHLEN]; + if (getcwd(old_dir, MAXPATHLEN) == NULL) { + perror("getcwd"); + return 1; + } + if (chdir(new_dir) == -1) { + perror(new_dir); + return 1; + } + retval=add_to_jar(fd, file, updating); + if (chdir(old_dir) == -1) { + perror(old_dir); + return 1; + } + return retval; +} + +int +add_to_jar (int fd, const char *file, const int updating) +{ struct stat statbuf; DIR *dir; struct dirent *de; zipentry *ze; + zipentry *existing = NULL; int stat_return; - char *old_dir = NULL; - + /* This is a quick compatibility fix -- Simon Weijgers * It fixes this: * "normal" jar : org/apache/java/io/LogRecord.class @@ -832,17 +1092,6 @@ int add_to_jar(int fd, const char *new_dir, const char *file){ while (*file=='.' && *(file+1)=='/') file+=2; - /* If new_dir isn't null, we need to change to that directory. However, - we also need to return to the old directory when we're done */ - if(new_dir != NULL){ - old_dir = getcwd(NULL, 0); - - if(chdir(new_dir) == -1){ - perror(new_dir); - return 1; - } - } - if(jarfile && !strcmp(file, jarfile)){ if(verbose) printf("skipping: %s\n", file); @@ -897,9 +1146,6 @@ int add_to_jar(int fd, const char *new_dir, const char *file){ PACK_UB2(file_header, LOC_FNLEN, nlen); PACK_UB4(file_header, LOC_MODTIME, mod_time); - if(verbose) - printf("adding: %s (in=%d) (out=%d) (stored 0%%)\n", fullname, 0, 0); - ze = (zipentry*)malloc(sizeof(zipentry)); if(ze == NULL){ perror("malloc"); @@ -916,10 +1162,36 @@ int add_to_jar(int fd, const char *new_dir, const char *file){ ze->mod_date = (ub2)((mod_time & 0xffff0000) >> 16); ze->compressed = FALSE; - add_entry(ze); + if (updating) + { + if ((existing = find_entry (ze->filename)) != NULL) + { + if (existing->usize != 0) + { + /* XXX overwriting non-directory with directory? */ + fprintf (stderr, "%s: %s: can't overwrite non-directory with directory\n", + progname, fullname); + return 1; + } + } + if (lseek (fd, end_of_entries, SEEK_SET) == -1) + { + fprintf (stderr, "%s %d\n", __FILE__, __LINE__); + perror ("lseek"); + return 1; + } + } - write(fd, file_header, 30); - write(fd, fullname, nlen); + if (!existing) + { + add_entry (ze); + write (fd, file_header, 30); + write (fd, fullname, nlen); + end_of_entries = lseek (fd, 0, SEEK_CUR); + + if (verbose) + printf ("adding: %s (in=%d) (out=%d) (stored 0%%)\n", fullname, 0, 0); + } while(!use_explicit_list_only && (de = readdir(dir)) != NULL){ if(de->d_name[0] == '.') @@ -933,7 +1205,7 @@ int add_to_jar(int fd, const char *new_dir, const char *file){ strcpy(t_ptr, de->d_name); - if(add_to_jar(fd, NULL, fullname)){ + if (add_to_jar(fd, fullname, updating)) { fprintf(stderr, "Error adding file to jar!\n"); return 1; } @@ -948,10 +1220,10 @@ int add_to_jar(int fd, const char *new_dir, const char *file){ add_fd = open(file, O_RDONLY | O_BINARY); if(add_fd < 0){ fprintf(stderr, "Error opening %s.\n", file); - return 0; + return 1; } - if(add_file_to_jar(fd, add_fd, file, &statbuf)){ + if(add_file_to_jar(fd, add_fd, file, &statbuf, updating)){ fprintf(stderr, "Error adding file to jar!\n"); return 1; } @@ -959,19 +1231,12 @@ int add_to_jar(int fd, const char *new_dir, const char *file){ } else { fprintf(stderr, "Illegal file specified: %s\n", file); } - - if(old_dir != NULL){ - if(chdir(old_dir)) - perror(old_dir); - - free(old_dir); - } - return 0; } -int add_file_to_jar(int jfd, int ffd, const char *fname, struct stat *statbuf){ - +int add_file_to_jar(int jfd, int ffd, const char *fname, struct stat *statbuf, + const int updating) +{ unsigned short file_name_length; unsigned long mod_time; ub1 rd_buff[RDSZ]; @@ -979,6 +1244,18 @@ int add_file_to_jar(int jfd, int ffd, const char *fname, struct stat *statbuf){ off_t offset = 0; int rdamt; struct zipentry *ze; + struct zipentry *existing = NULL; + + if (updating) + { + existing = find_entry (fname); + if (existing && looks_like_dir (fname)) + { + fprintf (stderr, "%s: %s is a directory in the archive\n", + progname, fname); + return 1; + } + } mod_time = unix2dostime(&(statbuf->st_mtime)); file_name_length = strlen(fname); @@ -1033,13 +1310,29 @@ int add_file_to_jar(int jfd, int ffd, const char *fname, struct stat *statbuf){ ze->csize = statbuf->st_size; ze->usize = ze->csize; - ze->offset = lseek(jfd, 0, SEEK_CUR); + + if (existing) + ze->offset = existing->offset; + else if (updating) + ze->offset = end_of_entries; + else + ze->offset = lseek(jfd, 0, SEEK_CUR); + if(do_compress) ze->compressed = TRUE; else ze->compressed = FALSE; - - add_entry(ze); + + if (!existing) + add_entry(ze); + if (updating && lseek (jfd, ze->offset, SEEK_SET) < 0) + { + perror ("lseek"); + return 1; + } + + /* We can safely write the header here, since it will be the same size + as before */ /* Write the local header */ write(jfd, file_header, 30); @@ -1049,14 +1342,31 @@ int add_file_to_jar(int jfd, int ffd, const char *fname, struct stat *statbuf){ if(verbose){ - printf("adding: %s ", fname); + if (existing) + printf ("updating: %s ", fname); + else + printf("adding: %s ", fname); fflush(stdout); } if(do_compress){ /* compress the file */ - compress_file(ffd, jfd, ze); + compress_file(ffd, jfd, ze, existing); } else { + /* If we are not writing the last entry, make space for it. */ + if (existing && existing->next_entry) + { + if (ze->usize > existing->usize) + { + if (shift_down (jfd, existing->next_entry->offset, + ze->usize - existing->usize, existing->next_entry)) + { + fprintf (stderr, "%s: %s\n", progname, strerror (errno)); + return 1; + } + } + } + /* Write the contents of the file (uncompressed) to the zip file */ /* calculate the CRC as we go along */ ze->crc = crc32(0L, Z_NULL, 0); @@ -1100,12 +1410,42 @@ int add_file_to_jar(int jfd, int ffd, const char *fname, struct stat *statbuf){ /* Sun's jar tool will only allow a data descriptor if the entry is compressed, but we'll save 16 bytes/entry if we only use it when we can't seek back on the file */ + /* Technically, you CAN'T have a data descriptor unless the data + part has an obvious end, which DEFLATED does. Otherwise, there + would not be any way to determine where the data descriptor is. + Store an uncompressed file that ends with 0x504b0708, and see. + -- csm */ if(write(jfd, data_descriptor, 16) != 16){ perror("write"); return 0; } } + + if (existing) + { + int dd = (existing->flags & (1 << 3)) ? 12 : 0; + if (existing->next_entry && ze->csize < existing->csize + dd) + { + if (shift_up (jfd, existing->next_entry->offset, + existing->csize + dd - ze->csize, + existing->next_entry)) + { + perror (progname); + return 1; + } + } + /* Replace the existing entry data with this entry's. */ + existing->csize = ze->csize; + existing->usize = ze->usize; + existing->crc = ze->crc; + existing->mod_time = ze->mod_time; + existing->mod_date = ze->mod_date; + free (ze->filename); + free (ze); + } + else if (updating) + end_of_entries = lseek (jfd, 0, SEEK_CUR); if(verbose) printf("(in=%d) (out=%d) (%s %d%%)\n", @@ -1121,13 +1461,10 @@ int create_central_header(int fd){ ub1 end_header[22]; int start_offset; int dir_size; - int *iheader; int total_in = 0, total_out = 22; zipentry *ze; - iheader = (int*)header; - /* magic number */ header[0] = 'P'; header[1] = 'K'; @@ -1455,7 +1792,8 @@ int extract_jar(int fd, char **files, int file_num){ } if(f_fd != -1 && handle){ - f_fd = creat((const char *)filename, 00644); + f_fd = open((const char *)filename, + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if(f_fd < 0){ fprintf(stderr, "Error extracting JAR archive!\n"); @@ -1469,11 +1807,10 @@ int extract_jar(int fd, char **files, int file_num){ exit(1); } + if (eflen > 0) + consume(&pbf, eflen); + if(method == 8 || flags & 0x0008){ - if(seekable) - lseek(fd, eflen, SEEK_CUR); - else - consume(&pbf, eflen); inflate_file(&pbf, f_fd, &ze); } else { @@ -1506,11 +1843,6 @@ int extract_jar(int fd, char **files, int file_num){ 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 */ @@ -1550,7 +1882,6 @@ int extract_jar(int fd, char **files, int file_num){ } int list_jar(int fd, char **files, int file_num){ - int rdamt; ub4 signature; ub4 csize; ub4 usize; @@ -1570,7 +1901,7 @@ int list_jar(int fd, char **files, int file_num){ int i, j; time_t tdate; struct tm *s_tm; - char ascii_date[30]; + char ascii_date[31]; zipentry ze; #ifdef DEBUG @@ -1661,6 +1992,7 @@ int list_jar(int fd, char **files, int file_num){ tdate = dos2unixtime(mdate); s_tm = localtime(&tdate); strftime(ascii_date, 30, "%a %b %d %H:%M:%S %Z %Y", s_tm); + ascii_date[30] = '\0'; } if(filename_len < fnlen + 1){ @@ -1712,7 +2044,7 @@ int list_jar(int fd, char **files, int file_num){ init_inflation(); for(;;){ - if((rdamt = pb_read(&pbf, scratch, 4)) != 4){ + if(pb_read(&pbf, scratch, 4) != 4){ perror("read"); break; } @@ -1741,7 +2073,7 @@ int list_jar(int fd, char **files, int file_num){ break; } - if((rdamt = pb_read(&pbf, (file_header + 4), 26)) != 26){ + if(pb_read(&pbf, (file_header + 4), 26) != 26){ perror("read"); break; } @@ -1787,6 +2119,7 @@ int list_jar(int fd, char **files, int file_num){ free(filename); filename = malloc(sizeof(ub1) * (fnlen + 1)); + ascii_date[30] = '\0'; filename_len = fnlen + 1; } @@ -1853,6 +2186,14 @@ int consume(pb_file *pbf, int amt){ printf("Consuming %d bytes\n", amt); #endif + if (seekable){ + if (amt <= (int)pbf->buff_amt) + pb_read(pbf, buff, amt); + else { + lseek(pbf->fd, amt - pbf->buff_amt, SEEK_CUR); + pb_read(pbf, buff, pbf->buff_amt); /* clear pbf */ + } + } else while(tc < amt){ rdamt = pb_read(pbf, buff, ((amt - tc) < RDSZ ? (amt - tc) : RDSZ)); #ifdef DEBUG @@ -1862,7 +2203,7 @@ int consume(pb_file *pbf, int amt){ } #ifdef DEBUG - printf("%d bytes consumed\n", tc); + printf("%d bytes consumed\n", amt); #endif return 0; @@ -1873,11 +2214,11 @@ void usage(const char *filename){ exit (1); } -void version () +void version (void) { printf("jar (%s) %s\n\n", PACKAGE, VERSION); printf("Copyright 1999, 2000, 2001 Bryan Burns\n"); - printf("Copyright 2002 Free Software Foundation\n"); + printf("Copyright 2002, 2004 Free Software Foundation\n"); printf("\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); @@ -1904,6 +2245,8 @@ Store many files together in a single `jar' file.\n\ -E don't include the files found in a directory\n\ -f FILE specify archive file name\n\ --help print this help, then exit\n\ +"); + printf("\ -m FILE include manifest information from specified manifest file\n\ -M Do not create a manifest file for the entries\n\ -v generate verbose output on standard output\n\ @@ -1925,8 +2268,7 @@ Example 2: use an existing manifest file 'mymanifest' and archive all the\n\ } static char * -jt_strdup(s) - char *s; +jt_strdup(char *s) { char *result = (char*)malloc(strlen(s) + 1); if (result == (char*)0)