Пример #1
0
/* Opens a temporary file for writing.
 * Success: Writes name into fnametmp, returns fd.
 * Failure: Clobbers fnametmp, returns -1.
 * Calling cleanup_set() is the caller's job. */
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
{
	int fd;

	if (!get_tmpname(fnametmp, fname))
		return -1;

	/* We initially set the perms without the setuid/setgid bits or group
	 * access to ensure that there is no race condition.  They will be
	 * correctly updated after the right owner and group info is set.
	 * (Thanks to [email protected] for pointing this out.) */
	fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);

#if 0
	/* 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 (fd == -1 && relative_paths && errno == ENOENT
	    && create_directory_path(fnametmp) == 0) {
		/* Get back to name with XXXXXX in it. */
		get_tmpname(fnametmp, fname);
		fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
	}
#endif

	if (fd == -1) {
		rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
			full_fname(fnametmp));
		return -1;
	}

	return fd;
}
Пример #2
0
void doit(void)
{
	char filename[TMPNAME_SIZE];

	assert(get_tmpname(filename)!=NULL);

	run("SSLKEYLOGFILE", filename);
}
Пример #3
0
/* Opens a temporary file for writing.
 * Success: Writes name into fnametmp, returns fd.
 * Failure: Clobbers fnametmp, returns -1.
 * Calling cleanup_set() is the caller's job. */
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
{
	int fd;
	mode_t added_perms;

	if (!get_tmpname(fnametmp, fname))
		return -1;

	if (am_root < 0) {
		/* For --fake-super, the file must be useable by the copying
		 * user, just like it would be for root. */
		added_perms = S_IRUSR|S_IWUSR;
	} else {
		/* For a normal copy, we need to be able to tweak things like xattrs. */
		added_perms = S_IWUSR;
	}

	/* We initially set the perms without the setuid/setgid bits or group
	 * access to ensure that there is no race condition.  They will be
	 * correctly updated after the right owner and group info is set.
	 * (Thanks to [email protected] for pointing this out.) */
	fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS, (char*)fname);

#if 0 /* was SUPPORT_ACLS */
	/* 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 (fd == -1 && relative_paths && errno == ENOENT
	    && create_directory_path(fnametmp) == 0) {
		/* Get back to name with XXXXXX in it. */
		get_tmpname(fnametmp, fname);
		fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS, fname);
	}
#endif

	if (fd == -1) {
		rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
			full_fname(fnametmp));
		return -1;
	}

	return fd;
}
Пример #4
0
bool
SrmDevice::download(CommPortPtr dev, const QDir &tmpdir,
                    QString &tmpname, QString &filename,
                    StatusCallback statusCallback, QString &err)
{
    // Totally ghetto, proof-of-concept integration with srmio.
    cb = statusCallback;
    QString path;
    if (!dev2path(dev, path, err))
        return false;
    if (!get_tmpname(tmpdir, tmpname, err))
        return false;
    SrmpcConn srm(path, logfunc);
    if (!srm.d) {
        err = "Couldn't open device " + path + ": " + strerror(errno);
        return false;
    }
    int opt_all = 0; // XXX: what does this do?
    int opt_fixup = 1; // fix bad data like srmwin.exe does
    SrmioData srmdata(srmpc_get_data(srm.d, opt_all, opt_fixup));
    if (!srmdata.d) {
        err = "srmpc_get_data failed";
        return false;
    }
    if (srm_data_write_srm7(srmdata.d, tmpname.toAscii().constData()) < 0) {
        err = "Couldn't write to file " + tmpname + ": " + strerror(errno);
        return false;
    }
    // Read it back in to get the ride start time.
    SrmFileReader reader;
    QStringList errs;
    QFile file(tmpname);
    QStringList errors;
    boost::scoped_ptr<RideFile> ride(
        RideFileFactory::instance().openRideFile(file, errors));
    BOOST_FOREACH(QString err, errors)
        fprintf(stderr, "error: %s\n", err.toAscii().constData());
    filename = ride->startTime().toString("yyyy_MM_dd_hh_mm_ss") + ".srm";
    return true;
}
Пример #5
0
static FILE *open_temp_file(char *fnametmp, const char *fname)
{
	FILE *f;
	int fd;

	if (get_tmpname(fnametmp, fname) == 0) {
		csync_debug(1, "ERROR: Couldn't find tempname for file %s\n", fname);
		return NULL;
	}

	f = NULL;
	fd = open(fnametmp, O_CREAT | O_EXCL | O_RDWR, S_IWUSR | S_IRUSR);
	if (fd >= 0) {
		f = fdopen(fd, "wb+");
			/* not unlinking since rename wouldn't work then */
	}
	if (fd < 0 || !f) {
		csync_debug(1, "ERROR: Could not open result from tempnam(%s)!\n", fnametmp);
		return NULL;
	}

	return f;
}
Пример #6
0
bool
SrmDevice::download( const QDir &tmpdir,
                    QList<DeviceDownloadFile> &files,
                    QString &err)
{
    srmio_error_t serr;
    struct _srmio_pc_xfer_block_t block;
    srmio_data_t data( NULL );
    srmio_data_t *splitList( NULL );
    srmio_data_t *split;
    int mfirst( -1 );
    size_t block_cnt, block_num( 0 );
    size_t prog_sum( 0 ), prog_prev( 0 );
    size_t chunks_done( 0 );
    srmio_time_t splitGap( 72000 ); // 2h - NOTE: we could make this configurable

    if( ! is_open ){
        if( ! open( err ) )
            return false;
    }

    // fetch preview in case user didn't
    if( srmio_pc_can_preview(pc) && rideList.size() == 0 ){
        if( ! preview( err ) )
            return false;
    }

    data = srmio_data_new( &serr );
    if( ! data ){
        err = tr("failed to allocate data handle: %1")
            .arg(serr.message);
        goto fail;
    }

    if( m_Cancelled ){
        err = tr("download cancelled");
        goto fail;
    }

    if( ! srmio_pc_xfer_start( pc, &serr )){
        err = tr("failed to start download: %1")
            .arg(serr.message);
        goto fail;
    }

    if( ! srmio_pc_xfer_get_blocks( pc, &block_cnt, &serr ) ){
        err = tr("failed to get number of data blocks: %1")
            .arg(serr.message);
        goto fail1;
    }

    for( int i = 0; i < rideList.size(); ++i ){
        if( rideList.at(i)->wanted )
            prog_sum += rideList.at(i)->work;
    }

    while( srmio_pc_xfer_block_next( pc, &block )){
        bool wanted = false;
        struct _srmio_chunk_t chunk;
        bool is_int;
        bool is_first;
        size_t prog_total;

        if( rideList.empty() ){
            wanted = true;

        } else {
            for( int i = 0; i < rideList.size(); ++i ){
                if( rideList.at(i)->startTime.toTime_t() == block.start / 10 ){
                    wanted = rideList.at(i)->wanted;
                    break;
                }
            }
        }

        if( ! wanted ){
            emit updateStatus(tr("skipping unselected ride block %1")
                .arg(block_num +1));
            ++block_num;
            continue;
        }

        data->slope = block.slope;
        data->zeropos = block.zeropos;
        data->circum = block.circum;
        if( block.athlete ){
            if( data->athlete )
                free( data->athlete );
            data->athlete = strdup( block.athlete );
        }

        if( ! rideList.empty() ){
            prog_total = prog_sum;

        } else if( block_cnt == 1 ){
            prog_total = block.total;

        } else {
            prog_total = block_cnt * 1000;
        }

        while( srmio_pc_xfer_chunk_next( pc, &chunk, &is_int, &is_first  ) ){
            if( m_Cancelled ){
                err = tr("download cancelled");
                goto fail1;
            }

            if( chunks_done % 16 == 0 ){
                size_t block_done;

                srmio_pc_xfer_block_progress( pc, &block_done );
                if( ! rideList.empty() ){
                    block_done += prog_prev;

                } else if( block_cnt == 1 ){
                    // unchanged

                } else {
                    block_done = (double)block_num * 1000
                        + 1000 * block.total / block_done;
                }

                emit updateProgress( tr("progress: %1/%2")
                    .arg(block_done)
                    .arg(prog_total));
            }

            if( ! srmio_data_add_chunk( data, &chunk, &serr ) ){
                err = tr("adding chunk failed: %1")
                    .arg(serr.message);
                goto fail1;
            }

            ++chunks_done;

            /* finish previous marker */
            if( mfirst >= 0 && ( ! is_int || is_first ) )
                if( ! srmio_data_add_marker( data, mfirst, data->cused -2, &serr ) ){
                    err = tr("adding marker failed: %1")
                        .arg(serr.message);
                    goto fail1;
                }

            /* start marker */
            if( is_first ){
                mfirst = (int)data->cused -1;

            } else if( ! is_int ){
                mfirst = -1;

            }
        }

        /* finalize marker at block end */
        if( mfirst >= 0 ){
            if( ! srmio_data_add_marker( data, mfirst, data->cused -1, &serr ) ){;
                err = tr("adding marker failed: %1")
                  .arg(serr.message);
                goto fail1;
            }
            mfirst = -1;
        }

        if( ! rideList.empty() )
            prog_prev += block.total;
        else
            prog_prev += 1000;

        if( block.athlete )
            free( block.athlete );
        block.athlete = NULL;

        ++block_num;
    }

    if( srmio_pc_xfer_state_success != srmio_pc_xfer_status( pc, &serr ) ){
        err = tr( "download failed: %1")
            .arg(serr.message);
        goto fail;
    }

    if( ! srmio_pc_xfer_finish( pc, &serr ) ){
        err = tr( "download failed: %1")
            .arg(serr.message);
        goto fail;
    }

    emit updateStatus( tr("got %1 records").arg(data->cused) );

    if( m_Cancelled ){
        err = tr("download cancelled");
        goto fail;
    }

    if( ! data->cused ){
        err = tr("no data available");
        goto fail;
    }

    splitList = srmio_data_split( data, splitGap, 1000, &serr );
    if( ! splitList ){
        err = tr("Couldn't split data: %1")
            .arg(serr.message);
        goto fail;
    }

    for( split = splitList; *split; ++split ){
        FILE *fh( NULL );
        srmio_time_t stime;
        srmio_data_t fixed;
        DeviceDownloadFile file;

        // skip empty hunks ... shouldn't happen, just to be safe
        if( ! (*split)->cused ){
            continue;
        }

        fixed = srmio_data_fixup( *split, &serr );
        if( ! fixed ){
            err = tr("Couldn't fixup data: %1")
                .arg(serr.message);
            goto fail;
        }

        // skip empty hunks ... shouldn't happen, just to be safe
        if( ! fixed->cused ){
            srmio_data_free(fixed);
            continue;
        }

        file.extension = "srm";
        if (!get_tmpname(tmpdir, file.name, err))
            goto fail;

        if( ! srmio_data_time_start( fixed, &stime, &serr ) ){
            srmio_data_free(fixed);
            err = tr("Couldn't get start time of data: %1")
                .arg(serr.message);
            goto fail;
        }
        file.startTime.setTime_t( 0.1 * stime );

        fh = fopen( file.name.toAscii().constData(), "wb" );
        if( ! fh ){
            srmio_data_free(fixed);
            err = tr( "failed to open file %1: %2")
                .arg(file.name)
                .arg(strerror(errno));
            goto fail;
        }

        if( ! srmio_file_srm7_write(fixed, fh, &serr) ){
            srmio_data_free(fixed);
            err = tr("Couldn't write to file %1: %2")
                .arg(file.name)
                .arg(serr.message);
            fclose(fh);
            goto fail;
        }

        files.append(file);

        fclose( fh );
        srmio_data_free(fixed);

    }

    for( split = splitList; *split; ++split )
        srmio_data_free( *split );
    free(splitList);

    srmio_data_free( data );
    return true;

fail1:
    srmio_pc_xfer_finish(pc, NULL);

fail:
    if( data ) srmio_data_free( data );
    if( splitList ){
        for( split = splitList; *split; ++split )
            srmio_data_free( *split );
        free(splitList);
    }
    close();
    return false;
}
Пример #7
0
void doit(void)
{
	int ret;
	gnutls_certificate_credentials_t xcred;
	gnutls_certificate_credentials_t clicred;
	const char *certfile;
	const char *ocspfile1;
	char certname[TMPNAME_SIZE], ocspname1[TMPNAME_SIZE];
	time_t t;
	FILE *fp;

	global_init();
	gnutls_global_set_time_function(mytime);

	assert(gnutls_certificate_allocate_credentials(&xcred) >= 0);
	assert(gnutls_certificate_allocate_credentials(&clicred) >= 0);

	certfile = get_tmpname(certname);

	fp = fopen(certfile, "wb");
	if (fp == NULL)
		fail("error in fopen\n");
	assert(fwrite(server_localhost_ca3_cert_chain_pem, 1, strlen(server_localhost_ca3_cert_chain_pem), fp)>0);
	assert(fwrite(server_ca3_key_pem, 1, strlen((char*)server_ca3_key_pem), fp)>0);
	fclose(fp);

	/* set cert with localhost name */
	ret = gnutls_certificate_set_x509_key_file2(xcred, certfile, certfile,
						    GNUTLS_X509_FMT_PEM, NULL, 0);
	if (ret < 0)
		fail("set_x509_key_file failed: %s\n", gnutls_strerror(ret));

	fp = fopen(certfile, "wb");
	if (fp == NULL)
		fail("error in fopen\n");
	assert(fwrite(server_localhost6_ca3_cert_chain_pem, 1, strlen(server_localhost6_ca3_cert_chain_pem), fp)>0);
	assert(fwrite(server_ca3_key_pem, 1, strlen((char*)server_ca3_key_pem), fp)>0);
	fclose(fp);

	gnutls_certificate_set_flags(xcred, GNUTLS_CERTIFICATE_SKIP_OCSP_RESPONSE_CHECK);

	/* set OCSP response */
	ocspfile1 = get_tmpname(ocspname1);
	fp = fopen(ocspfile1, "wb");
	if (fp == NULL)
		fail("error in fopen\n");
	assert(fwrite(ocsp_resp1.data, 1, ocsp_resp1.size, fp)>0);
	fclose(fp);

	ret = gnutls_certificate_set_ocsp_status_request_file(xcred, ocspfile1, 0);
	if (ret < 0)
		fail("ocsp file set failed: %s\n", gnutls_strerror(ret));

	t = gnutls_certificate_get_ocsp_expiration(xcred, 0, 0, 0);
	if (t != 1511689427)
		fail("error in OCSP validity time: %ld\n", (long int)t);

	t = gnutls_certificate_get_ocsp_expiration(xcred, 0, 1, 0);
	if (t != -1)
		fail("error in OCSP validity time: %ld\n", (long int)t);

	t = gnutls_certificate_get_ocsp_expiration(xcred, 0, -1, 0);
	if (t != 1511689427)
		fail("error in OCSP validity time: %ld\n", (long int)t);


	/* make sure that our invalid OCSP responses are not considered in verification
	 */
	gnutls_certificate_set_verify_flags(clicred, GNUTLS_VERIFY_DISABLE_CRL_CHECKS);
	if (gnutls_certificate_get_verify_flags(clicred) != GNUTLS_VERIFY_DISABLE_CRL_CHECKS)
		fail("error in gnutls_certificate_set_verify_flags\n");

	ret = gnutls_certificate_set_x509_trust_mem(clicred, &ca3_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fail("error in setting trust cert: %s\n", gnutls_strerror(ret));
	}

	test_cli_serv(xcred, clicred, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2", "localhost", &ocsp_resp1, check_response, NULL); /* the DNS name of the first cert */

	test_cli_serv(xcred, clicred, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3", "localhost", &ocsp_resp1, check_response, NULL); /* the DNS name of the first cert */

	gnutls_certificate_free_credentials(xcred);
	gnutls_certificate_free_credentials(clicred);
	gnutls_global_deinit();
	remove(ocspfile1);
	remove(certfile);
}
Пример #8
0
void doit(void)
{
	int ret;
	gnutls_certificate_credentials_t xcred;
	gnutls_certificate_credentials_t clicred;
	const char *certfile = "does-not-exist.pem";
	gnutls_datum_t tcert;
	FILE *fp;

	if (gnutls_fips140_mode_enabled()) {
		exit(77);
	}

	global_init();
	assert(gnutls_certificate_allocate_credentials(&xcred) >= 0);

	/* this will fail */
	ret = gnutls_certificate_set_x509_simple_pkcs12_file(xcred, certfile,
						   GNUTLS_X509_FMT_PEM, "1234");
	if (ret != GNUTLS_E_FILE_ERROR)
		fail("gnutls_certificate_set_x509_simple_pkcs12_file failed: %s\n", gnutls_strerror(ret));

	gnutls_certificate_free_credentials(xcred);

	assert(gnutls_certificate_allocate_credentials(&clicred) >= 0);
	assert(gnutls_certificate_allocate_credentials(&xcred) >= 0);

	ret = gnutls_certificate_set_x509_trust_mem(clicred, &ca3_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		fail("set_x509_trust_file failed: %s\n", gnutls_strerror(ret));

	certfile = get_tmpname(NULL);

	fp = fopen(certfile, "w");
	if (fp == NULL)
		fail("error in fopen\n");

	assert(fwrite(server_ca3_pkcs12_pem, 1, strlen((char*)server_ca3_pkcs12_pem), fp)>0);
	fclose(fp);

	ret = gnutls_certificate_set_x509_simple_pkcs12_file(xcred, certfile,
						    GNUTLS_X509_FMT_PEM, "1234");
	if (ret < 0)
		fail("gnutls_certificate_set_x509_simple_pkcs12_file failed: %s\n", gnutls_strerror(ret));

	/* verify whether the stored certificate match the ones we have */
	ret = gnutls_certificate_get_crt_raw(xcred, 0, 0, &tcert);
	if (ret < 0) {
		fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
		exit(1);
	}

	compare(&tcert, server_localhost_ca3_cert_pem);

	remove(certfile);

	test_cli_serv(xcred, clicred, "NORMAL", "localhost", NULL, NULL, NULL); /* the DNS name of the first cert */

	gnutls_certificate_free_credentials(xcred);
	gnutls_certificate_free_credentials(clicred);
	gnutls_global_deinit();
}
Пример #9
0
/**
 * 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;
}