示例#1
0
void state_search(struct snapraid_state* state, const char* dir)
{
	char path[PATH_MAX];

	msg_progress("Importing...\n");

	/* add the final slash */
	pathimport(path, sizeof(path), dir);
	pathslash(path, sizeof(path));

	search_dir(state, 0, path, "");
}
示例#2
0
文件: elem.c 项目: CrawX/snapraid
struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, int skip)
{
	struct snapraid_disk* disk;

	disk = malloc_nofail(sizeof(struct snapraid_disk));
	pathcpy(disk->name, sizeof(disk->name), name);
	pathimport(disk->dir, sizeof(disk->dir), dir);

	/* ensure that the dir terminate with "/" if it isn't empty */
	pathslash(disk->dir, sizeof(disk->dir));

	disk->smartctl[0] = 0;
	disk->device = dev;
	disk->tick = 0;
	disk->total_blocks = 0;
	disk->free_blocks = 0;
	disk->first_free_block = 0;
	disk->has_volatile_inodes = 0;
	disk->has_unreliable_physical = 0;
	disk->has_different_uuid = 0;
	disk->has_unsupported_uuid = 0;
	disk->had_empty_uuid = 0;
	disk->mapping_idx = -1;
	disk->skip_access = skip;
	tommy_list_init(&disk->filelist);
	tommy_list_init(&disk->deletedlist);
	tommy_hashdyn_init(&disk->inodeset);
	tommy_hashdyn_init(&disk->pathset);
	tommy_hashdyn_init(&disk->stampset);
	tommy_list_init(&disk->linklist);
	tommy_hashdyn_init(&disk->linkset);
	tommy_list_init(&disk->dirlist);
	tommy_hashdyn_init(&disk->dirset);
	tommy_tree_init(&disk->fs_parity, chunk_parity_compare);
	tommy_tree_init(&disk->fs_file, chunk_file_compare);
	disk->fs_last = 0;

	return disk;
}
示例#3
0
static void search_dir(struct snapraid_state* state, struct snapraid_disk* disk, const char* dir, const char* sub)
{
	DIR* d;

	d = opendir(dir);
	if (!d) {
		/* LCOV_EXCL_START */
		msg_error("Error opening directory '%s'. %s.\n", dir, strerror(errno));
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	while (1) {
		char path_next[PATH_MAX];
		char sub_next[PATH_MAX];
		char out[PATH_MAX];
		struct snapraid_filter* reason = 0;
		struct stat st;
		const char* name;
		struct dirent* dd;

		/* clear errno to detect erroneous conditions */
		errno = 0;
		dd = readdir(d);
		if (dd == 0 && errno != 0) {
			/* LCOV_EXCL_START */
			msg_error("Error reading directory '%s'. %s.\n", dir, strerror(errno));
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
		if (dd == 0) {
			break; /* finished */
		}

		/* skip "." and ".." files */
		name = dd->d_name;
		if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
			continue;

		pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
		pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);

		/* exclude hidden files even before calling lstat() */
		if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) {
			msg_verbose("Excluding hidden '%s'\n", path_next);
			continue;
		}

		/* exclude content files even before calling lstat() */
		if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) {
			msg_verbose("Excluding content '%s'\n", path_next);
			continue;
		}

#if HAVE_STRUCT_DIRENT_D_STAT
		/* convert dirent to lstat result */
		dirent_lstat(dd, &st);

		/* if the st_mode field is missing, takes care to fill it using normal lstat() */
		/* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */
		/* because we use a directory reading method that doesn't read info about ReparsePoint. */
		/* Note that here we cannot call here lstat_sync(), because we don't know what kind */
		/* of file is it, and lstat_sync() doesn't always work */
		if (st.st_mode == 0) {
			if (lstat(path_next, &st) != 0) {
				/* LCOV_EXCL_START */
				msg_error("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
		}
#else
		/* get lstat info about the file */
		if (lstat(path_next, &st) != 0) {
			/* LCOV_EXCL_START */
			msg_error("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
#endif

		if (S_ISREG(st.st_mode)) {
			if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
				search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st));
			} else {
				msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
			}
		} else if (S_ISDIR(st.st_mode)) {
			if (disk == 0 || filter_dir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
				pathslash(path_next, sizeof(path_next));
				pathslash(sub_next, sizeof(sub_next));
				search_dir(state, disk, path_next, sub_next);
			} else {
				msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
			}
		}
	}

	if (closedir(d) != 0) {
		/* LCOV_EXCL_START */
		msg_error("Error closing directory '%s'. %s.\n", dir, strerror(errno));
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}
}
示例#4
0
文件: pool.c 项目: GDXN/snapraid
/**
 * Clean a directory tree removing all the symlinks and empty directories.
 * Return == 0 if the directory is empty, and it can be removed
 */
static int clean_dir(struct snapraid_state* state, const char* dir)
{
	DIR* d;
	int ignored = 0;

	d = opendir(dir);
	if (!d) {
		/* LCOV_EXCL_START */
		fprintf(stderr, "Error opening pool directory '%s'. %s.\n", dir, strerror(errno));
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}
   
	while (1) { 
		char path_next[PATH_MAX];
		struct stat st;
		const char* name;
		struct dirent* dd;

		/* clear errno to detect erroneous conditions */
		errno = 0;
		dd = readdir(d);
		if (dd == 0 && errno != 0) {
			/* LCOV_EXCL_START */
			fprintf(stderr, "Error reading pool directory '%s'. %s.\n", dir, strerror(errno));
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
		if (dd == 0 && errno == 0) {
			break; /* finished */
		}

		/* skip "." and ".." files */
		name = dd->d_name;
		if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
			continue;

		pathprint(path_next, sizeof(path_next), "%s%s", dir, name);

#if HAVE_STRUCT_DIRENT_D_STAT
		/* convert dirent to lstat result */
		dirent_lstat(dd, &st);
#else
		/* get lstat info about the file */
		if (lstat(path_next, &st) != 0) {
			/* LCOV_EXCL_START */
			fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
#endif

		if (S_ISLNK(st.st_mode)) {
			int ret;

			/* delete the link */
			ret = remove(path_next);
			if (ret < 0) {
				/* LCOV_EXCL_START */
				fprintf(stderr, "Error removing symlink '%s'. %s.\n", path_next, strerror(errno));
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
		} else if (S_ISDIR(st.st_mode)) {
			/* recurse */
			pathslash(path_next, sizeof(path_next));
			if (clean_dir(state, path_next) == 0) {
				int ret;

				/* directory is empty, try to remove it */
				ret = rmdir(path_next);
				if (ret < 0) {
#ifdef _WIN32
					if (errno == EACCES) {
						/* in Windows just ignore EACCES errors removing directories */
						/* because it could happen that the directory is in use */
						/* and it cannot be removed */
						fprintf(stderr, "Directory '%s' not removed because it's in use.\n", path_next);
						ignored = 1;
					} else
#endif
					{
						/* LCOV_EXCL_START */
						fprintf(stderr, "Error removing pool directory '%s'. %s.\n", path_next, strerror(errno));
						exit(EXIT_FAILURE);
						/* LCOV_EXCL_STOP */
					}
				}
			} else {
				/* something was ignored inside the subdir */
				ignored = 1;
			}
		} else {
			ignored = 1;
			if (state->opt.verbose) {
				printf("Ignoring pool file '%s'\n", path_next);
			}
		}
	}

	if (closedir(d) != 0) {
		/* LCOV_EXCL_START */
		fprintf(stderr, "Error closing pool directory '%s'. %s.\n", dir, strerror(errno));
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	return ignored;
}
示例#5
0
文件: pool.c 项目: GDXN/snapraid
void state_pool(struct snapraid_state* state)
{
	tommy_node* i;
	char pool_dir[PATH_MAX];
	char share_dir[PATH_MAX];
	unsigned count;

	if (state->pool[0] == 0) {
		/* LCOV_EXCL_START */
		fprintf(stderr, "To use the 'pool' command you must set the pool directory in the configuration file\n");
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	printf("Cleaning...\n");

	/* pool directory with final slash */
	pathprint(pool_dir, sizeof(pool_dir), "%s", state->pool);
	pathslash(pool_dir, sizeof(pool_dir));

	/* share directory with final slash */
	pathprint(share_dir, sizeof(share_dir), "%s", state->share);
	pathslash(share_dir, sizeof(share_dir));

	/* first clear the previous pool tree */
	clean_dir(state, pool_dir);

	printf("Pooling...\n");

	/* for each disk */
	count = 0;
	for(i=state->disklist;i!=0;i=i->next) {
		tommy_node* j;
		struct snapraid_disk* disk = i->data;

		/* for each file */
		for(j=disk->filelist;j!=0;j=j->next) {
			struct snapraid_file* file = j->data;
			make_link(pool_dir, share_dir, disk, file->sub);
			++count;
		}

		/* for each link */
		for(j=disk->linklist;j!=0;j=j->next) {
			struct snapraid_link* link = j->data;
			make_link(pool_dir, share_dir, disk, link->sub);
			++count;
		}

		/* we ignore empty dirs in disk->dir */
	}

	if (count)
		printf("%u links created\n", count);
	else
		printf("No link created\n");

	fprintf(stdlog, "summary:link_count::%u\n", count);
	fprintf(stdlog, "summary:exit:ok\n");
	fflush(stdlog);
}