From bb733c2283b7f9ffb1f05d57457475adb91bd04a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 9 Jan 2012 15:57:45 +0000 Subject: Make lilv_state_save take a full filename with extension. Use a proper path joining function for separator normalisation. git-svn-id: http://svn.drobilla.net/lad/trunk/lilv@3927 a436a847-0d15-0410-975c-d299462d15a1 --- lilv/lilv.h | 2 +- src/lilv_internal.h | 1 + src/state.c | 18 ++++++++++-------- src/util.c | 15 +++++++++++++++ test/lilv_test.c | 14 +++++++++----- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lilv/lilv.h b/lilv/lilv.h index a00f337..aeb59df 100644 --- a/lilv/lilv.h +++ b/lilv/lilv.h @@ -1258,7 +1258,7 @@ lilv_state_restore(const LilvState* state, @param state State to save. @param uri URI of state, may be NULL. @param dir Path of the bundle directory to save into, may be NULL. - @param filename Filename for the state file (no extension), may be NULL. + @param filename Filename for the state file, may be NULL. @param features Host provided features. The format of state on disk is compatible with that defined in the LV2 diff --git a/src/lilv_internal.h b/src/lilv_internal.h index be3f5de..856b8fb 100644 --- a/src/lilv_internal.h +++ b/src/lilv_internal.h @@ -352,6 +352,7 @@ int lilv_flock(FILE* file, bool lock); char* lilv_realpath(const char* path); int lilv_symlink(const char* oldpath, const char* newpath); int lilv_mkdir_p(const char* path); +char* lilv_path_join(const char* a, const char* b); char* lilv_find_free_path(const char* in_path, diff --git a/src/state.c b/src/state.c index 958354c..3afd13c 100644 --- a/src/state.c +++ b/src/state.c @@ -242,7 +242,7 @@ absolute_path(LV2_State_Map_Path_Handle handle, path = lilv_strdup(abstract_path); } else { // Relative path inside state directory - path = lilv_strjoin(state->dir, "/", abstract_path, NULL); + path = lilv_path_join(state->dir, abstract_path); } return path; @@ -539,8 +539,8 @@ new_state_from_model(LilvWorld* world, prop.size = strlen((const char*)sord_node_get_string(o)) + 1; prop.type = map->map(map->handle, LV2_STATE_PATH_URI); prop.flags = LV2_STATE_IS_PORTABLE; - prop.value = lilv_strjoin( - state->dir, "/", sord_node_get_string(o), NULL); + prop.value = lilv_path_join( + state->dir, (const char*)sord_node_get_string(o)); #endif } else { LilvNode* onode = lilv_node_new_from_node(world, o); @@ -824,11 +824,13 @@ lilv_state_save(LilvWorld* world, } if (!filename) { - filename = default_filename = pathify(state->label); + char* gen_name = pathify(state->label); + filename = default_filename = lilv_strjoin(gen_name, ".ttl", NULL); + free(gen_name); } - char* const path = lilv_strjoin(dir, "/", filename, ".ttl", NULL); - FILE* fd = fopen(path, "w"); + char* const path = lilv_path_join(dir, filename); + FILE* fd = fopen(path, "w"); if (!fd) { LILV_ERRORF("Failed to open %s (%s)\n", path, strerror(errno)); free(default_dir); @@ -840,7 +842,7 @@ lilv_state_save(LilvWorld* world, // FIXME: make parameter non-const? ((LilvState*)state)->dir = lilv_strdup(dir); - char* const manifest = lilv_strjoin(dir, "/manifest.ttl", NULL); + char* const manifest = lilv_path_join(dir, "manifest.ttl"); SerdEnv* env = serd_env_new(NULL); serd_env_set_prefix_from_strings(env, USTR("lv2"), USTR(LILV_NS_LV2)); @@ -923,7 +925,7 @@ lilv_state_save(LilvWorld* world, const PathMap* pm = (const PathMap*)zix_tree_get(i); char* real_dir = lilv_strjoin(lilv_realpath(dir), "/", NULL); - char* rel_path = lilv_strjoin(dir, "/", pm->rel, NULL); + char* rel_path = lilv_path_join(dir, pm->rel); char* target_path = lilv_path_is_child(pm->abs, state->file_dir) ? lilv_path_relative_to(pm->abs, real_dir) : lilv_strdup(pm->abs); diff --git a/src/util.c b/src/util.c index 7980b74..3857b9c 100644 --- a/src/util.c +++ b/src/util.c @@ -256,6 +256,21 @@ lilv_path_is_absolute(const char* path) return false; } +char* +lilv_path_join(const char* a, const char* b) +{ + const size_t a_len = strlen(a); + const size_t b_len = strlen(b); + const size_t pre_len = a_len - (lilv_is_dir_sep(a[a_len - 1]) ? 1 : 0); + char* path = calloc(1, a_len + b_len + 2); + memcpy(path, a, pre_len); + path[pre_len] = LILV_DIR_SEP[0]; + memcpy(path + pre_len + 1, + b + (lilv_is_dir_sep(b[0]) ? 1 : 0), + lilv_is_dir_sep(b[0]) ? b_len - 1 : b_len); + return path; +} + static void lilv_size_mtime(const char* path, off_t* size, time_t* time) { diff --git a/test/lilv_test.c b/test/lilv_test.c index 0591d20..7f7c77b 100644 --- a/test/lilv_test.c +++ b/test/lilv_test.c @@ -1157,7 +1157,7 @@ test_state(void) // Save state to a directory int ret = lilv_state_save(world, &unmap, state, NULL, - "./state.lv2", "state", NULL); + "./state.lv2", "state.ttl", NULL); TEST_ASSERT(!ret); // Load state from directory @@ -1221,7 +1221,7 @@ test_state(void) // Save state to a directory ret = lilv_state_save(world, &unmap, fstate, NULL, - "./fstate.lv2", "fstate", ffeatures); + "./fstate.lv2", "fstate.ttl", ffeatures); TEST_ASSERT(!ret); // Load state from directory @@ -1239,7 +1239,7 @@ test_state(void) // Save state to a directory again ret = lilv_state_save(world, &unmap, fstate, NULL, - "./fstate6.lv2", "fstate6", ffeatures); + "./fstate6.lv2", "fstate6.ttl", ffeatures); TEST_ASSERT(!ret); // Reload it and ensure it's identical to the other loaded version @@ -1257,7 +1257,7 @@ test_state(void) // Save the changed state to a directory again ret = lilv_state_save(world, &unmap, fstate7, NULL, - "./fstate7.lv2", "fstate7", ffeatures); + "./fstate7.lv2", "fstate7.ttl", ffeatures); TEST_ASSERT(!ret); // Reload it and ensure it's changed @@ -1381,6 +1381,10 @@ test_string(void) TEST_ASSERT(!strcmp((s = lilv_path_relative_to("/a", "/b/c/")), "/a")); TEST_ASSERT(!strcmp((s = lilv_path_relative_to("/a/b/c", "/a/b/d/")), "../c")); TEST_ASSERT(!strcmp((s = lilv_path_relative_to("/a/b/c", "/a/b/d/e/")), "../../c")); + TEST_ASSERT(!strcmp((s = lilv_path_join("/a", "b")), "/a/b")); + TEST_ASSERT(!strcmp((s = lilv_path_join("/a", "/b")), "/a/b")); + TEST_ASSERT(!strcmp((s = lilv_path_join("/a/", "/b")), "/a/b")); + TEST_ASSERT(!strcmp((s = lilv_path_join("/a/", "b")), "/a/b")); return 1; } @@ -1398,11 +1402,11 @@ static struct TestCase tests[] = { TEST_CASE(plugin), TEST_CASE(port), TEST_CASE(ui), - TEST_CASE(state), TEST_CASE(bad_port_symbol), TEST_CASE(bad_port_index), TEST_CASE(bad_port_index), TEST_CASE(string), + TEST_CASE(state), { NULL, NULL } }; -- cgit v1.2.1