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));
62 l = g_slist_append(l, g_build_filename(g_get_user_data_dir(), subdir, NULL));
70 l = g_slist_append(l, g_strdup(FIRMWARE_DIR));
74 datadirs = g_get_system_data_dirs();
76 l = g_slist_append(l, g_build_filename(*datadirs++, subdir, NULL));
95 SR_PRIV int64_t sr_file_get_size(FILE *file)
97 off_t filepos, filesize;
106 filepos = ftello(file);
110 if (fseeko(file, 0, SEEK_END) < 0)
113 filesize = ftello(file);
117 if (fseeko(file, filepos, SEEK_SET) < 0)
123 static FILE *try_open_file(
const char *datadir,
const char *subdir,
130 filename = g_build_filename(datadir, subdir, name, NULL);
132 filename = g_build_filename(datadir, name, NULL);
134 file = g_fopen(filename,
"rb");
137 sr_info(
"Opened '%s'.", filename);
139 sr_spew(
"Attempt to open '%s' failed: %s",
140 filename, g_strerror(errno));
146 static int resource_open_default(
struct sr_resource *res,
147 const char *name,
void *cb_data)
149 GSList *paths, *p = NULL;
159 sr_err(
"%s: unknown type %d.", __func__, res->
type);
165 file = try_open_file((
const char *)(p->data), NULL, name);
168 g_slist_free_full(paths, g_free);
171 sr_dbg(
"Failed to locate '%s'.", name);
175 filesize = sr_file_get_size(file);
177 sr_err(
"Failed to obtain size of '%s': %s",
178 name, g_strerror(errno));
182 res->
size = filesize;
188 static int resource_close_default(
struct sr_resource *res,
void *cb_data)
196 sr_err(
"%s: invalid handle.", __func__);
200 if (fclose(file) < 0) {
201 sr_err(
"Failed to close file: %s", g_strerror(errno));
209 static gssize resource_read_default(
const struct sr_resource *res,
210 void *buf,
size_t count,
void *cb_data)
219 sr_err(
"%s: invalid handle.", __func__);
222 if (count > G_MAXSSIZE) {
223 sr_err(
"%s: count %zu too large.", __func__, count);
227 n_read = fread(buf, 1, count, file);
229 if (n_read != count && ferror(file)) {
230 sr_err(
"Failed to read resource file: %s", g_strerror(errno));
256 sr_err(
"%s: ctx was NULL.", __func__);
259 if (open_cb && close_cb && read_cb) {
260 ctx->resource_open_cb = open_cb;
261 ctx->resource_close_cb = close_cb;
262 ctx->resource_read_cb = read_cb;
263 ctx->resource_cb_data = cb_data;
264 }
else if (!open_cb && !close_cb && !read_cb) {
265 ctx->resource_open_cb = &resource_open_default;
266 ctx->resource_close_cb = &resource_close_default;
267 ctx->resource_read_cb = &resource_read_default;
268 ctx->resource_cb_data = ctx;
270 sr_err(
"%s: inconsistent callback pointers.", __func__);
291 struct sr_resource *res,
int type,
const char *name)
299 ret = (*ctx->resource_open_cb)(res, name, ctx->resource_cb_data);
302 sr_err(
"Failed to open resource '%s' (use loglevel 5/spew for"
324 ret = (*ctx->resource_close_cb)(res, ctx->resource_cb_data);
327 sr_err(
"Failed to close resource.");
347 const struct sr_resource *res,
void *buf,
size_t count)
351 n_read = (*ctx->resource_read_cb)(res, buf, count,
352 ctx->resource_cb_data);
354 sr_err(
"Failed to read resource.");
374 int type,
const char *name,
size_t *size,
size_t max_size)
381 if (sr_resource_open(ctx, &res, type, name) !=
SR_OK)
384 if (res.
size > max_size) {
385 sr_err(
"Size %" PRIu64
" of '%s' exceeds limit %zu.",
386 res.
size, name, max_size);
387 sr_resource_close(ctx, &res);
392 buf = g_try_malloc(res_size);
394 sr_err(
"Failed to allocate buffer for '%s'.", name);
395 sr_resource_close(ctx, &res);
399 n_read = sr_resource_read(ctx, &res, buf, res_size);
400 sr_resource_close(ctx, &res);
402 if (n_read < 0 || (
size_t)n_read != res_size) {
404 sr_err(
"Failed to read '%s': premature end of file.",
void * handle
File handle or equivalent; set by resource open callback.
Generic/unspecified error.
uint64_t size
Size of resource in bytes; set by resource open callback.
gssize(* sr_resource_read_callback)(const struct sr_resource *res, void *buf, size_t count, void *cb_data)
The public libsigrok header file to be used by frontends.
int type
Resource type (SR_RESOURCE_FIRMWARE, ...)
int(* sr_resource_open_callback)(struct sr_resource *res, const char *name, void *cb_data)
GSList * sr_resourcepaths_get(int res_type)
Get a list of paths where we look for resource (e.g.
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.
int(* sr_resource_close_callback)(struct sr_resource *res, void *cb_data)
Opaque structure representing a libsigrok context.