📄 jartool.c
字号:
}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((const char *)start) == 0) dir = TRUE;#ifdef DEBUG printf("Leftovers are \"%s\" (%d)\n", start, strlen((const char *)start));#endif /* If the entry was just a directory, don't write to file, etc */ if(strlen((const char *)start) == 0) f_fd = -1; free(tmp_buff); } if(f_fd != -1 && handle){ 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"); perror((const char *)filename); exit(1); } } if(method != 8 && flags & 0x0008){ fprintf(stderr, "Error in JAR file! (not compressed but data desc.)\n"); exit(1); } if (eflen > 0) consume(&pbf, eflen); if(method == 8 || flags & 0x0008){ 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 < (int)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 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){ 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[31]; 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); }#ifdef WORDS_BIGENDIAN tmp = L2BI(tmp);#endif 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); }#ifdef WORDS_BIGENDIAN cen_size = L2BS(cen_size);#endif /* 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); }#ifdef WORDS_BIGENDIAN tmp = L2BI(tmp);#endif /* printf("Central header offset = %d\n", tmp); */ if(lseek(fd, tmp, SEEK_SET) != (int)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); ascii_date[30] = '\0'; } if(filename_len < fnlen + 1){ 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], (const char *)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(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(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 + 1){ if(filename != NULL) free(filename); filename = malloc(sizeof(ub1) * (fnlen + 1)); ascii_date[30] = '\0'; 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 %ld bytes\n", (long)size);#endif consume(&pbf, size); } /* print out the listing */ if(file_num > 0){ for(j = 0; j < file_num; j++) if(strcmp(files[j], (const char *)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 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 printf("got %d bytes\n", rdamt);#endif tc += rdamt; }#ifdef DEBUG printf("%d bytes consumed\n", amt);#endif return 0;}void usage(const char *filename){ 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, 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"); exit (0);}void help(const char *filename){ printf("\Usage: %s {ctxuV}[vfm0ME@] [jar-file] [manifest-file] [-C dir] files ...\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); 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\"); 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\\n\Example 1: to archive two class files into an archive called classes.jar: \n\ jar cvf classes.jar Foo.class Bar.class \n\Example 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\"); 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 voidexpand_options (int *argcp, char ***argvp){ int argc = *argcp; char **argv = *argvp; /* Accept arguments with a leading "-" (eg "-cvf"), but don't do expansion if a long argument (like "--help") is detected. */ if (argc > 1 && argv[1][1] != '-') { char buf[3]; char **new_argv; int new_argc; int args_to_expand; char *p; char **in, **out; buf[0] = '-'; buf[2] = '\0'; args_to_expand = strlen (argv[1]); if (argv[1][0] == '-') --args_to_expand; new_argc = argc - 1 + args_to_expand; new_argv = (char **) malloc (new_argc * sizeof (char *)); in = argv; out = new_argv; *out++ = *in++; p = *in++; if (*p == '-') p++; while (*p != '\0') { 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]); } } ++p; } /* Copy remaining options. */ while (in < argv + argc) *out++ = *in++; *argcp = new_argc; *argvp = new_argv; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -