Ejemplo n.º 1
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 */
	}
}
Ejemplo n.º 2
0
Archivo: pool.c Proyecto: 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;
}