24 #include <glib/gstdio.h>
26 #include "libsigrok-internal.h"
29 #define LOG_PREFIX "resource"
51 SR_PRIV int64_t sr_file_get_size(FILE *file)
53 off_t filepos, filesize;
62 filepos = ftello(file);
66 if (fseeko(file, 0, SEEK_END) < 0)
69 filesize = ftello(file);
73 if (fseeko(file, filepos, SEEK_SET) < 0)
79 static FILE *try_open_file(
const char *datadir,
const char *subdir,
85 filename = g_build_filename(datadir, subdir, name, NULL);
86 file = g_fopen(filename,
"rb");
89 sr_info(
"Opened '%s'.", filename);
91 sr_spew(
"Attempt to open '%s' failed: %s",
92 filename, g_strerror(errno));
98 static int resource_open_default(
struct sr_resource *res,
99 const char *name,
void *cb_data)
103 const char *builtindir;
106 const char *
const *datadirs;
114 builtindir = FIRMWARE_DIR;
116 subdir =
"sigrok-firmware";
119 sr_err(
"%s: unknown type %d.", __func__, res->
type);
123 file = try_open_file(g_get_user_data_dir(), subdir, name);
130 file = try_open_file(builtindir,
"", name);
133 datadirs = g_get_system_data_dirs();
134 while (*datadirs && !file)
135 file = try_open_file(*datadirs++, subdir, name);
138 sr_err(
"Failed to locate '%s'.", name);
142 filesize = sr_file_get_size(file);
144 sr_err(
"Failed to obtain size of '%s': %s",
145 name, g_strerror(errno));
149 res->
size = filesize;
155 static int resource_close_default(
struct sr_resource *res,
void *cb_data)
163 sr_err(
"%s: invalid handle.", __func__);
167 if (fclose(file) < 0) {
168 sr_err(
"Failed to close file: %s", g_strerror(errno));
176 static gssize resource_read_default(
const struct sr_resource *res,
177 void *buf,
size_t count,
void *cb_data)
186 sr_err(
"%s: invalid handle.", __func__);
189 if (count > G_MAXSSIZE) {
190 sr_err(
"%s: count %zu too large.", __func__, count);
194 n_read = fread(buf, 1, count, file);
196 if (n_read != count && ferror(file)) {
197 sr_err(
"Failed to read resource file: %s", g_strerror(errno));
223 sr_err(
"%s: ctx was NULL.", __func__);
226 if (open_cb && close_cb && read_cb) {
227 ctx->resource_open_cb = open_cb;
228 ctx->resource_close_cb = close_cb;
229 ctx->resource_read_cb = read_cb;
230 ctx->resource_cb_data = cb_data;
231 }
else if (!open_cb && !close_cb && !read_cb) {
232 ctx->resource_open_cb = &resource_open_default;
233 ctx->resource_close_cb = &resource_close_default;
234 ctx->resource_read_cb = &resource_read_default;
235 ctx->resource_cb_data = ctx;
237 sr_err(
"%s: inconsistent callback pointers.", __func__);
258 struct sr_resource *res,
int type,
const char *name)
266 ret = (*ctx->resource_open_cb)(res, name, ctx->resource_cb_data);
269 sr_err(
"Failed to open resource '%s'.", name);
290 ret = (*ctx->resource_close_cb)(res, ctx->resource_cb_data);
293 sr_err(
"Failed to close resource.");
313 const struct sr_resource *res,
void *buf,
size_t count)
317 n_read = (*ctx->resource_read_cb)(res, buf, count,
318 ctx->resource_cb_data);
320 sr_err(
"Failed to read resource.");
340 int type,
const char *name,
size_t *size,
size_t max_size)
347 if (sr_resource_open(ctx, &res, type, name) !=
SR_OK)
350 if (res.
size > max_size) {
351 sr_err(
"Size %" PRIu64
" of '%s' exceeds limit %zu.",
352 res.
size, name, max_size);
353 sr_resource_close(ctx, &res);
358 buf = g_try_malloc(res_size);
360 sr_err(
"Failed to allocate buffer for '%s'.", name);
361 sr_resource_close(ctx, &res);
365 n_read = sr_resource_read(ctx, &res, buf, res_size);
366 sr_resource_close(ctx, &res);
368 if (n_read < 0 || (
size_t)n_read != res_size) {
370 sr_err(
"Failed to read '%s': premature end of file.",
gssize(* sr_resource_read_callback)(const struct sr_resource *res, void *buf, size_t count, void *cb_data)
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.
The public libsigrok header file to be used by frontends.
Generic/unspecified error.
int type
Resource type (SR_RESOURCE_FIRMWARE, ...)
Opaque structure representing a libsigrok context.
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(* sr_resource_close_callback)(struct sr_resource *res, void *cb_data)