Example #1
0
static int
verify_object(struct conf *conf, struct manifest *mf, struct object *obj,
              struct hashtable *stated_files, struct hashtable *hashed_files)
{
	for (uint32_t i = 0; i < obj->n_file_info_indexes; i++) {
		struct file_info *fi = &mf->file_infos[obj->file_info_indexes[i]];
		char *path = mf->files[fi->index];
		struct file_stats *st = hashtable_search(stated_files, path);
		if (!st) {
			struct stat file_stat;
			if (x_stat(path, &file_stat) != 0) {
				return 0;
			}
			st = x_malloc(sizeof(*st));
			st->size = file_stat.st_size;
			st->mtime = file_stat.st_mtime;
			st->ctime = file_stat.st_ctime;
			hashtable_insert(stated_files, x_strdup(path), st);
		}

		if (fi->size != st->size) {
			return 0;
		}

		if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
			if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
				cc_log("mtime/ctime hit for %s", path);
				continue;
			} else {
				cc_log("mtime/ctime miss for %s", path);
			}
		}

		struct file_hash *actual = hashtable_search(hashed_files, path);
		if (!actual) {
			struct mdfour hash;
			hash_start(&hash);
			int result = hash_source_code_file(conf, &hash, path);
			if (result & HASH_SOURCE_CODE_ERROR) {
				cc_log("Failed hashing %s", path);
				return 0;
			}
			if (result & HASH_SOURCE_CODE_FOUND_TIME) {
				return 0;
			}
			actual = x_malloc(sizeof(*actual));
			hash_result_as_bytes(&hash, actual->hash);
			actual->size = hash.totalN;
			hashtable_insert(hashed_files, x_strdup(path), actual);
		}
		if (memcmp(fi->hash, actual->hash, mf->hash_size) != 0
		    || fi->size != actual->size) {
			return 0;
		}
	}

	return 1;
}
Example #2
0
/****************************************************************************
Create a directory given an absolute path, perms based upon another directory
path
****************************************************************************/
int make_bak_dir(const char *fullpath)
{
	char fbuf[MAXPATHLEN], *rel, *end, *p;
	struct file_struct *file;
	int len = backup_dir_len;
	stat_x sx;

	while (*fullpath == '.' && fullpath[1] == '/') {
		fullpath += 2;
		len -= 2;
	}

	if (strlcpy(fbuf, fullpath, sizeof fbuf) >= sizeof fbuf)
		return -1;

	rel = fbuf + len;
	end = p = rel + strlen(rel);

	/* Try to find an existing dir, starting from the deepest dir. */
	while (1) {
		if (--p == fbuf)
			return -1;
		if (*p == '/') {
			*p = '\0';
			if (mkdir_defmode(fbuf) == 0)
				break;
			if (errno != ENOENT) {
				rsyserr(FERROR, errno,
					"make_bak_dir mkdir %s failed",
					full_fname(fbuf));
				return -1;
			}
		}
	}

	/* Make all the dirs that we didn't find on the way here. */
	while (1) {
		if (p >= rel) {
			/* Try to transfer the directory settings of the
			 * actual dir that the files are coming from. */
			if (x_stat(rel, &sx.st, NULL) < 0) {
				rsyserr(FERROR, errno,
					"make_bak_dir stat %s failed",
					full_fname(rel));
			} else {
#ifdef SUPPORT_ACLS
				sx.acc_acl = sx.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
				sx.xattr = NULL;
#endif
				if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
					continue;
#ifdef SUPPORT_ACLS
				if (preserve_acls && !S_ISLNK(file->mode)) {
					get_acl(rel, &sx);
					cache_tmp_acl(file, &sx);
					free_acl(&sx);
				}
#endif
#ifdef SUPPORT_XATTRS
				if (preserve_xattrs) {
					get_xattr(rel, &sx);
					cache_tmp_xattr(file, &sx);
					free_xattr(&sx);
				}
#endif
				set_file_attrs(fbuf, file, NULL, NULL, 0);
				unmake_file(file);
#ifdef SUPPORT_ACLS
				uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
				uncache_tmp_xattrs();
#endif
			}
		}
		*p = '/';
		p += strlen(p);
		if (p == end)
			break;
		if (mkdir_defmode(fbuf) < 0) {
			rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
				full_fname(fbuf));
			return -1;
		}
	}

	return 0;
}
Example #3
0
static int
verify_object(struct conf *conf, struct manifest *mf, struct object *obj,
              struct hashtable *stated_files, struct hashtable *hashed_files)
{
	for (uint32_t i = 0; i < obj->n_file_info_indexes; i++) {
		struct file_info *fi = &mf->file_infos[obj->file_info_indexes[i]];
		char *path = mf->files[fi->index];
		struct file_stats *st = hashtable_search(stated_files, path);
		if (!st) {
			struct stat file_stat;
			if (x_stat(path, &file_stat) != 0) {
				return 0;
			}
			st = x_malloc(sizeof(*st));
			st->size = file_stat.st_size;
			st->mtime = file_stat.st_mtime;
			st->ctime = file_stat.st_ctime;
			hashtable_insert(stated_files, x_strdup(path), st);
		}

		if (fi->size != st->size) {
			return 0;
		}

		// Clang stores the mtime of the included files in the precompiled header,
		// and will error out if that header is later used without rebuilding.
		if ((guessed_compiler == GUESSED_CLANG
		     || guessed_compiler == GUESSED_UNKNOWN)
		    && output_is_precompiled_header
		    && fi->mtime != st->mtime) {
			cc_log("Precompiled header includes %s, which has a new mtime", path);
			return 0;
		}

		if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
			if (!(conf->sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME)) {
				if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
					cc_log("mtime/ctime hit for %s", path);
					continue;
				} else {
					cc_log("mtime/ctime miss for %s", path);
				}
			} else {
				if (fi->mtime == st->mtime) {
					cc_log("mtime hit for %s", path);
					continue;
				} else {
					cc_log("mtime miss for %s", path);
				}
			}
		}

		struct file_hash *actual = hashtable_search(hashed_files, path);
		if (!actual) {
			struct hash *hash = hash_init();
			int result = hash_source_code_file(conf, hash, path);
			if (result & HASH_SOURCE_CODE_ERROR) {
				cc_log("Failed hashing %s", path);
				hash_free(hash);
				return 0;
			}
			if (result & HASH_SOURCE_CODE_FOUND_TIME) {
				hash_free(hash);
				return 0;
			}
			actual = x_malloc(sizeof(*actual));
			hash_result_as_bytes(hash, actual->hash);
			actual->size = hash_input_size(hash);
			hashtable_insert(hashed_files, x_strdup(path), actual);
			hash_free(hash);
		}
		if (memcmp(fi->hash, actual->hash, mf->hash_size) != 0
		    || fi->size != actual->size) {
			return 0;
		}
	}

	return 1;
}
Example #4
0
/* Create a backup path from the given fname, putting the result into
 * backup_dir_buf.  Any new directories (compared to the prior backup
 * path) are ensured to exist as directories, replacing anything else
 * that may be in the way (e.g. a symlink). */
static BOOL copy_valid_path(const char *fname)
{
	const char *f;
	int val;
	BOOL ret = True;
	stat_x sx;
	char *b, *rel = backup_dir_buf + backup_dir_len, *name = rel;

	for (f = fname, b = rel; *f && *f == *b; f++, b++) {
		if (*b == '/')
			name = b + 1;
	}

	if (stringjoin(rel, backup_dir_remainder, fname, backup_suffix, NULL) >= backup_dir_remainder) {
		rprintf(FERROR, "backup filename too long\n");
		*name = '\0';
		return False;
	}

	for ( ; ; name = b + 1) {
		if ((b = strchr(name, '/')) == NULL)
			return True;
		*b = '\0';

		val = validate_backup_dir();
		if (val == 0)
			break;
		if (val < 0) {
			*name = '\0';
			return False;
		}

		*b = '/';
	}

	init_stat_x(&sx);

	for ( ; b; name = b + 1, b = strchr(name, '/')) {
		*b = '\0';

		while (do_mkdir(backup_dir_buf, ACCESSPERMS) < 0) {
			if (errno == EEXIST) {
				val = validate_backup_dir();
				if (val > 0)
					break;
				if (val == 0)
					continue;
			} else
				rsyserr(FERROR, errno, "backup mkdir %s failed", backup_dir_buf);
			*name = '\0';
			ret = False;
			goto cleanup;
		}

		/* Try to transfer the directory settings of the actual dir
		 * that the files are coming from. */
		if (x_stat(rel, &sx.st, NULL) < 0)
			rsyserr(FERROR, errno, "backup stat %s failed", full_fname(rel));
		else {
			struct file_struct *file;
			if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
				continue;
#ifdef SUPPORT_ACLS
			if (preserve_acls && !S_ISLNK(file->mode)) {
				get_acl(rel, &sx);
				cache_tmp_acl(file, &sx);
				free_acl(&sx);
			}
#endif
#ifdef SUPPORT_XATTRS
			if (preserve_xattrs) {
				get_xattr(rel, &sx);
				cache_tmp_xattr(file, &sx);
				free_xattr(&sx);
			}
#endif
			set_file_attrs(backup_dir_buf, file, NULL, NULL, 0);
			unmake_file(file);
		}

		*b = '/';
	}

  cleanup:

#ifdef SUPPORT_ACLS
	uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
	uncache_tmp_xattrs();
#endif

	return ret;
}