summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordoko <doko@138bc75d-0d04-0410-961f-82ee72b054a4>2004-07-06 21:40:08 +0000
committerdoko <doko@138bc75d-0d04-0410-961f-82ee72b054a4>2004-07-06 21:40:08 +0000
commit1f445250410fd24b8185675685c85d401fb9538d (patch)
treecede115c5e69e77d0b68edda7dfceb560ccb5b15
parent5e611c5f37d48ca2c450c2cbd1a28f7be2422863 (diff)
downloadppe42-gcc-1f445250410fd24b8185675685c85d401fb9538d.tar.gz
ppe42-gcc-1f445250410fd24b8185675685c85d401fb9538d.zip
2004-07-06 Matthias Klose <doko@debian.org>
* Makefile.in: Regenerate. * fastjar.texi: Update for '-u'. 2004-05-19 Casey Marshall <csm@gnu.org> PR 7854 * Makefile.am (jar_SOURCES): added shift.c, shift.h. (jar_CPPFLAGS): define WITH_SHIFT_DOWN. * compress.c Added FSF copyright. (write_data): new function. (compress_file): call write_data. * jartool.c Updated copyright year. (progname): new variable. (end_of_entries): new variable. (main): open and read file when updating. (find_entry): new function. (looks_like_dir): new function. (read_entries): new function. (make_manifest): added parameter `updating'. Call `add_file_to_jar' with `updating'. (add_to_jar_with_dir): added parameter `updating'. Call `add_to_jar' with `updating'. (add_to_jar): added parameter `updating'. Call `add_file_to_jar' with `updating'. Don't add directories if they already exist. (add_file_to_jar): added parameter `updating'. Update entries if they already exist. * jartool.h Added #ifndef __FASTJAR_JARTOOL_H__. (struct zipentry): added `flags'. * shift.c: new file. * shift.h: new file. * zipfile.h (CEN_FLAGS): new constant. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84171 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--fastjar/ChangeLog46
-rw-r--r--fastjar/Makefile.am5
-rw-r--r--fastjar/Makefile.in51
-rw-r--r--fastjar/compress.c72
-rw-r--r--fastjar/compress.h2
-rw-r--r--fastjar/fastjar.texi3
-rw-r--r--fastjar/jartool.c443
-rw-r--r--fastjar/jartool.h7
-rw-r--r--fastjar/shift.c166
-rw-r--r--fastjar/shift.h29
-rw-r--r--fastjar/zipfile.h1
11 files changed, 731 insertions, 94 deletions
diff --git a/fastjar/ChangeLog b/fastjar/ChangeLog
index 57dc2aa6b03..ff7196914f5 100644
--- a/fastjar/ChangeLog
+++ b/fastjar/ChangeLog
@@ -1,3 +1,49 @@
+2004-07-06 Matthias Klose <doko@debian.org>
+
+ * Makefile.in: Regenerate.
+ * fastjar.texi: Update for '-u'.
+
+2004-05-19 Casey Marshall <csm@gnu.org>
+
+ PR 7854
+ * Makefile.am
+ (jar_SOURCES): added shift.c, shift.h.
+ (jar_CPPFLAGS): define WITH_SHIFT_DOWN.
+
+ * compress.c
+ Added FSF copyright.
+ (write_data): new function.
+ (compress_file): call write_data.
+
+ * jartool.c
+ Updated copyright year.
+ (progname): new variable.
+ (end_of_entries): new variable.
+ (main): open and read file when updating.
+ (find_entry): new function.
+ (looks_like_dir): new function.
+ (read_entries): new function.
+ (make_manifest): added parameter `updating'.
+ Call `add_file_to_jar' with `updating'.
+ (add_to_jar_with_dir): added parameter `updating'.
+ Call `add_to_jar' with `updating'.
+ (add_to_jar): added parameter `updating'.
+ Call `add_file_to_jar' with `updating'.
+ Don't add directories if they already exist.
+ (add_file_to_jar): added parameter `updating'.
+ Update entries if they already exist.
+
+ * jartool.h
+ Added #ifndef __FASTJAR_JARTOOL_H__.
+ (struct zipentry): added `flags'.
+
+ * shift.c: new file.
+
+ * shift.h: new file.
+
+ * zipfile.h
+ (CEN_FLAGS): new constant.
+
2004-07-05 Kelley Cook <kcook@gcc.gnu.org>
* Makefile.am: Silence two automake warnings.
diff --git a/fastjar/Makefile.am b/fastjar/Makefile.am
index 3efd12eb51c..3358e47ef60 100644
--- a/fastjar/Makefile.am
+++ b/fastjar/Makefile.am
@@ -46,10 +46,11 @@ AM_CPPFLAGS = -I. -I$(top_srcdir) $(ZINCS) -I$(top_srcdir)/../include
LIBIBERTY = ../libiberty/libiberty.a
bin_PROGRAMS = jar grepjar
-jar_SOURCES = jartool.c dostime.c compress.c pushback.c jartool.h \
-zipfile.h dostime.h compress.h pushback.h
+jar_SOURCES = jartool.c dostime.c compress.c pushback.c shift.c jartool.h \
+zipfile.h dostime.h compress.h pushback.h shift.h
jar_LDADD = $(ZLIBS) $(LIBIBERTY)
jar_DEPENDENCIES = $(ZDEPS) $(LIBIBERTY)
+jar_CPPFLAGS = -DWITH_SHIFT_DOWN
grepjar_SOURCES = jargrep.c dostime.c compress.c pushback.c jartool.h \
zipfile.h dostime.h compress.h pushback.h
diff --git a/fastjar/Makefile.in b/fastjar/Makefile.in
index 0d81acee770..b0fc08389be 100644
--- a/fastjar/Makefile.in
+++ b/fastjar/Makefile.in
@@ -41,11 +41,11 @@ POST_UNINSTALL = :
bin_PROGRAMS = jar$(EXEEXT) grepjar$(EXEEXT)
subdir = .
DIST_COMMON = README $(am__configure_deps) $(fastjar_TEXINFOS) \
- $(srcdir)/../install-sh $(srcdir)/../missing \
- $(srcdir)/../mkinstalldirs $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in $(srcdir)/config.h.in \
- $(srcdir)/install-defs.sh.in $(top_srcdir)/configure AUTHORS \
- COPYING ChangeLog INSTALL NEWS
+ $(srcdir)/../compile $(srcdir)/../install-sh \
+ $(srcdir)/../missing $(srcdir)/../mkinstalldirs \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/install-defs.sh.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/../config/accross.m4 $(top_srcdir)/configure.ac
@@ -64,8 +64,9 @@ am_grepjar_OBJECTS = jargrep.$(OBJEXT) dostime.$(OBJEXT) \
grepjar_OBJECTS = $(am_grepjar_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = ../libiberty/libiberty.a
-am_jar_OBJECTS = jartool.$(OBJEXT) dostime.$(OBJEXT) \
- compress.$(OBJEXT) pushback.$(OBJEXT)
+am_jar_OBJECTS = jar-jartool.$(OBJEXT) jar-dostime.$(OBJEXT) \
+ jar-compress.$(OBJEXT) jar-pushback.$(OBJEXT) \
+ jar-shift.$(OBJEXT)
jar_OBJECTS = $(am_jar_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
depcomp =
@@ -129,7 +130,6 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
GENINSRC_FALSE = @GENINSRC_FALSE@
GENINSRC_TRUE = @GENINSRC_TRUE@
-GREP = @GREP@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -229,11 +229,12 @@ AM_MAKEFLAGS = \
AM_CPPFLAGS = -I. -I$(top_srcdir) $(ZINCS) -I$(top_srcdir)/../include
LIBIBERTY = ../libiberty/libiberty.a
-jar_SOURCES = jartool.c dostime.c compress.c pushback.c jartool.h \
-zipfile.h dostime.h compress.h pushback.h
+jar_SOURCES = jartool.c dostime.c compress.c pushback.c shift.c jartool.h \
+zipfile.h dostime.h compress.h pushback.h shift.h
jar_LDADD = $(ZLIBS) $(LIBIBERTY)
jar_DEPENDENCIES = $(ZDEPS) $(LIBIBERTY)
+jar_CPPFLAGS = -DWITH_SHIFT_DOWN
grepjar_SOURCES = jargrep.c dostime.c compress.c pushback.c jartool.h \
zipfile.h dostime.h compress.h pushback.h
@@ -362,6 +363,36 @@ distclean-compile:
.c.obj:
$(COMPILE) -c `$(CYGPATH_W) '$<'`
+jar-jartool.o: jartool.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-jartool.o `test -f 'jartool.c' || echo '$(srcdir)/'`jartool.c
+
+jar-jartool.obj: jartool.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-jartool.obj `if test -f 'jartool.c'; then $(CYGPATH_W) 'jartool.c'; else $(CYGPATH_W) '$(srcdir)/jartool.c'; fi`
+
+jar-dostime.o: dostime.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-dostime.o `test -f 'dostime.c' || echo '$(srcdir)/'`dostime.c
+
+jar-dostime.obj: dostime.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-dostime.obj `if test -f 'dostime.c'; then $(CYGPATH_W) 'dostime.c'; else $(CYGPATH_W) '$(srcdir)/dostime.c'; fi`
+
+jar-compress.o: compress.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-compress.o `test -f 'compress.c' || echo '$(srcdir)/'`compress.c
+
+jar-compress.obj: compress.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-compress.obj `if test -f 'compress.c'; then $(CYGPATH_W) 'compress.c'; else $(CYGPATH_W) '$(srcdir)/compress.c'; fi`
+
+jar-pushback.o: pushback.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-pushback.o `test -f 'pushback.c' || echo '$(srcdir)/'`pushback.c
+
+jar-pushback.obj: pushback.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-pushback.obj `if test -f 'pushback.c'; then $(CYGPATH_W) 'pushback.c'; else $(CYGPATH_W) '$(srcdir)/pushback.c'; fi`
+
+jar-shift.o: shift.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-shift.o `test -f 'shift.c' || echo '$(srcdir)/'`shift.c
+
+jar-shift.obj: shift.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jar_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jar-shift.obj `if test -f 'shift.c'; then $(CYGPATH_W) 'shift.c'; else $(CYGPATH_W) '$(srcdir)/shift.c'; fi`
+
.texi.info:
restore=: && \
backupdir="$(am__leading_dot)am$$$$" && \
diff --git a/fastjar/compress.c b/fastjar/compress.c
index fa7bc2ed3f1..ec1d5c4b7ab 100644
--- a/fastjar/compress.c
+++ b/fastjar/compress.c
@@ -74,6 +74,7 @@
/*
compress.c - code for handling deflation
Copyright (C) 1999 Bryan Burns
+ Copyright (C) 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -109,8 +110,12 @@
#include "jartool.h"
#include "pushback.h"
#include "compress.h"
+#include "shift.h"
+
+int write_data (int, void *, size_t, struct zipentry *);
extern int seekable;
+extern off_t end_of_entries;
static z_stream zs;
@@ -133,7 +138,36 @@ void init_compression(){
}
}
-int compress_file(int in_fd, int out_fd, struct zipentry *ze){
+int
+write_data (int fd, void *buf, size_t len, struct zipentry *ze)
+{
+#ifdef WITH_SHIFT_DOWN
+ struct zipentry *next = NULL;
+ off_t here = lseek (fd, 0, SEEK_CUR);
+ /*
+ * If we are updating and there is not enough space before the next
+ * entry, expand the file.
+ */
+ if (ze)
+ {
+ next = ze->next_entry;
+ if (next && here + len >= next->offset)
+ {
+ if (shift_down (fd, next->offset, (here + len) - next->offset, next))
+ {
+ perror ("can't expand file");
+ exit (1);
+ }
+ }
+ }
+#endif /* WITH_SHIFT_DOWN */
+
+ return write (fd, buf, len);
+}
+
+int compress_file(int in_fd, int out_fd, struct zipentry *ze,
+ struct zipentry *existing)
+{
Bytef in_buff[RDSZ];
Bytef out_buff[RDSZ];
unsigned int rdamt, wramt;
@@ -183,10 +217,11 @@ int compress_file(int in_fd, int out_fd, struct zipentry *ze){
/* If the output buffer is full, dump it to disk */
if(zs.avail_out == 0){
- if(write(out_fd, out_buff, RDSZ) != RDSZ){
- perror("write");
- exit(1);
- }
+ if (write_data (out_fd, out_buff, RDSZ, existing) != RDSZ)
+ {
+ perror("write");
+ exit(1);
+ }
/* clear the output buffer */
zs.next_out = out_buff;
@@ -201,10 +236,11 @@ int compress_file(int in_fd, int out_fd, struct zipentry *ze){
wramt = RDSZ - zs.avail_out;
- if(write(out_fd, out_buff, wramt) != (int)wramt){
- perror("write");
- exit(1);
- }
+ if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
+ {
+ perror("write");
+ exit(1);
+ }
/* clear the output buffer */
zs.next_out = out_buff;
zs.avail_out = (uInt)RDSZ;
@@ -215,10 +251,11 @@ int compress_file(int in_fd, int out_fd, struct zipentry *ze){
while(deflate(&zs, Z_FINISH) == Z_OK){
wramt = RDSZ - zs.avail_out;
- if(write(out_fd, out_buff, wramt) != (int)wramt){
- perror("write");
- exit(1);
- }
+ if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
+ {
+ perror("write");
+ exit(1);
+ }
zs.next_out = out_buff;
zs.avail_out = (uInt)RDSZ;
@@ -228,10 +265,11 @@ int compress_file(int in_fd, int out_fd, struct zipentry *ze){
if(zs.avail_out != RDSZ){
wramt = RDSZ - zs.avail_out;
- if(write(out_fd, out_buff, wramt) != (int)wramt){
- perror("write");
- exit(1);
- }
+ if (write_data (out_fd, out_buff, wramt, existing) != (int)wramt)
+ {
+ perror("write");
+ exit(1);
+ }
}
/* update fastjar's entry information */
diff --git a/fastjar/compress.h b/fastjar/compress.h
index 9b3341e5ae9..9e98034817b 100644
--- a/fastjar/compress.h
+++ b/fastjar/compress.h
@@ -46,7 +46,7 @@
void init_compression(void);
/* Compresses the file specified by in_fd and appends it to out_fd */
-int compress_file(int in_fd, int out_fd, struct zipentry *ze);
+int compress_file(int, int, struct zipentry *, struct zipentry *);
/* Frees memory used by compression function */
void end_compression(void);
diff --git a/fastjar/fastjar.texi b/fastjar/fastjar.texi
index e033da8b400..e07b37a8ce4 100644
--- a/fastjar/fastjar.texi
+++ b/fastjar/fastjar.texi
@@ -125,8 +125,7 @@ List table of contents for archive.
Extract named (or all) files from archive.
@item -u
-Update existing archive. This option is disabled due to bugs (currently
-fails with exit status 1 and does nothing).
+Update existing archive.
@end table
diff --git a/fastjar/jartool.c b/fastjar/jartool.c
index 59e71767f8d..b4b66744e0c 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 Free Software Foundation
Copyright (C) 1999, 2000, 2001 Bryan Burns
This program is free software; you can redistribute it and/or
@@ -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,15 +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*);
-int add_to_jar_with_dir(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 inline struct zipentry *find_entry (const char *);
+static inline int looks_like_dir (const char *);
/* global variables */
ub1 file_header[30];
@@ -305,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)
@@ -340,6 +350,8 @@ int main(int argc, char **argv){
int new_argc;
char **new_argv;
+ progname = argv[0];
+
do_compress = TRUE;
verbose = FALSE;
@@ -418,15 +430,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)
@@ -435,7 +443,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]);
}
@@ -445,8 +454,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);
}
@@ -470,8 +479,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);
}
@@ -484,28 +493,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 ())){
@@ -514,17 +546,19 @@ int main(int argc, char **argv){
const char *dir_to_change = get_next_arg ();
const char *file_to_add = get_next_arg ();
if (!dir_to_change || !file_to_add) {
- fprintf(stderr, "Error: missing argument for -C.\n");
- exit(1);
- }
- if (add_to_jar_with_dir(jarfd, dir_to_change, file_to_add)) {
- fprintf(stderr,
- "Error adding %s (in directory %s) to jar archive!\n",
- file_to_add, dir_to_change);
+ 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, arg)){
+ if(add_to_jar(jarfd, arg, action == ACTION_UPDATE)){
fprintf(stderr, "Error adding %s to jar archive!\n", arg);
exit(1);
}
@@ -533,11 +567,20 @@ 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");
+
+ /* Check if the file shrunk when we updated it. */
+ if (action == ACTION_UPDATE)
+ ftruncate (jarfd, lseek (jarfd, 0, SEEK_CUR));
+
+ 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);
@@ -688,7 +731,175 @@ void add_entry(struct zipentry *ze){
number_of_entries++;
}
-int make_manifest(int jfd, const char *mf_name){
+static inline 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 inline 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 */
@@ -812,7 +1023,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);
}
@@ -823,9 +1034,16 @@ int make_manifest(int jfd, const char *mf_name){
}
/* Implements -C by wrapping add_to_jar. new_dir is the directory
- to switch to. */
+ 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)
+add_to_jar_with_dir (int fd, const char* new_dir, const char* file,
+ const int updating)
{
int retval;
char old_dir[MAXPATHLEN];
@@ -837,7 +1055,7 @@ add_to_jar_with_dir (int fd, const char* new_dir, const char* file)
perror(new_dir);
return 1;
}
- retval=add_to_jar(fd, file);
+ retval=add_to_jar(fd, file, updating);
if (chdir(old_dir) == -1) {
perror(old_dir);
return 1;
@@ -846,11 +1064,13 @@ add_to_jar_with_dir (int fd, const char* new_dir, const char* file)
}
int
-add_to_jar (int fd, const char *file) {
+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;
/* This is a quick compatibility fix -- Simon Weijgers <simon@weijgers.com>
@@ -917,9 +1137,6 @@ add_to_jar (int fd, 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");
@@ -936,10 +1153,36 @@ add_to_jar (int fd, 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;
+ }
+ }
+
+ if (!existing)
+ {
+ add_entry (ze);
+ write (fd, file_header, 30);
+ write (fd, fullname, nlen);
+ end_of_entries = lseek (fd, 0, SEEK_CUR);
- write(fd, file_header, 30);
- write(fd, fullname, nlen);
+ 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] == '.')
@@ -953,7 +1196,7 @@ add_to_jar (int fd, const char *file) {
strcpy(t_ptr, de->d_name);
- if (add_to_jar(fd, fullname)) {
+ if (add_to_jar(fd, fullname, updating)) {
fprintf(stderr, "Error adding file to jar!\n");
return 1;
}
@@ -971,7 +1214,7 @@ add_to_jar (int fd, const char *file) {
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;
}
@@ -982,8 +1225,9 @@ add_to_jar (int fd, const char *file) {
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];
@@ -991,6 +1235,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);
@@ -1045,13 +1301,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);
@@ -1061,14 +1333,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);
@@ -1112,12 +1401,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",
@@ -1890,7 +2209,7 @@ void version ()
{
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");
diff --git a/fastjar/jartool.h b/fastjar/jartool.h
index e0aed6523b4..11f0c889c14 100644
--- a/fastjar/jartool.h
+++ b/fastjar/jartool.h
@@ -52,6 +52,10 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#ifndef __FASTJAR_JARTOOL_H__
+#define __FASTJAR_JARTOOL_H__
+
+#include <sys/types.h>
#include "config.h"
#define ACTION_NONE 0
@@ -104,9 +108,12 @@ struct zipentry {
ub4 usize;
ub4 offset;
ub1 compressed;
+ ub2 flags;
char *filename;
struct zipentry *next_entry;
};
typedef struct zipentry zipentry;
+
+#endif /* __FASTJAR_JARTOOL_H__ */
diff --git a/fastjar/shift.c b/fastjar/shift.c
new file mode 100644
index 00000000000..dde90358719
--- /dev/null
+++ b/fastjar/shift.c
@@ -0,0 +1,166 @@
+/* shift.c -- utilities to move regions of data in a file.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+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. */
+
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "jartool.h"
+#include "shift.h"
+
+#define BUFFER_SIZE 1024
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ * Shift the contents of a file up by `amount' bytes, starting at `begin'.
+ * The file is not truncated, data from `amount' to `begin - amount' is
+ * overwritten. The current file pointer of `fd' is preserved. Note that
+ * this might be past the new "end" of the file.
+ *
+ * If this function is passed a `struct zipentry', then all `offset'
+ * fields from that entry down the list that are greater than or equal
+ * to `begin' will be decreased by `amount'.
+ *
+ * fd - The file descriptor.
+ * begin - The offset of the first byte that should be shifted.
+ * amount - The number of bytes to shift by.
+ * ze - A pointer into a list of zip entries that should be updated
+ * to reflect the modified offset.
+ */
+int
+shift_up (int fd, off_t begin, off_t amount, struct zipentry *ze)
+{
+ extern off_t end_of_entries;
+ int len, moved = 0;
+ ub1 buffer[BUFFER_SIZE];
+ off_t where, end, save;
+
+ if (amount <= 0)
+ return 0;
+
+ if ((save = lseek (fd, 0, SEEK_CUR)) == -1)
+ return 1;
+ if ((end = lseek (fd, 0, SEEK_END)) == -1)
+ return 1;
+ if (end < begin)
+ return 0;
+
+ where = begin;
+
+ do
+ {
+ if (lseek (fd, where, SEEK_SET) < 0)
+ return 1;
+ if ((len = read (fd, buffer, BUFFER_SIZE)) < 0)
+ return 1;
+ if (len == 0)
+ break;
+ if (lseek (fd, where - amount, SEEK_SET) < 0)
+ return 1;
+ if (write (fd, buffer, len) < 0)
+ return 1;
+ where += len;
+ }
+ while (where < end);
+
+ for (; ze; ze = ze->next_entry)
+ {
+ if (ze->offset >= begin)
+ {
+ ze->offset -= amount;
+ moved = 1;
+ }
+ }
+ if (moved)
+ end_of_entries -= amount;
+
+ if (lseek (fd, save, SEEK_SET) == -1)
+ return 1;
+ return 0;
+}
+
+/*
+ * Shift the contents of this file down by `amount' bytes, extending the
+ * end of file, starting at `begin'. This function will preserve the
+ * current file pointer of `fd'. Naturally, this function will fail if
+ * `fd' is not seekable.
+ *
+ * If this function is passed a `struct zipentry', then all `offset'
+ * fields from that entry down the list that are greater than or equal
+ * to `begin' will be increased by `amount'.
+ *
+ * fd - The file descriptor.
+ * begin - The offset of the first byte that should be shifted.
+ * amount - The number of bytes to shift by.
+ * ze - A pointer into a list of zip entries that should be updated
+ * to reflect the modified offset.
+ */
+int
+shift_down (int fd, off_t begin, off_t amount, struct zipentry *ze)
+{
+ extern off_t end_of_entries;
+ int off, len, moved = 0;
+ ub1 buffer[BUFFER_SIZE];
+ off_t where, save;
+
+ if (amount <= 0)
+ return 0;
+
+ if ((save = lseek (fd, 0, SEEK_CUR)) == -1)
+ return 1;
+ if ((where = lseek (fd, 0, SEEK_END)) == -1)
+ return 1;
+ if (where < begin)
+ return 0;
+ off = (where - begin) % BUFFER_SIZE;
+ if (off == 0)
+ where -= BUFFER_SIZE;
+ else
+ where -= off;
+
+ do
+ {
+ if (lseek (fd, where, SEEK_SET) < 0)
+ return 1;
+ if ((len = read (fd, buffer, BUFFER_SIZE)) < 0)
+ return 1;
+ if (lseek (fd, where + amount, SEEK_SET) < 0)
+ return 1;
+ if (write (fd, buffer, len) < 0)
+ return 1;
+ where -= BUFFER_SIZE;
+ }
+ while (where >= begin);
+
+ for (; ze; ze = ze->next_entry)
+ {
+ if (ze->offset >= begin)
+ {
+ ze->offset += amount;
+ moved = 1;
+ }
+ }
+ if (moved)
+ end_of_entries += amount;
+
+ if (lseek (fd, save, SEEK_SET) == -1)
+ return 1;
+
+ return 0;
+}
diff --git a/fastjar/shift.h b/fastjar/shift.h
new file mode 100644
index 00000000000..0a792555c79
--- /dev/null
+++ b/fastjar/shift.h
@@ -0,0 +1,29 @@
+/* shift.h -- utilities to move regions of data in a file.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+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. */
+
+
+#ifndef __FASTJAR_SHIFT_H__
+#define __FASTJAR_SHIFT_H__
+
+#include <sys/types.h>
+#include "jartool.h"
+
+int shift_down (int, off_t, off_t, struct zipentry *);
+int shift_up (int, off_t, off_t, struct zipentry *);
+
+#endif /* __FASTJAR_SHIFT_H__ */
diff --git a/fastjar/zipfile.h b/fastjar/zipfile.h
index 7dc9527e707..dc034586bcc 100644
--- a/fastjar/zipfile.h
+++ b/fastjar/zipfile.h
@@ -47,6 +47,7 @@
#define LOC_FNLEN 26 /* filename length */
#define LOC_EFLEN 28 /* extra-field length */
+#define CEN_FLAGS 8
#define CEN_COMP 10 /* compression method */
#define CEN_MODTIME 12
#define CEN_MODDATE 14
OpenPOWER on IntegriCloud