📄 jartool.c
字号:
} } 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); 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] == '.') continue; if(jarfile && !strcmp(de->d_name, jarfile)){ /* we don't want to add ourselves. Believe me */ if(verbose) printf("skipping: %s\n", de->d_name); continue; } strcpy(t_ptr, de->d_name); if (add_to_jar(fd, fullname, updating)) { fprintf(stderr, "Error adding file to jar!\n"); return 1; } } free(fullname); closedir(dir); } else if(S_ISREG(statbuf.st_mode)){ int add_fd; add_fd = open(file, O_RDONLY | O_BINARY); if(add_fd < 0){ fprintf(stderr, "Error opening %s.\n", file); return 1; } if(add_file_to_jar(fd, add_fd, file, &statbuf, updating)){ fprintf(stderr, "Error adding file to jar!\n"); return 1; } } else { fprintf(stderr, "Illegal file specified: %s\n", file); } return 0;}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]; uLong crc = 0; 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); if(!seekable && !do_compress){ crc = crc32(0L, Z_NULL, 0); while((rdamt = read(ffd, rd_buff, RDSZ)) != 0) crc = crc32(crc, rd_buff, rdamt); lseek(ffd, 0, SEEK_SET); } /* data descriptor */ if(!seekable && do_compress){ PACK_UB2(file_header, LOC_EXTRA, 8); } else { PACK_UB2(file_header, LOC_EXTRA, 0); } if(do_compress){ PACK_UB2(file_header, LOC_COMP, 8); } else { PACK_UB2(file_header, LOC_COMP, 0); } PACK_UB4(file_header, LOC_MODTIME, mod_time); PACK_UB2(file_header, LOC_FNLEN, file_name_length); if(!seekable && !do_compress){ PACK_UB4(file_header, LOC_CRC, crc); PACK_UB4(file_header, LOC_USIZE, statbuf->st_size); PACK_UB4(file_header, LOC_CSIZE, statbuf->st_size); } else memset((file_header + LOC_CRC), '\0', 12); /* clear crc/usize/csize */ ze = (zipentry*)malloc(sizeof(zipentry)); if(ze == NULL){ perror("malloc"); exit(1); } memset(ze, 0, sizeof(zipentry)); /* clear all the fields*/ ze->filename = (char*)malloc((file_name_length + 1) * sizeof(char)); strcpy(ze->filename, fname); ze->mod_time = (ub2)(mod_time & 0x0000ffff); ze->mod_date = (ub2)((mod_time & 0xffff0000) >> 16); if(!seekable && !do_compress) ze->crc = crc; ze->csize = statbuf->st_size; ze->usize = ze->csize; 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; 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); /* write the file name to the zip file */ write(jfd, fname, file_name_length); if(verbose){ if (existing) printf ("updating: %s ", fname); else printf("adding: %s ", fname); fflush(stdout); } if(do_compress){ /* compress the file */ 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); while((rdamt = read(ffd, rd_buff, RDSZ)) != 0){ ze->crc = crc32(ze->crc, rd_buff, rdamt); if(write(jfd, rd_buff, rdamt) != rdamt){ perror("write"); return 0; } } } close(ffd); /* write out data descriptor */ PACK_UB4(data_descriptor, 4, ze->crc); PACK_UB4(data_descriptor, 8, ze->csize); PACK_UB4(data_descriptor, 12, ze->usize); /* we need to seek back and fill the header */ if(seekable){ offset = (ze->csize + strlen(ze->filename) + 16); if(lseek(jfd, -offset, SEEK_CUR) == (off_t)-1){ perror("lseek"); exit(1); } if(write(jfd, (data_descriptor + 4), 12) != 12){ perror("write"); return 0; } offset -= 12; if(lseek(jfd, offset, SEEK_CUR) == (off_t)-1){ perror("lseek"); exit(1); } } else if(do_compress){ /* 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", (int)ze->usize, (int)ze->csize, (do_compress ? "deflated" : "stored"), (do_compress ? ((int)((1 - ze->csize/(float)ze->usize) * 100)) : 0)); return 0;}int create_central_header(int fd){ ub1 header[46]; ub1 end_header[22]; int start_offset; int dir_size; int total_in = 0, total_out = 22; zipentry *ze; /* magic number */ header[0] = 'P'; header[1] = 'K'; header[2] = 1; header[3] = 2; /* version made by */ header[4] = 10; header[5] = 0; /* version needed to extract */ header[6] = 10; header[7] = 0; /* bit flag */ header[8] = 0; header[9] = 0; /* compression method */ header[10] = 0; header[11] = 0; /* file mod time */ header[12] = 0; header[13] = 0; /* file mod date */ header[14] = 0; header[15] = 0; /* crc 32 */ header[16] = 0; header[17] = 0; header[18] = 0; header[19] = 0; /* compressed size */ header[20] = 0; header[21] = 0; header[22] = 0; header[23] = 0; /* uncompressed size */ header[24] = 0; header[25] = 0; header[26] = 0; header[27] = 0; /* filename length */ header[28] = 0; header[29] = 0; /* extra field length */ header[30] = 0; header[31] = 0; /* file comment length */ header[32] = 0; header[33] = 0; /* disk number start */ header[34] = 0; header[35] = 0; /* internal file attribs */ header[36] = 0; header[37] = 0; /* external file attribs */ header[38] = 0; header[39] = 0; header[40] = 0; header[41] = 0; /* relative offset of local header */ header[42] = 0; header[43] = 0; header[44] = 0; header[45] = 0; start_offset = lseek(fd, 0, SEEK_CUR); for(ze = ziptail; ze != NULL; ze = ze->next_entry){ total_in += ze->usize; total_out += ze->csize + 76 + strlen(ze->filename) * 2; if(ze->compressed){ PACK_UB2(header, CEN_COMP, 8); } else { PACK_UB2(header, CEN_COMP, 0); } PACK_UB2(header, CEN_MODTIME, ze->mod_time); PACK_UB2(header, CEN_MODDATE, ze->mod_date); PACK_UB4(header, CEN_CRC, ze->crc); PACK_UB4(header, CEN_CSIZE, ze->csize); PACK_UB4(header, CEN_USIZE, ze->usize); PACK_UB2(header, CEN_FNLEN, strlen(ze->filename)); PACK_UB4(header, CEN_OFFSET, ze->offset); write(fd, header, 46); write(fd, ze->filename, strlen(ze->filename)); } dir_size = lseek(fd, 0, SEEK_CUR) - start_offset; /* magic number */ end_header[0] = 0x50; end_header[1] = 0x4b; end_header[2] = 0x05; end_header[3] = 0x06; /* number of this disk */ end_header[4] = 0; end_header[5] = 0; /* number of disk w/ start of central header */ end_header[6] = 0; end_header[7] = 0; /* total number of entries in central dir on this disk*/ PACK_UB2(end_header, 8, number_of_entries); /* total number of entries in central dir*/ PACK_UB2(end_header, 10, number_of_entries); /* size of central dir. */ PACK_UB4(end_header, 12, dir_size); /* offset of start of central dir */ PACK_UB4(end_header, 16, start_offset); /* zipfile comment length */ end_header[20] = 0; end_header[21] = 0; write(fd, end_header, 22); if(verbose) printf("Total:\n------\n(in = %d) (out = %d) (%s %d%%)\n", total_in, total_out, (do_compress ? "deflated" : "stored"), (int)((1 - (total_out / (float)total_in)) * 100) ); return 0;}int extract_jar(int fd, char **files, int file_num){ int rdamt; int out_a, in_a; ub4 signature; ub4 csize; ub4 crc; ub2 fnlen; ub2 eflen; ub2 flags; ub2 method; ub1 *filename = NULL; int filename_len = 0; ub4 rd_buff[RDSZ]; pb_file pbf; ub1 scratch[16]; zipentry ze; int f_fd; int dir; int handle; int j; init_inflation(); pb_init(&pbf, fd); for(;;){ f_fd = 0; crc = 0; ze.crc = 0; dir = FALSE; /* by default, the file isn't a dir */ handle = TRUE; /* by default we'll extract/create the file */ 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){ printf("Ick! %#x\n", signature); 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 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 + 1){ 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], (const char *)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(strchr((const char *)filename, '/') != NULL && handle){ /* Loop through all the directories in the path, (everything w/ a '/') */ const ub1 *start = filename; char *tmp_buff; struct stat sbuf; tmp_buff = malloc(sizeof(char) * strlen((const char *)filename)); for(;;){ const ub1 *idx = (const unsigned char *)strchr((const char *)start, '/'); if(idx == NULL) break; else if(idx == start){ start++; continue; } start = idx + 1; strncpy(tmp_buff, (const char *)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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -