Skip to content

Commit bdff3d8

Browse files
committed
gufi_query descend fallback to calling lstat if d_type was not set
1 parent 3ea272a commit bdff3d8

File tree

5 files changed

+64
-38
lines changed

5 files changed

+64
-38
lines changed

include/descend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct descend_counters {
8484
size_t external_dbs;
8585
};
8686

87+
struct work *try_skip_lstat(const unsigned char d_type, struct work *work);
88+
8789
/*
8890
* Push the subdirectories in the current directory onto the queue
8991
* and process non directories using a user provided function

include/gufi_query/gqw.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ size_t gqw_size(gqw_t *gqw);
8989
/* allocate a gqw and fill in some fields */
9090
gqw_t *new_gqw_with_name(const char *prefix, const size_t prefix_len,
9191
const char *basename, const size_t basename_len,
92-
int *isdir, const int next_level,
92+
const unsigned char d_type, const int next_level,
9393
const char *sqlite3_prefix, const size_t sqlite3_prefix_len);
9494

9595
/* call compress_struct to compress a gqw, but call this to decompress */

src/descend.c

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,39 @@ static int work_serialize_and_free(const int fd, QPTPool_f func, void *work, siz
8080
}
8181
#endif
8282

83+
struct work *try_skip_lstat(const unsigned char d_type, struct work *work) {
84+
switch (d_type) {
85+
case DT_DIR:
86+
work->statuso.st_mode = S_IFDIR;
87+
break;
88+
case DT_LNK:
89+
work->statuso.st_mode = S_IFLNK;
90+
break;
91+
case DT_REG:
92+
work->statuso.st_mode = S_IFREG;
93+
break;
94+
case DT_FIFO:
95+
case DT_SOCK:
96+
case DT_CHR:
97+
case DT_BLK:
98+
break;
99+
case DT_UNKNOWN:
100+
default:
101+
/* some filesystems don't support d_type - fall back to calling lstat */
102+
if (lstat(work->name, &work->statuso) != 0) {
103+
const int err = errno;
104+
fprintf(stderr, "Error: Could not stat \"%s\": %s (%d)\n",
105+
work->name, strerror(err), err);
106+
return NULL;
107+
}
108+
109+
work->lstat_called = 1;
110+
break;
111+
}
112+
113+
return work;
114+
}
115+
83116
/*
84117
* Push the subdirectories in the current directory onto the queue
85118
* and process non directories using a user provided function.
@@ -141,30 +174,8 @@ int descend(QPTPool_t *ctx, const size_t id, void *args,
141174
child->root_parent = work->root_parent;
142175
child->pinode = inode;
143176

144-
switch (dir_child->d_type) {
145-
case DT_DIR:
146-
child->statuso.st_mode = S_IFDIR;
147-
break;
148-
case DT_LNK:
149-
child->statuso.st_mode = S_IFLNK;
150-
break;
151-
case DT_REG:
152-
child->statuso.st_mode = S_IFREG;
153-
break;
154-
case DT_FIFO:
155-
case DT_SOCK:
156-
case DT_CHR:
157-
case DT_BLK:
158-
break;
159-
case DT_UNKNOWN:
160-
default:
161-
/* some filesystems don't support d_type - fall back to calling lstat */
162-
if (lstat(child->name, &child->statuso) != 0) {
163-
continue;
164-
}
165-
166-
child->lstat_called = 1;
167-
break;
177+
if (!try_skip_lstat(dir_child->d_type, child)) {
178+
continue;
168179
}
169180

170181
/* push subdirectories onto the queue */

src/gufi_query/gqw.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,13 @@ OF SUCH DAMAGE.
6262

6363

6464

65+
#include <errno.h>
6566
#include <stdlib.h>
67+
#include <string.h>
6668
#include <sys/stat.h>
6769
#include <sys/types.h>
6870

71+
#include "descend.h"
6972
#include "dbutils.h"
7073
#include "gufi_query/gqw.h"
7174
#include "utils.h"
@@ -86,7 +89,7 @@ size_t gqw_size(gqw_t *gqw) {
8689
*/
8790
gqw_t *new_gqw_with_name(const char *prefix, const size_t prefix_len,
8891
const char *basename, const size_t basename_len,
89-
int *isdir, const int next_level,
92+
const unsigned char d_type, const int next_level,
9093
const char *sqlite3_prefix, const size_t sqlite3_prefix_len) {
9194
/* +1 for path separator */
9295
const size_t name_len = prefix_len + 1 + basename_len;
@@ -102,18 +105,26 @@ gqw_t *new_gqw_with_name(const char *prefix, const size_t prefix_len,
102105
"/", (size_t) 1,
103106
basename, basename_len);
104107

105-
if (!*isdir) {
106-
/* allow for paths immediately under the input paths to be symlinks */
107-
if (next_level < 2) {
108-
struct stat st;
109-
if (stat(gqw->work.name, &st) == 0) {
110-
*isdir = S_ISDIR(st.st_mode);
111-
}
112-
/* errors are ignored */
108+
/* allow for paths immediately under the input paths to be symlinks */
109+
if (next_level < 2) {
110+
if (stat(gqw->work.name, &gqw->work.statuso) != 0) {
111+
const int err = errno;
112+
fprintf(stderr, "Error: Could not stat \"%s\": %s (%d)\n",
113+
gqw->work.name, strerror(err), err);
114+
free(gqw);
115+
return NULL;
116+
}
117+
118+
gqw->work.lstat_called = 1;
119+
}
120+
else {
121+
if (!try_skip_lstat(d_type, &gqw->work)) {
122+
free(gqw);
123+
return NULL;
113124
}
114125
}
115126

116-
if (*isdir) {
127+
if (S_ISDIR(gqw->work.statuso.st_mode)) {
117128
gqw->sqlite3_name = gqw->work.name + name_len + 1;
118129

119130
/* append converted entry name to converted directory */

src/gufi_query/process_queries.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,15 @@ static size_t descend2(QPTPool_t *ctx,
110110
continue;
111111
}
112112

113-
int isdir = (entry->d_type == DT_DIR);
114113
gqw_t *child = new_gqw_with_name(gqw->work.name, gqw->work.name_len,
115114
entry->d_name, len,
116-
&isdir, next_level,
115+
entry->d_type, next_level,
117116
gqw->sqlite3_name, gqw->sqlite3_name_len);
117+
if (!child) {
118+
continue;
119+
}
118120

119-
if (isdir) {
121+
if (S_ISDIR(child->work.statuso.st_mode)) {
120122
if (subdir_within_range(in, next_level, entry->d_name, len) != 1) {
121123
free(child);
122124
continue;

0 commit comments

Comments
 (0)