Exemple #1
0
static int do_backup_phase2_client(struct config *conf, int resume, struct cntr *cntr)
{
    int ret=0;
    int quit=0;
    char cmd;
    char *buf=NULL;
    size_t len=0;
    char attribs[MAXSTRING];

    struct sbuf sb;

    init_sbuf(&sb);

    if(!resume)
    {
        // Only do this bit if the server did not tell us to resume.
        if(async_write_str(CMD_GEN, "backupphase2")
                || async_read_expect(CMD_GEN, "ok"))
            return -1;
    }

    while(!quit)
    {
        if(async_read(&cmd, &buf, &len))
        {
            ret=-1;
            quit++;
        }
        else if(buf)
        {
            //logp("now: %c:%s\n", cmd, buf);
            if(cmd==CMD_DATAPTH)
            {
                sb.datapth=buf;
                buf=NULL;
                continue;
            }
            else if(cmd==CMD_STAT)
            {
                // Ignore the stat data - we will fill it
                // in again. Some time may have passed by now,
                // and it is best to make it as fresh as
                // possible.
                free(buf);
                buf=NULL;
                continue;
            }
            else if(cmd==CMD_FILE
                    || cmd==CMD_ENC_FILE
                    || cmd==CMD_METADATA
                    || cmd==CMD_ENC_METADATA
                    || cmd==CMD_EFS_FILE)
            {
                int forget=0;
                int64_t winattr=0;
                struct stat statbuf;
                char *extrameta=NULL;
                size_t elen=0;
                unsigned long long bytes=0;
                BFILE bfd;
                FILE *fp=NULL;

                sb.path=buf;
                buf=NULL;

#ifdef HAVE_WIN32
                if(win32_lstat(sb.path, &statbuf, &winattr))
#else
                if(lstat(sb.path, &statbuf))
#endif
                {
                    logw(cntr, "Path has vanished: %s", sb.path);
                    if(forget_file(&sb, cmd, cntr))
                    {
                        ret=-1;
                        quit++;
                    }
                    free_sbuf(&sb);
                    continue;
                }

                if(conf->min_file_size
                        && statbuf.st_size<(boffset_t)conf->min_file_size)
                {
                    logw(cntr, "File size decreased below min_file_size after initial scan: %s", sb.path);
                    forget++;
                }
                else if(conf->max_file_size
                        && statbuf.st_size>(boffset_t)conf->max_file_size)
                {
                    logw(cntr, "File size increased above max_file_size after initial scan: %s", sb.path);
                    forget++;
                }

                if(!forget)
                {
                    encode_stat(attribs, &statbuf, winattr);
                    if(open_file_for_send(&bfd, &fp,
                                          sb.path, winattr, cntr))
                        forget++;
                }

                if(forget)
                {
                    if(forget_file(&sb, cmd, cntr))
                    {
                        ret=-1;
                        quit++;
                    }
                    free_sbuf(&sb);
                    continue;
                }

                if(cmd==CMD_METADATA
                        || cmd==CMD_ENC_METADATA)
                {
                    if(get_extrameta(sb.path,
                                     &statbuf, &extrameta, &elen,
                                     cntr))
                    {
                        logw(cntr, "Meta data error for %s", sb.path);
                        free_sbuf(&sb);
                        close_file_for_send(&bfd, &fp);
                        continue;
                    }
                    if(!extrameta)
                    {
                        logw(cntr, "No meta data after all: %s", sb.path);
                        free_sbuf(&sb);
                        close_file_for_send(&bfd, &fp);
                        continue;
                    }
                }

                if(cmd==CMD_FILE && sb.datapth)
                {
                    unsigned long long sentbytes=0;
                    // Need to do sig/delta stuff.
                    if(async_write_str(CMD_DATAPTH, sb.datapth)
                            || async_write_str(CMD_STAT, attribs)
                            || async_write_str(CMD_FILE, sb.path)
                            || load_signature_and_send_delta(
                                &bfd, fp,
                                &bytes, &sentbytes, cntr))
                    {
                        logp("error in sig/delta for %s (%s)\n", sb.path, sb.datapth);
                        ret=-1;
                        quit++;
                    }
                    else
                    {
                        do_filecounter(cntr, CMD_FILE_CHANGED, 1);
                        do_filecounter_bytes(cntr, bytes);
                        do_filecounter_sentbytes(cntr, sentbytes);
                    }
                }
                else
                {
                    //logp("need to send whole file: %s\n",
                    //	sb.path);
                    // send the whole file.
                    if(async_write_str(CMD_STAT, attribs)
                            || async_write_str(cmd, sb.path)
                            || send_whole_file_w(cmd, sb.path,
                                                 NULL, 0, &bytes,
                                                 conf->encryption_password,
                                                 cntr, conf->compression,
                                                 &bfd, fp,
                                                 extrameta, elen))
                    {
                        ret=-1;
                        quit++;
                    }
                    else
                    {
                        do_filecounter(cntr, cmd, 1);
                        do_filecounter_bytes(cntr, bytes);
                        do_filecounter_sentbytes(cntr, bytes);
                    }
                }
                close_file_for_send(&bfd, &fp);
                free_sbuf(&sb);
                if(extrameta) free(extrameta);
            }
            else if(cmd==CMD_WARNING)
            {
                do_filecounter(cntr, cmd, 0);
                free(buf);
                buf=NULL;
            }
            else if(cmd==CMD_GEN && !strcmp(buf, "backupphase2end"))
            {
                if(async_write_str(CMD_GEN, "okbackupphase2end"))
                    ret=-1;
                quit++;
            }
            else
            {
                logp("unexpected cmd from server: %c %s\n",
                     cmd, buf);
                ret=-1;
                quit++;
                free(buf);
                buf=NULL;
            }
        }
    }
    return ret;
}
Exemple #2
0
static int do_backup_phase2_client(struct config *conf, int resume, struct cntr *p1cntr, struct cntr *cntr)
{
	int ret=0;
	int quit=0;
	char cmd;
	char *buf=NULL;
	size_t len=0;
	char attribs[MAXSTRING];
	// For efficiency, open Windows files for the VSS data, and do not
	// close them until another time around the loop, when the actual
	// data is read.
	BFILE bfd;
	// Windows VSS headers tell us how much file
	// data to expect.
	size_t datalen=0;
#ifdef HAVE_WIN32
	binit(&bfd, 0);
#endif

	struct sbuf sb;

	init_sbuf(&sb);

	if(!resume)
	{
		// Only do this bit if the server did not tell us to resume.
		if(async_write_str(CMD_GEN, "backupphase2")
		  || async_read_expect(CMD_GEN, "ok"))
			return -1;
	}
	else if(conf->send_client_counters)
	{
		// On resume, the server might update the client with the
 		// counters.
		if(recv_counters(p1cntr, cntr))
			return -1;	
	}

	while(!quit)
	{
		if(async_read(&cmd, &buf, &len))
		{
			ret=-1;
			quit++;
		}
		else if(buf)
		{
			//logp("now: %c:%s\n", cmd, buf);
			if(cmd==CMD_DATAPTH)
			{
				sb.datapth=buf;
				buf=NULL;
				continue;
			}
			else if(cmd==CMD_STAT)
			{
				// Ignore the stat data - we will fill it
				// in again. Some time may have passed by now,
				// and it is best to make it as fresh as
				// possible.
				free(buf);
				buf=NULL;
				continue;
			}
			else if(cmd==CMD_FILE
			  || cmd==CMD_ENC_FILE
			  || cmd==CMD_METADATA
			  || cmd==CMD_ENC_METADATA
			  || cmd==CMD_VSS
			  || cmd==CMD_ENC_VSS
			  || cmd==CMD_VSS_T
			  || cmd==CMD_ENC_VSS_T
			  || cmd==CMD_EFS_FILE)
			{
				int forget=0;
				int64_t winattr=0;
				struct stat statbuf;
				char *extrameta=NULL;
				size_t elen=0;
				unsigned long long bytes=0;
				FILE *fp=NULL;
				int compression=conf->compression;

				sb.path=buf;
				buf=NULL;

#ifdef HAVE_WIN32
				if(win32_lstat(sb.path, &statbuf, &winattr))
#else
				if(lstat(sb.path, &statbuf))
#endif
				{
					logw(cntr, "Path has vanished: %s", sb.path);
					if(forget_file(&sb, cmd, cntr))
					{
						ret=-1;
						quit++;
					}
					free_sbuf(&sb);
					continue;
				}

				if(conf->min_file_size
				  && statbuf.st_size<
					(boffset_t)conf->min_file_size
				  && (cmd==CMD_FILE
				  || cmd==CMD_ENC_FILE
				  || cmd==CMD_EFS_FILE))
				{
					logw(cntr, "File size decreased below min_file_size after initial scan: %c:%s", cmd, sb.path);
					forget++;
				}
				else if(conf->max_file_size
				  && statbuf.st_size>
					(boffset_t)conf->max_file_size
				  && (cmd==CMD_FILE
				  || cmd==CMD_ENC_FILE
				  || cmd==CMD_EFS_FILE))
				{
					logw(cntr, "File size increased above max_file_size after initial scan: %c:%s", cmd, sb.path);
					forget++;
				}

				if(!forget)
				{
					compression=in_exclude_comp(conf->excom,
					  conf->excmcount, sb.path,
					  conf->compression);
					encode_stat(attribs,
					  &statbuf, winattr, compression);
					if(open_file_for_send(
#ifdef HAVE_WIN32
						&bfd, NULL,
#else
						NULL, &fp,
#endif
						sb.path, winattr,
						&datalen, cntr))
							forget++;
				}

				if(forget)
				{
					if(forget_file(&sb, cmd, cntr))
					{
						ret=-1;
						quit++;
					}
					free_sbuf(&sb);
					continue;
				}

				if(cmd==CMD_METADATA
				  || cmd==CMD_ENC_METADATA
				  || cmd==CMD_VSS
				  || cmd==CMD_ENC_VSS
#ifdef HAVE_WIN32
				  || conf->strip_vss
#endif
				  )
				{
					if(get_extrameta(
#ifdef HAVE_WIN32
						&bfd,
#else
						NULL,
#endif
						sb.path,
						&statbuf, &extrameta, &elen,
						winattr, cntr,
						&datalen))
					{
						logw(cntr, "Meta data error for %s", sb.path);
						free_sbuf(&sb);
						close_file_for_send(&bfd, &fp);
						continue;
					}
					if(extrameta)
					{
#ifdef HAVE_WIN32
						if(conf->strip_vss)
						{
							free(extrameta);
							extrameta=NULL;
							elen=0;
						}
#endif
					}
					else
					{
						logw(cntr, "No meta data after all: %s", sb.path);
						free_sbuf(&sb);
						close_file_for_send(&bfd, &fp);
						continue;
					}
				}

				if(cmd==CMD_FILE && sb.datapth)
				{
					unsigned long long sentbytes=0;
					// Need to do sig/delta stuff.
					if(async_write_str(CMD_DATAPTH, sb.datapth)
					  || async_write_str(CMD_STAT, attribs)
					  || async_write_str(CMD_FILE, sb.path)
					  || load_signature_and_send_delta(
						&bfd, fp,
						&bytes, &sentbytes, cntr,
						datalen))
					{
						logp("error in sig/delta for %s (%s)\n", sb.path, sb.datapth);
						ret=-1;
						quit++;
					}
					else
					{
						do_filecounter(cntr, CMD_FILE_CHANGED, 1);
						do_filecounter_bytes(cntr, bytes);
						do_filecounter_sentbytes(cntr, sentbytes);
					}
				}
				else
				{
					//logp("need to send whole file: %s\n",
					//	sb.path);
					// send the whole file.

					if((async_write_str(CMD_STAT, attribs)
					  || async_write_str(cmd, sb.path))
					  || send_whole_file_w(cmd, sb.path,
						NULL, 0, &bytes,
						conf->encryption_password,
						cntr, compression,
						&bfd, fp,
						extrameta, elen,
						datalen))
					{
						ret=-1;
						quit++;
					}
					else
					{
						do_filecounter(cntr, cmd, 1);
						do_filecounter_bytes(cntr, bytes);
						do_filecounter_sentbytes(cntr, bytes);
					}
				}
#ifdef HAVE_WIN32
				// If using Windows do not close bfd - it needs
				// to stay open to read VSS/file data/VSS.
				// It will get closed either when given a
				// different file path, or when this function
				// exits.
				
				//if(cmd!=CMD_VSS
				// && cmd!=CMD_ENC_VSS)
				//	close_file_for_send(&bfd, NULL);
#else
				close_file_for_send(NULL, &fp);
#endif
				free_sbuf(&sb);
				if(extrameta) free(extrameta);
			}
			else if(cmd==CMD_WARNING)
			{
				do_filecounter(cntr, cmd, 0);
				free(buf);
				buf=NULL;
			}
			else if(cmd==CMD_GEN && !strcmp(buf, "backupphase2end"))
			{
				if(async_write_str(CMD_GEN, "okbackupphase2end"))
					ret=-1;
				quit++;
			}
			else
			{
				logp("unexpected cmd from server: %c %s\n",
					cmd, buf);
				ret=-1;
				quit++;
				free(buf);
				buf=NULL;
			}
		}
	}
#ifdef HAVE_WIN32
	// It is possible for a bfd to still be open.
	close_file_for_send(&bfd, NULL);
#endif
	return ret;
}
Exemple #3
0
static int deal_with_data(struct asfd *asfd, struct sbuf *sb,
	BFILE *bfd, size_t *datalen, struct conf *conf)
{
	int ret=-1;
	int forget=0;
	FILE *fp=NULL;
	size_t elen=0;
	char *extrameta=NULL;
	unsigned long long bytes=0;

	sb->compression=conf->compression;

	iobuf_copy(&sb->path, asfd->rbuf);
	iobuf_init(asfd->rbuf);

#ifdef HAVE_WIN32
	if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
#else
	if(lstat(sb->path.buf, &sb->statp))
#endif
	{
		logw(asfd, conf, "Path has vanished: %s", sb->path.buf);
		if(forget_file(asfd, sb, conf)) goto error;
		goto end;
	}

	if(size_checks(asfd, sb, conf)) forget++;

	if(!forget)
	{
		sb->compression=in_exclude_comp(conf->excom,
			sb->path.buf, conf->compression);
		if(attribs_encode(sb)) goto error;
		else if(open_file_for_sendl(asfd,
#ifdef HAVE_WIN32
			bfd, NULL,
#else
			NULL, &fp,
#endif
			sb->path.buf, sb->winattr, datalen, conf->atime, conf))
				forget++;
	}

	if(forget)
	{
		if(forget_file(asfd, sb, conf)) goto error;
		goto end;
	}

	if(sb->path.cmd==CMD_METADATA
	  || sb->path.cmd==CMD_ENC_METADATA
	  || sb->path.cmd==CMD_VSS
	  || sb->path.cmd==CMD_ENC_VSS
#ifdef HAVE_WIN32
	  || conf->strip_vss
#endif
	  )
	{
		if(get_extrameta(asfd,
#ifdef HAVE_WIN32
			bfd,
#endif
			sb->path.buf, &sb->statp, &extrameta, &elen,
			sb->winattr, conf, datalen))
		{
			logw(asfd, conf, "Meta data error for %s", sb->path.buf);
			goto end;
		}
		if(extrameta)
		{
#ifdef HAVE_WIN32
			if(conf->strip_vss)
			{
				free(extrameta);
				extrameta=NULL;
				elen=0;
			}
#endif
		}
		else
		{
			logw(asfd, conf,
				"No meta data after all: %s", sb->path.buf);
			goto end;
		}
	}

	if(sb->path.cmd==CMD_FILE
	  && sb->burp1->datapth.buf)
	{
		unsigned long long sentbytes=0;
		// Need to do sig/delta stuff.
		if(asfd->write(asfd, &(sb->burp1->datapth))
		  || asfd->write(asfd, &sb->attr)
		  || asfd->write(asfd, &sb->path)
		  || load_signature_and_send_delta(asfd, bfd, fp,
			&bytes, &sentbytes, conf, *datalen))
		{
			logp("error in sig/delta for %s (%s)\n",
				sb->path.buf, sb->burp1->datapth.buf);
			goto end;
		}
		else
		{
			cntr_add(conf->cntr, CMD_FILE_CHANGED, 1);
			cntr_add_bytes(conf->cntr, bytes);
			cntr_add_sentbytes(conf->cntr, sentbytes);
		}
	}
	else
	{
		//logp("need to send whole file: %s\n", sb.path);
		// send the whole file.

		if((asfd->write(asfd, &sb->attr)
		  || asfd->write(asfd, &sb->path))
		  || send_whole_file_w(asfd, sb, NULL, 0, &bytes,
			conf->encryption_password, conf, sb->compression,
			bfd, fp, extrameta, elen, *datalen))
				goto end;
		else
		{
			cntr_add(conf->cntr, sb->path.cmd, 1);
			cntr_add_bytes(conf->cntr, bytes);
			cntr_add_sentbytes(conf->cntr, bytes);
		}
	}

end:
	ret=0;
error:
#ifdef HAVE_WIN32
	// If using Windows do not close bfd - it needs
	// to stay open to read VSS/file data/VSS.
	// It will get closed either when given a
	// different file path, or when this function
	// exits.
#else
	close_file_for_sendl(NULL, &fp, asfd);
#endif
	sbuf_free_content(sb);
	if(extrameta) free(extrameta);
	return ret;
}