tree schema REFACTOR optimize local file search
Avoid redundant asprintf() and stat() calls.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index baf2c46..c7ba064 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -2038,13 +2038,12 @@
LY_ERR ret = LY_EMEM;
size_t len, flen, match_len = 0, dir_len;
ly_bool implicit_cwd = 0;
- char *wd, *wn = NULL;
+ char *wd, *wn;
DIR *dir = NULL;
struct dirent *file;
char *match_name = NULL;
LYS_INFORMAT format_aux, match_format = 0;
struct ly_set *dirs;
- struct stat st;
LY_CHECK_ARG_RET(NULL, localfile, LY_EINVAL);
@@ -2088,7 +2087,6 @@
/* start searching */
while (dirs->count) {
free(wd);
- free(wn); wn = NULL;
dirs->count--;
wd = (char *)dirs->objs[dirs->count];
@@ -2102,101 +2100,102 @@
dir_len = strlen(wd);
if (!dir) {
LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
- } else {
- while ((file = readdir(dir))) {
- if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
- /* skip . and .. */
- continue;
- }
- free(wn);
+ continue;
+ }
+
+ /* search the directory */
+ while ((file = readdir(dir))) {
+ if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
+ /* skip . and .. */
+ continue;
+ }
+
+ if ((file->d_type == DT_DIR) && (dirs->count || !implicit_cwd)) {
+ /* we have another subdirectory in searchpath to explore,
+ * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
LOGMEM(NULL);
goto cleanup;
}
- if (stat(wn, &st) == -1) {
- LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
- file->d_name, wd, strerror(errno));
- continue;
- }
- if (S_ISDIR(st.st_mode) && (dirs->count || !implicit_cwd)) {
- /* we have another subdirectory in searchpath to explore,
- * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
- ret = ly_set_add(dirs, wn, 0, NULL);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* continue with the next item in current directory */
- wn = NULL;
- continue;
- } else if (!S_ISREG(st.st_mode)) {
- /* not a regular file (note that we see the target of symlinks instead of symlinks */
- continue;
+ if ((ret = ly_set_add(dirs, wn, 0, NULL))) {
+ free(wn);
+ goto cleanup;
}
- /* here we know that the item is a file which can contain a module */
- if (strncmp(name, file->d_name, len) ||
- ((file->d_name[len] != '.') && (file->d_name[len] != '@'))) {
- /* different filename than the module we search for */
- continue;
- }
+ /* continue with the next item in current directory */
+ continue;
+ } else if (file->d_type != DT_REG) {
+ /* not a regular file (note that we see the target of symlinks instead of symlinks */
+ continue;
+ }
- /* get type according to filename suffix */
- flen = strlen(file->d_name);
- if ((flen >= LY_YANG_SUFFIX_LEN + 1) &&
- !strcmp(&file->d_name[flen - LY_YANG_SUFFIX_LEN], LY_YANG_SUFFIX)) {
- format_aux = LYS_IN_YANG;
- } else if ((flen >= LY_YIN_SUFFIX_LEN + 1) &&
- !strcmp(&file->d_name[flen - LY_YIN_SUFFIX_LEN], LY_YIN_SUFFIX)) {
- format_aux = LYS_IN_YIN;
- } else {
- /* not supportde suffix/file format */
- continue;
- }
+ /* here we know that the item is a file which can contain a module */
+ if (strncmp(name, file->d_name, len) || ((file->d_name[len] != '.') && (file->d_name[len] != '@'))) {
+ /* different filename than the module we search for */
+ continue;
+ }
- if (revision) {
- /* we look for the specific revision, try to get it from the filename */
- if (file->d_name[len] == '@') {
- /* check revision from the filename */
- if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
- /* another revision */
- continue;
- } else {
- /* exact revision */
- free(match_name);
- match_name = wn;
- wn = NULL;
- match_len = dir_len + 1 + len;
- match_format = format_aux;
- goto success;
- }
+ /* get type according to filename suffix */
+ flen = strlen(file->d_name);
+ if ((flen >= LY_YANG_SUFFIX_LEN + 1) && !strcmp(&file->d_name[flen - LY_YANG_SUFFIX_LEN], LY_YANG_SUFFIX)) {
+ format_aux = LYS_IN_YANG;
+ } else if ((flen >= LY_YIN_SUFFIX_LEN + 1) && !strcmp(&file->d_name[flen - LY_YIN_SUFFIX_LEN], LY_YIN_SUFFIX)) {
+ format_aux = LYS_IN_YIN;
+ } else {
+ /* not supported suffix/file format */
+ continue;
+ }
+
+ if (revision) {
+ /* we look for the specific revision, try to get it from the filename */
+ if (file->d_name[len] == '@') {
+ /* check revision from the filename */
+ if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
+ /* another revision */
+ continue;
} else {
- /* continue trying to find exact revision match, use this only if not found */
+ /* exact revision */
free(match_name);
- match_name = wn;
- wn = NULL;
+ if (asprintf(&match_name, "%s/%s", wd, file->d_name) == -1) {
+ LOGMEM(NULL);
+ goto cleanup;
+ }
match_len = dir_len + 1 + len;
match_format = format_aux;
- continue;
+ goto success;
}
} else {
- /* remember the revision and try to find the newest one */
- if (match_name) {
- if ((file->d_name[len] != '@') ||
- lysp_check_date(NULL, &file->d_name[len + 1],
- flen - ((format_aux == LYS_IN_YANG) ? LY_YANG_SUFFIX_LEN : LY_YIN_SUFFIX_LEN) - len - 1, NULL)) {
- continue;
- } else if ((match_name[match_len] == '@') &&
- (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
- continue;
- }
- free(match_name);
+ /* continue trying to find exact revision match, use this only if not found */
+ free(match_name);
+ if (asprintf(&match_name, "%s/%s", wd, file->d_name) == -1) {
+ LOGMEM(NULL);
+ goto cleanup;
}
-
- match_name = wn;
- wn = NULL;
match_len = dir_len + 1 + len;
match_format = format_aux;
continue;
}
+ } else {
+ /* remember the revision and try to find the newest one */
+ if (match_name) {
+ if ((file->d_name[len] != '@') ||
+ lysp_check_date(NULL, &file->d_name[len + 1],
+ flen - ((format_aux == LYS_IN_YANG) ? LY_YANG_SUFFIX_LEN : LY_YIN_SUFFIX_LEN) - len - 1, NULL)) {
+ continue;
+ } else if ((match_name[match_len] == '@') &&
+ (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
+ continue;
+ }
+ free(match_name);
+ }
+
+ if (asprintf(&match_name, "%s/%s", wd, file->d_name) == -1) {
+ LOGMEM(NULL);
+ goto cleanup;
+ }
+ match_len = dir_len + 1 + len;
+ match_format = format_aux;
+ continue;
}
}
}
@@ -2210,7 +2209,6 @@
ret = LY_SUCCESS;
cleanup:
- free(wn);
free(wd);
if (dir) {
closedir(dir);