X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/332cf6df7c32dbaa47cbfe515121da7bd53974e8..e73eed8563d21ef9ce83725cb09a3c2e14a40dbe:/io.c diff --git a/io.c b/io.c index 1c858802..62990b97 100644 --- a/io.c +++ b/io.c @@ -7,8 +7,9 @@ * Copyright (C) 2003-2007 Wayne Davison * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,8 +17,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + * with this program; if not, visit the http://fsf.org website. */ /* Rsync provides its own multiplexing system, which is used to send @@ -50,7 +50,6 @@ extern int checksum_seed; extern int protocol_version; extern int remove_source_files; extern int preserve_hard_links; -extern char *filesfrom_host; extern struct stats stats; extern struct file_list *cur_flist, *first_flist; #ifdef ICONV_OPTION @@ -112,11 +111,11 @@ static char int_byte_extra[64] = { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, /* (C0 - FF)/4 */ }; +enum festatus { FES_SUCCESS, FES_REDO, FES_NO_SEND }; + static void readfd(int fd, char *buffer, size_t N); static void writefd(int fd, const char *buf, size_t len); static void writefd_unbuffered(int fd, const char *buf, size_t len); -static void decrement_active_files(int ndx); -static void decrement_flist_in_progress(int ndx, int redo); static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len, int convert); struct flist_ndx_item { @@ -175,6 +174,42 @@ static int flist_ndx_pop(struct flist_ndx_list *lp) return ndx; } +static void got_flist_entry_status(enum festatus status, const char *buf) +{ + int ndx = IVAL(buf, 0); + struct file_list *flist = flist_for_ndx(ndx); + + assert(flist != NULL); + assert(ndx >= flist->ndx_start); + + if (remove_source_files) { + active_filecnt--; + active_bytecnt -= F_LENGTH(flist->files[ndx - flist->ndx_start]); + } + + if (inc_recurse) + flist->in_progress--; + + switch (status) { + case FES_SUCCESS: + if (remove_source_files) + send_msg(MSG_SUCCESS, buf, 4, 0); + if (preserve_hard_links) { + struct file_struct *file = flist->files[ndx - flist->ndx_start]; + if (F_IS_HLINKED(file)) + flist_ndx_push(&hlink_list, ndx); + } + break; + case FES_REDO: + if (inc_recurse) + flist->to_redo++; + flist_ndx_push(&redo_list, ndx); + break; + case FES_NO_SEND: + break; + } +} + static void check_timeout(void) { time_t t; @@ -327,11 +362,7 @@ static void read_msg_fd(void) if (len != 4 || !am_generator) goto invalid_msg; readfd(fd, buf, 4); - if (remove_source_files) - decrement_active_files(IVAL(buf,0)); - flist_ndx_push(&redo_list, IVAL(buf,0)); - if (inc_recurse) - decrement_flist_in_progress(IVAL(buf,0), 1); + got_flist_entry_status(FES_REDO, buf); break; case MSG_FLIST: if (len != 4 || !am_generator || !inc_recurse) @@ -340,8 +371,16 @@ static void read_msg_fd(void) /* Read extra file list from receiver. */ assert(iobuf_in != NULL); assert(iobuf_f_in == fd); + if (verbose > 3) { + rprintf(FINFO, "[%s] receiving flist for dir %d\n", + who_am_i(), IVAL(buf,0)); + } flist = recv_file_list(fd); flist->parent_ndx = IVAL(buf,0); +#ifdef SUPPORT_HARD_LINKS + if (preserve_hard_links) + match_hard_links(flist); +#endif break; case MSG_FLIST_EOF: if (len != 0 || !am_generator || !inc_recurse) @@ -357,22 +396,14 @@ static void read_msg_fd(void) case MSG_SUCCESS: if (len != 4 || !am_generator) goto invalid_msg; - readfd(fd, buf, len); - if (remove_source_files) { - decrement_active_files(IVAL(buf,0)); - send_msg(MSG_SUCCESS, buf, len, 0); - } - if (preserve_hard_links) - flist_ndx_push(&hlink_list, IVAL(buf,0)); - if (inc_recurse) - decrement_flist_in_progress(IVAL(buf,0), 0); + readfd(fd, buf, 4); + got_flist_entry_status(FES_SUCCESS, buf); break; case MSG_NO_SEND: if (len != 4 || !am_generator) goto invalid_msg; - readfd(fd, buf, len); - if (inc_recurse) - decrement_flist_in_progress(IVAL(buf,0), 0); + readfd(fd, buf, 4); + got_flist_entry_status(FES_NO_SEND, buf); break; case MSG_SOCKERR: case MSG_CLIENT: @@ -423,40 +454,6 @@ void increment_active_files(int ndx, int itemizing, enum logcode code) active_bytecnt += F_LENGTH(cur_flist->files[ndx - cur_flist->ndx_start]); } -static void decrement_active_files(int ndx) -{ - struct file_list *flist = flist_for_ndx(ndx); - assert(flist != NULL); - active_filecnt--; - active_bytecnt -= F_LENGTH(flist->files[ndx - flist->ndx_start]); -} - -static void decrement_flist_in_progress(int ndx, int redo) -{ - struct file_list *flist = cur_flist ? cur_flist : first_flist; - - while (ndx < flist->ndx_start) { - if (flist == first_flist) { - invalid_ndx: - rprintf(FERROR, - "Invalid file index: %d (%d - %d) [%s]\n", - ndx, first_flist->ndx_start, - first_flist->prev->ndx_start + first_flist->prev->count - 1, - who_am_i()); - exit_cleanup(RERR_PROTOCOL); - } - flist = flist->prev; - } - while (ndx >= flist->ndx_start + flist->count) { - if (!(flist = flist->next)) - goto invalid_ndx; - } - - flist->in_progress--; - if (redo) - flist->to_redo++; -} - /* Write an message to a multiplexed stream. If this fails, rsync exits. */ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len, int convert) { @@ -673,7 +670,7 @@ static int read_timeout(int fd, char *buf, size_t len) io_filesfrom_bp = io_filesfrom_buf; else io_filesfrom_bp += l; - } else { + } else if (errno != EINTR) { /* XXX should we complain? */ io_filesfrom_f_out = -1; } @@ -684,11 +681,13 @@ static int read_timeout(int fd, char *buf, size_t len) io_filesfrom_buf, sizeof io_filesfrom_buf); if (l <= 0) { - /* Send end-of-file marker */ - io_filesfrom_buf[0] = '\0'; - io_filesfrom_buf[1] = '\0'; - io_filesfrom_buflen = io_filesfrom_lastchar? 2 : 1; - io_filesfrom_f_in = -1; + if (l == 0 || errno != EINTR) { + /* Send end-of-file marker */ + io_filesfrom_buf[0] = '\0'; + io_filesfrom_buf[1] = '\0'; + io_filesfrom_buflen = io_filesfrom_lastchar? 2 : 1; + io_filesfrom_f_in = -1; + } } else { if (!eol_nulls) { char *s = io_filesfrom_buf + l; @@ -757,17 +756,14 @@ static int read_timeout(int fd, char *buf, size_t len) return cnt; } -/* Read a line into the "fname" buffer (which must be at least MAXPATHLEN - * characters long). */ -int read_filesfrom_line(int fd, char *fname) +/* Read a line into the "buf" buffer. */ +int read_line(int fd, char *buf, size_t bufsiz, int dump_comments, int rl_nulls) { - char ch, *s, *eob = fname + MAXPATHLEN - 1; + char ch, *s, *eob = buf + bufsiz - 1; int cnt; - int reading_remotely = filesfrom_host != NULL; - int nulls = eol_nulls || reading_remotely; start: - s = fname; + s = buf; while (1) { cnt = read(fd, &ch, 1); if (cnt < 0 && (errno == EWOULDBLOCK @@ -782,17 +778,15 @@ int read_filesfrom_line(int fd, char *fname) tv.tv_usec = 0; if (!select(fd+1, &r_fds, NULL, &e_fds, &tv)) check_timeout(); - if (FD_ISSET(fd, &e_fds)) { - rsyserr(FINFO, errno, - "select exception on fd %d", fd); - } + /*if (FD_ISSET(fd, &e_fds)) + rprintf(FINFO, "select exception on fd %d\n", fd); */ continue; } if (cnt != 1) break; - if (nulls? !ch : (ch == '\r' || ch == '\n')) { - /* Skip empty lines if reading locally. */ - if (!reading_remotely && s == fname) + if (rl_nulls ? ch == '\0' : (ch == '\r' || ch == '\n')) { + /* Skip empty lines if dumping comments. */ + if (dump_comments && s == buf) continue; break; } @@ -801,11 +795,57 @@ int read_filesfrom_line(int fd, char *fname) } *s = '\0'; - /* Dump comments. */ - if (*fname == '#' || *fname == ';') + if (dump_comments && (*buf == '#' || *buf == ';')) goto start; - return s - fname; + return s - buf; +} + +int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls, + char ***argv_p, int *argc_p, char **request_p) +{ + int maxargs = MAX_ARGS; + int dot_pos = 0; + int argc = 0; + char **argv, *p; + + if (!(argv = new_array(char *, maxargs))) + out_of_memory("read_args"); + if (mod_name) + argv[argc++] = "rsyncd"; + + while (1) { + if (read_line(f_in, buf, bufsiz, 0, rl_nulls) == 0) + break; + + if (argc == maxargs) { + maxargs += MAX_ARGS; + if (!(argv = realloc_array(argv, char *, maxargs))) + out_of_memory("read_args"); + } + + if (dot_pos) { + if (request_p) { + *request_p = strdup(buf); + request_p = NULL; + } + if (mod_name) + glob_expand_module(mod_name, buf, &argv, &argc, &maxargs); + else + glob_expand(buf, &argv, &argc, &maxargs); + } else { + if (!(p = strdup(buf))) + out_of_memory("read_args"); + argv[argc++] = p; + if (*p == '.' && p[1] == '\0') + dot_pos = argc; + } + } + + *argc_p = argc; + *argv_p = argv; + + return dot_pos ? dot_pos : argc; } int io_start_buffering_out(int f_out) @@ -871,7 +911,7 @@ void maybe_send_keepalive(void) if (protocol_version >= 30) send_msg(MSG_NOOP, "", 0, 0); else { - write_int(sock_f_out, cur_flist->count); + write_int(sock_f_out, cur_flist->used); write_shortint(sock_f_out, ITEM_IS_NEW); } } @@ -1364,10 +1404,8 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len) continue; } - if (FD_ISSET(fd, &e_fds)) { - rsyserr(FINFO, errno, - "select exception on fd %d", fd); - } + /*if (FD_ISSET(fd, &e_fds)) + rprintf(FINFO, "select exception on fd %d\n", fd); */ if (using_r_fds && FD_ISSET(msg_fd_in, &r_fds)) read_msg_fd(); @@ -1401,7 +1439,7 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len) (long)len, who_am_i()); /* If the other side is sending us error messages, try * to grab any messages they sent before they died. */ - while (fd == sock_f_out && io_multiplexing_in) { + while (!am_server && fd == sock_f_out && io_multiplexing_in) { set_io_timeout(30); ignore_timeout = 0; readfd_unbuffered(sock_f_in, io_filesfrom_buf, @@ -1680,16 +1718,13 @@ int32 read_ndx(int f) return num; } -/** - * Read a line of up to @p maxlen characters into @p buf (not counting - * the trailing null). Strips the (required) trailing newline and all - * carriage returns. - * - * @return 1 for success; 0 for I/O error or truncation. - **/ -int read_line(int f, char *buf, size_t maxlen) +/* Read a line of up to bufsiz-1 characters into buf. Strips + * the (required) trailing newline and all carriage returns. + * Returns 1 for success; 0 for I/O error or truncation. */ +int read_line_old(int f, char *buf, size_t bufsiz) { - while (maxlen) { + bufsiz--; /* leave room for the null */ + while (bufsiz > 0) { buf[0] = 0; read_buf(f, buf, 1); if (buf[0] == 0) @@ -1698,11 +1733,11 @@ int read_line(int f, char *buf, size_t maxlen) break; if (buf[0] != '\r') { buf++; - maxlen--; + bufsiz--; } } *buf = '\0'; - return maxlen > 0; + return bufsiz > 0; } void io_printf(int fd, const char *format, ...)