mirror of
https://github.com/sheumann/hush.git
synced 2024-12-26 10:32:02 +00:00
tar et al: die if bb_copyfd_size copies less than asked for.
(we have bb_copyfd_exact_size now for that kind of usage)
This commit is contained in:
parent
0a8a774179
commit
714701c890
@ -67,10 +67,10 @@ void data_extract_all(archive_handle_t *archive_handle)
|
||||
/* Regular file */
|
||||
dst_fd = xopen3(file_header->name, O_WRONLY | O_CREAT | O_EXCL,
|
||||
file_header->mode);
|
||||
bb_copyfd_size(archive_handle->src_fd, dst_fd, file_header->size);
|
||||
bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
|
||||
close(dst_fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case S_IFDIR:
|
||||
res = mkdir(file_header->name, file_header->mode);
|
||||
if ((errno != EISDIR) && (res == -1)
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
void data_extract_to_buffer(archive_handle_t *archive_handle)
|
||||
{
|
||||
const unsigned int size = archive_handle->file_header->size;
|
||||
unsigned int size = archive_handle->file_header->size;
|
||||
|
||||
archive_handle->buffer = xzalloc(size + 1);
|
||||
|
||||
xread(archive_handle->src_fd, archive_handle->buffer, size);
|
||||
}
|
||||
|
@ -4,9 +4,11 @@
|
||||
*/
|
||||
|
||||
#include "unarchive.h"
|
||||
#include <unistd.h>
|
||||
//#include <unistd.h>
|
||||
|
||||
void data_extract_to_stdout(archive_handle_t *archive_handle)
|
||||
{
|
||||
bb_copyfd_size(archive_handle->src_fd, STDOUT_FILENO, archive_handle->file_header->size);
|
||||
bb_copyfd_exact_size(archive_handle->src_fd,
|
||||
STDOUT_FILENO,
|
||||
archive_handle->file_header->size);
|
||||
}
|
||||
|
@ -96,7 +96,8 @@ char get_header_ar(archive_handle_t *archive_handle)
|
||||
if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
|
||||
archive_handle->action_header(typed);
|
||||
if (archive_handle->sub_archive) {
|
||||
while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS);
|
||||
while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS)
|
||||
/* repeat */;
|
||||
} else {
|
||||
archive_handle->action_data(archive_handle);
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ char get_header_tar(archive_handle_t *archive_handle)
|
||||
}
|
||||
|
||||
/* Strip trailing '/' in directories */
|
||||
/* Must be done after mode is set as '/' is used to check if its a directory */
|
||||
/* Must be done after mode is set as '/' is used to check if it's a directory */
|
||||
cp = last_char_is(file_header->name, '/');
|
||||
|
||||
if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
|
||||
|
@ -13,7 +13,6 @@
|
||||
*/
|
||||
void seek_by_read(const archive_handle_t *archive_handle, const unsigned int jump_size)
|
||||
{
|
||||
if (jump_size) {
|
||||
bb_copyfd_size(archive_handle->src_fd, -1, jump_size);
|
||||
}
|
||||
if (jump_size)
|
||||
bb_copyfd_exact_size(archive_handle->src_fd, -1, jump_size);
|
||||
}
|
||||
|
@ -452,26 +452,28 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
|
||||
|
||||
/* If it was a regular file, write out the body */
|
||||
if (inputFileFd >= 0) {
|
||||
off_t readSize = 0;
|
||||
size_t readSize;
|
||||
/* Wwrite the file to the archive. */
|
||||
/* We record size into header first, */
|
||||
/* and then write out file. If file shrinks in between, */
|
||||
/* tar will be corrupted. So we don't allow for that. */
|
||||
/* NB: GNU tar 1.16 warns and pads with zeroes */
|
||||
/* or even seeks back and updates header */
|
||||
bb_copyfd_exact_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
|
||||
////off_t readSize;
|
||||
////readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
|
||||
////if (readSize != statbuf->st_size && readSize >= 0) {
|
||||
//// bb_error_msg_and_die("short read from %s, aborting", fileName);
|
||||
////}
|
||||
|
||||
/* write the file to the archive */
|
||||
readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
|
||||
/* readSize < 0 means that error was already reported */
|
||||
if (readSize != statbuf->st_size && readSize >= 0) {
|
||||
/* Deadly. We record size into header first, */
|
||||
/* and then write out file. If file shrinks in between, */
|
||||
/* tar will be corrupted. So bail out. */
|
||||
/* NB: GNU tar 1.16 warns and pads with zeroes */
|
||||
/* or even seeks back and updates header */
|
||||
bb_error_msg_and_die("short read from %s, aborting", fileName);
|
||||
}
|
||||
/* Check that file did not grow in between? */
|
||||
/* if (safe_read(inputFileFd,1) == 1) warn but continue? */
|
||||
/* if (safe_read(inputFileFd, 1) == 1) warn but continue? */
|
||||
|
||||
close(inputFileFd);
|
||||
|
||||
/* Pad the file up to the tar block size */
|
||||
/* (a few tricks here in the name of code size) */
|
||||
readSize = (-(int)readSize) & (TAR_BLOCK_SIZE-1);
|
||||
readSize = (-(int)statbuf->st_size) & (TAR_BLOCK_SIZE-1);
|
||||
memset(bb_common_bufsiz1, 0, readSize);
|
||||
xwrite(tbInfo->tarFd, bb_common_bufsiz1, readSize);
|
||||
}
|
||||
|
@ -54,9 +54,9 @@ typedef union {
|
||||
static void unzip_skip(int fd, off_t skip)
|
||||
{
|
||||
if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) {
|
||||
if ((errno != ESPIPE) || (bb_copyfd_size(fd, -1, skip) != skip)) {
|
||||
if (errno != ESPIPE)
|
||||
bb_error_msg_and_die("seek failure");
|
||||
}
|
||||
bb_copyfd_exact_size(fd, -1, skip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,10 +75,8 @@ static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd)
|
||||
if (zip_header->formatted.method == 0) {
|
||||
/* Method 0 - stored (not compressed) */
|
||||
off_t size = zip_header->formatted.ucmpsize;
|
||||
if (size && (bb_copyfd_size(src_fd, dst_fd, size) != size)) {
|
||||
bb_error_msg_and_die("cannot complete extraction");
|
||||
}
|
||||
|
||||
if (size)
|
||||
bb_copyfd_exact_size(src_fd, dst_fd, size);
|
||||
} else {
|
||||
/* Method 8 - inflate */
|
||||
inflate_init(zip_header->formatted.cmpsize);
|
||||
@ -249,8 +247,8 @@ int unzip_main(int argc, char **argv)
|
||||
unzip_skip(src_fd, zip_header.formatted.extra_len);
|
||||
|
||||
if ((verbosity == v_list) && !list_header_done){
|
||||
printf(" Length Date Time Name\n"
|
||||
" -------- ---- ---- ----\n");
|
||||
puts(" Length Date Time Name\n"
|
||||
" -------- ---- ---- ----");
|
||||
list_header_done = 1;
|
||||
}
|
||||
|
||||
@ -274,10 +272,8 @@ int unzip_main(int argc, char **argv)
|
||||
dst_fn);
|
||||
total_entries++;
|
||||
i = 'n';
|
||||
|
||||
} else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */
|
||||
i = -1;
|
||||
|
||||
} else if (last_char_is(dst_fn, '/')) { /* Extract directory */
|
||||
if (stat(dst_fn, &stat_buf) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
@ -298,17 +294,15 @@ int unzip_main(int argc, char **argv)
|
||||
i = 'n';
|
||||
|
||||
} else { /* Extract file */
|
||||
_check_file:
|
||||
_check_file:
|
||||
if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */
|
||||
if (errno != ENOENT) {
|
||||
bb_perror_msg_and_die("cannot stat '%s'",dst_fn);
|
||||
}
|
||||
i = 'y';
|
||||
|
||||
} else { /* File already exists */
|
||||
if (overwrite == o_never) {
|
||||
i = 'n';
|
||||
|
||||
} else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */
|
||||
if (overwrite == o_always) {
|
||||
i = 'y';
|
||||
@ -319,7 +313,6 @@ int unzip_main(int argc, char **argv)
|
||||
}
|
||||
i = key_buf[0];
|
||||
}
|
||||
|
||||
} else { /* File is not regular file */
|
||||
bb_error_msg_and_die("'%s' exists but is not regular file",dst_fn);
|
||||
}
|
||||
@ -338,7 +331,7 @@ int unzip_main(int argc, char **argv)
|
||||
printf(" inflating: %s\n", dst_fn);
|
||||
}
|
||||
if (unzip_extract(&zip_header, src_fd, dst_fd)) {
|
||||
failed = 1;
|
||||
failed = 1;
|
||||
}
|
||||
if (dst_fd != STDOUT_FILENO) {
|
||||
/* closing STDOUT is potentially bad for future business */
|
||||
|
@ -25,9 +25,8 @@ int bb_cat(char **argv)
|
||||
if (f) {
|
||||
off_t r = bb_copyfd_eof(fileno(f), STDOUT_FILENO);
|
||||
fclose_if_not_stdin(f);
|
||||
if (r >= 0) {
|
||||
if (r >= 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
retval = EXIT_FAILURE;
|
||||
} while (*++argv);
|
||||
|
@ -203,8 +203,13 @@ extern int recursive_action(const char *fileName, int recurse,
|
||||
extern int device_open(const char *device, int mode);
|
||||
extern int get_console_fd(void);
|
||||
extern char *find_block_device(char *path);
|
||||
extern off_t bb_copyfd_size(int fd1, int fd2, off_t size);
|
||||
/* bb_copyfd_XX print read/write errors and return -1 if they occur */
|
||||
extern off_t bb_copyfd_eof(int fd1, int fd2);
|
||||
extern off_t bb_copyfd_size(int fd1, int fd2, off_t size);
|
||||
extern void bb_copyfd_exact_size(int fd1, int fd2, off_t size);
|
||||
/* "short" copy can be detected by return value < size */
|
||||
/* this helper yells "short read!" if param is not -1 */
|
||||
extern void complain_copyfd_and_die(off_t sz) ATTRIBUTE_NORETURN;
|
||||
extern char bb_process_escape_sequence(const char **ptr);
|
||||
extern char *bb_get_last_path_component(char *path);
|
||||
extern int ndelay_on(int fd);
|
||||
|
@ -24,7 +24,7 @@ typedef struct file_headers_s {
|
||||
} file_header_t;
|
||||
|
||||
typedef struct archive_handle_s {
|
||||
/* define if the header and data component should processed */
|
||||
/* define if the header and data component should be processed */
|
||||
char (*filter)(struct archive_handle_s *);
|
||||
llist_t *accept;
|
||||
/* List of files that have been rejected */
|
||||
|
@ -39,7 +39,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
|
||||
|
||||
rd = safe_read(src_fd, buffer, size > BUFSIZ ? BUFSIZ : size);
|
||||
|
||||
if (!rd) { /* eof - all done. */
|
||||
if (!rd) { /* eof - all done */
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
@ -56,22 +56,31 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
|
||||
}
|
||||
}
|
||||
total += rd;
|
||||
if (status < 0) {
|
||||
if (status < 0) { /* if we aren't copying till EOF... */
|
||||
size -= rd;
|
||||
if (!size) {
|
||||
status = 0;
|
||||
/* 'size' bytes copied - all done */
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
out:
|
||||
RELEASE_CONFIG_BUFFER(buffer);
|
||||
|
||||
return status ? -1 : total;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void complain_copyfd_and_die(off_t sz)
|
||||
{
|
||||
if (sz != -1)
|
||||
bb_error_msg_and_die("short read");
|
||||
/* if sz == -1, bb_copyfd_XX already complained */
|
||||
exit(xfunc_error_retval);
|
||||
}
|
||||
#endif
|
||||
|
||||
off_t bb_copyfd_size(int fd1, int fd2, off_t size)
|
||||
{
|
||||
if (size) {
|
||||
@ -80,6 +89,17 @@ off_t bb_copyfd_size(int fd1, int fd2, off_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bb_copyfd_exact_size(int fd1, int fd2, off_t size)
|
||||
{
|
||||
off_t sz = bb_copyfd_size(fd1, fd2, size);
|
||||
if (sz == size)
|
||||
return;
|
||||
if (sz != -1)
|
||||
bb_error_msg_and_die("short read");
|
||||
/* if sz == -1, bb_copyfd_XX already complained */
|
||||
exit(xfunc_error_retval);
|
||||
}
|
||||
|
||||
off_t bb_copyfd_eof(int fd1, int fd2)
|
||||
{
|
||||
return bb_full_fd_action(fd1, fd2, 0);
|
||||
|
@ -22,8 +22,8 @@ typedef struct ftp_host_info_s {
|
||||
struct sockaddr_in *s_in;
|
||||
} ftp_host_info_t;
|
||||
|
||||
static char verbose_flag = 0;
|
||||
static char do_continue = 0;
|
||||
static char verbose_flag;
|
||||
static char do_continue;
|
||||
|
||||
static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
|
||||
{
|
||||
@ -112,7 +112,9 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
||||
const char *local_path, char *server_path)
|
||||
{
|
||||
char buf[512];
|
||||
off_t filesize = 0;
|
||||
/* I think 'filesize' usage here is bogus. Let's see... */
|
||||
//off_t filesize = -1;
|
||||
#define filesize ((off_t)-1)
|
||||
int fd_data;
|
||||
int fd_local = -1;
|
||||
off_t beg_range = 0;
|
||||
@ -124,11 +126,10 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
||||
fd_data = xconnect_ftpdata(server, buf);
|
||||
|
||||
if (ftpcmd("SIZE ", server_path, control_stream, buf) == 213) {
|
||||
filesize = BB_STRTOOFF(buf + 4, NULL, 10);
|
||||
if (errno || filesize < 0)
|
||||
bb_error_msg_and_die("SIZE error: %s", buf + 4);
|
||||
//filesize = BB_STRTOOFF(buf + 4, NULL, 10);
|
||||
//if (errno || filesize < 0)
|
||||
// bb_error_msg_and_die("SIZE error: %s", buf + 4);
|
||||
} else {
|
||||
filesize = -1;
|
||||
do_continue = 0;
|
||||
}
|
||||
|
||||
@ -154,7 +155,8 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
||||
if (ftpcmd(buf, NULL, control_stream, buf) != 350) {
|
||||
do_continue = 0;
|
||||
} else {
|
||||
filesize -= beg_range;
|
||||
//if (filesize != -1)
|
||||
// filesize -= beg_range;
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,11 +175,11 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
||||
|
||||
/* Copy the file */
|
||||
if (filesize != -1) {
|
||||
if (-1 == bb_copyfd_size(fd_data, fd_local, filesize))
|
||||
exit(EXIT_FAILURE);
|
||||
if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
if (-1 == bb_copyfd_eof(fd_data, fd_local))
|
||||
exit(EXIT_FAILURE);
|
||||
if (bb_copyfd_eof(fd_data, fd_local) == -1)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* close it all down */
|
||||
@ -277,14 +279,11 @@ int ftpgetput_main(int argc, char **argv)
|
||||
/* content-length of the file */
|
||||
unsigned opt;
|
||||
char *port = "ftp";
|
||||
|
||||
/* socket to ftp server */
|
||||
FILE *control_stream;
|
||||
struct sockaddr_in s_in;
|
||||
|
||||
/* continue a prev transfer (-c) */
|
||||
ftp_host_info_t *server;
|
||||
|
||||
int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = NULL;
|
||||
|
||||
/* Check to see if the command is ftpget or ftput */
|
||||
|
Loading…
Reference in New Issue
Block a user