2 Directory enumeration check
3 Copyright (C) Ralph Boehme <slowl@samba.org> 2016
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/types.h>
35 #define ERROR(err, fmt, ...) \
37 do_log(__FILE__, __LINE__, __FUNCTION__, (fmt), __VA_ARGS__); \
41 #define LOG(fmt, ...) \
43 do_log(__FILE__, __LINE__, __FUNCTION__, (fmt), __VA_ARGS__); \
52 static void do_log(const char *file, int line, const char *func, const char *fmt, ...)
59 len = vasprintf(&message, fmt, args);
65 printf("%s:%d(%s): %s\n", file, line, func, message);
70 * Read n entries from a directory
72 * If check_name is not NULL, the first entry's name is compared
75 * If plast_name is not NULL, the last name is returned *AND* the
76 * directory location is rewound to its position.
78 static bool enumdir_check(DIR *dir,
81 const char *check_name,
84 struct dirent *de = NULL;
88 for (i = 0; i < n; i++) {
89 prev_offset = telldir(dir);
90 if (prev_offset == -1) {
91 ERROR(ERR_SYSCALL, "telldir error %s", strerror(errno));
96 ERROR(ERR_SYSCALL, "readir error %s", strerror(errno));
99 if (i == 0 && check_name != NULL) {
100 if (strcmp(check_name, de->d_name) != 0) {
101 ERROR(ERR_CALL, "expected %s got %s", check_name, de->d_name);
105 printf("%s\n", de->d_name);
109 if (plast_name != NULL) {
110 seekdir(dir, prev_offset);
111 *plast_name = strdup(de->d_name);
112 if (*plast_name == NULL) {
113 ERROR(ERR_CALL, "strdup error %s", strerror(errno));
121 * This is the number of entries that shall be fetched via readir() in
122 * a loop. It is modelled after the behavour of a SMB client doing a
123 * SMB2 query directory request with a buffer size of 64k. The plus
124 * one is the entry that will rewind with seekdir().
126 #define ENUM_NUM_1 372 + 1
127 #define ENUM_NUM_2 372 + 1
128 #define ENUM_NUM_3 9 /* 372 + 372 + 9 = 753 */
130 int main(int argc, char **argv)
134 const char *dirpath = NULL;
135 char *last_name = NULL;
138 ERROR(ERR_USAGE, "usage: %s PATH", argv[0]);
142 dir = opendir(dirpath);
144 ERROR(ERR_SYSCALL, "opendir %s error %s", dirpath, strerror(errno));
147 ok = enumdir_check(dir, true, ENUM_NUM_1, NULL, &last_name);
149 ERROR(ERR_CALL, "enum_check: %s", strerror(errno));
152 printf("Last entry: %s, rewound to it...\n", last_name);
154 ok = enumdir_check(dir, true, ENUM_NUM_2,
155 last_name, &last_name);
157 ERROR(ERR_CALL, "enum_check: %s", strerror(errno));
160 printf("Last entry: %s, rewound to it...\n", last_name);
162 ok = enumdir_check(dir, true, ENUM_NUM_3,
163 last_name, &last_name);
165 ERROR(ERR_CALL, "enum_check: %s", strerror(errno));