* Access to resource files.
*/
+/** Retrieve the size of the open stream @a file.
+ *
+ * This function only works on seekable streams. However, the set of seekable
+ * streams is generally congruent with the set of streams that have a size.
+ * Code that needs to work with any type of stream (including pipes) should
+ * require neither seekability nor advance knowledge of the size.
+ * On failure, the return value is negative and errno is set.
+ *
+ * @param file An I/O stream opened in binary mode.
+ * @return The size of @a file in bytes, or a negative value on failure.
+ *
+ * @private
+ */
+SR_PRIV int64_t sr_file_get_size(FILE *file)
+{
+ off_t filepos, filesize;
+
+ /* ftello() and fseeko() are not standard C, but part of POSIX.1-2001.
+ * Thus, if these functions are available at all, they can reasonably
+ * be expected to also conform to POSIX semantics. In particular, this
+ * means that ftello() after fseeko(..., SEEK_END) has a defined result
+ * and can be used to get the size of a seekable stream.
+ * On Windows, the result is fully defined only for binary streams.
+ */
+ filepos = ftello(file);
+ if (filepos < 0)
+ return -1;
+
+ if (fseeko(file, 0, SEEK_END) < 0)
+ return -1;
+
+ filesize = ftello(file);
+ if (filesize < 0)
+ return -1;
+
+ if (fseeko(file, filepos, SEEK_SET) < 0)
+ return -1;
+
+ return filesize;
+}
+
static FILE *try_open_file(const char *datadir, const char *subdir,
const char *name)
{
const char *name, void *cb_data)
{
int64_t filesize;
- const char *builtindir, *subdir;
+#ifdef FIRMWARE_DIR
+ const char *builtindir;
+#endif
+ const char *subdir;
const char *const *datadirs;
FILE *file;
switch (res->type) {
case SR_RESOURCE_FIRMWARE:
+#ifdef FIRMWARE_DIR
builtindir = FIRMWARE_DIR;
+#endif
subdir = "sigrok-firmware";
break;
default:
* Scan the hard-coded directory before the system directories to
* avoid picking up possibly outdated files from a system install.
*/
+#ifdef FIRMWARE_DIR
if (!file)
file = try_open_file(builtindir, "", name);
-
+#endif
if (!file) {
datadirs = g_get_system_data_dirs();
while (*datadirs && !file)
return SR_OK;
}
-static ssize_t resource_read_default(const struct sr_resource *res,
+static gssize resource_read_default(const struct sr_resource *res,
void *buf, size_t count, void *cb_data)
{
FILE *file;
sr_err("%s: invalid handle.", __func__);
return SR_ERR_ARG;
}
- if (count > SSIZE_MAX) {
+ if (count > G_MAXSSIZE) {
sr_err("%s: count %zu too large.", __func__, count);
return SR_ERR_ARG;
}
*
* @private
*/
-SR_PRIV ssize_t sr_resource_read(struct sr_context *ctx,
+SR_PRIV gssize sr_resource_read(struct sr_context *ctx,
const struct sr_resource *res, void *buf, size_t count)
{
- ssize_t n_read;
+ gssize n_read;
n_read = (*ctx->resource_read_cb)(res, buf, count,
ctx->resource_cb_data);
{
struct sr_resource res;
void *buf;
- ssize_t n_read;
+ size_t res_size;
+ gssize n_read;
if (sr_resource_open(ctx, &res, type, name) != SR_OK)
return NULL;
sr_resource_close(ctx, &res);
return NULL;
}
- buf = g_try_malloc(res.size);
+ res_size = res.size;
+
+ buf = g_try_malloc(res_size);
if (!buf) {
sr_err("Failed to allocate buffer for '%s'.", name);
sr_resource_close(ctx, &res);
return NULL;
}
- n_read = sr_resource_read(ctx, &res, buf, res.size);
+ n_read = sr_resource_read(ctx, &res, buf, res_size);
sr_resource_close(ctx, &res);
- if (n_read < 0 || (size_t)n_read != res.size) {
+ if (n_read < 0 || (size_t)n_read != res_size) {
if (n_read >= 0)
sr_err("Failed to read '%s': premature end of file.",
name);
return NULL;
}
- *size = res.size;
+ *size = res_size;
return buf;
}