/* skip regfile */ int tar_skip_regfile(TAR *t) { int i, k; size_t size; char buf[T_BLOCKSIZE]; if (!TH_ISREG(t)) { errno = EINVAL; return -1; } size = th_get_size(t); for (i = size; i > 0; i -= T_BLOCKSIZE) { k = tar_block_read(t, buf); if (k != T_BLOCKSIZE) { if (k != -1) errno = EINVAL; return -1; } } return 0; }
/* add file contents to a tarchive */ int tar_append_regfile(TAR *t, const char *realname) { char block[T_BLOCKSIZE]; int filefd; int i, j; size_t size; int rv = -1; #if defined(O_BINARY) filefd = open(realname, O_RDONLY|O_BINARY); #else filefd = open(realname, O_RDONLY); #endif if (filefd == -1) { #ifdef DEBUG perror("open()"); #endif return -1; } size = th_get_size(t); for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE) { j = read(filefd, &block, T_BLOCKSIZE); if (j != T_BLOCKSIZE) { if (j != -1) errno = EINVAL; goto fail; } if (tar_block_write(t, &block) == -1) goto fail; } if (i > 0) { j = read(filefd, &block, i); if (j == -1) goto fail; memset(&(block[i]), 0, T_BLOCKSIZE - i); if (tar_block_write(t, &block) == -1) goto fail; } /* success! */ rv = 0; fail: close(filefd); return rv; }
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; }
/* add file contents to a tarchive */ int tar_append_regfile(TAR *t, char *realname) { char block[T_BLOCKSIZE]; int filefd; int j; size_t size, i; filefd = open(realname, O_RDONLY); if (filefd == -1) { #ifdef DEBUG perror("open()"); #endif return -1; } size = th_get_size(t); for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE) { j = read(filefd, &block, T_BLOCKSIZE); if (j != T_BLOCKSIZE) { if (j != -1) errno = EINVAL; return -1; } if (tar_block_write(t, &block) == -1) return -1; } if (i > 0) { j = read(filefd, &block, i); if (j == -1) return -1; memset(&(block[i]), 0, T_BLOCKSIZE - i); if (tar_block_write(t, &block) == -1) return -1; } close(filefd); return 0; }
void th_print_long_ls(TAR *t) { char modestring[12]; struct passwd *pw; struct group *gr; uid_t uid; gid_t gid; char username[_POSIX_LOGIN_NAME_MAX]; char groupname[_POSIX_LOGIN_NAME_MAX]; time_t mtime; struct tm *mtm; #ifdef HAVE_STRFTIME char timebuf[18]; #else const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #endif uid = th_get_uid(t); pw = getpwuid(uid); if (pw == NULL) snprintf(username, sizeof(username), "%d", uid); else strlcpy(username, pw->pw_name, sizeof(username)); gid = th_get_gid(t); gr = getgrgid(gid); if (gr == NULL) snprintf(groupname, sizeof(groupname), "%d", gid); else strlcpy(groupname, gr->gr_name, sizeof(groupname)); strmode(th_get_mode(t), modestring); printf("%.10s %-8.8s %-8.8s ", modestring, username, groupname); if (TH_ISCHR(t) || TH_ISBLK(t)) printf(" %3d, %3d ", th_get_devmajor(t), th_get_devminor(t)); else printf("%9ld ", (long)th_get_size(t)); mtime = th_get_mtime(t); mtm = localtime(&mtime); #ifdef HAVE_STRFTIME strftime(timebuf, sizeof(timebuf), "%h %e %H:%M %Y", mtm); printf("%s", timebuf); #else printf("%.3s %2d %2d:%02d %4d", months[mtm->tm_mon], mtm->tm_mday, mtm->tm_hour, mtm->tm_min, mtm->tm_year + 1900); #endif printf(" %s", th_get_pathname(t)); if (TH_ISSYM(t) || TH_ISLNK(t)) { if (TH_ISSYM(t)) printf(" -> "); else printf(" link to "); if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL) printf("%s", t->th_buf.gnu_longlink); else printf("%.100s", t->th_buf.linkname); } putchar('\n'); }
/* extract regular file */ int tar_extract_regfile(TAR *t, char *realname) { mode_t mode; size_t size; uid_t uid; gid_t gid; int fdout; int i, k; char buf[T_BLOCKSIZE]; char *filename; #ifdef DEBUG printf("==> tar_extract_regfile(t=0x%lx, realname=\"%s\")\n", t, realname); #endif if (!TH_ISREG(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); size = th_get_size(t); uid = th_get_uid(t); gid = th_get_gid(t); if (mkdirhier(dirname(filename)) == -1) return -1; #ifdef DEBUG printf(" ==> extracting: %s (mode %04o, uid %d, gid %d, %d bytes)\n", filename, mode, uid, gid, size); #endif fdout = open(filename, O_WRONLY | O_CREAT | O_TRUNC #ifdef O_BINARY | O_BINARY #endif , 0666); if (fdout == -1) { #ifdef DEBUG perror("open()"); #endif return -1; } #if 0 /* change the owner. (will only work if run as root) */ if (fchown(fdout, uid, gid) == -1 && errno != EPERM) { #ifdef DEBUG perror("fchown()"); #endif return -1; } /* make sure the mode isn't inheritted from a file we're overwriting */ if (fchmod(fdout, mode & 07777) == -1) { #ifdef DEBUG perror("fchmod()"); #endif return -1; } #endif /* extract the file */ for (i = size; i > 0; i -= T_BLOCKSIZE) { k = tar_block_read(t, buf); if (k != T_BLOCKSIZE) { if (k != -1) errno = EINVAL; return -1; } /* write block to output file */ if (write(fdout, buf, ((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1) return -1; } /* close output file */ if (close(fdout) == -1) return -1; #ifdef DEBUG printf("### done extracting %s\n", filename); #endif return 0; }
/* wrapper function for th_read_internal() to handle GNU extensions */ int th_read(TAR *t) { int i, j; size_t sz; char *ptr; #ifdef DEBUG printf("==> th_read(t=0x%lx)\n", t); #endif if (t->th_buf.gnu_longname != NULL) free(t->th_buf.gnu_longname); if (t->th_buf.gnu_longlink != NULL) free(t->th_buf.gnu_longlink); memset(&(t->th_buf), 0, sizeof(struct tar_header)); i = th_read_internal(t); if (i == 0) return 1; else if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* check for GNU long link extention */ if (TH_ISLONGLINK(t)) { sz = th_get_size(t); j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); #ifdef DEBUG printf(" th_read(): GNU long linkname detected " "(%ld bytes, %d blocks)\n", sz, j); #endif t->th_buf.gnu_longlink = (char *)malloc(j * T_BLOCKSIZE); if (t->th_buf.gnu_longlink == NULL) return -1; for (ptr = t->th_buf.gnu_longlink; j > 0; j--, ptr += T_BLOCKSIZE) { #ifdef DEBUG printf(" th_read(): reading long linkname " "(%d blocks left, ptr == %ld)\n", j, ptr); #endif i = tar_block_read(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } #ifdef DEBUG printf(" th_read(): read block == \"%s\"\n", ptr); #endif } #ifdef DEBUG printf(" th_read(): t->th_buf.gnu_longlink == \"%s\"\n", t->th_buf.gnu_longlink); #endif i = th_read_internal(t); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } /* check for GNU long name extention */ if (TH_ISLONGNAME(t)) { sz = th_get_size(t); j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); #ifdef DEBUG printf(" th_read(): GNU long filename detected " "(%ld bytes, %d blocks)\n", sz, j); #endif t->th_buf.gnu_longname = (char *)malloc(j * T_BLOCKSIZE); if (t->th_buf.gnu_longname == NULL) return -1; for (ptr = t->th_buf.gnu_longname; j > 0; j--, ptr += T_BLOCKSIZE) { #ifdef DEBUG printf(" th_read(): reading long filename " "(%d blocks left, ptr == %ld)\n", j, ptr); #endif i = tar_block_read(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } #ifdef DEBUG printf(" th_read(): read block == \"%s\"\n", ptr); #endif } #ifdef DEBUG printf(" th_read(): t->th_buf.gnu_longname == \"%s\"\n", t->th_buf.gnu_longname); #endif i = th_read_internal(t); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } #if 0 /* ** work-around for old archive files with broken typeflag fields ** NOTE: I fixed this in the TH_IS*() macros instead */ /* ** (directories are signified with a trailing '/') */ if (t->th_buf.typeflag == AREGTYPE && t->th_buf.name[strlen(t->th_buf.name) - 1] == '/') t->th_buf.typeflag = DIRTYPE; /* ** fallback to using mode bits */ if (t->th_buf.typeflag == AREGTYPE) { mode = (mode_t)oct_to_int(t->th_buf.mode); if (S_ISREG(mode)) t->th_buf.typeflag = REGTYPE; else if (S_ISDIR(mode)) t->th_buf.typeflag = DIRTYPE; else if (S_ISFIFO(mode)) t->th_buf.typeflag = FIFOTYPE; else if (S_ISCHR(mode)) t->th_buf.typeflag = CHRTYPE; else if (S_ISBLK(mode)) t->th_buf.typeflag = BLKTYPE; else if (S_ISLNK(mode)) t->th_buf.typeflag = SYMTYPE; } #endif return 0; }
/* write a header block */ int th_write(TAR *t) { int i, j; char type2; size_t sz, sz2; char *ptr; char buf[T_BLOCKSIZE]; #ifdef DEBUG printf("==> th_write(TAR=\"%s\")\n", t->pathname); th_print(t); #endif if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL) { #ifdef DEBUG printf("th_write(): using gnu_longlink (\"%s\")\n", t->th_buf.gnu_longlink); #endif /* save old size and type */ type2 = t->th_buf.typeflag; sz2 = th_get_size(t); /* write out initial header block with fake size and type */ t->th_buf.typeflag = GNU_LONGLINK_TYPE; sz = strlen(t->th_buf.gnu_longlink); th_set_size(t, sz); th_finish(t); i = tar_block_write(t, &(t->th_buf)); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* write out extra blocks containing long name */ for (j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0), ptr = t->th_buf.gnu_longlink; j > 1; j--, ptr += T_BLOCKSIZE) { i = tar_block_write(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } memset(buf, 0, T_BLOCKSIZE); strncpy(buf, ptr, T_BLOCKSIZE); i = tar_block_write(t, &buf); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* reset type and size to original values */ t->th_buf.typeflag = type2; th_set_size(t, sz2); } if ((t->options & TAR_GNU) && t->th_buf.gnu_longname != NULL) { #ifdef DEBUG printf("th_write(): using gnu_longname (\"%s\")\n", t->th_buf.gnu_longname); #endif /* save old size and type */ type2 = t->th_buf.typeflag; sz2 = th_get_size(t); /* write out initial header block with fake size and type */ t->th_buf.typeflag = GNU_LONGNAME_TYPE; sz = strlen(t->th_buf.gnu_longname); th_set_size(t, sz); th_finish(t); i = tar_block_write(t, &(t->th_buf)); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* write out extra blocks containing long name */ for (j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0), ptr = t->th_buf.gnu_longname; j > 1; j--, ptr += T_BLOCKSIZE) { i = tar_block_write(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } memset(buf, 0, T_BLOCKSIZE); strncpy(buf, ptr, T_BLOCKSIZE); i = tar_block_write(t, &buf); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* reset type and size to original values */ t->th_buf.typeflag = type2; th_set_size(t, sz2); } th_finish(t); #ifdef DEBUG /* print tar header */ th_print(t); #endif i = tar_block_write(t, &(t->th_buf)); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } #ifdef DEBUG puts("th_write(): returning 0"); #endif return 0; }
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); }