diff options
-rw-r--r-- | src/lilv_internal.h | 11 | ||||
-rw-r--r-- | src/util.c | 83 | ||||
-rw-r--r-- | src/world.c | 53 |
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) */ @@ -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 |