summaryrefslogtreecommitdiffstats
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c83
1 files changed, 49 insertions, 34 deletions
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);
+ }
+}