Example #1
0
LILV_API
int
lilv_state_save(LilvWorld*       world,
                LV2_URID_Map*    map,
                LV2_URID_Unmap*  unmap,
                const LilvState* state,
                const char*      uri,
                const char*      dir,
                const char*      filename)
{
	if (!filename || !dir || lilv_mkdir_p(dir)) {
		return 1;
	}

	char*       abs_dir = absolute_dir(dir);
	char* const path    = lilv_path_join(abs_dir, filename);
	FILE*       fd      = fopen(path, "w");
	if (!fd) {
		LILV_ERRORF("Failed to open %s (%s)\n", path, strerror(errno));
		free(abs_dir);
		free(path);
		return 4;
	}

	// FIXME: make parameter non-const?
	if (state->dir && strcmp(state->dir, abs_dir)) {
		free(state->dir);
		((LilvState*)state)->dir = lilv_strdup(abs_dir);
	}

	// Create symlinks to files if necessary
	lilv_state_make_links(state, abs_dir);

	// Write state to Turtle file
	SerdNode    file   = serd_node_new_file_uri(USTR(path), NULL, NULL, false);
	SerdEnv*    env    = NULL;
	SerdWriter* writer = ttl_file_writer(fd, &file, &env);

	SerdNode node = uri ? serd_node_from_string(SERD_URI, USTR(uri)) : file;
	int ret       = lilv_state_write(
		world, map, unmap, state, writer, (const char*)node.buf, dir);

	serd_node_free(&file);
	serd_writer_free(writer);
	serd_env_free(env);
	fclose(fd);

	char* const manifest = lilv_path_join(abs_dir, "manifest.ttl");
	add_state_to_manifest(state->plugin_uri, manifest, uri, path);

	free(manifest);
	free(abs_dir);
	free(path);
	return ret;
}
Example #2
0
void
lilv_dir_for_each(const char* path,
                  void*       data,
                  void (*f)(const char* path, const char* name, void* data))
{
#ifdef _WIN32
	char*           pat = lilv_path_join(path, "*");
	WIN32_FIND_DATA fd;
	HANDLE          fh  = FindFirstFile(pat, &fd);
	if (fh != INVALID_HANDLE_VALUE) {
		do {
			f(path, fd.cFileName, data);
		} while (FindNextFile(fh, &fd));
	}
	free(pat);
#else
	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);
	}
#endif
}
Example #3
0
static char*
absolute_dir(const char* path)
{
	char* abs_path = lilv_path_absolute(path);
	char* base     = lilv_path_join(abs_path, NULL);
	free(abs_path);
	return base;
}
Example #4
0
static char*
abstract_path(LV2_State_Map_Path_Handle handle,
              const char*               abs_path)
{
	LilvState*    state     = (LilvState*)handle;
	char*         path      = NULL;
	char*         real_path = lilv_realpath(abs_path);
	const PathMap key       = { (char*)real_path, NULL };
	ZixTreeIter*  iter      = NULL;

	if (abs_path[0] == '\0') {
		return lilv_strdup(abs_path);
	} else if (!zix_tree_find(state->abs2rel, &key, &iter)) {
		// Already mapped path in a previous call
		PathMap* pm = (PathMap*)zix_tree_get(iter);
		free(real_path);
		return lilv_strdup(pm->rel);
	} else if (lilv_path_is_child(real_path, state->dir)) {
		// File in state directory (loaded, or created by plugin during save
		path = lilv_path_relative_to(real_path, state->dir);
	} else if (lilv_path_is_child(real_path, state->file_dir)) {
		// File created by plugin earlier
		path = lilv_path_relative_to(real_path, state->file_dir);
		if (state->copy_dir) {
			if (!lilv_path_exists(state->copy_dir, NULL)) {
				lilv_mkdir_p(state->copy_dir);
			}
			char* cpath = lilv_path_join(state->copy_dir, path);
			char* copy  = lilv_get_latest_copy(real_path, cpath);
			if (!copy || !lilv_file_equals(real_path, copy)) {
				// No recent enough copy, make a new one
				copy = lilv_find_free_path(cpath, lilv_path_exists, NULL);
				lilv_copy_file(real_path, copy);
			}
			free(real_path);
			free(cpath);

			// Refer to the latest copy in plugin state
			real_path = copy;
		}
	} else {
		// New path outside state directory
		const char* slash = strrchr(real_path, '/');
		const char* name  = slash ? (slash + 1) : real_path;

		// Find a free name in the (virtual) state directory
		path = lilv_find_free_path(name, lilv_state_has_path, state);
	}

	// Add record to path mapping
	PathMap* pm = (PathMap*)malloc(sizeof(PathMap));
	pm->abs = real_path;
	pm->rel = lilv_strdup(path);
	zix_tree_insert(state->abs2rel, pm, NULL);
	zix_tree_insert(state->rel2abs, pm, NULL);

	return path;
}
Example #5
0
static char*
make_path(LV2_State_Make_Path_Handle handle, const char* path)
{
	LilvState* state = (LilvState*)handle;
	if (!lilv_path_exists(state->dir, NULL)) {
		lilv_mkdir_p(state->dir);
	}

	return lilv_path_join(state->dir, path);
}
Example #6
0
static void
lilv_state_make_links(const LilvState* state, const char* dir)
{
	// Create symlinks to files
	for (ZixTreeIter* i = zix_tree_begin(state->abs2rel);
	     i != zix_tree_end(state->abs2rel);
	     i = zix_tree_iter_next(i)) {
		const PathMap* pm = (const PathMap*)zix_tree_get(i);

		char* path = lilv_path_join(dir, pm->rel);
		if (lilv_path_is_child(pm->abs, state->copy_dir)
		    && strcmp(state->copy_dir, dir)) {
			// Link directly to snapshot in the copy directory
			char* target = lilv_path_relative_to(pm->abs, dir);
			lilv_symlink(target, path);
			free(target);
		} else if (!lilv_path_is_child(pm->abs, dir)) {
			const char* link_dir = state->link_dir ? state->link_dir : dir;
			char*       pat      = lilv_path_join(link_dir, pm->rel);
			if (!strcmp(dir, link_dir)) {
				// Link directory is save directory, make link at exact path
				remove(pat);
				lilv_symlink(pm->abs, pat);
			} else {
				// Make a link in the link directory to external file
				char* lpath = lilv_find_free_path(pat, link_exists, pm->abs);
				if (!lilv_path_exists(lpath, NULL)) {
					lilv_symlink(pm->abs, lpath);
				}

				// Make a link in the save directory to the external link
				char* target = lilv_path_relative_to(lpath, dir);
				lilv_symlink(target, path);
				free(target);
				free(lpath);
			}
			free(pat);
		}
		free(path);
	}
}
Example #7
0
char*
lilv_path_absolute(const char* path)
{
	if (lilv_path_is_absolute(path)) {
		return lilv_strdup(path);
	} else {
		char* cwd      = getcwd(NULL, 0);
		char* abs_path = lilv_path_join(cwd, path);
		free(cwd);
		return abs_path;
	}
}
Example #8
0
static void
update_latest(const char* path, const char* name, void* data)
{
	Latest* latest     = (Latest*)data;
	char*   entry_path = lilv_path_join(path, name);
	unsigned num;
	if (sscanf(entry_path, latest->pattern, &num) == 1) {
		off_t  entry_size = 0;
		time_t entry_time = 0;
		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);
	}
}
Example #9
0
static char*
absolute_path(LV2_State_Map_Path_Handle handle,
              const char*               state_path)
{
	LilvState* state = (LilvState*)handle;
	char*      path  = NULL;
	if (lilv_path_is_absolute(state_path)) {
		// Absolute path, return identical path
		path = lilv_strdup(state_path);
	} else if (state->dir) {
		// Relative path inside state directory
		path = lilv_path_join(state->dir, state_path);
	} else {
		// State has not been saved, unmap
		path = lilv_strdup(lilv_state_rel2abs(state, state_path));
	}

	return path;
}