mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Ensures to call lstat_ex() only on regular files.
This commit is contained in:
parent
524360d8c2
commit
c513af08ff
5 changed files with 57 additions and 17 deletions
|
|
@ -265,6 +265,17 @@ static void import_dir(struct snapraid_state* state, const char* dir)
|
|||
#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 */
|
||||
if (st.st_mode == 0) {
|
||||
if (lstat(path, &st) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", path, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* get lstat info about the file */
|
||||
if (lstat(path, &st) != 0) {
|
||||
|
|
|
|||
|
|
@ -142,13 +142,14 @@ struct windows_stat {
|
|||
int windows_fstat(int fd, struct windows_stat* st);
|
||||
|
||||
/**
|
||||
* Like the C lstat() but without some information.
|
||||
* Like the C lstat(), but with some limitations.
|
||||
*
|
||||
* The st_ino field may be 0 if it's not possible to read it in a fast way.
|
||||
* Specifically this always happens.
|
||||
*
|
||||
* In case of hardlinks, the size and the attributes of the file can
|
||||
* be completely bogus, because changes made by other hardlinks are reported in the
|
||||
* directory entry only when the file is opened.
|
||||
* be completely bogus, because changes made by other hardlinks are reported
|
||||
* in the directory entry only when the file is opened.
|
||||
*
|
||||
* MSDN CreateHardLinks
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363860%28v=vs.85%29.aspx
|
||||
|
|
@ -181,9 +182,14 @@ int windows_mkdir(const char* file);
|
|||
int windows_rmdir(const char* file);
|
||||
|
||||
/**
|
||||
* Like the C lstat().
|
||||
|
||||
* It doesn't work for all kind of files and directories. For example "\System Volume Information" cannot be opened.
|
||||
* Like the C lstat(), but with some limitations.
|
||||
*
|
||||
* This call fills all the st_* fields of the stat struct.
|
||||
*
|
||||
* It doesn't work for all kinds of files and directories.
|
||||
* You must call it only for regular files.
|
||||
* For example, "\System Volume Information" cannot be accessed.
|
||||
*
|
||||
* Note that instead lstat() works for all the files.
|
||||
*/
|
||||
#define HAVE_LSTAT_EX 1
|
||||
|
|
@ -266,10 +272,15 @@ struct windows_dirent* windows_readdir(windows_dir* dirstream);
|
|||
int windows_closedir(windows_dir* dirstream);
|
||||
|
||||
/**
|
||||
* Convert a dirent record to a lstat record.
|
||||
* Convert a dirent record to a lstat record, but with some limitations.
|
||||
*
|
||||
* The st_mode field may be 0 if the file is a reparse point.
|
||||
* Specifically this happens if we are using GetFileInformationByHandleEx()
|
||||
* to read the directory stream.
|
||||
*
|
||||
* The st_ino field may be 0 if it's not possible to read it in a fast way.
|
||||
* Specifically this happens if we are using FindFirst/FindNext to enumerate
|
||||
* the directory.
|
||||
*
|
||||
* In such cases, call lstat_ex() to fill the missing fields.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -67,6 +67,17 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
|
|||
#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 */
|
||||
if (st.st_mode == 0) {
|
||||
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 */
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* get lstat info about the file */
|
||||
if (lstat(path_next, &st) != 0) {
|
||||
|
|
|
|||
|
|
@ -1019,6 +1019,8 @@ static int scan_dir(struct snapraid_scan* scan, int output, const char* dir, con
|
|||
#if HAVE_STRUCT_DIRENT_D_STAT
|
||||
/* convert dirent to lstat result */
|
||||
dirent_lstat(dd, &entry->d_stat);
|
||||
|
||||
/* note that at this point the st_mode may be 0 */
|
||||
#endif
|
||||
memcpy(entry->d_name, dd->d_name, name_len + 1);
|
||||
|
||||
|
|
@ -1084,10 +1086,12 @@ static int scan_dir(struct snapraid_scan* scan, int output, const char* dir, con
|
|||
/* get the type from stat */
|
||||
st = DSTAT(path_next, dd, &st_buf);
|
||||
|
||||
#if HAVE_LSTAT_EX
|
||||
/* if the stat entry is incomplete, take care to fill it using the extended lstat() */
|
||||
#if HAVE_STRUCT_DIRENT_D_STAT
|
||||
/* if the st_mode field is missing, takes care to fill it using normal lstat() */
|
||||
/* at now this can happen only in Windows, but we cannot call here lstat_ex(), */
|
||||
/* because we don't know what kind of file is it, and lstat_ex() doesn't always work */
|
||||
if (st->st_mode == 0) {
|
||||
if (lstat_ex(path_next, st) != 0) {
|
||||
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);
|
||||
|
|
@ -1115,8 +1119,9 @@ static int scan_dir(struct snapraid_scan* scan, int output, const char* dir, con
|
|||
st = DSTAT(path_next, dd, &st_buf);
|
||||
|
||||
#if HAVE_LSTAT_EX
|
||||
/* if the stat entry is incomplete, take care to fill it using the extended lstat() */
|
||||
if (st->st_ino == 0) {
|
||||
/* if the st_ino field is missing, takes care to fill it using the extended lstat() */
|
||||
/* this can happen only in Windows */
|
||||
if (st->st_ino == 0) {
|
||||
if (lstat_ex(path_next, st) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
|
||||
|
|
@ -1177,8 +1182,9 @@ static int scan_dir(struct snapraid_scan* scan, int output, const char* dir, con
|
|||
} else if (type == 2) { /* DIR */
|
||||
if (filter_dir(&state->filterlist, disk->name, sub_next) == 0) {
|
||||
#ifndef _WIN32
|
||||
/* late stat */
|
||||
if (!st) st = DSTAT(path_next, dd, &st_buf);
|
||||
/* late stat, if not yet called */
|
||||
if (!st)
|
||||
st = DSTAT(path_next, dd, &st_buf);
|
||||
|
||||
/* in Unix don't follow mount points in different devices */
|
||||
/* in Windows we are already skipping them reporting them as special files */
|
||||
|
|
@ -1207,8 +1213,9 @@ static int scan_dir(struct snapraid_scan* scan, int output, const char* dir, con
|
|||
}
|
||||
} else {
|
||||
if (filter_path(&state->filterlist, disk->name, sub_next) == 0) {
|
||||
/* late stat */
|
||||
if (!st) st = DSTAT(path_next, dd, &st_buf);
|
||||
/* late stat, if not yet called */
|
||||
if (!st)
|
||||
st = DSTAT(path_next, dd, &st_buf);
|
||||
|
||||
fprintf(stderr, "WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* copy the options */
|
||||
state->opt = *opt;
|
||||
|
||||
/* if unsed, sort by physical order */
|
||||
/* if unset, sort by physical order */
|
||||
if (!state->opt.force_order)
|
||||
state->opt.force_order = SORT_PHYSICAL;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue