?? jartool.c
字號(hào):
#endif flags = UNPACK_UB2(file_header, LOC_EXTRA);#ifdef DEBUG printf("Flags are %#hx\n", flags);#endif method = UNPACK_UB2(file_header, LOC_COMP);#ifdef DEBUG printf("Compression method is %#hx\n", method);#endif /* if there isn't a data descriptor */ if(!(flags & 0x0008)){ crc = UNPACK_UB4(file_header, LOC_CRC);#ifdef DEBUG printf("CRC is %x\n", crc);#endif } if(filename_len < fnlen){ if(filename != NULL) free(filename); filename = malloc(sizeof(ub1) * (fnlen + 1)); filename_len = fnlen + 1; } pb_read(&pbf, filename, fnlen); filename[fnlen] = '\0';#ifdef DEBUG printf("filename is %s\n", filename);#endif if(file_num > 0){ handle = FALSE; for(j = 0; j < file_num; j++) if(strcmp(files[j], filename) == 0){ handle = TRUE; break; } } if(!handle) f_fd = -1; /* OK, there is some directory information in the file. Nothing to do but ensure the directory(s) exist, and create them if they don't. What a pain! */ if(index(filename, '/') != NULL && handle){ /* Loop through all the directories in the path, (everything w/ a '/') */ ub1 *start = filename; char *tmp_buff; struct stat sbuf; tmp_buff = malloc(sizeof(char) * strlen(filename)); for(;;){ ub1 *idx = index(start, '/'); if(idx == NULL) break; else if(idx == start){ start++; continue; } start = idx + 1; strncpy(tmp_buff, filename, (idx - filename)); tmp_buff[(idx - filename)] = '\0';#ifdef DEBUG printf("checking the existance of %s\n", tmp_buff);#endif if(stat(tmp_buff, &sbuf) < 0){ if(errno != ENOENT){ perror("stat"); exit(1); } } else if(S_ISDIR(sbuf.st_mode)){#ifdef DEBUG printf("Directory exists\n");#endif continue; }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(start) == 0) dir = TRUE;#ifdef DEBUG printf("Leftovers are \"%s\" (%d)\n", start, strlen(start));#endif /* If the entry was just a directory, don't write to file, etc */ if(strlen(start) == 0) f_fd = -1; free(tmp_buff); } if(f_fd != -1 && handle){ f_fd = creat(filename, 00644); if(f_fd < 0){ fprintf(stderr, "Error extracting JAR archive!\n"); perror(filename); exit(1); } } if(method != 8 && flags & 0x0008){ fprintf(stderr, "Error in JAR file! (not compressed but data desc.)\n"); exit(1); } if(method == 8 || flags & 0x0008){ if(seekable) lseek(fd, eflen, SEEK_CUR); else consume(&pbf, eflen); 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 < 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(seekable) lseek(fd, eflen, SEEK_CUR); else consume(&pbf, eflen); } /* 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){ int rdamt; 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[30]; 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); } 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); } /* 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); } /* printf("Central header offset = %d\n", tmp); */ if(lseek(fd, tmp, SEEK_SET) != 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); } if(filename_len < fnlen){ 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], 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((rdamt = 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((rdamt = 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){ if(filename != NULL) free(filename); filename = malloc(sizeof(ub1) * (fnlen + 1)); 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 %d bytes\n", size);#endif consume(&pbf, size); } /* print out the listing */ if(file_num > 0){ for(j = 0; j < file_num; j++) if(strcmp(files[j], 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 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", tc);#endif return 0;}void usage(char *filename){ fprintf(stderr, "Usage: %s {ctxuV}[vfm0M] [jar-file] [manifest-file] [-C dir] files ...\nOptions\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 -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\nIf any file is a directory then it is processed recursively.\nThe manifest file name and the archive file name needs to be specified\nin the same order the 'm' and 'f' flags are specified.\n\nExample 1: to archive two class files into an archive called classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExample 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", filename); exit(1);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -