Beispiel #1
0
static int process_unchanged_file(struct sbuf *cb, FILE *ucfp, struct cntr *cntr)
{
	if(sbuf_to_manifest(cb, ucfp, NULL))
	{
		free_sbuf(cb);
		return -1;
	}
	else
	{
		do_filecounter_same(cntr, cb->cmd);
	}
	if(cb->endfile) do_filecounter_bytes(cntr,
		 strtoull(cb->endfile, NULL, 10));
	free_sbuf(cb);
	return 1;
}
Beispiel #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;
}
Beispiel #3
0
int send_file(FF_PKT *ff, bool top_level, struct config *conf, struct cntr *p1cntr)
{
   char msg[128]="";
   char attribs[MAXSTRING];

   if(!file_is_included(conf->incexcdir, conf->iecount,
	conf->incext, conf->incount,
	conf->excext, conf->excount,
	conf->increg, conf->ircount,
	conf->excreg, conf->ercount,
	ff->fname, top_level)) return 0;
#ifdef HAVE_WIN32
// Useful Windows attributes debug
/*
	printf("\n%llu", ff->winattr);
	printf("\n%s\n", ff->fname);
if(ff->winattr & FILE_ATTRIBUTE_READONLY) printf("readonly\n");
if(ff->winattr & FILE_ATTRIBUTE_HIDDEN) printf("hidden\n");
if(ff->winattr & FILE_ATTRIBUTE_SYSTEM) printf("system\n");
if(ff->winattr & FILE_ATTRIBUTE_DIRECTORY) printf("directory\n");
if(ff->winattr & FILE_ATTRIBUTE_ARCHIVE) printf("archive\n");
if(ff->winattr & FILE_ATTRIBUTE_DEVICE) printf("device\n");
if(ff->winattr & FILE_ATTRIBUTE_NORMAL) printf("normal\n");
if(ff->winattr & FILE_ATTRIBUTE_TEMPORARY) printf("temporary\n");
if(ff->winattr & FILE_ATTRIBUTE_SPARSE_FILE) printf("sparse\n");
if(ff->winattr & FILE_ATTRIBUTE_REPARSE_POINT) printf("reparse\n");
if(ff->winattr & FILE_ATTRIBUTE_COMPRESSED) printf("compressed\n");
if(ff->winattr & FILE_ATTRIBUTE_OFFLINE) printf("offline\n");
if(ff->winattr & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) printf("notcont\n");
if(ff->winattr & FILE_ATTRIBUTE_ENCRYPTED) printf("encrypted\n");
if(ff->winattr & FILE_ATTRIBUTE_VIRTUAL) printf("virtual\n");
*/
	if(ff->winattr & FILE_ATTRIBUTE_ENCRYPTED)
	{
//		if(ff->type!=FT_DIREND)
//			logw(p1cntr, "EFS not yet supported: %s", ff->fname);
//		return 0;

		if(ff->type==FT_REGE
		  || ff->type==FT_REG
		  || ff->type==FT_DIRBEGIN)
		{
			encode_stat(attribs,
				&ff->statp, ff->winattr, conf->compression);
			if(async_write_str(CMD_STAT, attribs)
			  || async_write_str(CMD_EFS_FILE, ff->fname))
				return -1;
			do_filecounter(p1cntr, CMD_EFS_FILE, 1);
			if(ff->type==FT_REG)
				do_filecounter_bytes(p1cntr,
					(unsigned long long)ff->statp.st_size);
			return 0;
		}
		else if(ff->type==FT_DIREND)
			return 0;
		else
		{
			// Hopefully, here is never reached.
			logw(p1cntr, "EFS type %d not yet supported: %s",
				ff->type,
				ff->fname);
			return 0;
		}
	}
#endif

   //logp("%d: %s\n", ff->type, ff->fname);

   switch (ff->type) {
   case FT_LNKSAVED:
        //printf("Lnka: %s -> %s\n", ff->fname, ff->link);
   	encode_stat(attribs, &ff->statp, ff->winattr, conf->compression);
	if(async_write_str(CMD_STAT, attribs)
	  || async_write_str(CMD_HARD_LINK, ff->fname)
	  || async_write_str(CMD_HARD_LINK, ff->link))
		return -1;
	do_filecounter(p1cntr, CMD_HARD_LINK, 1);
	// At least FreeBSD 8.2 can have different xattrs on hard links.
	if(maybe_send_extrameta(ff->fname, CMD_HARD_LINK, attribs, p1cntr))
		return -1;
      break;
   case FT_FIFO:
   case FT_REGE:
   case FT_REG:
      encode_stat(attribs, &ff->statp, ff->winattr,
		in_exclude_comp(conf->excom, conf->excmcount,
			ff->fname, conf->compression));
      if(async_write_str(CMD_STAT, attribs)
	|| async_write_str(filesymbol, ff->fname))
		return -1;
      do_filecounter(p1cntr, filesymbol, 1);
      if(ff->type==FT_REG)
	do_filecounter_bytes(p1cntr, (unsigned long long)ff->statp.st_size);
      if(maybe_send_extrameta(ff->fname, filesymbol, attribs, p1cntr))
		return -1;
      break;
   case FT_LNK:
	//printf("link: %s -> %s\n", ff->fname, ff->link);
   	encode_stat(attribs, &ff->statp, ff->winattr, conf->compression);
	if(async_write_str(CMD_STAT, attribs)
	  || async_write_str(CMD_SOFT_LINK, ff->fname)
	  || async_write_str(CMD_SOFT_LINK, ff->link))
		return -1;
	do_filecounter(p1cntr, CMD_SOFT_LINK, 1);
        if(maybe_send_extrameta(ff->fname, CMD_SOFT_LINK, attribs, p1cntr))
		return -1;
      break;
   case FT_DIREND:
      return 0;
   case FT_NOFSCHG:
   case FT_DIRBEGIN:
   case FT_REPARSE:
   case FT_JUNCTION:
	{
         char errmsg[100] = "";
         if (ff->type == FT_NOFSCHG)
            snprintf(errmsg, sizeof(errmsg), _("\t[will not descend: file system change not allowed]"));
	 if(*errmsg)
	 {
		snprintf(msg, sizeof(msg),
			"%s%s%s\n", "Dir: ", ff->fname, errmsg);
		logw(p1cntr, "%s", msg);
	 }
	 else
	 {
		encode_stat(attribs,
			&ff->statp, ff->winattr, conf->compression);
	      	if(async_write_str(CMD_STAT, attribs)) return -1;
#if defined(WIN32_VSS)
		if(async_write_str(filesymbol, ff->fname)) return -1;
		do_filecounter(p1cntr, filesymbol, 1);
#else
		if(async_write_str(CMD_DIRECTORY, ff->fname)) return -1;
		do_filecounter(p1cntr, CMD_DIRECTORY, 1);
        	if(maybe_send_extrameta(ff->fname, CMD_DIRECTORY,
			attribs, p1cntr)) return -1;
#endif
	 }
	}
      break;
   case FT_SPEC: // special file - fifo, socket, device node...
      encode_stat(attribs, &ff->statp, ff->winattr, conf->compression);
      if(async_write_str(CMD_STAT, attribs)
	  || async_write_str(CMD_SPECIAL, ff->fname))
		return -1;
      do_filecounter(p1cntr, CMD_SPECIAL, 1);
      if(maybe_send_extrameta(ff->fname, CMD_SPECIAL, attribs, p1cntr))
		return -1;
      break;
   case FT_NOACCESS:
      logw(p1cntr, _("Err: Could not access %s: %s"), ff->fname, strerror(errno));
      break;
   case FT_NOFOLLOW:
      logw(p1cntr, _("Err: Could not follow ff->link %s: %s"), ff->fname, strerror(errno));
      break;
   case FT_NOSTAT:
      logw(p1cntr, _("Err: Could not stat %s: %s"), ff->fname, strerror(errno));
      break;
   case FT_NOCHG:
      logw(p1cntr, _("Skip: File not saved. No change. %s"), ff->fname);
      break;
   case FT_ISARCH:
      logw(p1cntr, _("Err: Attempt to backup archive. Not saved. %s"), ff->fname);
      break;
   case FT_NOOPEN:
      logw(p1cntr, _("Err: Could not open directory %s: %s"), ff->fname, strerror(errno));
      break;
   case FT_RAW:
      logw(p1cntr, _("Err: Raw partition: %s"), ff->fname);
      break;
   default:
      logw(p1cntr, _("Err: Unknown file ff->type %d: %s"), ff->type, ff->fname);
      break;
   }
   return 0;
}
Beispiel #4
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;
}
Beispiel #5
0
// a = length of struct bu array
// i = position to restore from
static int restore_manifest(struct bu *arr, int a, int i, const char *tmppath1, const char *tmppath2, regex_t *regex, int srestore, enum action act, const char *client, char **dir_for_notify, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf)
{
	int ret=0;
	gzFile zp=NULL;
	char *manifest=NULL;
	char *datadir=NULL;
	FILE *logfp=NULL;
	char *logpath=NULL;
	char *logpathz=NULL;
	// For sending status information up to the server.
	char status=STATUS_RESTORING;

	if(act==ACTION_RESTORE) status=STATUS_RESTORING;
	else if(act==ACTION_VERIFY) status=STATUS_VERIFYING;

	if(
	    (act==ACTION_RESTORE && !(logpath=prepend_s(arr[i].path, "restorelog", strlen("restorelog"))))
	 || (act==ACTION_RESTORE && !(logpathz=prepend_s(arr[i].path, "restorelog.gz", strlen("restorelog.gz"))))
	 || (act==ACTION_VERIFY && !(logpath=prepend_s(arr[i].path, "verifylog", strlen("verifylog"))))
	 || (act==ACTION_VERIFY && !(logpathz=prepend_s(arr[i].path, "verifylog.gz", strlen("verifylog.gz"))))
	 || !(manifest=prepend_s(arr[i].path, "manifest.gz", strlen("manifest.gz"))))
	{
		log_and_send_oom(__FUNCTION__);
		ret=-1;
	}
	else if(!(logfp=open_file(logpath, "ab")) || set_logfp(logfp, cconf))
	{
		char msg[256]="";
		snprintf(msg, sizeof(msg),
			"could not open log file: %s", logpath);
		log_and_send(msg);
		ret=-1;
	}

	*dir_for_notify=strdup(arr[i].path);

	log_restore_settings(cconf, srestore);

	// First, do a pass through the manifest to set up the counters.
	// This is the equivalent of a phase1 scan during backup.
	if(!ret && !(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		int ars=0;
		int quit=0;
		struct sbuf sb;
		init_sbuf(&sb);
		while(!quit)
		{
			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if((!srestore
				    || check_srestore(cconf, sb.path))
				  && check_regex(regex, sb.path))
				{
					do_filecounter(p1cntr, sb.cmd, 0);
					if(sb.endfile)
					  do_filecounter_bytes(p1cntr,
                 			    strtoull(sb.endfile, NULL, 10));
/*
					if(sb.cmd==CMD_FILE
					  || sb.cmd==CMD_ENC_FILE
					  || sb.cmd==CMD_METADATA
					  || sb.cmd==CMD_ENC_METADATA
					  || sb.cmd==CMD_VSS
					  || sb.cmd==CMD_ENC_VSS
					  || sb.cmd==CMD_VSS_T
					  || sb.cmd==CMD_ENC_VSS_T
					  || sb.cmd==CMD_EFS_FILE)
						do_filecounter_bytes(p1cntr,
							(unsigned long long)
							sb.statp.st_size);
*/
				}
			}
			free_sbuf(&sb);
		}
		free_sbuf(&sb);
		gzclose_fp(&zp);
	}

	if(cconf->send_client_counters)
	{
		if(send_counters(client, p1cntr, cntr))
		{
			ret=-1;
		}
	}

	// Now, do the actual restore.
	if(!ret && !(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		char cmd;
		int s=0;
		int quit=0;
		size_t len=0;
		struct sbuf sb;
		// For out-of-sequence directory restoring so that the
		// timestamps come out right:
		int scount=0;
		struct sbuf **sblist=NULL;

		init_sbuf(&sb);

		while(!quit)
		{
			int ars=0;
			char *buf=NULL;
			if(async_read_quick(&cmd, &buf, &len))
			{
				logp("read quick error\n");
				ret=-1; quit++; break;
			}
			if(buf)
			{
				//logp("got read quick\n");
				if(cmd==CMD_WARNING)
				{
					logp("WARNING: %s\n", buf);
					do_filecounter(cntr, cmd, 0);
					free(buf); buf=NULL;
					continue;
				}
				else if(cmd==CMD_INTERRUPT)
				{
					// Client wanted to interrupt the
					// sending of a file. But if we are
					// here, we have already moved on.
					// Ignore.
					free(buf); buf=NULL;
					continue;
				}
				else
				{
					logp("unexpected cmd from client: %c:%s\n", cmd, buf);
					free(buf); buf=NULL;
					ret=-1; quit++; break;
				}
			}

			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if((!srestore
				    || check_srestore(cconf, sb.path))
				  && check_regex(regex, sb.path)
				  && restore_ent(client,
					&sb, &sblist, &scount,
					arr, a, i, tmppath1, tmppath2,
					act, status, cconf,
					cntr, p1cntr))
				{
					ret=-1;
					quit++;
				}
			}
			free_sbuf(&sb);
		}
		gzclose_fp(&zp);
		// Restore any directories that are left in the list.
		if(!ret) for(s=scount-1; s>=0; s--)
		{
			if(restore_sbuf(sblist[s], arr, a, i,
				tmppath1, tmppath2, act, client, status,
				p1cntr, cntr, cconf))
			{
				ret=-1;
				break;
			}
		}
		free_sbufs(sblist, scount);

		if(!ret) ret=do_restore_end(act, cntr);

		//print_endcounter(cntr);
		print_filecounters(p1cntr, cntr, act);

		reset_filecounter(p1cntr, time(NULL));
		reset_filecounter(cntr, time(NULL));
	}
	set_logfp(NULL, cconf);
	compress_file(logpath, logpathz, cconf);
	if(manifest) free(manifest);
	if(datadir) free(datadir);
	if(logpath) free(logpath);
	if(logpathz) free(logpathz);
	return ret;
}
Beispiel #6
0
// a = length of struct bu array
// i = position to restore from
static int restore_file(struct bu *arr, int a, int i, const char *datapth, const char *fname, const char *tmppath1, const char *tmppath2, int act, const char *endfile, char cmd, int64_t winattr, int compression, struct cntr *cntr, struct config *cconf)
{
	int x=0;
	char msg[256]="";
	// Go up the array until we find the file in the data directory.
	for(x=i; x<a; x++)
	{
		char *path=NULL;
		struct stat statp;
		if(!(path=prepend_s(arr[x].data, datapth, strlen(datapth))))
		{
			log_and_send_oom(__FUNCTION__);
			return -1;
		}

		//logp("server file: %s\n", path);

		if(lstat(path, &statp) || !S_ISREG(statp.st_mode))
		{
			free(path);
			continue;
		}
		else
		{
			int patches=0;
			struct stat dstatp;
			const char *tmp=NULL;
			const char *best=NULL;
			unsigned long long bytes=0;

			best=path;
			tmp=tmppath1;
			// Now go down the array, applying any deltas.
			for(x-=1; x>=i; x--)
			{
				char *dpath=NULL;

				if(!(dpath=prepend_s(arr[x].delta,
						datapth, strlen(datapth))))
				{
					log_and_send_oom(__FUNCTION__);
					free(path);
					return -1;
				}

				if(lstat(dpath, &dstatp)
				  || !S_ISREG(dstatp.st_mode))
				{
					free(dpath);
					continue;
				}

				if(!patches)
				{
					// Need to gunzip the first one.
					if(inflate_or_link_oldfile(best, tmp,
						compression))
					{
						logp("error when inflating %s\n", best);
						free(path);
						free(dpath);
						return -1;
					}
					best=tmp;
					if(tmp==tmppath1) tmp=tmppath2;
					else tmp=tmppath1;
				}

				if(do_patch(best, dpath, tmp,
				  FALSE /* do not gzip the result */,
				  compression /* from the manifest */,
				  cntr, cconf))
				{
					char msg[256]="";
					snprintf(msg, sizeof(msg),
						"error when patching %s\n",
							path);
					log_and_send(msg);
					free(path);
					free(dpath);
					return -1;
				}

				best=tmp;
				if(tmp==tmppath1) tmp=tmppath2;
				else tmp=tmppath1;
				unlink(tmp);
				patches++;
			}


			if(act==ACTION_RESTORE)
			{
				if(send_file(fname, patches, best, datapth,
					&bytes, cmd, winattr, compression,
					cntr, cconf))
				{
					free(path);
					return -1;
				}
				else
				{
					do_filecounter(cntr, cmd, 0);
					do_filecounter_bytes(cntr,
                 			    strtoull(endfile, NULL, 10));
				}
			}
			else if(act==ACTION_VERIFY)
			{
				if(verify_file(fname, patches, best, datapth,
					&bytes, endfile, cmd, compression,
					cntr))
				{
					free(path);
					return -1;
				}
				else
				{
					do_filecounter(cntr, cmd, 0);
					do_filecounter_bytes(cntr,
                 			    strtoull(endfile, NULL, 10));
				}
			}
			do_filecounter_sentbytes(cntr, bytes);
			free(path);
			return 0;
		}
	}

	logw(cntr, "restore could not find %s (%s)\n", fname, datapth);
	//return -1;
	return 0;
}
Beispiel #7
0
// returns 1 for finished ok.
static int do_stuff_to_receive(struct sbuf *rb, FILE *p2fp, const char *datadirtmp, struct dpth *dpth, const char *working, char **last_requested, const char *deltmppath, struct cntr *cntr, struct config *cconf)
{
	int ret=0;
	char rcmd;
	size_t rlen=0;
	size_t wlen=0;
	char *rbuf=NULL;

	// This also attempts to write anything in the write buffer.
	if(async_rw(&rcmd, &rbuf, &rlen, '\0', NULL, &wlen))
	{
		logp("error in async_rw\n");
		return -1;
	}

	if(rbuf)
	{
		if(rcmd==CMD_WARNING)
		{
			logp("WARNING: %s\n", rbuf);
			do_filecounter(cntr, rcmd, 0);
		}
		else if(rb->fp || rb->zp)
		{
			// Currently writing a file (or meta data)
			if(rcmd==CMD_APPEND)
			{
				int app;
				//logp("rlen: %d\n", rlen);
				if((rb->zp
				  && (app=gzwrite(rb->zp, rbuf, rlen))<=0)
				|| (rb->fp
				  && (app=fwrite(rbuf, 1, rlen, rb->fp))<=0))
				{
					logp("error when appending: %d\n", app);
					async_write_str(CMD_ERROR, "write failed");
					ret=-1;
				}
				do_filecounter_recvbytes(cntr, rlen);
			}
			else if(rcmd==CMD_END_FILE)
			{
				// Finished the file.
				// Write it to the phase2 file, and free the
				// buffers.

				if(close_fp(&(rb->fp)))
				{
					logp("error closing delta for %s in receive\n", rb->path);
					ret=-1;
				}
				if(gzclose_fp(&(rb->zp)))
				{
					logp("error gzclosing delta for %s in receive\n", rb->path);
					ret=-1;
				}
				rb->endfile=rbuf;
				rb->elen=rlen;
				rbuf=NULL;
				if(!ret && rb->receivedelta
				  && finish_delta(rb, working, deltmppath))
					ret=-1;
				else if(!ret)
				{
					if(sbuf_to_manifest(rb, p2fp, NULL))
						ret=-1;
					else
					{
					  char cmd=rb->cmd;
					  if(rb->receivedelta)
						do_filecounter_changed(cntr,
							cmd);
					  else
						do_filecounter(cntr, cmd, 0);
					  if(*last_requested
					  && !strcmp(rb->path, *last_requested))
					  {
						free(*last_requested);
						*last_requested=NULL;
					  }
					}
				}

				if(!ret)
				{
					char *cp=NULL;
					cp=strchr(rb->endfile, ':');
					if(rb->endfile)
					 do_filecounter_bytes(cntr,
					  strtoull(rb->endfile, NULL, 10));
					if(cp)
					{
						// checksum stuff goes here
					}
				}

				free_sbuf(rb);
			}
			else
			{
				logp("unexpected cmd from client while writing file: %c %s\n", rcmd, rbuf);
				ret=-1;
			}
		}
		// Otherwise, expecting to be told of a file to save.
		else if(rcmd==CMD_DATAPTH)
		{
			rb->datapth=rbuf;
			rbuf=NULL;
		}
		else if(rcmd==CMD_STAT)
		{
			rb->statbuf=rbuf;
			rb->slen=rlen;
			rbuf=NULL;
		}
		else if(filedata(rcmd))
		{
			rb->cmd=rcmd;
			rb->plen=rlen;
			rb->path=rbuf;
			rbuf=NULL;

			if(rb->datapth)
			{
				// Receiving a delta.
				if(start_to_receive_delta(rb,
				  working, deltmppath, cconf))
				{
					logp("error in start_to_receive_delta\n");
					ret=-1;
				}
			}
			else
			{
				// Receiving a whole new file.
				if(start_to_receive_new_file(rb,
					datadirtmp, dpth, cntr, cconf))
				{
					logp("error in start_to_receive_new_file\n");
					ret=-1;
				}
			}
		}
		else if(rcmd==CMD_GEN && !strcmp(rbuf, "okbackupphase2end"))
		{
			ret=1;
			//logp("got okbackupphase2end\n");
		}
		else if(rcmd==CMD_INTERRUPT)
		{
			// Interrupt - forget about the last requested file
			// if it matches. Otherwise, we can get stuck on the
			// select in the async stuff, waiting for something
			// that will never arrive.
			if(*last_requested && !strcmp(rbuf, *last_requested))
			{
				free(*last_requested);
				*last_requested=NULL;
			}
		}
		else
		{
			logp("unexpected cmd from client while expecting a file: %c %s\n", rcmd, rbuf);
			ret=-1;
		}

		if(rbuf) { free(rbuf); rbuf=NULL; }
	}

	//logp("returning: %d\n", ret);
	return ret;
}