/*ARGSUSED*/ void blobSetFilename(blob *b, const char *dir, const char *filename) { assert(b != NULL); assert(b->magic == BLOBCLASS); assert(filename != NULL); cli_dbgmsg("blobSetFilename: %s\n", filename); if(b->name) free(b->name); b->name = cli_strdup(filename); if(b->name) sanitiseName(b->name); }
int cli_untar(const char *dir, int desc, unsigned int posix) { int size = 0; int in_block = 0; char fullname[NAME_MAX + 1]; FILE *outfile = NULL; cli_dbgmsg("In untar(%s, %d)\n", dir ? dir : "", desc); for(;;) { char block[BLOCKSIZE]; const int nread = cli_readn(desc, block, (unsigned int)sizeof(block)); if(!in_block && nread == 0) break; if(nread < 0) { if(outfile) fclose(outfile); cli_errmsg("cli_untar: block read error\n"); return CL_EIO; } if(!in_block) { char type; const char *suffix; size_t suffixLen = 0; int fd, directory; char magic[7], name[101], osize[13]; if(outfile) { if(fclose(outfile)) { cli_errmsg("cli_untar: cannot close file %s\n", fullname); return CL_EIO; } outfile = (FILE*)0; } if(block[0] == '\0') /* We're done */ break; /* Notice assumption that BLOCKSIZE > 262 */ if(posix) { strncpy(magic, block+257, 5); magic[5] = '\0'; if(strcmp(magic, "ustar") != 0) { cli_dbgmsg("Incorrect magic string '%s' in tar header\n", magic); return CL_EFORMAT; } } type = block[156]; /* * Extra types from [email protected] */ switch(type) { case '0': /* plain file */ case '\0': /* plain file */ case '7': /* contiguous file */ directory = 0; break; case '1': /* Link to already archived file */ case '5': /* directory */ case '2': /* sym link */ case '3': /* char device */ case '4': /* block device */ case '6': /* fifo special */ directory = 1; break; case 'L': /* GNU extension - ././@LongLink */ cli_errmsg("cli_untar: only standard TAR files are currently supported\n", type); return CL_EFORMAT; default: /*cli_errmsg("cli_untar: unknown type flag %c\n", type); return CL_EFORMAT;*/ /* * It isn't really a tar file */ cli_dbgmsg("cli_untar: unknown type flag %c\n", type); /* * We don't know that it's clean at all, * it would be better to have a * CL_CONTINUE return value since it * may be a different format */ return CL_CLEAN; } if(directory) { in_block = 0; continue; } strncpy(name, block, 100); name[100] = '\0'; /* * see also fileblobSetFilename() * TODO: check if the suffix needs to be put back */ sanitiseName(name); suffix = strrchr(name, '.'); if(suffix == NULL) suffix = ""; else { suffixLen = strlen(suffix); if(suffixLen > 4) { /* Found a full stop which isn't a suffix */ suffix = ""; suffixLen = 0; } } snprintf(fullname, sizeof(fullname) - 1 - suffixLen, "%s/%.*sXXXXXX", dir, (int)(sizeof(fullname) - 9 - suffixLen - strlen(dir)), name); #if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN) || defined(C_KFREEBSD_GNU) fd = mkstemp(fullname); #else (void)mktemp(fullname); fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600); #endif if(fd < 0) { cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno)); cli_dbgmsg("%lu %d %d\n", suffixLen, sizeof(fullname), strlen(fullname)); return CL_ETMPFILE; } cli_dbgmsg("cli_untar: extracting %s\n", fullname); in_block = 1; if((outfile = fdopen(fd, "wb")) == NULL) { cli_errmsg("cli_untar: cannot create file %s\n", fullname); close(fd); return CL_ETMPFILE; } strncpy(osize, block+124, 12); osize[12] = '\0'; size = octal(osize); if(size < 0) { cli_errmsg("Invalid size in tar header\n"); if(outfile) fclose(outfile); return CL_EFORMAT; } cli_dbgmsg("cli_untar: size = %d\n", size); } else { /* write or continue writing file contents */ const int nbytes = size>512? 512:size; const int nwritten = fwrite(block, 1, (size_t)nbytes, outfile); if(nwritten != nbytes) { cli_errmsg("cli_untar: only wrote %d bytes to file %s (out of disk space?)\n", nwritten, fullname); if(outfile) fclose(outfile); return CL_EIO; } size -= nbytes; } if (size == 0) in_block = 0; } if(outfile) return fclose(outfile); return 0; }