summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lilv_internal.h11
-rw-r--r--src/util.c83
-rw-r--r--src/world.c53
3 files changed, 75 insertions, 72 deletions
diff --git a/src/lilv_internal.h b/src/lilv_internal.h
index 9950a61..43f92cd 100644
--- a/src/lilv_internal.h
+++ b/src/lilv_internal.h
@@ -342,8 +342,6 @@ char* lilv_strdup(const char* str);
char* lilv_get_lang(void);
char* lilv_expand(const char* path);
char* lilv_dirname(const char* path);
-char* lilv_find_free_path(
- const char* in_path, bool (*exists)(const char*, void*), void* user_data);
int lilv_copy_file(const char* src, const char* dst);
bool lilv_path_exists(const char* path, void* ignored);
bool lilv_path_is_absolute(const char* path);
@@ -352,6 +350,15 @@ char* lilv_path_relative_to(const char* path, const char* base);
bool lilv_path_is_child(const char* path, const char* dir);
int lilv_flock(FILE* file, bool lock);
+char*
+lilv_find_free_path(const char* in_path,
+ bool (*exists)(const char*, void*), void* user_data);
+
+void
+lilv_dir_for_each(const char* path,
+ void* data,
+ void (*f)(const char* path, const char* name, void* data));
+
typedef void (*VoidFunc)(void);
/** dlsym wrapper to return a function pointer (without annoying warning) */
diff --git a/src/util.c b/src/util.c
index cda7468..86300a1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -264,46 +264,45 @@ lilv_size_mtime(const char* path, off_t* size, time_t* time)
*time = buf.st_mtime;
}
+typedef struct {
+ char* pattern;
+ off_t orig_size;
+ time_t time;
+ char* latest;
+} Latest;
+
+static void
+update_latest(const char* path, const char* name, void* data)
+{
+ Latest* latest = (Latest*)data;
+ char* entry_path = lilv_strjoin(path, "/", name, NULL);
+ unsigned num;
+ if (sscanf(entry_path, latest->pattern, &num) == 1) {
+ off_t entry_size;
+ time_t entry_time;
+ lilv_size_mtime(entry_path, &entry_size, &entry_time);
+ if (entry_size == latest->orig_size && entry_time >= latest->time) {
+ free(latest->latest);
+ latest->latest = entry_path;
+ }
+ }
+ if (entry_path != latest->latest) {
+ free(entry_path);
+ }
+}
+
/** Return the latest copy of the file at @c path that is newer. */
char*
lilv_get_latest_copy(const char* path)
{
- char* dirname = lilv_dirname(path);
- DIR* dir = opendir(dirname);
- if (!dir) {
- free(dirname);
- return NULL;
- }
+ char* dirname = lilv_dirname(path);
+ Latest latest = { lilv_strjoin(path, "%u", NULL), 0, 0, NULL };
+ lilv_size_mtime(path, &latest.orig_size, &latest.time);
- char* pat = lilv_strjoin(path, "%u", NULL);
- char* latest = NULL;
-
- off_t path_size;
- time_t path_time;
- lilv_size_mtime(path, &path_size, &path_time);
-
- struct dirent entry;
- struct dirent* result;
- while (!readdir_r(dir, &entry, &result) && result) {
- char* entry_path = lilv_strjoin(dirname, "/", entry.d_name, NULL);
- unsigned num;
- if (sscanf(entry_path, pat, &num) == 1) {
- off_t entry_size;
- time_t entry_time;
- lilv_size_mtime(entry_path, &entry_size, &entry_time);
- if (entry_size == path_size && entry_time >= path_time) {
- free(latest);
- latest = entry_path;
- }
- }
- if (entry_path != latest) {
- free(entry_path);
- }
- }
- free(dirname);
- free(pat);
+ lilv_dir_for_each(dirname, &latest, update_latest);
- return latest;
+ free(latest.pattern);
+ return latest.latest;
}
char*
@@ -363,3 +362,19 @@ lilv_flock(FILE* file, bool lock)
return 0;
#endif
}
+
+void
+lilv_dir_for_each(const char* path,
+ void* data,
+ void (*f)(const char* path, const char* name, void* data))
+{
+ DIR* dir = opendir(path);
+ if (dir) {
+ struct dirent entry;
+ struct dirent* result;
+ while (!readdir_r(dir, &entry, &result) && result) {
+ f(path, entry.d_name, data);
+ }
+ closedir(dir);
+ }
+}
diff --git a/src/world.c b/src/world.c
index 32e4f63..6d223cb 100644
--- a/src/world.c
+++ b/src/world.c
@@ -14,15 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define _POSIX_SOURCE 1 /* for readdir_r */
-
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <dirent.h>
-
#include "lilv_internal.h"
LILV_API
@@ -549,6 +545,22 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri)
serd_node_free(&manifest_uri);
}
+static void
+load_dir_entry(const char* dir, const char* name, void* data)
+{
+ LilvWorld* world = (LilvWorld*)data;
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ return;
+
+ const char* scheme = (dir[0] == '/') ? "file://" : "file:///";
+ char* uri = lilv_strjoin(scheme, dir, "/", name, "/", NULL);
+ LilvNode* uri_val = lilv_new_uri(world, uri);
+
+ lilv_world_load_bundle(world, uri_val);
+ lilv_node_free(uri_val);
+ free(uri);
+}
+
/** Load all bundles in the directory at @a dir_path. */
static void
lilv_world_load_directory(LilvWorld* world, const char* dir_path)
@@ -559,38 +571,7 @@ lilv_world_load_directory(LilvWorld* world, const char* dir_path)
return;
}
- DIR* pdir = opendir(path);
- if (!pdir) {
- free(path);
- return;
- }
-
-#ifdef __WIN32__
- static const char* const file_scheme = "file:///";
-#else
- static const char* const file_scheme = "file://";
-#endif
-
- struct dirent entry;
- struct dirent* result;
- while (!readdir_r(pdir, &entry, &result) && result) {
- if (!strcmp(entry.d_name, ".") || !strcmp(entry.d_name, ".."))
- continue;
-
- char* uri = lilv_strjoin(file_scheme,
- path, "/",
- entry.d_name, "/",
- NULL);
-
- LilvNode* uri_val = lilv_new_uri(world, uri);
- lilv_world_load_bundle(world, uri_val);
- lilv_node_free(uri_val);
-
- free(uri);
- }
-
- free(path);
- closedir(pdir);
+ lilv_dir_for_each(path, world, load_dir_entry);
}
static bool