24 #include <glib/gstdio.h> 26 #include "libsigrok-internal.h" 29 #define LOG_PREFIX "resource" 49 const char *subdir = NULL;
52 const char *
const *datadirs;
55 subdir =
"sigrok-firmware";
57 env = g_getenv(
"SIGROK_FIRMWARE_DIR");
59 l = g_slist_append(l, g_strdup(env));
61 env = g_getenv(
"SIGROK_FIRMWARE_PATH");
63 char **dir_list, **dir_iter, *dir_item;
64 dir_list = g_strsplit(env, G_SEARCHPATH_SEPARATOR_S, 0);
65 for (dir_iter = dir_list; *dir_iter; dir_iter++) {
67 if (!dir_item || !*dir_item)
69 l = g_slist_append(l, g_strdup(dir_item));
75 l = g_slist_append(l, g_build_filename(g_get_user_data_dir(), subdir, NULL));
83 l = g_slist_append(l, g_strdup(FIRMWARE_DIR));
87 datadirs = g_get_system_data_dirs();
89 l = g_slist_append(l, g_build_filename(*datadirs++, subdir, NULL));
108 SR_PRIV int64_t sr_file_get_size(FILE *file)
110 off_t filepos, filesize;
119 filepos = ftello(file);
123 if (fseeko(file, 0, SEEK_END) < 0)
126 filesize = ftello(file);
130 if (fseeko(file, filepos, SEEK_SET) < 0)
136 static FILE *try_open_file(
const char *datadir,
const char *subdir,
143 filename = g_build_filename(datadir, subdir, name, NULL);
145 filename = g_build_filename(datadir, name, NULL);
147 file = g_fopen(filename,
"rb");
150 sr_info(
"Opened '%s'.", filename);
152 sr_spew(
"Attempt to open '%s' failed: %s",
153 filename, g_strerror(errno));
159 static int resource_open_default(
struct sr_resource *res,
160 const char *
name,
void *cb_data)
162 GSList *paths, *p = NULL;
172 sr_err(
"%s: unknown type %d.", __func__, res->
type);
178 file = try_open_file((
const char *)(p->data), NULL,
name);
181 g_slist_free_full(paths, g_free);
184 sr_dbg(
"Failed to locate '%s'.",
name);
188 filesize = sr_file_get_size(file);
190 sr_err(
"Failed to obtain size of '%s': %s",
191 name, g_strerror(errno));
195 res->
size = filesize;
201 static int resource_close_default(
struct sr_resource *res,
void *cb_data)
209 sr_err(
"%s: invalid handle.", __func__);
213 if (fclose(file) < 0) {
214 sr_err(
"Failed to close file: %s", g_strerror(errno));
222 static gssize resource_read_default(
const struct sr_resource *res,
223 void *buf,
size_t count,
void *cb_data)
232 sr_err(
"%s: invalid handle.", __func__);
235 if (count > G_MAXSSIZE) {
236 sr_err(
"%s: count %zu too large.", __func__, count);
240 n_read = fread(buf, 1, count, file);
242 if (n_read != count && ferror(file)) {
243 sr_err(
"Failed to read resource file: %s", g_strerror(errno));
269 sr_err(
"%s: ctx was NULL.", __func__);
272 if (open_cb && close_cb && read_cb) {
273 ctx->resource_open_cb = open_cb;
274 ctx->resource_close_cb = close_cb;
275 ctx->resource_read_cb = read_cb;
276 ctx->resource_cb_data = cb_data;
277 }
else if (!open_cb && !close_cb && !read_cb) {
278 ctx->resource_open_cb = &resource_open_default;
279 ctx->resource_close_cb = &resource_close_default;
280 ctx->resource_read_cb = &resource_read_default;
281 ctx->resource_cb_data = ctx;
283 sr_err(
"%s: inconsistent callback pointers.", __func__);
312 ret = (*ctx->resource_open_cb)(res, name, ctx->resource_cb_data);
315 sr_err(
"Failed to open resource '%s' (use loglevel 5/spew for" 337 ret = (*ctx->resource_close_cb)(res, ctx->resource_cb_data);
340 sr_err(
"Failed to close resource.");
360 const struct sr_resource *res,
void *buf,
size_t count)
364 n_read = (*ctx->resource_read_cb)(res, buf, count,
365 ctx->resource_cb_data);
367 sr_err(
"Failed to read resource.");
387 int type,
const char *
name,
size_t *
size,
size_t max_size)
397 if (res.
size > max_size) {
398 sr_err(
"Size %" PRIu64
" of '%s' exceeds limit %zu.",
400 sr_resource_close(ctx, &res);
405 buf = g_try_malloc(res_size);
407 sr_err(
"Failed to allocate buffer for '%s'.",
name);
408 sr_resource_close(ctx, &res);
412 n_read = sr_resource_read(ctx, &res, buf, res_size);
413 sr_resource_close(ctx, &res);
415 if (n_read < 0 || (
size_t)n_read != res_size) {
417 sr_err(
"Failed to read '%s': premature end of file.",
GSList * sr_resourcepaths_get(int res_type)
Get a list of paths where we look for resource (e.g.
int(* sr_resource_open_callback)(struct sr_resource *res, const char *name, void *cb_data)
int sr_resource_set_hooks(struct sr_context *ctx, sr_resource_open_callback open_cb, sr_resource_close_callback close_cb, sr_resource_read_callback read_cb, void *cb_data)
Install resource access hooks.
typedef void(__LZO_CDECL *lzo_free_func_t)(lzo_callback_p self
gssize(* sr_resource_read_callback)(const struct sr_resource *res, void *buf, size_t count, void *cb_data)
Generic/unspecified error.
Opaque structure representing a libsigrok context.
The public libsigrok header file to be used by frontends.
void * handle
File handle or equivalent; set by resource open callback.
uint64_t size
Size of resource in bytes; set by resource open callback.
int type
Resource type (SR_RESOURCE_FIRMWARE, ...)
int(* sr_resource_close_callback)(struct sr_resource *res, void *cb_data)