mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
It's often useful to know how much data was actually copied, therefore let's introduce an nullable parameter `@copied` to `pv_gbytes_memcpy`. Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
182 lines
3.9 KiB
C
182 lines
3.9 KiB
C
/*
|
|
* Glib convenience functions
|
|
*
|
|
* Copyright IBM Corp. 2022
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
/* Must be included before any other header */
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <openssl/crypto.h>
|
|
|
|
#include "libpv/glib-helper.h"
|
|
|
|
struct __data {
|
|
void *data;
|
|
size_t size;
|
|
GFreeFunc free_func;
|
|
};
|
|
|
|
static void __data_clear_and_free(void *p)
|
|
{
|
|
struct __data *ptr = p;
|
|
|
|
if (!ptr)
|
|
return;
|
|
|
|
if (ptr->data) {
|
|
OPENSSL_cleanse(ptr->data, ptr->size);
|
|
ptr->free_func(ptr->data);
|
|
}
|
|
g_free(ptr);
|
|
}
|
|
|
|
static GBytes *pv_sec_gbytes_new_take_func(void *data, size_t size, GFreeFunc free_func)
|
|
{
|
|
struct __data *tmp = g_new(struct __data, 1);
|
|
|
|
tmp->data = data;
|
|
tmp->size = size;
|
|
tmp->free_func = free_func;
|
|
|
|
return g_bytes_new_with_free_func(data, size, __data_clear_and_free, tmp);
|
|
}
|
|
|
|
GBytes *pv_sec_gbytes_new_take(void *data, size_t size)
|
|
{
|
|
return pv_sec_gbytes_new_take_func(data, size, g_free);
|
|
}
|
|
|
|
GBytes *pv_sec_gbytes_new(const void *data, size_t size)
|
|
{
|
|
g_autofree void *tmp_data = NULL;
|
|
|
|
g_return_val_if_fail(data || size != 0, NULL);
|
|
|
|
tmp_data = g_malloc(size);
|
|
memcpy(tmp_data, data, size);
|
|
return pv_sec_gbytes_new_take(g_steal_pointer(&tmp_data), size);
|
|
}
|
|
|
|
int pv_file_seek(FILE *file, long offset, int whence, GError **error)
|
|
{
|
|
int cached_errno;
|
|
int ret = fseek(file, offset, whence);
|
|
|
|
if (ret) {
|
|
cached_errno = errno;
|
|
g_set_error(error, PV_GLIB_HELPER_ERROR, PV_GLIB_HELPER_FILE_ERROR,
|
|
"Cannot seek: %s", g_strerror(cached_errno));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
size_t pv_file_write(FILE *file, const void *ptr, size_t size, GError **error)
|
|
{
|
|
int cached_errno;
|
|
size_t n = fwrite(ptr, 1, size, file);
|
|
|
|
if (n != size) {
|
|
cached_errno = errno;
|
|
g_set_error(error, PV_GLIB_HELPER_ERROR, PV_GLIB_HELPER_FILE_ERROR,
|
|
"Cannot write: %s", g_strerror(cached_errno));
|
|
}
|
|
return n;
|
|
}
|
|
|
|
long pv_file_close(FILE *file, GError **error)
|
|
{
|
|
int cached_errno;
|
|
int ret = fclose(file);
|
|
|
|
if (ret) {
|
|
cached_errno = errno;
|
|
g_set_error(error, PV_GLIB_HELPER_ERROR, PV_GLIB_HELPER_FILE_ERROR,
|
|
"Cannot close: %s", g_strerror(cached_errno));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void pv_auto_close_file(FILE *file)
|
|
{
|
|
if (!file)
|
|
return;
|
|
|
|
(void)pv_file_close(file, NULL);
|
|
}
|
|
|
|
long pv_file_tell(FILE *file, GError **error)
|
|
{
|
|
int cached_errno;
|
|
long n = ftell(file);
|
|
|
|
if (n < 0) {
|
|
cached_errno = errno;
|
|
g_set_error(error, PV_GLIB_HELPER_ERROR, PV_GLIB_HELPER_FILE_ERROR,
|
|
"Cannot tell: %s", g_strerror(cached_errno));
|
|
}
|
|
return n;
|
|
}
|
|
|
|
FILE *pv_file_open(const char *filename, const char *mode, GError **error)
|
|
{
|
|
FILE *file = fopen(filename, mode);
|
|
int cached_errno;
|
|
|
|
if (!file) {
|
|
cached_errno = errno;
|
|
g_set_error(error, PV_GLIB_HELPER_ERROR, PV_GLIB_HELPER_FILE_ERROR,
|
|
"Cannot open '%s'. %s", filename, g_strerror(cached_errno));
|
|
return NULL;
|
|
}
|
|
return file;
|
|
}
|
|
|
|
GBytes *pv_file_get_content_as_g_bytes(const char *filename, GError **error)
|
|
{
|
|
g_autofree char *data = NULL;
|
|
size_t data_size;
|
|
|
|
if (!g_file_get_contents(filename, &data, &data_size, error))
|
|
return NULL;
|
|
|
|
return g_bytes_new_take(g_steal_pointer(&data), data_size);
|
|
}
|
|
|
|
GBytes *pv_file_get_content_as_secure_bytes(const char *filename)
|
|
{
|
|
g_autoptr(FILE) f = fopen(filename, "rb");
|
|
g_autofree char *data = NULL;
|
|
ssize_t file_size;
|
|
size_t data_size;
|
|
|
|
if (!f)
|
|
return NULL;
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
file_size = ftell(f);
|
|
if (file_size < 0)
|
|
return NULL;
|
|
data_size = (size_t)file_size;
|
|
fseek(f, 0, SEEK_SET);
|
|
data = g_malloc0(data_size);
|
|
if (data_size != fread(data, 1, data_size, f))
|
|
return NULL;
|
|
return pv_sec_gbytes_new_take(g_steal_pointer(&data), data_size);
|
|
}
|
|
|
|
void *pv_gbytes_memcpy(void *dst, size_t dst_size, GBytes *src, size_t *copied)
|
|
{
|
|
size_t src_size;
|
|
const void *src_data = g_bytes_get_data(src, &src_size);
|
|
|
|
if (dst_size < src_size)
|
|
return NULL;
|
|
if (copied)
|
|
*copied = src_size;
|
|
return memcpy(dst, src_data, src_size);
|
|
}
|