qrexec-lib: convert tabs to spaces

- Fix compile error on gcc 6 (-Werror=misleading-indentation)
- Follow coding style: https://www.qubes-os.org/doc/coding-style/
This commit is contained in:
Marek Marczykowski-Górecki 2016-06-02 02:32:46 +02:00
parent 93f676d998
commit 410ad3d25f
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
11 changed files with 648 additions and 648 deletions

View File

@ -28,88 +28,88 @@
static int total_mem;
static char *limited_malloc(int len)
{
char *ret;
total_mem += len;
if (total_mem > BUFFER_LIMIT) {
fprintf(stderr, "attempt to allocate >BUFFER_LIMIT\n");
exit(1);
}
ret = malloc(len);
if (!ret) {
perror("malloc");
exit(1);
}
return ret;
char *ret;
total_mem += len;
if (total_mem > BUFFER_LIMIT) {
fprintf(stderr, "attempt to allocate >BUFFER_LIMIT\n");
exit(1);
}
ret = malloc(len);
if (!ret) {
perror("malloc");
exit(1);
}
return ret;
}
static void limited_free(char *ptr, int len)
{
free(ptr);
total_mem -= len;
free(ptr);
total_mem -= len;
}
void buffer_init(struct buffer *b)
{
b->buflen = 0;
b->data = NULL;
b->buflen = 0;
b->data = NULL;
}
void buffer_free(struct buffer *b)
{
if (b->buflen)
limited_free(b->data, b->buflen);
buffer_init(b);
if (b->buflen)
limited_free(b->data, b->buflen);
buffer_init(b);
}
/*
The following two functions can be made much more efficient.
Yet the profiling output show they are not significant CPU hogs, so
we keep them so simple to make them obviously correct.
*/
The following two functions can be made much more efficient.
Yet the profiling output show they are not significant CPU hogs, so
we keep them so simple to make them obviously correct.
*/
void buffer_append(struct buffer *b, const char *data, int len)
{
int newsize;
char *qdata;
if (len < 0 || len > BUFFER_LIMIT) {
fprintf(stderr, "buffer_append %d\n", len);
exit(1);
}
if (len == 0)
return;
newsize = len + b->buflen;
qdata = limited_malloc(len + b->buflen);
memcpy(qdata, b->data, b->buflen);
memcpy(qdata + b->buflen, data, len);
buffer_free(b);
b->buflen = newsize;
b->data = qdata;
int newsize;
char *qdata;
if (len < 0 || len > BUFFER_LIMIT) {
fprintf(stderr, "buffer_append %d\n", len);
exit(1);
}
if (len == 0)
return;
newsize = len + b->buflen;
qdata = limited_malloc(len + b->buflen);
memcpy(qdata, b->data, b->buflen);
memcpy(qdata + b->buflen, data, len);
buffer_free(b);
b->buflen = newsize;
b->data = qdata;
}
void buffer_remove(struct buffer *b, int len)
{
int newsize;
char *qdata = NULL;
if (len < 0 || len > b->buflen) {
fprintf(stderr, "buffer_remove %d/%d\n", len, b->buflen);
exit(1);
}
newsize = b->buflen - len;
if (newsize > 0) {
qdata = limited_malloc(newsize);
memcpy(qdata, b->data + len, newsize);
}
buffer_free(b);
b->buflen = newsize;
b->data = qdata;
int newsize;
char *qdata = NULL;
if (len < 0 || len > b->buflen) {
fprintf(stderr, "buffer_remove %d/%d\n", len, b->buflen);
exit(1);
}
newsize = b->buflen - len;
if (newsize > 0) {
qdata = limited_malloc(newsize);
memcpy(qdata, b->data + len, newsize);
}
buffer_free(b);
b->buflen = newsize;
b->data = qdata;
}
int buffer_len(struct buffer *b)
{
return b->buflen;
return b->buflen;
}
void *buffer_data(struct buffer *b)
{
return b->data;
return b->data;
}

View File

@ -6,44 +6,44 @@
notify_progress_t *notify_progress_func = NULL;
void register_notify_progress(notify_progress_t *func)
{
notify_progress_func = func;
notify_progress_func = func;
}
int copy_file(int outfd, int infd, long long size, unsigned long *crc32)
{
char buf[4096];
long long written = 0;
int ret;
int count;
while (written < size) {
if (size - written > (int)sizeof(buf))
count = sizeof buf;
else
count = size - written;
ret = read(infd, buf, count);
if (!ret)
return COPY_FILE_READ_EOF;
if (ret < 0)
return COPY_FILE_READ_ERROR;
/* acumulate crc32 if requested */
if (crc32)
*crc32 = Crc32_ComputeBuf(*crc32, buf, ret);
if (!write_all(outfd, buf, ret))
return COPY_FILE_WRITE_ERROR;
if (notify_progress_func != NULL)
notify_progress_func(ret, 0);
written += ret;
}
return COPY_FILE_OK;
char buf[4096];
long long written = 0;
int ret;
int count;
while (written < size) {
if (size - written > (int)sizeof(buf))
count = sizeof buf;
else
count = size - written;
ret = read(infd, buf, count);
if (!ret)
return COPY_FILE_READ_EOF;
if (ret < 0)
return COPY_FILE_READ_ERROR;
/* acumulate crc32 if requested */
if (crc32)
*crc32 = Crc32_ComputeBuf(*crc32, buf, ret);
if (!write_all(outfd, buf, ret))
return COPY_FILE_WRITE_ERROR;
if (notify_progress_func != NULL)
notify_progress_func(ret, 0);
written += ret;
}
return COPY_FILE_OK;
}
const char * copy_file_status_to_str(int status)
{
switch (status) {
case COPY_FILE_OK: return "OK";
case COPY_FILE_READ_EOF: return "Unexpected end of data while reading";
case COPY_FILE_READ_ERROR: return "Error reading";
case COPY_FILE_WRITE_ERROR: return "Error writing";
default: return "????????";
}
switch (status) {
case COPY_FILE_OK: return "OK";
case COPY_FILE_READ_EOF: return "Unexpected end of data while reading";
case COPY_FILE_READ_ERROR: return "Error reading";
case COPY_FILE_WRITE_ERROR: return "Error writing";
default: return "????????";
}
}

View File

@ -28,56 +28,56 @@
static do_exec_t *exec_func = NULL;
void register_exec_func(do_exec_t *func) {
exec_func = func;
exec_func = func;
}
void fix_fds(int fdin, int fdout, int fderr)
{
int i;
for (i = 0; i < 256; i++)
if (i != fdin && i != fdout && i != fderr)
close(i);
dup2(fdin, 0);
dup2(fdout, 1);
dup2(fderr, 2);
close(fdin);
close(fdout);
if (fderr != 2)
close(fderr);
int i;
for (i = 0; i < 256; i++)
if (i != fdin && i != fdout && i != fderr)
close(i);
dup2(fdin, 0);
dup2(fdout, 1);
dup2(fderr, 2);
close(fdin);
close(fdout);
if (fderr != 2)
close(fderr);
}
void do_fork_exec(const char *cmdline, int *pid, int *stdin_fd, int *stdout_fd,
int *stderr_fd)
int *stderr_fd)
{
int inpipe[2], outpipe[2], errpipe[2];
int inpipe[2], outpipe[2], errpipe[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inpipe) ||
socketpair(AF_UNIX, SOCK_STREAM, 0, outpipe) ||
(stderr_fd && socketpair(AF_UNIX, SOCK_STREAM, 0, errpipe))) {
perror("socketpair");
exit(1);
}
switch (*pid = fork()) {
case -1:
perror("fork");
exit(-1);
case 0:
if (stderr_fd) {
fix_fds(inpipe[0], outpipe[1], errpipe[1]);
} else
fix_fds(inpipe[0], outpipe[1], 2);
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inpipe) ||
socketpair(AF_UNIX, SOCK_STREAM, 0, outpipe) ||
(stderr_fd && socketpair(AF_UNIX, SOCK_STREAM, 0, errpipe))) {
perror("socketpair");
exit(1);
}
switch (*pid = fork()) {
case -1:
perror("fork");
exit(-1);
case 0:
if (stderr_fd) {
fix_fds(inpipe[0], outpipe[1], errpipe[1]);
} else
fix_fds(inpipe[0], outpipe[1], 2);
if (exec_func != NULL)
exec_func(cmdline);
exit(-1);
default:;
}
close(inpipe[0]);
close(outpipe[1]);
*stdin_fd = inpipe[1];
*stdout_fd = outpipe[0];
if (stderr_fd) {
close(errpipe[1]);
*stderr_fd = errpipe[0];
}
if (exec_func != NULL)
exec_func(cmdline);
exit(-1);
default:;
}
close(inpipe[0]);
close(outpipe[1]);
*stdin_fd = inpipe[1];
*stdout_fd = outpipe[0];
if (stderr_fd) {
close(errpipe[1]);
*stderr_fd = errpipe[0];
}
}

View File

@ -27,90 +27,90 @@
void perror_wrapper(const char * msg)
{
int prev=errno;
perror(msg);
errno=prev;
int prev=errno;
perror(msg);
errno=prev;
}
void set_nonblock(int fd)
{
int fl = fcntl(fd, F_GETFL, 0);
if (fl & O_NONBLOCK)
return;
fcntl(fd, F_SETFL, fl | O_NONBLOCK);
int fl = fcntl(fd, F_GETFL, 0);
if (fl & O_NONBLOCK)
return;
fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}
void set_block(int fd)
{
int fl = fcntl(fd, F_GETFL, 0);
if (!(fl & O_NONBLOCK))
return;
fcntl(fd, F_SETFL, fl & ~O_NONBLOCK);
int fl = fcntl(fd, F_GETFL, 0);
if (!(fl & O_NONBLOCK))
return;
fcntl(fd, F_SETFL, fl & ~O_NONBLOCK);
}
int write_all(int fd, const void *buf, int size)
{
int written = 0;
int ret;
while (written < size) {
ret = write(fd, (char *) buf + written, size - written);
if (ret == -1 && errno == EINTR)
continue;
if (ret <= 0) {
return 0;
}
written += ret;
}
// fprintf(stderr, "sent %d bytes\n", size);
return 1;
int written = 0;
int ret;
while (written < size) {
ret = write(fd, (char *) buf + written, size - written);
if (ret == -1 && errno == EINTR)
continue;
if (ret <= 0) {
return 0;
}
written += ret;
}
// fprintf(stderr, "sent %d bytes\n", size);
return 1;
}
int read_all(int fd, void *buf, int size)
{
int got_read = 0;
int ret;
while (got_read < size) {
ret = read(fd, (char *) buf + got_read, size - got_read);
if (ret == -1 && errno == EINTR)
continue;
if (ret == 0) {
errno = 0;
fprintf(stderr, "EOF\n");
return 0;
}
if (ret < 0) {
if (errno != EAGAIN)
perror_wrapper("read");
return 0;
}
if (got_read == 0) {
// force blocking operation on further reads
set_block(fd);
}
got_read += ret;
}
// fprintf(stderr, "read %d bytes\n", size);
return 1;
int got_read = 0;
int ret;
while (got_read < size) {
ret = read(fd, (char *) buf + got_read, size - got_read);
if (ret == -1 && errno == EINTR)
continue;
if (ret == 0) {
errno = 0;
fprintf(stderr, "EOF\n");
return 0;
}
if (ret < 0) {
if (errno != EAGAIN)
perror_wrapper("read");
return 0;
}
if (got_read == 0) {
// force blocking operation on further reads
set_block(fd);
}
got_read += ret;
}
// fprintf(stderr, "read %d bytes\n", size);
return 1;
}
int copy_fd_all(int fdout, int fdin)
{
int ret;
char buf[4096];
for (;;) {
ret = read(fdin, buf, sizeof(buf));
if (ret == -1 && errno == EINTR)
continue;
if (!ret)
break;
if (ret < 0) {
perror_wrapper("read");
return 0;
}
if (!write_all(fdout, buf, ret)) {
perror_wrapper("write");
return 0;
}
}
return 1;
int ret;
char buf[4096];
for (;;) {
ret = read(fdin, buf, sizeof(buf));
if (ret == -1 && errno == EINTR)
continue;
if (!ret)
break;
if (ret < 0) {
perror_wrapper("read");
return 0;
}
if (!write_all(fdout, buf, ret)) {
perror_wrapper("write");
return 0;
}
}
return 1;
}

View File

@ -24,8 +24,8 @@
#include <libvchan.h>
struct buffer {
char *data;
int buflen;
char *data;
int buflen;
};
/* return codes for buffered writes */
@ -48,7 +48,7 @@ int write_stdin(int fd, const char *data, int len, struct buffer *buffer);
int fork_and_flush_stdin(int fd, struct buffer *buffer);
void do_fork_exec(const char *cmdline, int *pid, int *stdin_fd, int *stdout_fd,
int *stderr_fd);
int *stderr_fd);
void wait_for_vchan_or_argfd(libvchan_t *vchan, int max, fd_set * rdset, fd_set * wrset);
int read_vchan_all(libvchan_t *vchan, void *data, size_t size);
int write_vchan_all(libvchan_t *vchan, const void *data, size_t size);

View File

@ -35,32 +35,32 @@
#include <sys/types.h>
struct file_header {
unsigned int namelen;
unsigned int mode;
unsigned long long filelen;
unsigned int atime;
unsigned int atime_nsec;
unsigned int mtime;
unsigned int mtime_nsec;
unsigned int namelen;
unsigned int mode;
unsigned long long filelen;
unsigned int atime;
unsigned int atime_nsec;
unsigned int mtime;
unsigned int mtime_nsec;
};
struct result_header {
uint32_t error_code;
uint32_t _pad;
uint64_t crc32;
uint32_t error_code;
uint32_t _pad;
uint64_t crc32;
} __attribute__((packed));
/* optional info about last processed file */
struct result_header_ext {
uint32_t last_namelen;
char last_name[0];
uint32_t last_namelen;
char last_name[0];
} __attribute__((packed));
enum {
COPY_FILE_OK,
COPY_FILE_READ_EOF,
COPY_FILE_READ_ERROR,
COPY_FILE_WRITE_ERROR
COPY_FILE_OK,
COPY_FILE_READ_EOF,
COPY_FILE_READ_ERROR,
COPY_FILE_WRITE_ERROR
};
/* feedback handling */

View File

@ -34,91 +34,91 @@ _Noreturn static void call_error_handler(const char *fmt, ...)
static int write_all_with_crc(int fd, const void *buf, int size)
{
crc32_sum = Crc32_ComputeBuf(crc32_sum, buf, size);
return write_all(fd, buf, size);
crc32_sum = Crc32_ComputeBuf(crc32_sum, buf, size);
return write_all(fd, buf, size);
}
void notify_end_and_wait_for_result(void)
{
struct file_header end_hdr;
struct file_header end_hdr;
/* nofity end of transfer */
memset(&end_hdr, 0, sizeof(end_hdr));
end_hdr.namelen = 0;
end_hdr.filelen = 0;
write_all_with_crc(1, &end_hdr, sizeof(end_hdr));
/* nofity end of transfer */
memset(&end_hdr, 0, sizeof(end_hdr));
end_hdr.namelen = 0;
end_hdr.filelen = 0;
write_all_with_crc(1, &end_hdr, sizeof(end_hdr));
set_block(0);
wait_for_result();
set_block(0);
wait_for_result();
}
void wait_for_result(void)
{
struct result_header hdr;
struct result_header_ext hdr_ext;
char last_filename[MAX_PATH_LENGTH + 1];
char last_filename_prefix[] = "; Last file: ";
struct result_header hdr;
struct result_header_ext hdr_ext;
char last_filename[MAX_PATH_LENGTH + 1];
char last_filename_prefix[] = "; Last file: ";
if (!read_all(0, &hdr, sizeof(hdr))) {
if (errno == EAGAIN) {
// no result sent and stdin still open
return;
} else {
// other read error or EOF
exit(1); // hopefully remote has produced error message
}
}
if (!read_all(0, &hdr_ext, sizeof(hdr_ext))) {
// remote used old result_header struct
hdr_ext.last_namelen = 0;
}
if (hdr_ext.last_namelen > MAX_PATH_LENGTH) {
// read only at most MAX_PATH_LENGTH chars
hdr_ext.last_namelen = MAX_PATH_LENGTH;
}
if (!read_all(0, last_filename, hdr_ext.last_namelen)) {
fprintf(stderr, "Failed to get last filename\n");
hdr_ext.last_namelen = 0;
}
last_filename[hdr_ext.last_namelen] = '\0';
if (!hdr_ext.last_namelen)
/* set prefix to empty string */
last_filename_prefix[0] = '\0';
if (!read_all(0, &hdr, sizeof(hdr))) {
if (errno == EAGAIN) {
// no result sent and stdin still open
return;
} else {
// other read error or EOF
exit(1); // hopefully remote has produced error message
}
}
if (!read_all(0, &hdr_ext, sizeof(hdr_ext))) {
// remote used old result_header struct
hdr_ext.last_namelen = 0;
}
if (hdr_ext.last_namelen > MAX_PATH_LENGTH) {
// read only at most MAX_PATH_LENGTH chars
hdr_ext.last_namelen = MAX_PATH_LENGTH;
}
if (!read_all(0, last_filename, hdr_ext.last_namelen)) {
fprintf(stderr, "Failed to get last filename\n");
hdr_ext.last_namelen = 0;
}
last_filename[hdr_ext.last_namelen] = '\0';
if (!hdr_ext.last_namelen)
/* set prefix to empty string */
last_filename_prefix[0] = '\0';
errno = hdr.error_code;
if (hdr.error_code != 0) {
switch (hdr.error_code) {
case EEXIST:
call_error_handler("File copy: not overwriting existing file. Clean QubesIncoming dir, and retry copy%s%s", last_filename_prefix, last_filename);
break;
case EINVAL:
call_error_handler("File copy: Corrupted data from packer%s%s", last_filename_prefix, last_filename);
break;
case EDQUOT:
if (ignore_quota_error) {
/* skip also CRC check as sender and receiver might be
* desynchronized in this case */
return;
}
/* fall though */
default:
call_error_handler("File copy: %s%s%s",
strerror(hdr.error_code), last_filename_prefix, last_filename);
}
}
if (hdr.crc32 != crc32_sum) {
call_error_handler("File transfer failed: checksum mismatch");
}
errno = hdr.error_code;
if (hdr.error_code != 0) {
switch (hdr.error_code) {
case EEXIST:
call_error_handler("File copy: not overwriting existing file. Clean QubesIncoming dir, and retry copy%s%s", last_filename_prefix, last_filename);
break;
case EINVAL:
call_error_handler("File copy: Corrupted data from packer%s%s", last_filename_prefix, last_filename);
break;
case EDQUOT:
if (ignore_quota_error) {
/* skip also CRC check as sender and receiver might be
* desynchronized in this case */
return;
}
/* fall though */
default:
call_error_handler("File copy: %s%s%s",
strerror(hdr.error_code), last_filename_prefix, last_filename);
}
}
if (hdr.crc32 != crc32_sum) {
call_error_handler("File transfer failed: checksum mismatch");
}
}
void write_headers(const struct file_header *hdr, const char *filename)
{
if (!write_all_with_crc(1, hdr, sizeof(*hdr))
|| !write_all_with_crc(1, filename, hdr->namelen)) {
set_block(0);
wait_for_result();
exit(1);
}
if (!write_all_with_crc(1, hdr, sizeof(*hdr))
|| !write_all_with_crc(1, filename, hdr->namelen)) {
set_block(0);
wait_for_result();
exit(1);
}
}
int copy_file_with_crc(int outfd, int infd, long long size) {
@ -127,100 +127,100 @@ int copy_file_with_crc(int outfd, int infd, long long size) {
int single_file_processor(const char *filename, const struct stat *st)
{
struct file_header hdr;
int fd;
mode_t mode = st->st_mode;
struct file_header hdr;
int fd;
mode_t mode = st->st_mode;
hdr.namelen = strlen(filename) + 1;
hdr.mode = mode;
hdr.atime = st->st_atim.tv_sec;
hdr.atime_nsec = st->st_atim.tv_nsec;
hdr.mtime = st->st_mtim.tv_sec;
hdr.mtime_nsec = st->st_mtim.tv_nsec;
hdr.namelen = strlen(filename) + 1;
hdr.mode = mode;
hdr.atime = st->st_atim.tv_sec;
hdr.atime_nsec = st->st_atim.tv_nsec;
hdr.mtime = st->st_mtim.tv_sec;
hdr.mtime_nsec = st->st_mtim.tv_nsec;
if (S_ISREG(mode)) {
int ret;
fd = open(filename, O_RDONLY);
if (fd < 0)
call_error_handler("open %s", filename);
hdr.filelen = st->st_size;
write_headers(&hdr, filename);
ret = copy_file(1, fd, hdr.filelen, &crc32_sum);
if (ret != COPY_FILE_OK) {
if (ret != COPY_FILE_WRITE_ERROR)
call_error_handler("Copying file %s: %s", filename,
copy_file_status_to_str(ret));
else {
set_block(0);
wait_for_result();
exit(1);
}
}
close(fd);
}
if (S_ISDIR(mode)) {
hdr.filelen = 0;
write_headers(&hdr, filename);
}
if (S_ISLNK(mode)) {
char name[st->st_size + 1];
if (readlink(filename, name, sizeof(name)) != st->st_size)
call_error_handler("readlink %s", filename);
hdr.filelen = st->st_size;
write_headers(&hdr, filename);
if (!write_all_with_crc(1, name, st->st_size)) {
set_block(0);
wait_for_result();
exit(1);
}
}
// check for possible error from qfile-unpacker
wait_for_result();
return 0;
if (S_ISREG(mode)) {
int ret;
fd = open(filename, O_RDONLY);
if (fd < 0)
call_error_handler("open %s", filename);
hdr.filelen = st->st_size;
write_headers(&hdr, filename);
ret = copy_file(1, fd, hdr.filelen, &crc32_sum);
if (ret != COPY_FILE_OK) {
if (ret != COPY_FILE_WRITE_ERROR)
call_error_handler("Copying file %s: %s", filename,
copy_file_status_to_str(ret));
else {
set_block(0);
wait_for_result();
exit(1);
}
}
close(fd);
}
if (S_ISDIR(mode)) {
hdr.filelen = 0;
write_headers(&hdr, filename);
}
if (S_ISLNK(mode)) {
char name[st->st_size + 1];
if (readlink(filename, name, sizeof(name)) != st->st_size)
call_error_handler("readlink %s", filename);
hdr.filelen = st->st_size;
write_headers(&hdr, filename);
if (!write_all_with_crc(1, name, st->st_size)) {
set_block(0);
wait_for_result();
exit(1);
}
}
// check for possible error from qfile-unpacker
wait_for_result();
return 0;
}
int do_fs_walk(const char *file, int ignore_symlinks)
{
char *newfile;
struct stat st;
struct dirent *ent;
DIR *dir;
char *newfile;
struct stat st;
struct dirent *ent;
DIR *dir;
if (lstat(file, &st))
call_error_handler("stat %s", file);
if (lstat(file, &st))
call_error_handler("stat %s", file);
if (S_ISLNK(st.st_mode) && ignore_symlinks)
return 0;
single_file_processor(file, &st);
if (!S_ISDIR(st.st_mode))
return 0;
dir = opendir(file);
if (!dir)
call_error_handler("opendir %s", file);
while ((ent = readdir(dir))) {
char *fname = ent->d_name;
if (!strcmp(fname, ".") || !strcmp(fname, ".."))
continue;
if (asprintf(&newfile, "%s/%s", file, fname) >= 0) {
do_fs_walk(newfile, ignore_symlinks);
free(newfile);
} else {
fprintf(stderr, "asprintf failed\n");
exit(1);
}
}
closedir(dir);
// directory metadata is resent; this makes the code simple,
// and the atime/mtime is set correctly at the second time
single_file_processor(file, &st);
return 0;
single_file_processor(file, &st);
if (!S_ISDIR(st.st_mode))
return 0;
dir = opendir(file);
if (!dir)
call_error_handler("opendir %s", file);
while ((ent = readdir(dir))) {
char *fname = ent->d_name;
if (!strcmp(fname, ".") || !strcmp(fname, ".."))
continue;
if (asprintf(&newfile, "%s/%s", file, fname) >= 0) {
do_fs_walk(newfile, ignore_symlinks);
free(newfile);
} else {
fprintf(stderr, "asprintf failed\n");
exit(1);
}
}
closedir(dir);
// directory metadata is resent; this makes the code simple,
// and the atime/mtime is set correctly at the second time
single_file_processor(file, &st);
return 0;
}
void qfile_pack_init(void) {
crc32_sum = 0;
ignore_quota_error = 0;
// this will allow checking for possible feedback packet in the middle of transfer
set_nonblock(0);
signal(SIGPIPE, SIG_IGN);
// this will allow checking for possible feedback packet in the middle of transfer
set_nonblock(0);
signal(SIGPIPE, SIG_IGN);
error_handler = NULL;
}

View File

@ -28,51 +28,51 @@
int wait_for_vchan_or_argfd_once(libvchan_t *ctrl, int max, fd_set * rdset, fd_set * wrset)
{
int vfd, ret;
struct timespec tv = { 1, 100000000 };
sigset_t empty_set;
int vfd, ret;
struct timespec tv = { 1, 100000000 };
sigset_t empty_set;
sigemptyset(&empty_set);
sigemptyset(&empty_set);
vfd = libvchan_fd_for_select(ctrl);
FD_SET(vfd, rdset);
if (vfd > max)
max = vfd;
max++;
ret = pselect(max, rdset, wrset, NULL, &tv, &empty_set);
if (ret < 0) {
if (errno != EINTR) {
perror("select");
exit(1);
} else {
FD_ZERO(rdset);
FD_ZERO(wrset);
fprintf(stderr, "eintr\n");
return 1;
}
vfd = libvchan_fd_for_select(ctrl);
FD_SET(vfd, rdset);
if (vfd > max)
max = vfd;
max++;
ret = pselect(max, rdset, wrset, NULL, &tv, &empty_set);
if (ret < 0) {
if (errno != EINTR) {
perror("select");
exit(1);
} else {
FD_ZERO(rdset);
FD_ZERO(wrset);
fprintf(stderr, "eintr\n");
return 1;
}
}
if (!libvchan_is_open(ctrl)) {
fprintf(stderr, "libvchan_is_eof\n");
exit(0);
}
if (FD_ISSET(vfd, rdset))
// the following will never block; we need to do this to
// clear libvchan_fd pending state
libvchan_wait(ctrl);
if (libvchan_data_ready(ctrl))
return 1;
return ret;
}
if (!libvchan_is_open(ctrl)) {
fprintf(stderr, "libvchan_is_eof\n");
exit(0);
}
if (FD_ISSET(vfd, rdset))
// the following will never block; we need to do this to
// clear libvchan_fd pending state
libvchan_wait(ctrl);
if (libvchan_data_ready(ctrl))
return 1;
return ret;
}
void wait_for_vchan_or_argfd(libvchan_t *ctrl, int max, fd_set * rdset, fd_set * wrset)
{
fd_set r = *rdset, w = *wrset;
do {
*rdset = r;
*wrset = w;
}
while (wait_for_vchan_or_argfd_once(ctrl, max, rdset, wrset) == 0);
fd_set r = *rdset, w = *wrset;
do {
*rdset = r;
*wrset = w;
}
while (wait_for_vchan_or_argfd_once(ctrl, max, rdset, wrset) == 0);
}
int write_vchan_all(libvchan_t *vchan, const void *data, size_t size) {

View File

@ -29,45 +29,45 @@
int get_server_socket(const char *socket_address)
{
struct sockaddr_un sockname;
int s;
struct sockaddr_un sockname;
int s;
unlink(socket_address);
unlink(socket_address);
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
printf("socket() failed\n");
exit(1);
}
memset(&sockname, 0, sizeof(sockname));
sockname.sun_family = AF_UNIX;
strncpy(sockname.sun_path, socket_address, sizeof sockname.sun_path);
sockname.sun_path[sizeof sockname.sun_path - 1] = 0;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
printf("socket() failed\n");
exit(1);
}
memset(&sockname, 0, sizeof(sockname));
sockname.sun_family = AF_UNIX;
strncpy(sockname.sun_path, socket_address, sizeof sockname.sun_path);
sockname.sun_path[sizeof sockname.sun_path - 1] = 0;
if (bind(s, (struct sockaddr *) &sockname, sizeof(sockname)) == -1) {
printf("bind() failed\n");
close(s);
exit(1);
}
// chmod(sockname.sun_path, 0666);
if (listen(s, 5) == -1) {
perror("listen() failed\n");
close(s);
exit(1);
}
return s;
if (bind(s, (struct sockaddr *) &sockname, sizeof(sockname)) == -1) {
printf("bind() failed\n");
close(s);
exit(1);
}
// chmod(sockname.sun_path, 0666);
if (listen(s, 5) == -1) {
perror("listen() failed\n");
close(s);
exit(1);
}
return s;
}
int do_accept(int s)
{
struct sockaddr_un peer;
unsigned int addrlen;
int fd;
addrlen = sizeof(peer);
fd = accept(s, (struct sockaddr *) &peer, &addrlen);
if (fd == -1) {
perror("unix accept");
exit(1);
}
return fd;
struct sockaddr_un peer;
unsigned int addrlen;
int fd;
addrlen = sizeof(peer);
fd = accept(s, (struct sockaddr *) &peer, &addrlen);
if (fd == -1) {
perror("unix accept");
exit(1);
}
return fd;
}

View File

@ -39,206 +39,206 @@ void send_status_and_crc(int code, const char *last_filename);
void do_exit(int code, const char *last_filename)
{
close(0);
send_status_and_crc(code, last_filename);
exit(code);
close(0);
send_status_and_crc(code, last_filename);
exit(code);
}
void set_size_limit(unsigned long long new_bytes_limit, unsigned long long new_files_limit)
{
bytes_limit = new_bytes_limit;
files_limit = new_files_limit;
bytes_limit = new_bytes_limit;
files_limit = new_files_limit;
}
void set_verbose(int value)
{
verbose = value;
verbose = value;
}
void set_procfs_fd(int value)
{
procdir_fd = value;
use_tmpfile = 1;
procdir_fd = value;
use_tmpfile = 1;
}
unsigned long crc32_sum = 0;
int read_all_with_crc(int fd, void *buf, int size) {
int ret;
ret = read_all(fd, buf, size);
if (ret)
crc32_sum = Crc32_ComputeBuf(crc32_sum, buf, size);
return ret;
int ret;
ret = read_all(fd, buf, size);
if (ret)
crc32_sum = Crc32_ComputeBuf(crc32_sum, buf, size);
return ret;
}
void send_status_and_crc(int code, const char *last_filename) {
struct result_header hdr;
struct result_header_ext hdr_ext;
int saved_errno;
struct result_header hdr;
struct result_header_ext hdr_ext;
int saved_errno;
saved_errno = errno;
hdr.error_code = code;
hdr.crc32 = crc32_sum;
if (!write_all(1, &hdr, sizeof(hdr)))
perror("write status");
if (last_filename) {
hdr_ext.last_namelen = strlen(last_filename);
if (!write_all(1, &hdr_ext, sizeof(hdr_ext)))
perror("write status ext");
if (!write_all(1, last_filename, hdr_ext.last_namelen))
perror("write last_filename");
}
errno = saved_errno;
saved_errno = errno;
hdr.error_code = code;
hdr.crc32 = crc32_sum;
if (!write_all(1, &hdr, sizeof(hdr)))
perror("write status");
if (last_filename) {
hdr_ext.last_namelen = strlen(last_filename);
if (!write_all(1, &hdr_ext, sizeof(hdr_ext)))
perror("write status ext");
if (!write_all(1, last_filename, hdr_ext.last_namelen))
perror("write last_filename");
}
errno = saved_errno;
}
void fix_times_and_perms(struct file_header *untrusted_hdr,
const char *untrusted_name)
const char *untrusted_name)
{
struct timeval times[2] =
{ {untrusted_hdr->atime, untrusted_hdr->atime_nsec / 1000},
{untrusted_hdr->mtime,
untrusted_hdr->mtime_nsec / 1000}
};
if (chmod(untrusted_name, untrusted_hdr->mode & 07777)) /* safe because of chroot */
do_exit(errno, untrusted_name);
if (utimes(untrusted_name, times)) /* as above */
do_exit(errno, untrusted_name);
struct timeval times[2] =
{
{untrusted_hdr->atime, untrusted_hdr->atime_nsec / 1000},
{untrusted_hdr->mtime, untrusted_hdr->mtime_nsec / 1000}
};
if (chmod(untrusted_name, untrusted_hdr->mode & 07777)) /* safe because of chroot */
do_exit(errno, untrusted_name);
if (utimes(untrusted_name, times)) /* as above */
do_exit(errno, untrusted_name);
}
void process_one_file_reg(struct file_header *untrusted_hdr,
const char *untrusted_name)
const char *untrusted_name)
{
int ret;
int fdout = -1;
int ret;
int fdout = -1;
/* make the file inaccessible until fully written */
if (use_tmpfile) {
fdout = open(".", O_WRONLY | O_TMPFILE, 0700);
if (fdout < 0) {
if (errno==ENOENT || /* most likely, kernel too old for O_TMPFILE */
errno==EOPNOTSUPP) /* filesystem has no support for O_TMPFILE */
use_tmpfile = 0;
else
do_exit(errno, untrusted_name);
}
}
if (fdout < 0)
fdout = open(untrusted_name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0000); /* safe because of chroot */
if (fdout < 0)
do_exit(errno, untrusted_name);
/* sizes are signed elsewhere */
if (untrusted_hdr->filelen > LLONG_MAX || (bytes_limit && untrusted_hdr->filelen > bytes_limit))
do_exit(EDQUOT, untrusted_name);
if (bytes_limit && total_bytes > bytes_limit - untrusted_hdr->filelen)
do_exit(EDQUOT, untrusted_name);
total_bytes += untrusted_hdr->filelen;
ret = copy_file(fdout, 0, untrusted_hdr->filelen, &crc32_sum);
if (ret != COPY_FILE_OK) {
if (ret == COPY_FILE_READ_EOF
|| ret == COPY_FILE_READ_ERROR)
do_exit(LEGAL_EOF, untrusted_name); // hopefully remote will produce error message
else
do_exit(errno, untrusted_name);
}
if (use_tmpfile) {
char fd_str[7];
snprintf(fd_str, sizeof(fd_str), "%d", fdout);
if (linkat(procdir_fd, fd_str, AT_FDCWD, untrusted_name, AT_SYMLINK_FOLLOW) < 0)
do_exit(errno, untrusted_name);
}
close(fdout);
fix_times_and_perms(untrusted_hdr, untrusted_name);
/* make the file inaccessible until fully written */
if (use_tmpfile) {
fdout = open(".", O_WRONLY | O_TMPFILE, 0700);
if (fdout < 0) {
if (errno==ENOENT || /* most likely, kernel too old for O_TMPFILE */
errno==EOPNOTSUPP) /* filesystem has no support for O_TMPFILE */
use_tmpfile = 0;
else
do_exit(errno, untrusted_name);
}
}
if (fdout < 0)
fdout = open(untrusted_name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0000); /* safe because of chroot */
if (fdout < 0)
do_exit(errno, untrusted_name);
/* sizes are signed elsewhere */
if (untrusted_hdr->filelen > LLONG_MAX || (bytes_limit && untrusted_hdr->filelen > bytes_limit))
do_exit(EDQUOT, untrusted_name);
if (bytes_limit && total_bytes > bytes_limit - untrusted_hdr->filelen)
do_exit(EDQUOT, untrusted_name);
total_bytes += untrusted_hdr->filelen;
ret = copy_file(fdout, 0, untrusted_hdr->filelen, &crc32_sum);
if (ret != COPY_FILE_OK) {
if (ret == COPY_FILE_READ_EOF
|| ret == COPY_FILE_READ_ERROR)
do_exit(LEGAL_EOF, untrusted_name); // hopefully remote will produce error message
else
do_exit(errno, untrusted_name);
}
if (use_tmpfile) {
char fd_str[7];
snprintf(fd_str, sizeof(fd_str), "%d", fdout);
if (linkat(procdir_fd, fd_str, AT_FDCWD, untrusted_name, AT_SYMLINK_FOLLOW) < 0)
do_exit(errno, untrusted_name);
}
close(fdout);
fix_times_and_perms(untrusted_hdr, untrusted_name);
}
void process_one_file_dir(struct file_header *untrusted_hdr,
const char *untrusted_name)
const char *untrusted_name)
{
// fix perms only when the directory is sent for the second time
// it allows to transfer r.x directory contents, as we create it rwx initially
struct stat buf;
if (!mkdir(untrusted_name, 0700)) /* safe because of chroot */
return;
if (errno != EEXIST)
do_exit(errno, untrusted_name);
if (stat(untrusted_name,&buf) < 0)
do_exit(errno, untrusted_name);
total_bytes += buf.st_size;
/* size accumulated after the fact, so don't check limit here */
fix_times_and_perms(untrusted_hdr, untrusted_name);
// fix perms only when the directory is sent for the second time
// it allows to transfer r.x directory contents, as we create it rwx initially
struct stat buf;
if (!mkdir(untrusted_name, 0700)) /* safe because of chroot */
return;
if (errno != EEXIST)
do_exit(errno, untrusted_name);
if (stat(untrusted_name,&buf) < 0)
do_exit(errno, untrusted_name);
total_bytes += buf.st_size;
/* size accumulated after the fact, so don't check limit here */
fix_times_and_perms(untrusted_hdr, untrusted_name);
}
void process_one_file_link(struct file_header *untrusted_hdr,
const char *untrusted_name)
const char *untrusted_name)
{
char untrusted_content[MAX_PATH_LENGTH];
unsigned int filelen;
if (untrusted_hdr->filelen > MAX_PATH_LENGTH - 1)
do_exit(ENAMETOOLONG, untrusted_name);
filelen = untrusted_hdr->filelen; /* sanitized above */
total_bytes += filelen;
if (bytes_limit && total_bytes > bytes_limit)
do_exit(EDQUOT, untrusted_name);
if (!read_all_with_crc(0, untrusted_content, filelen))
do_exit(LEGAL_EOF, untrusted_name); // hopefully remote has produced error message
untrusted_content[filelen] = 0;
if (symlink(untrusted_content, untrusted_name)) /* safe because of chroot */
do_exit(errno, untrusted_name);
char untrusted_content[MAX_PATH_LENGTH];
unsigned int filelen;
if (untrusted_hdr->filelen > MAX_PATH_LENGTH - 1)
do_exit(ENAMETOOLONG, untrusted_name);
filelen = untrusted_hdr->filelen; /* sanitized above */
total_bytes += filelen;
if (bytes_limit && total_bytes > bytes_limit)
do_exit(EDQUOT, untrusted_name);
if (!read_all_with_crc(0, untrusted_content, filelen))
do_exit(LEGAL_EOF, untrusted_name); // hopefully remote has produced error message
untrusted_content[filelen] = 0;
if (symlink(untrusted_content, untrusted_name)) /* safe because of chroot */
do_exit(errno, untrusted_name);
}
void process_one_file(struct file_header *untrusted_hdr)
{
unsigned int namelen;
if (untrusted_hdr->namelen > MAX_PATH_LENGTH - 1)
do_exit(ENAMETOOLONG, NULL); /* filename too long so not received at all */
namelen = untrusted_hdr->namelen; /* sanitized above */
if (!read_all_with_crc(0, untrusted_namebuf, namelen))
do_exit(LEGAL_EOF, NULL); // hopefully remote has produced error message
untrusted_namebuf[namelen] = 0;
if (S_ISREG(untrusted_hdr->mode))
process_one_file_reg(untrusted_hdr, untrusted_namebuf);
else if (S_ISLNK(untrusted_hdr->mode))
process_one_file_link(untrusted_hdr, untrusted_namebuf);
else if (S_ISDIR(untrusted_hdr->mode))
process_one_file_dir(untrusted_hdr, untrusted_namebuf);
else
do_exit(EINVAL, untrusted_namebuf);
if (verbose && !S_ISDIR(untrusted_hdr->mode))
fprintf(stderr, "%s\n", untrusted_namebuf);
unsigned int namelen;
if (untrusted_hdr->namelen > MAX_PATH_LENGTH - 1)
do_exit(ENAMETOOLONG, NULL); /* filename too long so not received at all */
namelen = untrusted_hdr->namelen; /* sanitized above */
if (!read_all_with_crc(0, untrusted_namebuf, namelen))
do_exit(LEGAL_EOF, NULL); // hopefully remote has produced error message
untrusted_namebuf[namelen] = 0;
if (S_ISREG(untrusted_hdr->mode))
process_one_file_reg(untrusted_hdr, untrusted_namebuf);
else if (S_ISLNK(untrusted_hdr->mode))
process_one_file_link(untrusted_hdr, untrusted_namebuf);
else if (S_ISDIR(untrusted_hdr->mode))
process_one_file_dir(untrusted_hdr, untrusted_namebuf);
else
do_exit(EINVAL, untrusted_namebuf);
if (verbose && !S_ISDIR(untrusted_hdr->mode))
fprintf(stderr, "%s\n", untrusted_namebuf);
}
int do_unpack(void)
{
struct file_header untrusted_hdr;
struct file_header untrusted_hdr;
#ifdef HAVE_SYNCFS
int cwd_fd;
int saved_errno;
int cwd_fd;
int saved_errno;
#endif
total_bytes = total_files = 0;
/* initialize checksum */
crc32_sum = 0;
while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) {
/* check for end of transfer marker */
if (untrusted_hdr.namelen == 0) {
errno = 0;
break;
}
total_files++;
if (files_limit && total_files > files_limit)
do_exit(EDQUOT, untrusted_namebuf);
process_one_file(&untrusted_hdr);
}
total_bytes = total_files = 0;
/* initialize checksum */
crc32_sum = 0;
while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) {
/* check for end of transfer marker */
if (untrusted_hdr.namelen == 0) {
errno = 0;
break;
}
total_files++;
if (files_limit && total_files > files_limit)
do_exit(EDQUOT, untrusted_namebuf);
process_one_file(&untrusted_hdr);
}
#ifdef HAVE_SYNCFS
saved_errno = errno;
cwd_fd = open(".", O_RDONLY);
if (cwd_fd >= 0 && syncfs(cwd_fd) == 0 && close(cwd_fd) == 0)
errno = saved_errno;
saved_errno = errno;
cwd_fd = open(".", O_RDONLY);
if (cwd_fd >= 0 && syncfs(cwd_fd) == 0 && close(cwd_fd) == 0)
errno = saved_errno;
#endif
send_status_and_crc(errno, untrusted_namebuf);
return errno;
send_status_and_crc(errno, untrusted_namebuf);
return errno;
}

View File

@ -34,86 +34,86 @@ reports that "fd" is writable. Write as much as possible to fd.
*/
int flush_client_data(int fd, struct buffer *buffer)
{
int ret;
int len;
for (;;) {
len = buffer_len(buffer);
if (!len) {
return WRITE_STDIN_OK;
}
if (len > MAX_DATA_CHUNK)
len = MAX_DATA_CHUNK;
ret = write(fd, buffer_data(buffer), len);
if (ret == -1) {
if (errno != EAGAIN) {
return WRITE_STDIN_ERROR;
} else
return WRITE_STDIN_BUFFERED;
}
// we previously called buffer_remove(buffer, len)
// it will be wrong if we change MAX_DATA_CHUNK to something large
// as pipes writes are atomic only to PIPE_MAX limit
buffer_remove(buffer, ret);
}
int ret;
int len;
for (;;) {
len = buffer_len(buffer);
if (!len) {
return WRITE_STDIN_OK;
}
if (len > MAX_DATA_CHUNK)
len = MAX_DATA_CHUNK;
ret = write(fd, buffer_data(buffer), len);
if (ret == -1) {
if (errno != EAGAIN) {
return WRITE_STDIN_ERROR;
} else
return WRITE_STDIN_BUFFERED;
}
// we previously called buffer_remove(buffer, len)
// it will be wrong if we change MAX_DATA_CHUNK to something large
// as pipes writes are atomic only to PIPE_MAX limit
buffer_remove(buffer, ret);
}
}
/*
Write "len" bytes from "data" to "fd". If not all written, buffer the rest
to "buffer".
*/
* Write "len" bytes from "data" to "fd". If not all written, buffer the rest
* to "buffer".
*/
int write_stdin(int fd, const char *data, int len, struct buffer *buffer)
{
int ret;
int written = 0;
int ret;
int written = 0;
if (buffer_len(buffer)) {
buffer_append(buffer, data, len);
return WRITE_STDIN_BUFFERED;
}
while (written < len) {
ret = write(fd, data + written, len - written);
if (ret == 0) {
perror("write_stdin: write returns 0 ???");
exit(1);
}
if (ret == -1) {
if (errno != EAGAIN)
return WRITE_STDIN_ERROR;
if (buffer_len(buffer)) {
buffer_append(buffer, data, len);
return WRITE_STDIN_BUFFERED;
}
while (written < len) {
ret = write(fd, data + written, len - written);
if (ret == 0) {
perror("write_stdin: write returns 0 ???");
exit(1);
}
if (ret == -1) {
if (errno != EAGAIN)
return WRITE_STDIN_ERROR;
buffer_append(buffer, data + written,
len - written);
buffer_append(buffer, data + written,
len - written);
return WRITE_STDIN_BUFFERED;
}
written += ret;
}
return WRITE_STDIN_OK;
return WRITE_STDIN_BUFFERED;
}
written += ret;
}
return WRITE_STDIN_OK;
}
/*
Data feed process has exited, so we need to clear all control structures for
the client. However, if we have buffered data for the client (which is rare btw),
fire&forget a separate process to flush them.
*/
* Data feed process has exited, so we need to clear all control structures for
* the client. However, if we have buffered data for the client (which is rare btw),
* fire&forget a separate process to flush them.
*/
int fork_and_flush_stdin(int fd, struct buffer *buffer)
{
int i;
if (!buffer_len(buffer))
return 0;
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
break;
default:
return 1;
}
for (i = 0; i < MAX_FDS; i++)
if (i != fd && i != 2)
close(i);
set_block(fd);
write_all(fd, buffer_data(buffer), buffer_len(buffer));
_exit(0);
int i;
if (!buffer_len(buffer))
return 0;
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
break;
default:
return 1;
}
for (i = 0; i < MAX_FDS; i++)
if (i != fd && i != 2)
close(i);
set_block(fd);
write_all(fd, buffer_data(buffer), buffer_len(buffer));
_exit(0);
}