static int add_file(int argc, char *argv[]) { zip_source_t *zs; zip_uint64_t start = strtoull(argv[2], NULL, 10); zip_int64_t len = strtoll(argv[3], NULL, 10); if (strcmp(argv[1], "/dev/stdin") == 0) { if ((zs=zip_source_filep(za, stdin, start, len)) == NULL) { fprintf(stderr, "can't create zip_source from stdin: %s\n", zip_strerror(za)); return -1; } } else { if ((zs=zip_source_file(za, argv[1], start, len)) == NULL) { fprintf(stderr, "can't create zip_source from file: %s\n", zip_strerror(za)); return -1; } } if (zip_add(za, argv[0], zs) == -1) { zip_source_free(zs); fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za)); return -1; } return 0; }
int main(int argc, char *argv[]) { const char *archive; const char *file; const char *name; zip_t *za; zip_source_t *zs; int err; FILE *fp; prg = argv[0]; if (argc != 3) { fprintf(stderr, "usage: %s archive file\n", prg); return 1; } archive = argv[1]; file = argv[2]; if ((za=zip_open(archive, ZIP_CREATE, &err)) == NULL) { zip_error_t error; zip_error_init_with_code(&error, err); fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, zip_error_strerror(&error)); zip_error_fini(&error); return 1; } if ((fp=fopen(file, "r")) == NULL) { fprintf(stderr, "%s: can't open input file '%s': %s\n", prg, file, strerror(errno)); return 1; } if ((zs=zip_source_filep(za, fp, 0, -1)) == NULL) { fprintf(stderr, "%s: error creating file source for '%s': %s\n", prg, file, zip_strerror(za)); return 1; } if ((name=strrchr(file, '/')) == NULL) name = file; if (zip_add(za, name, zs) == -1) { zip_source_free(zs); fprintf(stderr, "%s: can't add file '%s': %s\n", prg, file, zip_strerror(za)); return 1; } if (zip_close(za) == -1) { fprintf(stderr, "%s: can't close zip archive '%s': %s\n", prg, archive, zip_strerror(za)); return 1; } return 0; }
static int zwr(struct zws *zws, size_t offset) { int err, fd; size_t len; DIR *dir; struct dirent *ent; zip_int64_t z64; struct zip_source *zsrc; FILE *fp; fd = openat(workdirfd, offset ? zws->name : ".", O_DIRECTORY|O_RDONLY); if (fd < 0) { ERROR("opendir %.*s failed in zwr", (int)offset, zws->name); return -1; } dir = fdopendir(fd); if (!dir) { close(fd); ERROR("opendir %.*s failed in zwr", (int)offset, zws->name); return -1; } if (offset != 0) zws->name[offset++] = '/'; ent = readdir(dir); while (ent != NULL) { len = strlen(ent->d_name); if (ent->d_name[0] == '.' && (len == 1 || (ent->d_name[1] == '.' && len == 2))) ; else if (offset + len >= sizeof(zws->name)) { ERROR("name too long in zwr"); errno = ENAMETOOLONG; goto error; } else { memcpy(zws->name + offset, ent->d_name, 1+len); if (!is_valid_filename(ent->d_name)) { ERROR("invalid name %s", zws->name); goto error; } switch (ent->d_type) { case DT_DIR: z64 = zip_dir_add(zws->zip, zws->name, ZIP_FL_ENC_UTF_8); if (z64 < 0) { ERROR("zip_dir_add of %s failed", zws->name); goto error; } err = zwr(zws, offset + len); if (err) goto error; break; case DT_REG: fd = openat(workdirfd, zws->name, O_RDONLY); if (fd < 0) { ERROR("openat of %s failed", zws->name); goto error; } fp = fdopen(fd, "r"); if (fp == NULL) { ERROR("fdopen of %s failed", zws->name); close(fd); goto error; } zsrc = zip_source_filep(zws->zip, fp, 0, 0); if (zsrc == NULL) { ERROR("zip_source_file of %s failed", zws->name); fclose(fp); goto error; } z64 = zip_file_add(zws->zip, zws->name, zsrc, ZIP_FL_ENC_UTF_8); if (z64 < 0) { ERROR("zip_file_add of %s failed", zws->name); zip_source_free(zsrc); goto error; } break; default: break; } } ent = readdir(dir); } closedir(dir); return 0; error: closedir(dir); return -1; }