int tar_extract_all(TAR *t, char *prefix) { char *filename; char buf[MAXPATHLEN]; int i; #ifdef TAR_DEBUG printf("==> tar_extract_all(TAR *t, \"%s\")\n", (prefix ? prefix : "(null)")); #endif while ((i = th_read(t)) == 0) { #ifdef TAR_DEBUG puts(" tar_extract_all(): calling th_get_pathname()"); #endif filename = th_get_pathname(t); if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); else strlcpy(buf, filename, sizeof(buf)); #ifdef TAR_DEBUG printf(" tar_extract_all(): calling tar_extract_file(t, " "\"%s\")\n", buf); #endif if (tar_extract_file(t, buf) != 0) return -1; } return (i == 1 ? 0 : -1); }
int tar_find(TAR *t, char *searchstr) { if (!searchstr) return 0; char *filename; int i, entryfound = 0; #ifdef DEBUG printf("==> tar_find(0x%lx, %s)\n", (long unsigned int)t, searchstr); #endif while ((i = th_read(t)) == 0) { filename = th_get_pathname(t); if (fnmatch(searchstr, filename, FNM_FILE_NAME | FNM_PERIOD) == 0) { entryfound++; #ifdef DEBUG printf("Found matching entry: %s\n", filename); #endif break; } } #ifdef DEBUG if (!entryfound) printf("No matching entry found.\n"); #endif return entryfound; }
int tar_extract_glob(TAR *t, char *globname, char *prefix) { char *filename; char buf[MAXPATHLEN]; int i; while ((i = th_read(t)) == 0) { filename = th_get_pathname(t); if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD)) { if (TH_ISREG(t) && tar_skip_regfile(t)) return -1; continue; } if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); else strlcpy(buf, filename, sizeof(buf)); if (tar_extract_file(t, filename) != 0) return -1; } return (i == 1 ? 0 : -1); }
static int par_list(char *file) { PAR *t; int i; if (par_open(&t, file, 1, O_RDONLY, 0, 0) == -1) { fprintf(stderr, "tar_open(): %s\n", strerror(errno)); return -1; } if (par_read_header(t) != 0) { fprintf(stderr, "par_read_header(): %s\n", strerror(errno)); par_close(t); return -1; } while ((i = th_read(t)) == 0) { th_print_long_ls(t); #ifdef DEBUG th_print(t); #endif if (TH_ISREG(t) && par_skip_regfile(t) != 0) { fprintf(stderr, "tar_skip_regfile(): %s\n", strerror(errno)); return -1; } } if (par_close(t) != 0) { fprintf(stderr, "tar_close(): %s\n", strerror(errno)); return -1; } return 0; }
static int list(char *tarfile) { TAR *t; int i; if (tar_open(&t, tarfile, #ifdef HAVE_LIBZ (use_zlib ? &gztype : NULL), #else NULL, #endif O_RDONLY, 0, (verbose ? TAR_VERBOSE : 0) | (use_gnu ? TAR_GNU : 0)) == -1) { fprintf(stderr, "tar_open(): %s\n", strerror(errno)); return -1; } while ((i = th_read(t)) == 0) { th_print_long_ls(t); #ifdef DEBUG th_print(t); #endif if (TH_ISREG(t) && tar_skip_regfile(t) != 0) { fprintf(stderr, "tar_skip_regfile(): %s\n", strerror(errno)); return -1; } } #ifdef DEBUG printf("th_read() returned %d\n", i); printf("EOF mark encountered after %ld bytes\n", # ifdef HAVE_LIBZ (use_zlib ? gzseek((gzFile) t->fd, 0, SEEK_CUR) : # endif lseek(t->fd, 0, SEEK_CUR) # ifdef HAVE_LIBZ ) # endif ); #endif if (tar_close(t) != 0) { fprintf(stderr, "tar_close(): %s\n", strerror(errno)); return -1; } (void)i; return 0; }
/* \internal Checks whether a tar file is valid. A valid tar file does not contains files that start with ./ or contain .. This is intended to prevent malicious packages placing binaries outside of the sandbox directory */ bool check_tar_valid( const QString &tarfile ) { TAR *tarHandle = get_tar_ptr( tarfile ); bool ret=true; QString filename; int i; while ( (i = th_read(tarHandle)) == 0) { filename = th_get_pathname( tarHandle ); if ( !filename.startsWith("./") || filename.contains( "..") ) { ret = false; qWarning() << "check_tar_valid:- tar contains invalid file path: " << filename << "\nAll paths must begin with ./ and not contain .." ; break; } else if ( TH_ISBLK(tarHandle) || TH_ISCHR(tarHandle) ) { ret = false; qWarning() << "check_tar_valid:-tar invalid, contains device special file:" << filename; break; } else if ( TH_ISLNK(tarHandle) ) { ret = false; qWarning() << "check_tar_valid:-tar invalid, contains hard link:" << filename; break; } else if (TH_ISSYM(tarHandle) ) { QString target; if ((tarHandle->options & TAR_GNU) && tarHandle->th_buf.gnu_longlink != NULL) target = tarHandle->th_buf.gnu_longlink; else target = tarHandle->th_buf.linkname; if ( target.startsWith("/") || target.contains( "..") ) { ret = false; qWarning() << "check_tar_valid:tar invalid, contains symlink whose target" << (target.startsWith("/")?"is an absolute path.":"references " "a parent directory.") << "Link:" << filename << "Target:" << target; break; } } if( TH_ISREG(tarHandle) ) tar_skip_regfile(tarHandle); } tar_close( tarHandle ); return ret; }
int util_tar_extract(const char *tar_filename, const char* index_file, const char* out_dir) { TAR *tar = NULL; int ret = tar_open(&tar, tar_filename, &gztype, O_RDONLY, 0, TAR_GNU); if (ret != 0) { ERROR_ERRNO("Fail to open tarfile: %s\n", tar_filename); return ret; } //ret = tar_extract_all(tar, tar_prefix); while (th_read(tar) == 0) { char *archive_filename = th_get_pathname(tar); char *out_filename = mem_printf("%s/%s", out_dir, archive_filename); char *mode = mem_alloc0(4*sizeof(char)); int_to_oct(th_get_mode(tar), mode, 4*sizeof(char)); uid_t uid = th_get_uid(tar); gid_t gid = th_get_gid(tar); INFO("Writing file %s to %s", archive_filename, out_filename); if (TH_ISCHR(tar)) { // writing file attributes to index file (TODO use hashmap to handle duplicates) file_printf_append(index_file, "%s c %s %d %d %d %d\n", archive_filename, mode, uid, gid, th_get_devmajor(tar), th_get_devminor(tar)); } else if (TH_ISBLK(tar)) { // writing file attributes to index file (TODO use hashmap to handle duplicates) file_printf_append(index_file, "%s b %s %d %d %d %d\n", archive_filename, mode, uid, gid, th_get_devmajor(tar), th_get_devminor(tar)); } else { if (tar_extract_file(tar, out_filename) != 0) { INFO_ERRNO("Skipping file: %s", archive_filename); } else { // writing file attributes to index file (TODO use hashmap to handle duplicates) file_printf_append(index_file, "%s m %s %d %d\n", archive_filename, mode, uid, gid); } } mem_free(mode); mem_free(archive_filename); mem_free(out_filename); } ret |= tar_close(tar); return ret; }
qlonglong targz_archive_size( const QString &tarfile ) { TAR *tarHandle = get_tar_ptr( tarfile ); qlonglong size = 0; int i; while ((i = th_read(tarHandle)) == 0) { size += th_get_size(tarHandle); if( TH_ISREG(tarHandle) ) tar_skip_regfile(tarHandle); } tar_close( tarHandle ); return size; }
static int sandbox_attr(void *fpctx,void *handle,const char *attr,glite_jp_attrval_t **attrval) { glite_jp_error_t err; glite_jp_context_t ctx = fpctx; glite_jp_attrval_t *out = NULL; int i,nout = 0, count = 0; sb_handle *h = handle; printf("sandbox_attr() called\n"); memset(&err,0,sizeof err); err.source = __FUNCTION__; glite_jp_clear_error(ctx); *attrval = NULL; if (!strcmp(attr, GLITE_JP_ATTR_ISB_FILENAME)) { while ((i = th_read(h->t)) == 0) { printf("-- %s\n", th_get_pathname(h->t)); if ( !(count % ALLOC_CHUNK) ) { *attrval = realloc(*attrval, (count + ALLOC_CHUNK + 1) * sizeof(**attrval) ); memset( (*attrval) + count, 0, (ALLOC_CHUNK + 1) * sizeof(**attrval)); } (*attrval)[count].name = strdup(GLITE_JP_ATTR_ISB_FILENAME); (*attrval)[count].value = strdup(th_get_pathname(h->t)); (*attrval)[count].origin = GLITE_JP_ATTR_ORIG_FILE; (*attrval)[count].timestamp = th_get_mtime(h->t); count++; if (TH_ISREG(h->t) && tar_skip_regfile(h->t) != 0) { err.code = EIO; err.desc = "tar_skip_regfile"; return glite_jp_stack_error(ctx,&err); } } } else if (!strcmp(attr, GLITE_JP_ATTR_OSB_FILENAME)) { printf("Namespace %s not implemented yet\n", GLITE_JP_ATTR_OSB_FILENAME); } else if (strstr(attr,GLITE_JP_OSB_CONTENT_NS)) { printf("Namespace %s not implemented yet\n", GLITE_JP_OSB_CONTENT_NS); } else if (strstr(attr,GLITE_JP_ISB_CONTENT_NS)) { char *fileName = (char *) attr + sizeof(GLITE_JP_ISB_CONTENT_NS); printf("untaring file: %s\n", fileName); while (th_read(h->t) == 0) { if ( !strcmp(fileName, th_get_pathname(h->t)) ) { /* extract the file */ int k; size_t size; char buf[T_BLOCKSIZE]; char *value; if (!TH_ISREG(h->t)) assert(0); // not a regular file size = th_get_size(h->t); value = (char *) malloc(size * sizeof(char) + 1); memset( value, 0, size * sizeof(char) + 1); for (i = 0; i < size; i += T_BLOCKSIZE) { k = tar_block_read(h->t, buf); if (k == -1) { err.code = errno; err.desc = "tar_block_read"; return glite_jp_stack_error(ctx,&err); } // tar_block_read calls glite_jppsbe_pread, which usually // returns whole block (read from the middle of uploaded // tar file // so cut k in order to the last chunk had correct size if (i + T_BLOCKSIZE > size) { k = size - i; } strncpy(value + i, buf, k); } *attrval = malloc(2 * sizeof(**attrval) ); memset( (*attrval), 0, 2 * sizeof(**attrval)); (*attrval)[0].name = strdup(attr); (*attrval)[0].value = value; (*attrval)[0].origin = GLITE_JP_ATTR_ORIG_FILE; (*attrval)[0].timestamp = th_get_mtime(h->t); } else if (TH_ISREG(h->t) && tar_skip_regfile(h->t) != 0) { err.code = EIO; err.desc = "tar_skip_regfile"; return glite_jp_stack_error(ctx,&err); } } } return glite_jp_stack_error(ctx,&err); }