コード例 #1
0
ファイル: receiver.c プロジェクト: clobrother/backuppc4
/**
 * main routine for receiver process.
 *
 * Receiver process runs on the same host as the generator process. */
int recv_files(int f_in, char *local_name)
{
	int fd1,fd2;
	STRUCT_STAT st;
	int iflags, xlen;
	char *fname, fbuf[MAXPATHLEN];
	char xname[MAXPATHLEN];
	char fnametmp[MAXPATHLEN];
	char *fnamecmp, *partialptr;
	char fnamecmpbuf[MAXPATHLEN];
	uchar fnamecmp_type;
	struct file_struct *file;
	struct stats initial_stats;
	int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
	enum logcode log_code = log_before_transfer ? FLOG : FINFO;
	int max_phase = protocol_version >= 29 ? 2 : 1;
	int dflt_perms = (ACCESSPERMS & ~orig_umask);
#if 0 /* was SUPPORT_ACLS */
	const char *parent_dirname = "";
#endif
	int ndx, recv_ok;

	if (verbose > 2)
		rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);

	if (delay_updates)
		delayed_bits = bitbag_create(cur_flist->used + 1);

	while (1) {
                struct sum_struct sum;
                int numMatchTokens = -1, nextToken = 0;
                char *nextData = NULL;
                static char file_sum[MAX_DIGEST_LEN];

		cleanup_disable();

		/* This call also sets cur_flist. */
		ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
					 xname, &xlen);
		if (ndx == NDX_DONE) {
			if (inc_recurse && first_flist) {
				if (read_batch)
					gen_wants_ndx(first_flist->used + first_flist->ndx_start);
				flist_free(first_flist);
				if (first_flist)
					continue;
			} else if (read_batch && first_flist)
				gen_wants_ndx(first_flist->used);
			if (++phase > max_phase)
				break;
			if (verbose > 2)
				rprintf(FINFO, "recv_files phase=%d\n", phase);
			if (phase == 2 && delay_updates)
				handle_delayed_updates(local_name);
			send_msg(MSG_DONE, "", 0, 0);
			continue;
		}

		if (ndx - cur_flist->ndx_start >= 0)
			file = cur_flist->files[ndx - cur_flist->ndx_start];
		else
			file = dir_flist->files[cur_flist->parent_ndx];
		fname = local_name ? local_name : f_name(file, fbuf);

		if (verbose > 2)
			rprintf(FINFO, "recv_files(%s)\n", fname);

#ifdef SUPPORT_XATTRS
		if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
			recv_xattr_request(file, f_in);
#endif

		if (!(iflags & ITEM_TRANSFER)) {
			maybe_log_item(file, iflags, itemizing, xname);
#ifdef SUPPORT_XATTRS
			if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
			 && !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))
				set_file_attrs(fname, file, NULL, fname, 0);
#endif
			continue;
		}
		if (phase == 2) {
			rprintf(FERROR,
				"got transfer request in phase 2 [%s]\n",
				who_am_i());
			exit_cleanup(RERR_PROTOCOL);
		}

		if (file->flags & FLAG_FILE_SENT) {
			if (csum_length == SHORT_SUM_LENGTH) {
				if (keep_partial && !partial_dir)
					make_backups = -make_backups; /* prevents double backup */
				if (append_mode)
					sparse_files = -sparse_files;
				append_mode = -append_mode;
				csum_length = SUM_LENGTH;
				redoing = 1;
			}
		} else {
			if (csum_length != SHORT_SUM_LENGTH) {
				if (keep_partial && !partial_dir)
					make_backups = -make_backups;
				if (append_mode)
					sparse_files = -sparse_files;
				append_mode = -append_mode;
				csum_length = SHORT_SUM_LENGTH;
				redoing = 0;
			}
		}

		if (!am_server && do_progress)
			set_current_file_index(file, ndx);
		stats.num_transferred_files++;
		stats.total_transferred_size += F_LENGTH(file);

		cleanup_got_literal = 0;

		if (daemon_filter_list.head
		    && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) {
			rprintf(FERROR, "attempt to hack rsync failed.\n");
			exit_cleanup(RERR_PROTOCOL);
		}

                read_sum_head(f_in, &sum);

		if (read_batch) {
			int wanted = redoing
				   ? we_want_redo(ndx)
				   : gen_wants_ndx(ndx);
			if (!wanted) {
				rprintf(FINFO,
					"(Skipping batched update for%s \"%s\")\n",
					redoing ? " resend of" : "",
					fname);
				discard_receive_data(f_in, F_LENGTH(file),
                                                     &sum, numMatchTokens, nextToken, nextData, file_sum);
				file->flags |= FLAG_FILE_SENT;
				continue;
			}
		}

		if (!do_xfers) { /* log the transfer */
			log_item(FCLIENT, file, &stats, iflags, NULL);
			if (read_batch)
				discard_receive_data(f_in, F_LENGTH(file),
                                                     &sum, numMatchTokens, nextToken, nextData, file_sum);
			continue;
		}
		if (write_batch < 0) {
			log_item(FCLIENT, file, &stats, iflags, NULL);
			if (!am_server)
				discard_receive_data(f_in, F_LENGTH(file),
                                                     &sum, numMatchTokens, nextToken, nextData, file_sum);
			continue;
		}

		partialptr = partial_dir ? partial_dir_fname(fname) : fname;

		if (protocol_version >= 29) {
			switch (fnamecmp_type) {
			case FNAMECMP_FNAME:
				fnamecmp = fname;
				break;
			case FNAMECMP_PARTIAL_DIR:
				fnamecmp = partialptr;
				break;
			case FNAMECMP_BACKUP:
				fnamecmp = get_backup_name(fname);
				break;
			case FNAMECMP_FUZZY:
				if (file->dirname) {
					pathjoin(fnamecmpbuf, MAXPATHLEN,
						 file->dirname, xname);
					fnamecmp = fnamecmpbuf;
				} else
					fnamecmp = xname;
				break;
			default:
				if (fnamecmp_type >= basis_dir_cnt) {
					rprintf(FERROR,
						"invalid basis_dir index: %d.\n",
						fnamecmp_type);
					exit_cleanup(RERR_PROTOCOL);
				}
				pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
					 basis_dir[fnamecmp_type], fname);
				fnamecmp = fnamecmpbuf;
				break;
			}
			if (!fnamecmp || (daemon_filter_list.head
			  && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0)) {
				fnamecmp = fname;
				fnamecmp_type = FNAMECMP_FNAME;
			}
		} else {
			/* Reminder: --inplace && --partial-dir are never
			 * enabled at the same time. */
			if (inplace && make_backups > 0) {
				if (!(fnamecmp = get_backup_name(fname)))
					fnamecmp = fname;
				else
					fnamecmp_type = FNAMECMP_BACKUP;
			} else if (partial_dir && partialptr)
				fnamecmp = partialptr;
			else
				fnamecmp = fname;
		}

		initial_stats = stats;

                /*
                 * Opening/reading/writing files in BackupPC is quite expensive, given the
                 * compression.  Before we open the file and call mkstemp, we peek ahead at
                 * the delta tokens to see if the file is unchanged.  If so, we skip the file
                 * open, mkstemp and writing.  The file is unchanged if the tokens
                 * are sequential matching block numbers, which are encoded as
                 * negative integers (ie: -1, -2, -3...), with no literal data
                 * tokens (which have positive numbers).
                 *
                 * If the file has changed, at some point a matching block token
                 * will be out of order, or we will encounter a literal data token.
                 * At that point, we stop reading ahead and proceed as normal.
                 * We pass the number of matching block tokens, and the first
                 * unexpected token, to receive_data(), so it can process all
                 * the tokens back (basically playing them back).
                 *
                 * Of course, this only applies if the file exists already,
                 * and protocol_version 30 is required since older protocols
                 * use MD4 for the full-file digest, not MD5.
                 *
                 * First we need to read the sum struct, then start reading the
                 * tokens.
                 */
                recv_ok = 0;
                if ( protocol_version >= 30 ) {
                    numMatchTokens = 0;
                    while ( (nextToken = recv_token(f_in, &nextData)) != 0 ) {
                        if ( nextToken != -numMatchTokens - 1 ) break;
                        numMatchTokens++;
                    }
                    if ( nextToken == 0 ) {
                        OFF_T flength = (OFF_T)numMatchTokens * sum.blength;
                        if ( sum.remainder && numMatchTokens > 0 )
                                flength -= sum.blength - sum.remainder;
                        /*
                         * Likely exact match - read the final file digest and make
                         * sure the digest and file size match the existing file.
                         * If so, this call creates the temporary file so the
                         * attributes can be checked/set, and then renamed as
                         * before.
                         */
                        read_buf(f_in, file_sum, MD5_DIGEST_LEN);
                        if ( !bpc_sysCall_checkFileMatch(fnamecmp, fnametmp, file, file_sum, flength) ) {
                            recv_ok = 1;
                            if ( log_before_transfer ) {
                                iflags &= ~ITEM_REPORT_CHANGE;
                                log_item(FCLIENT, file, &initial_stats, iflags, NULL);
                            }
                        }
                    }
                }
                if ( !recv_ok ) {
                    /*
                     * proceed as normal, remembering to replay the tokens we read ahead above:
                     * first, numMatchTokens: -1, -2, ..., -numMatchTokens,
                     * then (nextToken,nextData).  After that we go back to reading the
                     * remaining tokens from f_in.
                     */

                    /* open the file */
                    fd1 = do_open(fnamecmp, O_RDONLY, 0);

                    if ( fd1 < 0 && protocol_version >= 30 && always_checksum ) {
                        /*
                         * For protocol_version >= 30 and if always_checksum is set, we can use the
                         * MD5 whole-file digest to check for a potential match via the pool.
                         * Use that as the basis if the file is there.  The generator does
                         * the same in recv_generator().
                         */
                        if ( S_ISREG(file->mode) && !bpc_sysCall_poolFileCheck(fnamecmp, file) ) {
                            fd1 = do_open(fnamecmp, O_RDONLY, 0);
                        }
                    }

                    if (fd1 == -1 && protocol_version < 29) {
                            if (fnamecmp != fname) {
                                    fnamecmp = fname;
                                    fd1 = do_open(fnamecmp, O_RDONLY, 0);
                            }

                            if (fd1 == -1 && basis_dir[0]) {
                                    /* pre-29 allowed only one alternate basis */
                                    pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
                                             basis_dir[0], fname);
                                    fnamecmp = fnamecmpbuf;
                                    fd1 = do_open(fnamecmp, O_RDONLY, 0);
                            }
                    }

                    updating_basis_or_equiv = inplace
                        && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);

                    if (fd1 == -1) {
                            st.st_mode = 0;
                            st.st_size = 0;
                    } else if (do_fstat(fd1,&st) != 0) {
                            rsyserr(FERROR_XFER, errno, "fstat %s failed",
                                    full_fname(fnamecmp));
                            discard_receive_data(f_in, F_LENGTH(file),
                                                 &sum, numMatchTokens, nextToken, nextData, file_sum);
                            bpc_close(fd1);
                            if (inc_recurse)
                                    send_msg_int(MSG_NO_SEND, ndx);
                            continue;
                    }

                    if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
                            /* this special handling for directories
                             * wouldn't be necessary if robust_rename()
                             * and the underlying robust_unlink could cope
                             * with directories
                             */
                            rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
                                    full_fname(fnamecmp));
                            discard_receive_data(f_in, F_LENGTH(file),
                                                 &sum, numMatchTokens, nextToken, nextData, file_sum);
                            bpc_close(fd1);
                            if (inc_recurse)
                                    send_msg_int(MSG_NO_SEND, ndx);
                            continue;
                    }

                    if (fd1 != -1 && !S_ISREG(st.st_mode)) {
                            bpc_close(fd1);
                            fd1 = -1;
                    }

                    /* If we're not preserving permissions, change the file-list's
                     * mode based on the local permissions and some heuristics. */
                    if (!preserve_perms) {
                            int exists = fd1 != -1;
    #if 0 /* was SUPPORT_ACLS */
                            const char *dn = file->dirname ? file->dirname : ".";
                            if (parent_dirname != dn
                             && strcmp(parent_dirname, dn) != 0) {
                                    dflt_perms = default_perms_for_dir(dn);
                                    parent_dirname = dn;
                            }
    #endif
                            file->mode = dest_mode(file->mode, st.st_mode,
                                                   dflt_perms, exists);
                    }

                    /* We now check to see if we are writing the file "inplace" */
                    if (inplace)  {
                            fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
                            if (fd2 == -1) {
                                    rsyserr(FERROR_XFER, errno, "open %s failed",
                                            full_fname(fname));
                            }
                    } else {
                            fd2 = open_tmpfile(fnametmp, fname, file);
                            if (fd2 != -1)
                                    cleanup_set(fnametmp, partialptr, file, fd1, fd2);
                    }

                    if (fd2 == -1) {
                            discard_receive_data(f_in, F_LENGTH(file),
                                                 &sum, numMatchTokens, nextToken, nextData, file_sum);
                            if (fd1 != -1)
                                    bpc_close(fd1);
                            if (inc_recurse)
                                    send_msg_int(MSG_NO_SEND, ndx);
                            continue;
                    }

                    /* log the transfer */
                    if (log_before_transfer)
                            log_item(FCLIENT, file, &initial_stats, iflags, NULL);
                    else if (!am_server && verbose && do_progress)
                            rprintf(FINFO, "%s\n", fname);

                    /* recv file data */
                    recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
                                           fname, fd2, F_LENGTH(file),
                                           &sum, numMatchTokens, nextToken, nextData, file_sum);

                    if (fd1 != -1)
                            bpc_close(fd1);
                    if (bpc_close(fd2) < 0) {
                            rsyserr(FERROR, errno, "close failed on %s",
                                    full_fname(fnametmp));
                            exit_cleanup(RERR_FILEIO);
                    }
                }

                log_item(log_code, file, &initial_stats, iflags, NULL);

		if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
			if (partialptr == fname)
				partialptr = NULL;
			if (!finish_transfer(fname, fnametmp, fnamecmp,
					     partialptr, file, recv_ok, 1))
				recv_ok = -1;
			else if (fnamecmp == partialptr) {
				do_unlink(partialptr);
				handle_partial_dir(partialptr, PDIR_DELETE);
			}
		} else if (keep_partial && partialptr) {
			if (!handle_partial_dir(partialptr, PDIR_CREATE)) {
				rprintf(FERROR,
				    "Unable to create partial-dir for %s -- discarding %s.\n",
				    local_name ? local_name : f_name(file, NULL),
				    recv_ok ? "completed file" : "partial file");
				do_unlink(fnametmp);
				recv_ok = -1;
			} else if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
						    file, recv_ok, !partial_dir))
				recv_ok = -1;
			else if (delay_updates && recv_ok) {
				bitbag_set_bit(delayed_bits, ndx);
				recv_ok = 2;
			} else
				partialptr = NULL;
		} else
			do_unlink(fnametmp);

		cleanup_disable();

		if (read_batch)
			file->flags |= FLAG_FILE_SENT;

		switch (recv_ok) {
		case 2:
			break;
		case 1:
			if (remove_source_files || inc_recurse
			 || (preserve_hard_links && F_IS_HLINKED(file)))
				send_msg_int(MSG_SUCCESS, ndx);
			break;
		case 0: {
			enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
			if (msgtype == FERROR_XFER || verbose) {
				char *errstr, *redostr, *keptstr;
				if (!(keep_partial && partialptr) && !inplace)
					keptstr = "discarded";
				else if (partial_dir)
					keptstr = "put into partial-dir";
				else
					keptstr = "retained";
				if (msgtype == FERROR_XFER) {
					errstr = "ERROR";
					redostr = "";
				} else {
					errstr = "WARNING";
					redostr = read_batch ? " (may try again)"
							     : " (will try again)";
				}
				rprintf(msgtype,
					"%s: %s failed verification -- update %s%s.\n",
					errstr, local_name ? f_name(file, NULL) : fname,
					keptstr, redostr);
			}
			if (!redoing) {
				if (read_batch)
					flist_ndx_push(&batch_redo_list, ndx);
				send_msg_int(MSG_REDO, ndx);
				file->flags |= FLAG_FILE_SENT;
                                bpc_sysCall_printfileStatus(fname, "retry");
			} else if (inc_recurse)
				send_msg_int(MSG_NO_SEND, ndx);
                                bpc_sysCall_printfileStatus(fname, "fail");
			break;
		    }
		case -1:
			if (inc_recurse)
				send_msg_int(MSG_NO_SEND, ndx);
			break;
		}
	}
	if (make_backups < 0)
		make_backups = -make_backups;

	if (phase == 2 && delay_updates) /* for protocol_version < 29 */
		handle_delayed_updates(local_name);

	if (verbose > 2)
		rprintf(FINFO,"recv_files finished\n");

	return 0;
}
コード例 #2
0
 void
 Receiver_exec_i::run (::CORBA::UShort run)
 {
   if (this->ticker_)
     {
       this->reactor ()->cancel_timer (this->ticker_);
       delete this->ticker_;
       this->ticker_ = 0;
     }
   ACE_DEBUG ((LM_DEBUG, "Receiver_exec_i::run - "
                         "Starting run number <%d>\n",
                         run));
   TwoQueriesRestarter_var restarter =
     this->ciao_context_->get_connection_writer_restart ();
   if (!::CORBA::is_nil (restarter.in ()))
     {
       switch (run)
       {
         case 1:
           {
             this->samples_received_ += this->test_all (run);
             this->check_filter (run);
             this->read_all (run);
             //set filter for the next run
             this->set_filter (run + 1);
             // inform the sender that it may start the next run
             restarter->restart_write ();
           }
           break;
         case 2:
           {
             this->samples_received_ += this->test_all (run);
             check_filter (run);
             this->read_all (run);
             //set filter for the next run
             this->set_filter (run + 1);
             // inform the sender that it may start the next run
             restarter->restart_write ();
           }
           break;
         case 3:
           {
             this->samples_received_ += this->test_all (run);
             this->check_filter (run);
             this->read_all (run);
             //set filter for the next run
             this->set_filter (run + 1);
             // inform the sender that it may start the next run
             restarter->restart_write ();
           }
           break;
         case 4:
           {
             this->samples_received_ += this->test_all (run);
             this->read_all (run);
           }
       }
     }
   else
     {
       ACE_ERROR ((LM_ERROR, "Receiver_exec_i::run - "
                 "ERROR: Reference to Restarter not found\n"));
     }
 }
コード例 #3
0
static void raw(char *server, ISI_PARAM *par, int compress, ISI_SEQNO *begseqno, ISI_SEQNO *endseqno, char *SiteSpec)
{
  ISI *isi;
  ISI_RAW_PACKET raw;
  ISI_DATA_REQUEST *dreq;
  UINT8 buf[LOCALBUFLEN];
  UINT64 count = 0;
  int     save_errno;
  int     *int2x32;
  FILE    *fp_seq;
  char    station[8];
  char    chan[8];
  char    loc[8];
  char    loc_station[16];
  char    sequence_str[(8*3+4)*3+6];
  char    seq_filename[2*MAXCONFIGLINELEN+2];
  char    loopDir[2*MAXCONFIGLINELEN+2];
  char    *retmsg;

    dreq = BuildRawRequest(compress, begseqno, endseqno, SiteSpec);

    if (VERBOSE) {
        fprintf(stderr, "Client side data request\n");
        isiPrintDatreq(stderr, dreq);
    }

    if ((isi = isiInitiateDataRequest(server, par, dreq)) == NULL)
    {
        if (errno == ENOENT) {
            if (gDebug)
              fprintf(stderr, "can't connect to server %s, port %d\n", server, par->port);
            else
              syslog(LOG_ERR, "can't connect to server %s, port %d\n", server, par->port);
        } else {
            save_errno = errno;
            if (gDebug)
              perror("isiInitiateDataRequest");
            else
              syslog(LOG_ERR, "isiInitiateDataRequest: %s", strerror(save_errno));
        }
        exit(1);
    }

    isiFreeDataRequest(dreq);

    if (VERBOSE) {
        fprintf(stderr, "Server expanded data request\n");
        isiPrintDatreq(stderr, &isi->datreq);
    }

    while (ReadRawPacket(isi, &raw))
    {
        ++count;
//      if (VERBOSE) fprintf(stderr, "%s\n", isiRawHeaderString(&raw.hdr, buf));
        if (!isiDecompressRawPacket(&raw, buf, LOCALBUFLEN)) {
            fprintf(stderr, "isiDecompressRawPacket error\n");
        } // else if (VERBOSE) {
//            utilPrintHexDump(stderr, raw.payload, 64);
//      }

        SeedHeaderSNLC(raw.payload, station,chan,loc);
        if (filter != NULL) {
          // See if location/channel match our filter string
          sprintf(loc_station, "%2.2s/%3.3s", loc, chan);
          if (check_filter(filter, loc_station) != 1)
            continue;
        }
        int2x32 = (int *)&raw.hdr.seqno.counter;

        if (gDebug)
        {
          fprintf(stderr, "Read %s %s/%s %08x %08x %08x\n",
            station, loc, chan,
            raw.hdr.seqno.signature, int2x32[1], int2x32[0]);
        }

        // Save this record to buffer
        retmsg = WriteChan(station, chan, loc, raw.payload);
        if (retmsg != NULL)
        {
          if (gDebug)
            fprintf(stderr, "WriteChan: %s\n", retmsg);
          else
            syslog(LOG_ERR, "WriteChan: %s\n", retmsg);
        }

        // Save IDA sequence so on a restart, we pick up where we left off
        sprintf(sequence_str,
                "%08x%08x%08x\n"
                "%08x%08x%08x\n"
                "%08x%08x%08x\n",
                raw.hdr.seqno.signature, int2x32[1], int2x32[0],
                raw.hdr.seqno.signature, int2x32[1], int2x32[0],
                raw.hdr.seqno.signature, int2x32[1], int2x32[0]);
        LoopDirectory(loopDir);
        sprintf(seq_filename, "/%s/%s/isi.seq",
                loopDir, SiteSpec);
        if ((fp_seq=fopen(seq_filename, "w+")) == NULL)
        {
          if (gDebug)
            fprintf(stderr, "raw(): failed to create %s",
                  seq_filename);
          else
            syslog(LOG_ERR, "raw(): failed to create %s",
                  seq_filename);
          exit(1);
        } // unable to create index file
        else
        {
          fwrite(sequence_str, strlen(sequence_str), 1, fp_seq);
          fclose(fp_seq);
          fp_seq = NULL;
        } // save latest sequence number to file
    } // While no errors reading from ida disk loop

    if (gDebug)
      fprintf(stderr, "%llu packets received\n", count);
} // raw()
コード例 #4
0
int main(int argc, char **argv)
{
int i, request, isiport;
int depth=-1;
int iRecords;
ISI_PARAM par;
char *req = NULL;
char *log;
char *SiteSpec = NULL;
char *begstr = NULL;
char *endstr = NULL;
char *retstr = NULL;
char *configdir = "/etc/q330/DLG1";
ISI_SEQNO begseqno = ISI_OLDEST_SEQNO;
ISI_SEQNO endseqno = ISI_NEVER_SEQNO;
char *tmpstr;
int compress  = ISI_COMP_NONE;
int format    = ISI_FORMAT_GENERIC;
char configfile[2*MAXCONFIGLINELEN+2];
char seq_filename[2*MAXCONFIGLINELEN+2];
char loopDir[2*MAXCONFIGLINELEN+2];
char sequence_str[3][28];
int *int2x32;
char station[8];
char network[4];
char channel[4];
char location[4];
FILE *fp_seq;

    utilNetworkInit();
    isiInitDefaultPar(&par);

    for (i = 1; i < argc; i++) {
        if (strncmp(argv[i], "server=", strlen("server=")) == 0) {
            server = argv[i] + strlen("server=");
        } else if (strncmp(argv[i], "isiport=", strlen("isiport=")) == 0) {
            isiport = atoi(argv[i] + strlen("isiport="));
            isiSetServerPort(&par, isiport);
        } else if (strncmp(argv[i], "beg=", strlen("beg=")) == 0) {
            begstr = argv[i] + strlen("beg=");
        } else if (strncmp(argv[i], "end=", strlen("end=")) == 0) {
            endstr = argv[i] + strlen("end=");
        } else if (strncmp(argv[i], "debug=", strlen("debug=")) == 0) {
            gDebug = atoi(argv[i] + strlen("debug="));
            isiSetDebugFlag(&par, gDebug);
        } else if (strncmp(argv[i], "log=", strlen("log=")) == 0) {
            log = argv[i] + strlen("log=");
            isiStartLogging(&par, log, NULL, argv[0]);
        } else if (strncmp(argv[i], "filter=", strlen("filter=")) == 0) {
            filter = argv[i] + strlen("filter=");
        } else if (strncmp(argv[i], "dbgpath=", strlen("dbgpath=")) == 0) {
            isiSetDbgpath(&par, argv[i] + strlen("dbgpath="));
        } else if (strncmp(argv[i], "configdir=", strlen("configdir=")) == 0) {
            configdir = argv[i] + strlen("configdir=");
        } else if (strcmp(argv[i], "-v") == 0) {
            flags |= VERBOSE_REPORT;
        } else if (req == NULL) {
            req = argv[i];
        } else {
           if (gDebug)
           {
              fprintf(stderr, "%s: unrecognized argument: '%s'\n", argv[0], argv[i]);
              ShowUsage(argv[0]);
           }
        }
    }

    if (req == NULL)
    {
      ShowUsage(argv[0]);
      exit(1);
    }

    // If we are not in debug mode, run program as a daemon
    gDebug = gDebug || VERBOSE;
    if (gDebug == 0)
      daemonize();

    // Open diskloop.config file
    sprintf(configfile, "%s/diskloop.config", configdir);
    if ((retstr=ParseDiskLoopConfig(configfile)) != NULL)
    {
      if (gDebug)
        fprintf(stderr, "%s: %s\n", WHOAMI, retstr);
      else
        syslog(LOG_ERR, "%s\n", retstr);
      exit(1);
    }
    LogSNCL(station, network, channel, location);

    if (VERBOSE)  fprintf(stderr, "%s  %s\n", VersionIdentString, __DATE__);

    request = UNKNOWN;
    if (strcasecmp(req, "raw") == 0) {
        request = RAW;
        SiteSpec = station;
    } else if (strncasecmp(req, "raw=", strlen("raw=")) == 0) {
        request = RAW;
        SiteSpec = req + strlen("raw=");
        if (strlen(SiteSpec) == 0) SiteSpec = station;
    } else {
        ShowUsage(argv[0]);
    }

    // Check filter string for easy to find syntax errors
    if (check_filter(filter, "##/###") == -1)
    {
      fprintf(stderr, "Syntax error in filter string '%s'\n", filter);
      exit(1);
    }

    // Get beginning sequence number from continuity file
    if (begstr == NULL)
    {
        LoopDirectory(loopDir);
        sprintf(seq_filename, "/%s/%s/isi.seq",
                loopDir, SiteSpec);
        if ((fp_seq=fopen(seq_filename, "r")) == NULL)
        {
          if (gDebug)
            fprintf(stderr, "%s not found, starting at oldest ISI record\n",
                  seq_filename);
          else
            syslog(LOG_INFO, "%s not found, starting at oldest ISI record\n",
                  seq_filename);
        } // unable to find index file
        else
        {
          fgets(sequence_str[0], 28, fp_seq);
          fgets(sequence_str[1], 28, fp_seq);
          fgets(sequence_str[2], 28, fp_seq);
          if (strlen(sequence_str[0]) >= 24 &&
              strlen(sequence_str[1]) >= 24)
          {
            // if fist two lines agree, use them
            begstr = sequence_str[0];
            if (strncmp(sequence_str[0], sequence_str[1], 24) != 0)
            {
              // Otherwise use the 3rd line if it is valid length
              if (strlen(sequence_str[2]) >= 24)
                begstr = sequence_str[2];
              else
                begstr = NULL;
            } // first two lines did not aggree
          } // first two lines have enough characters

          // Check to see if we did not parse a valid resume index
          if (begstr == NULL)
          {
            if (gDebug)
              fprintf(stderr,
                    "%s contents invalid, starting at oldest ISI record\n",
                    seq_filename);
            else
              syslog(LOG_ERR,
                    "%s contents invalid, starting at oldest ISI record\n",
                    seq_filename);
          } // invalid resume index
          else
          {
            // Convert string into an index
            begstr[24] = 0;
            if (!isiStringToSeqno(begstr, &begseqno))
            {
              if (gDebug)
                fprintf(stderr, "illegal beg seqno '%s'\n", begstr);
              else
                syslog(LOG_ERR, "illegal beg seqno '%s'\n", begstr);
              exit(1);
            }
 
            // increment index by one to get next unsaved record
            begseqno.counter++;

            int2x32 = (int *)&begseqno.counter;
            sprintf(begstr, "%08x%08x%08x",
                    begseqno.signature, int2x32[1], int2x32[0]);
          } // else we have what could be an index string
        } // found index file so load last index
    } // if user did not specify a beginning sequence number

    switch (request) {
      case RAW: 
        if (VERBOSE) fprintf(stderr, "%s raw data request\n", server);

        if (begstr != NULL && !isiStringToSeqno(begstr, &begseqno)) {
            fprintf(stderr, "illegal beg seqno '%s'\n", begstr);
            exit(1);
        }
        if (endstr != NULL && !isiStringToSeqno(endstr, &endseqno)) {
            fprintf(stderr, "illegal end seqno '%s'\n", endstr);
            exit(1);
        }
        raw(server, &par, compress, &begseqno, &endseqno, SiteSpec);
        break;
      default:
        ShowUsage(argv[0]);
    } // switch request

    exit(0);
} // main()
コード例 #5
0
ファイル: receiver.c プロジェクト: OPSF/uClinux
/**
 * main routine for receiver process.
 *
 * Receiver process runs on the same host as the generator process. */
int recv_files(int f_in, struct file_list *flist, char *local_name)
{
	int next_gen_i = -1;
	int fd1,fd2;
	STRUCT_STAT st;
	int iflags, xlen;
	char *fname, fbuf[MAXPATHLEN];
	char xname[MAXPATHLEN];
	char fnametmp[MAXPATHLEN];
	char *fnamecmp, *partialptr, numbuf[4];
	char fnamecmpbuf[MAXPATHLEN];
	uchar fnamecmp_type;
	struct file_struct *file;
	struct stats initial_stats;
	int save_make_backups = make_backups;
	int itemizing = am_daemon ? daemon_log_format_has_i
		      : !am_server && log_format_has_i;
	int max_phase = protocol_version >= 29 ? 2 : 1;
	int i, recv_ok;

	if (verbose > 2)
		rprintf(FINFO,"recv_files(%d) starting\n",flist->count);

	if (flist->hlink_pool) {
		pool_destroy(flist->hlink_pool);
		flist->hlink_pool = NULL;
	}

	if (delay_updates)
		init_delayed_bits(flist->count);

	while (1) {
		cleanup_disable();

		i = read_int(f_in);
		if (i == -1) {
			if (read_batch) {
				get_next_gen_i(batch_gen_fd, next_gen_i,
					       flist->count);
				next_gen_i = -1;
			}
			if (++phase > max_phase)
				break;
			csum_length = SUM_LENGTH;
			if (verbose > 2)
				rprintf(FINFO, "recv_files phase=%d\n", phase);
			if (phase == 2 && delay_updates)
				handle_delayed_updates(flist, local_name);
			send_msg(MSG_DONE, "", 0);
			if (keep_partial && !partial_dir)
				make_backups = 0; /* prevents double backup */
			continue;
		}

		iflags = read_item_attrs(f_in, -1, i, &fnamecmp_type,
					 xname, &xlen);
		if (iflags == ITEM_IS_NEW) /* no-op packet */
			continue;

		file = flist->files[i];
		fname = local_name ? local_name : f_name_to(file, fbuf);

		if (verbose > 2)
			rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));

		if (!(iflags & ITEM_TRANSFER)) {
			maybe_log_item(file, iflags, itemizing, xname);
			continue;
		}
		if (phase == 2) {
			rprintf(FERROR,
				"got transfer request in phase 2 [%s]\n",
				who_am_i());
			exit_cleanup(RERR_PROTOCOL);
		}

		stats.current_file_index = i;
		stats.num_transferred_files++;
		stats.total_transferred_size += file->length;
		cleanup_got_literal = 0;

		if (server_filter_list.head
		    && check_filter(&server_filter_list, fname, 0) < 0) {
			rprintf(FERROR, "attempt to hack rsync failed.\n");
			exit_cleanup(RERR_PROTOCOL);
		}

		if (!do_xfers) { /* log the transfer */
			if (!am_server && log_format)
				log_item(file, &stats, iflags, NULL);
			if (read_batch)
				discard_receive_data(f_in, file->length);
			continue;
		}
		if (write_batch < 0) {
			log_item(file, &stats, iflags, NULL);
			if (!am_server)
				discard_receive_data(f_in, file->length);
			continue;
		}

		if (read_batch) {
			next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i);
			if (i < next_gen_i) {
				rprintf(FINFO, "(Skipping batched update for \"%s\")\n",
					safe_fname(fname));
				discard_receive_data(f_in, file->length);
				continue;
			}
			next_gen_i = -1;
		}

		partialptr = partial_dir ? partial_dir_fname(fname) : fname;

		if (protocol_version >= 29) {
			switch (fnamecmp_type) {
			case FNAMECMP_FNAME:
				fnamecmp = fname;
				break;
			case FNAMECMP_PARTIAL_DIR:
				fnamecmp = partialptr;
				break;
			case FNAMECMP_BACKUP:
				fnamecmp = get_backup_name(fname);
				break;
			case FNAMECMP_FUZZY:
				if (file->dirname) {
					pathjoin(fnamecmpbuf, MAXPATHLEN,
						 file->dirname, xname);
					fnamecmp = fnamecmpbuf;
				} else
					fnamecmp = xname;
				break;
			default:
				if (fnamecmp_type >= basis_dir_cnt) {
					rprintf(FERROR,
						"invalid basis_dir index: %d.\n",
						fnamecmp_type);
					exit_cleanup(RERR_PROTOCOL);
				}
				pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
					 basis_dir[fnamecmp_type], fname);
				fnamecmp = fnamecmpbuf;
				break;
			}
			if (!fnamecmp || (server_filter_list.head
			  && check_filter(&server_filter_list, fname, 0) < 0))
				fnamecmp = fname;
		} else {
			/* Reminder: --inplace && --partial-dir are never
			 * enabled at the same time. */
			if (inplace && make_backups) {
				if (!(fnamecmp = get_backup_name(fname)))
					fnamecmp = fname;
			} else if (partial_dir && partialptr)
				fnamecmp = partialptr;
			else
				fnamecmp = fname;
		}

		initial_stats = stats;

		/* open the file */
		fd1 = do_open(fnamecmp, O_RDONLY, 0);

		if (fd1 == -1 && protocol_version < 29) {
			if (fnamecmp != fname) {
				fnamecmp = fname;
				fd1 = do_open(fnamecmp, O_RDONLY, 0);
			}

			if (fd1 == -1 && basis_dir[0]) {
				/* pre-29 allowed only one alternate basis */
				pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
					 basis_dir[0], fname);
				fnamecmp = fnamecmpbuf;
				fd1 = do_open(fnamecmp, O_RDONLY, 0);
			}
		}

		if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
			rsyserr(FERROR, errno, "fstat %s failed",
				full_fname(fnamecmp));
			discard_receive_data(f_in, file->length);
			close(fd1);
			continue;
		}

		if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
			/* this special handling for directories
			 * wouldn't be necessary if robust_rename()
			 * and the underlying robust_unlink could cope
			 * with directories
			 */
			rprintf(FERROR,"recv_files: %s is a directory\n",
				full_fname(fnamecmp));
			discard_receive_data(f_in, file->length);
			close(fd1);
			continue;
		}

		if (fd1 != -1 && !S_ISREG(st.st_mode)) {
			close(fd1);
			fd1 = -1;
		}

		if (fd1 != -1 && !preserve_perms) {
			/* if the file exists already and we aren't preserving
			 * permissions then act as though the remote end sent
			 * us the file permissions we already have */
			file->mode = st.st_mode;
		}

		/* We now check to see if we are writing file "inplace" */
		if (inplace)  {
			fd2 = do_open(fname, O_WRONLY|O_CREAT, 0);
			if (fd2 == -1) {
				rsyserr(FERROR, errno, "open %s failed",
					full_fname(fname));
				discard_receive_data(f_in, file->length);
				if (fd1 != -1)
					close(fd1);
				continue;
			}
		} else {
			if (!get_tmpname(fnametmp,fname)) {
				discard_receive_data(f_in, file->length);
				if (fd1 != -1)
					close(fd1);
				continue;
			}

			/* we initially set the perms without the
			 * setuid/setgid bits to ensure that there is no race
			 * condition. They are then correctly updated after
			 * the lchown. Thanks to [email protected] for pointing
			 * this out.  We also set it initially without group
			 * access because of a similar race condition. */
			fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);

			/* in most cases parent directories will already exist
			 * because their information should have been previously
			 * transferred, but that may not be the case with -R */
			if (fd2 == -1 && relative_paths && errno == ENOENT
			    && create_directory_path(fnametmp, orig_umask) == 0) {
				/* Get back to name with XXXXXX in it. */
				get_tmpname(fnametmp, fname);
				fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
			}
			if (fd2 == -1) {
				rsyserr(FERROR, errno, "mkstemp %s failed",
					full_fname(fnametmp));
				discard_receive_data(f_in, file->length);
				if (fd1 != -1)
					close(fd1);
				continue;
			}

			if (partialptr)
				cleanup_set(fnametmp, partialptr, file, fd1, fd2);
		}

		/* log the transfer */
		if (log_before_transfer)
			log_item(file, &initial_stats, iflags, NULL);
		else if (!am_server && verbose && do_progress)
			rprintf(FINFO, "%s\n", safe_fname(fname));

		/* recv file data */
		recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
				       fname, fd2, file->length);

		if (!log_before_transfer)
			log_item(file, &initial_stats, iflags, NULL);

		if (fd1 != -1)
			close(fd1);
		if (close(fd2) < 0) {
			rsyserr(FERROR, errno, "close failed on %s",
				full_fname(fnametmp));
			exit_cleanup(RERR_FILEIO);
		}

		if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
			finish_transfer(fname, fnametmp, file, recv_ok, 1);
			if (partialptr != fname && fnamecmp == partialptr) {
				do_unlink(partialptr);
				handle_partial_dir(partialptr, PDIR_DELETE);
			}
		} else if (keep_partial && partialptr
		    && handle_partial_dir(partialptr, PDIR_CREATE)) {
			finish_transfer(partialptr, fnametmp, file, recv_ok,
					!partial_dir);
			if (delay_updates && recv_ok) {
				set_delayed_bit(i);
				recv_ok = -1;
			}
		} else {
			partialptr = NULL;
			do_unlink(fnametmp);
		}

		cleanup_disable();

		if (recv_ok > 0) {
			if (remove_sent_files
			    || (preserve_hard_links && file->link_u.links)) {
				SIVAL(numbuf, 0, i);
				send_msg(MSG_SUCCESS, numbuf, 4);
			}
		} else if (!recv_ok) {
			int msgtype = phase || read_batch ? FERROR : FINFO;
			if (msgtype == FERROR || verbose) {
				char *errstr, *redostr, *keptstr;
				if (!(keep_partial && partialptr) && !inplace)
					keptstr = "discarded";
				else if (partial_dir)
					keptstr = "put into partial-dir";
				else
					keptstr = "retained";
				if (msgtype == FERROR) {
					errstr = "ERROR";
					redostr = "";
				} else {
					errstr = "WARNING";
					redostr = " (will try again)";
				}
				rprintf(msgtype,
					"%s: %s failed verification -- update %s%s.\n",
					errstr, safe_fname(fname),
					keptstr, redostr);
			}
			if (!phase) {
				SIVAL(numbuf, 0, i);
				send_msg(MSG_REDO, numbuf, 4);
			}
		}
	}
	make_backups = save_make_backups;

	if (phase == 2 && delay_updates) /* for protocol_version < 29 */
		handle_delayed_updates(flist, local_name);

	if (verbose > 2)
		rprintf(FINFO,"recv_files finished\n");

	return 0;
}