OSDN Git Service

* config/locale/c_locale_generic.cc: Check errno for ERANGE
[pf3gnuchains/gcc-fork.git] / fastjar / jartool.c
index 5a5f235..dd71592 100644 (file)
@@ -1,6 +1,7 @@
 /*
   jartool.c - main functions for fastjar utility
-  Copyright (C) 1999, 2000  Bryan Burns
+  Copyright (C) 2002 Free Software Foundation
+  Copyright (C) 1999, 2000, 2001  Bryan Burns
   
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
-/* $Id: jartool.c,v 1.2 2000/12/13 18:11:57 tromey Exp $
+/*
+   Revision 1.10  2002/01/03 04:57:56  rodrigc
+   2001-01-02  Craig Rodrigues  <rodrigc@gcc.gnu.org>
+
+           PR bootstrap/5117
+           * configure.in (AC_CHECK_HEADERS): Check for stdlib.h.
+           * Makefile.am: Move grepjar to bin_PROGRAMS.
+           * config.h.in: Regenerated.
+           * Makefile.in: Regenerated.
+           * aclocal.m4: Regenerated.
+           * jargrep.c: Eliminate some signed/unsigned and default
+           uninitialized warnings. Use HAVE_STDLIB_H instead of
+           STDC_HEADERS macro.
+           * jartool.c: Likewise.
+           * compress.c: Likewise.
+
+   Revision 1.9  2001/10/12 00:49:42  bryce
+           * jatool.c (extract_jar): Account for null termination when
+       determining whether to expand "filename".
+
+   Revision 1.8  2001/08/29 01:35:31  apbianco
+   2001-08-28  Alexandre Petit-Bianco  <apbianco@redhat.com>
+
+       * jartool.c (add_to_jar): Return 1 if `stat' initialy failed.
+       Fixes PR java/3949.
+
+   (http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01641.html)
+
+   Revision 1.7  2001/08/27 23:09:37  tromey
+       * jartool.c (jarfile): Remove length limitation.
+       (main): Use jt_strdup when initializing jarfile.
+
+   Revision 1.6  2001/07/04 18:33:53  tromey
+       Modified from patch by Julian Hall <jules@acris.co.uk>:
+       * jartool.c (errno): Conditionally declare.
+       (O_BINARY): Conditionally define.
+       (main): Use open, not creat.  Use O_BINARY everywhere.
+       (make_manifest): Use O_BINARY.
+       (add_to_jar): Likewise.
+
+   Revision 1.5  2001/05/03 21:40:47  danglin
+       * jartool.c (jt_strdup): New function.
+       (get_next_arg): Use jt_strdup instead of strdup.
+
+   Revision 1.4  2000/12/28 21:47:37  robertl
+   2000-12-28  Robert Lipe <robertl@sco.com>
+
+           * jartool.c (MAXPATHLEN): Provide if not defined.
+
+   Revision 1.3  2000/12/14 18:45:35  ghazi
+   Warning fixes:
+
+       * compress.c: Include stdlib.h and compress.h.
+       (rcsid): Delete.
+       (report_str_error): Make static.
+       (ez_inflate_str): Delete unused variable.  Add parens in if-stmt.
+       (hrd_inflate_str): Likewise.
+
+       * compress.h (init_compression, end_compression, init_inflation,
+       end_inflation): Prototype void arguments.
+
+       * dostime.c (rcsid): Delete.
+
+       * jargrep.c: Include ctype.h, stdlib.h, zlib.h and compress.h.
+       Make functions static.  Cast ctype function argument to `unsigned
+       char'.  Add parens in if-stmts.  Constify.
+       (Usage): Change into a macro.
+       (jargrep): Remove unused parameter.
+
+       * jartool.c: Constify.  Add parens in if-stmts.  Align
+       signed/unsigned char pointers in functions calls using casts.
+       (rcsid): Delete.
+       (list_jar): Fix printf format specifier.
+       (usage): Chop long string into bits.  Reformat.
+
+       * pushback.c (rcsid): Delete.
 
-   $Log: jartool.c,v $
    Revision 1.2  2000/12/13 18:11:57  tromey
        * jartool.c (extract_jar): Use strchr, not index.
 
 
 #include <zlib.h>
 
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
 
 #ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
-#else
+#endif
+
+#ifndef MAXPATHLEN
 #define MAXPATHLEN 1024
 #endif
 
 #include <time.h>
 #endif
 
+#include <getopt.h>
+
 #include "jartool.h"
 #include "zipfile.h"
 #include "dostime.h"
 
 #endif
 
-static char version_string[] = VERSION;
-
+#ifndef errno
 extern int errno;
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
 
 void usage(const char*);
+void help(const char *);
+void version(void);
 void add_entry(struct zipentry *);
 void init_headers(void);
 
@@ -188,6 +273,8 @@ int create_central_header(int);
 int make_manifest(int, const char*);
 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);
 
 /* global variables */
 ub1 file_header[30];
@@ -195,7 +282,7 @@ ub1 data_descriptor[16];
 int do_compress;
 int seekable;
 int verbose;
-char jarfile[256];
+char *jarfile;
 
 /* If non zero, then don't recurse in directory. Instead, add the
    directory entry and relie on an explicit list of files to populate
@@ -211,19 +298,37 @@ zipentry *ziptail; /* tail of the linked list */
 
 int number_of_entries; /* number of entries in the linked list */
 
+/* This is used to mark options with no short value.  */
+#define LONG_OPT(Num)  ((Num) + 128)
+
+#define OPT_HELP     LONG_OPT (0)
+
+/* This holds all options except `-C', which is handled specially.  */
+#define OPTION_STRING "-ctxuvVf:m:0ME@"
+
+static const struct option options[] =
+{
+  { "help", no_argument, NULL, OPT_HELP },
+  { "version", no_argument, NULL, 'V' },
+  { NULL, no_argument, NULL, 0 }
+};
+
 int main(int argc, char **argv){
 
-  char mfile[256];
+  char *mfile = NULL;
   
   int action = ACTION_NONE;
   int manifest = TRUE;
-  int manifest_file = FALSE;
-  int file = FALSE;
-  int file_first = FALSE;
+  int opt;
   
-  int i, j;
+  int j;
   int jarfd = -1;
   
+  /* These are used to collect file names and `-C' options for the
+     second pass through the command line.  */
+  int new_argc;
+  char **new_argv;
+
   do_compress = TRUE;
   verbose = FALSE;
   
@@ -236,8 +341,18 @@ int main(int argc, char **argv){
   
   j = strlen(argv[1]);
   
-  for(i = 0; i < j; i++){
-    switch(argv[1][i]){
+  new_argc = 0;
+  new_argv = (char **) malloc (argc * sizeof (char *));
+
+  expand_options (&argc, &argv);
+  while ((opt = getopt_long (argc, argv, OPTION_STRING,
+                            options, NULL)) != -1) {
+    switch(opt){
+    case 1:
+      /* File name or unparsed option, due to RETURN_IN_ORDER.  In
+        particular `-C' is handled here and not elsewhere.  */
+      new_argv[new_argc++] = optarg;
+      break;
     case 'c':
       action = ACTION_CREATE;
       break;
@@ -254,17 +369,13 @@ int main(int argc, char **argv){
       verbose = TRUE;
       break;
     case 'V':
-      printf("%s\n", version_string);
+      version();
       exit(0);
     case 'f':
-      file = TRUE;
-      if(!manifest_file)
-        file_first = TRUE;
-      else
-        file_first = FALSE;
+      jarfile = optarg;
       break;
     case 'm':
-      manifest_file = TRUE;
+      mfile = optarg;
       break;
     case '0':
       do_compress = FALSE;
@@ -272,8 +383,11 @@ int main(int argc, char **argv){
     case 'M':
       manifest = FALSE;
       break;
-    case '-':
+
+    case OPT_HELP:
+      help(argv[0]);
       break;
+
     /* The following options aren't supported by the original jar tool. */
     case 'E':
       use_explicit_list_only = TRUE;
@@ -282,16 +396,25 @@ int main(int argc, char **argv){
       read_names_from_stdin = TRUE;
       break;
     default:
-      fprintf(stderr, "Illegal option: %c\n", argv[1][i]);
       usage(argv[0]);
     }
   }
 
+  /* We might have seen `--'.  In this case we want to make sure that
+     all following options are handled as file names.  */
+  while (optind < argc)
+    new_argv[new_argc++] = argv[optind++];
+
   if(action == ACTION_NONE){
     fprintf(stderr, "One of options -{ctxu} must be specified.\n");
     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)
@@ -304,34 +427,12 @@ int main(int argc, char **argv){
       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(jarfile){
+      jarfd = open(jarfile, O_CREAT | O_BINARY | O_WRONLY | O_TRUNC,
+                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
       if(jarfd < 0){
         fprintf(stderr, "Error opening %s for writing!\n", jarfile);
         perror(jarfile);
@@ -354,8 +455,8 @@ int main(int argc, char **argv){
     }
   } else if(action == ACTION_LIST || action == ACTION_EXTRACT){
 
-    if(file){
-      jarfd = open(jarfile, O_RDONLY);
+    if(jarfile){
+      jarfd = open(jarfile, O_RDONLY | O_BINARY);
 
       if(jarfd < 0){
         fprintf(stderr, "Error opening %s for reading!\n", jarfile);
@@ -376,8 +477,8 @@ int main(int argc, char **argv){
     const char *arg;
     init_headers();
 
-   if((action == ACTION_UPDATE) && file) {
-      if((jarfd = open(jarfile, O_RDWR)) < 0) {
+   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);
@@ -389,12 +490,12 @@ int main(int argc, char **argv){
   
 
     /* Add the META-INF/ directory and the manifest */
-    if(manifest && manifest_file)
+    if(manifest && mfile)
       make_manifest(jarfd, mfile);
     else if(manifest)
       make_manifest(jarfd, NULL);
     
-    init_args (argv, i);
+    init_args (new_argv, new_argc);
     /* now we add the files to the archive */
     while ((arg = get_next_arg ())){
 
@@ -424,9 +525,9 @@ int main(int argc, char **argv){
       fprintf(stderr, "Error closing jar archive!\n");
     }
   } else if(action == ACTION_LIST){
-    list_jar(jarfd, &argv[i], (argc - i));
+    list_jar(jarfd, &new_argv[0], new_argc);
   } else if(action == ACTION_EXTRACT){
-    extract_jar(jarfd, &argv[i], (argc - i));
+    extract_jar(jarfd, &new_argv[0], new_argc);
   }
   
   exit(0);
@@ -501,7 +602,7 @@ get_next_arg ()
       if (pos)
        {
          s [pos] = '\0';
-         return strdup (s);
+         return jt_strdup (s);
        }
       else
        return NULL;
@@ -688,7 +789,7 @@ int make_manifest(int jfd, const char *mf_name){
       exit(1);
     }
   
-    mfd = open(mf_name, O_RDONLY);
+    mfd = open(mf_name, O_RDONLY | O_BINARY);
 
     if(mfd < 0){
       fprintf(stderr, "Error opening %s.\n", mf_name);
@@ -744,6 +845,7 @@ int add_to_jar(int fd, const char *new_dir, const char *file){
   
   if(stat_return == -1){
     perror(file);
+    return 1;
   } else if(S_ISDIR(statbuf.st_mode)){
     char *fullname;
     char *t_ptr;
@@ -834,7 +936,7 @@ int add_to_jar(int fd, const char *new_dir, const char *file){
   } else if(S_ISREG(statbuf.st_mode)){
     int add_fd;
 
-    add_fd = open(file, O_RDONLY);
+    add_fd = open(file, O_RDONLY | O_BINARY);
     if(add_fd < 0){
       fprintf(stderr, "Error opening %s.\n", file);
       return 0;
@@ -1242,7 +1344,7 @@ int extract_jar(int fd, char **files, int file_num){
 #endif
     }
 
-    if(filename_len < fnlen){
+    if(filename_len < fnlen + 1){
       if(filename != NULL)
         free(filename);
       
@@ -1376,7 +1478,7 @@ int extract_jar(int fd, char **files, int file_num){
 
       ze.crc = crc32(ze.crc, NULL, 0); /* initialize the crc */
 
-      while(out_a < csize){
+      while(out_a < (int)csize){
         rdamt = (in_a > RDSZ ? RDSZ : in_a);
         if(pb_read(&pbf, rd_buff, rdamt) != rdamt){
           perror("read");
@@ -1519,7 +1621,7 @@ int list_jar(int fd, char **files, int file_num){
 
     /*   printf("Central header offset = %d\n", tmp); */
 
-    if(lseek(fd, tmp, SEEK_SET) != tmp){
+    if(lseek(fd, tmp, SEEK_SET) != (int)tmp){
       perror("lseek");
       exit(1);
     }
@@ -1758,26 +1860,47 @@ int consume(pb_file *pbf, int amt){
 }
 
 void usage(const char *filename){
-  fprintf(stderr, "\
+  fprintf(stderr, "Try `%s --help' for more information.\n", filename);
+  exit (1);
+}
+
+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("\
+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");
+  exit (0);
+}
+
+void help(const char *filename)
+{
+  printf("\
 Usage: %s {ctxuV}[vfm0ME@] [jar-file] [manifest-file] [-C dir] files ...\n\
-Options\n\
- -c  create new archive\n\
- -t  list table of contents for archive\n\
- -x  extract named (or all) files from archive\n\
+\n\
+Store many files together in a single `jar' file.\n\
+\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\
 ", filename);
-  fprintf(stderr, "\
- -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\n\
- -E  don't include the files found in a directory\n\
- -@  Read names from stdin\n\
+  printf("\n\
+  -@              read names from stdin\n\
+  -0              store only; use no ZIP compression\n\
+  -C DIR FILE     change to the specified directory and include\n\
+                  the following 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\
+  -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\
+  -V, --version   display version information\n\
 ");
-  fprintf(stderr, "\
+  printf("\n\
 If any file is a directory then it is processed recursively.\n\
 The manifest file name and the archive file name needs to be specified\n\
 in the same order the 'm' and 'f' flags are specified.\n\
@@ -1789,5 +1912,72 @@ Example 2: use an existing manifest file 'mymanifest' and archive all the\n\
      jar cvfm classes.jar mymanifest -C foo/ .\n\
 ");
 
-  exit(1);
+  exit(0);
+}
+
+static char *
+jt_strdup(s)
+     char *s;
+{
+  char *result = (char*)malloc(strlen(s) + 1);
+  if (result == (char*)0)
+    return (char*)0;
+  strcpy(result, s);
+  return result;
+}
+
+/* Convert "tar-style" first argument to a form expected by getopt.
+   This idea and the code comes from GNU tar.  This can allocate a new
+   argument vector.  This might leak some memory, but we don't care.  */
+static void
+expand_options (int *argcp, char ***argvp)
+{
+  int argc = *argcp;
+  char **argv = *argvp;
+
+  if (argc > 1 && argv[1][0] != '-')
+    {
+      char buf[3];
+      char **new_argv;
+      int new_argc;
+      char *p;
+      char **in, **out;
+
+      buf[0] = '-';
+      buf[2] = '\0';
+
+      new_argc = argc - 1 + strlen (argv[1]);
+      new_argv = (char **) malloc (new_argc * sizeof (char *));
+      in = argv;
+      out = new_argv;
+
+      *out++ = *in++;
+      for (p = *in++; *p; ++p)
+       {
+         char *opt;
+         buf[1] = *p;
+         *out++ = jt_strdup (buf);
+         /* If the option takes an argument, move the next argument
+            to just after this option.  */
+         opt = strchr (OPTION_STRING, *p);
+         if (opt && opt[1] == ':')
+           {
+             if (in < argv + argc)
+               *out++ = *in++;
+             else
+               {
+                 fprintf(stderr, "%s: option `%s' requires an argument.\n",
+                         argv[0], buf);
+                 usage(argv[0]);
+               }
+           }
+       }
+
+      /* Copy remaining options.  */
+      while (in < argv + argc)
+       *out++ = *in++;
+
+      *argcp = new_argc;
+      *argvp = new_argv;
+    }
 }