[ghex/support-block-devices-part-trois: 2/5] blockdev: Get basic read/write working. Lots of FIXMEs
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex/support-block-devices-part-trois: 2/5] blockdev: Get basic read/write working. Lots of FIXMEs
- Date: Fri, 17 Jun 2022 02:19:54 +0000 (UTC)
commit 0aea094a974a72216ea8662bd57f0f09854a4c26
Author: Logan Rathbone <poprocks gmail com>
Date: Tue Jun 7 22:16:49 2022 -0400
blockdev: Get basic read/write working. Lots of FIXMEs
TODOs -- better error handling; sanity checks; privilege escalation
meson.build | 25 +++++++-
meson_options.txt | 3 +-
src/hex-buffer-direct.c | 159 +++++++++++++++++++++++++++++++++++++++++-------
src/hex-buffer-direct.h | 2 +
src/hex-document.c | 2 +
src/meson.build | 10 +++
6 files changed, 175 insertions(+), 26 deletions(-)
---
diff --git a/meson.build b/meson.build
index ed846da..8fc22ea 100644
--- a/meson.build
+++ b/meson.build
@@ -17,6 +17,7 @@ endif
# Backend plugins: (nb: only mmap exists at this time along with malloc, which is baked in)
mmap_backend = get_option('mmap-buffer-backend')
+direct_backend = get_option('direct-buffer-backend')
gir = find_program('g-ir-scanner', required : get_option('introspection'))
generate_gir = gir.found() and (not meson.is_cross_build() or get_option('introspection').enabled())
@@ -90,8 +91,10 @@ config_h.set('LOCALEDIR', 'PACKAGE_LOCALE_DIR')
config_h.set('CONFIG_H_SHADED_BOX_MAX', shaded_box_max)
# nb: this config.h flag will likely be removed in a future release
-if mmap_backend
- config_h.set('BACKEND_MMAP', true)
+#if mmap_backend
+# config_h.set('BACKEND_MMAP', true)
+if direct_backend
+ config_h.set('BACKEND_DIRECT', true)
endif
config_h.set_quoted('LIBGTKHEX_RELEASE_STRING', 'gtkhex-@0@.0'.format(libgtkhex_api_version))
@@ -130,6 +133,23 @@ if mmap_backend
message('...DONE')
endif
+# direct buffer backend: Check for required headers
+if direct_backend
+ message('Checking dependencies for `direct` buffer backend...')
+
+ check_headers_direct = [
+ 'unistd.h',
+ 'fcntl.h',
+ 'sys/ioctl.h',
+ 'linux/fs.h',
+ ]
+ foreach h : check_headers_direct
+ cc.has_header(h, required: true)
+ endforeach
+
+ message('...DONE')
+endif
+
glib_ver = '>= 2.68.0'
gmodule_dep = dependency('gmodule-2.0')
glib_dep = dependency('glib-2.0', version: glib_ver)
@@ -165,6 +185,7 @@ summary({'prefix': ghex_prefix,
summary({'Development build': get_option('development'),
'`mmap` buffer backend': mmap_backend,
+ '`direct` buffer backend': direct_backend,
'Static HTML help': get_option('static-html-help'),
'API Documentation': build_gtk_doc,
}, section: 'Configuration')
diff --git a/meson_options.txt b/meson_options.txt
index a5795fc..e7276c6 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -3,7 +3,8 @@
option('docdir', type: 'string', value: 'share/doc', description: 'docdir (defaults to: share/doc)')
option('development', type: 'boolean', value: false, description: 'If this is a development build')
-option('mmap-buffer-backend', type : 'boolean', value: true, description: 'Build mmap buffer backend')
+option('mmap-buffer-backend', type : 'boolean', value: true, description: 'Build `mmap` buffer backend')
+option('direct-buffer-backend', type : 'boolean', value: true, description: 'Build `direct` buffer backend')
option('introspection', type: 'feature', value: 'auto', description: 'Generate gir data (requires
gobject-introspection)')
option('gtk_doc', type: 'boolean', value: false, description: 'Build reference manual (requires gtk-doc)')
option('static-html-help', type: 'boolean', value: false, description: 'Install static HTML help files (for
systems without Yelp)')
diff --git a/src/hex-buffer-direct.c b/src/hex-buffer-direct.c
index d2fa910..23a4ccc 100644
--- a/src/hex-buffer-direct.c
+++ b/src/hex-buffer-direct.c
@@ -66,6 +66,7 @@ struct _HexBufferDirect
gint64 payload; /* size of the payload */
gint64 clean_bytes; /* 'clean' size of the file (no additions or deletions */
+ GHashTable *changes;
};
static void hex_buffer_direct_iface_init (HexBufferInterface *iface);
@@ -146,6 +147,8 @@ set_error (HexBufferDirect *self, const char *blurb)
}
g_debug ("%s: %s", __func__, message);
+ g_clear_error (&self->error);
+
g_set_error (&self->error,
HEX_BUFFER_DIRECT_ERROR,
errno,
@@ -158,6 +161,35 @@ set_error (HexBufferDirect *self, const char *blurb)
g_free (message);
}
+/* mostly a helper for _get_data and _set_data */
+static char *
+get_file_data (HexBufferDirect *self,
+ gint64 offset,
+ size_t len)
+{
+ char *data = NULL;
+ off_t new_offset;
+ ssize_t nread;
+
+ data = g_malloc (len);
+ new_offset = lseek (self->fd, offset, SEEK_SET);
+
+ g_assert (offset == new_offset);
+
+ errno = 0;
+ nread = read (self->fd, data, len);
+
+ /* FIXME/TODO - test that if nread is less than amount requested, that it
+ * marries up with amount left in payload */
+ if (nread == -1)
+ {
+ set_error (self, _("Failed to read data from file."));
+ g_clear_pointer (&data, g_free);
+ }
+
+ return data;
+}
+
static int
create_fd_from_path (HexBufferDirect *self, const char *path)
{
@@ -212,6 +244,8 @@ static void
hex_buffer_direct_init (HexBufferDirect *self)
{
self->fd = -1;
+ self->changes = g_hash_table_new_full (g_int64_hash, g_int64_equal,
+ g_free, g_free);
}
static void
@@ -267,26 +301,28 @@ hex_buffer_direct_get_data (HexBuffer *buf,
size_t len)
{
HexBufferDirect *self = HEX_BUFFER_DIRECT (buf);
- char *data = NULL;
- off_t new_offset;
- ssize_t nread;
+ char *data;
g_return_val_if_fail (self->fd != -1, NULL);
- data = g_malloc (len);
- new_offset = lseek (self->fd, offset, SEEK_SET);
-
- g_assert (offset == new_offset);
+ data = get_file_data (self, offset, len);
- errno = 0;
- nread = read (self->fd, data, len);
+ if (! data)
+ {
+ return NULL;
+ }
- /* FIXME/TODO - test that if nread is less than amount requested, that it
- * marries up with amount left in payload */
- if (nread == -1)
+ for (size_t i = 0; i < len; ++i)
{
- set_error (self, _("Failed to read data from file."));
- g_clear_pointer (&data, g_free);
+ char *cp;
+ gint64 loc = offset + i;
+
+ cp = g_hash_table_lookup (self->changes, &loc);
+ if (cp)
+ {
+ g_debug ("found change - swapping byte at: %ld", loc);
+ data[i] = *cp;
+ }
}
return data;
@@ -354,10 +390,6 @@ hex_buffer_direct_read (HexBuffer *buf)
return FALSE;
}
- bytes = hex_buffer_util_get_file_size (self->file);
-
- self->payload = self->clean_bytes = bytes;
-
tmp_fd = create_fd_from_path (self, file_path);
if (tmp_fd < 0)
{
@@ -365,6 +397,25 @@ hex_buffer_direct_read (HexBuffer *buf)
return FALSE;
}
+ /* will only return > 0 for a regular file. */
+ bytes = hex_buffer_util_get_file_size (self->file);
+
+ if (! bytes) /* block device */
+ {
+ gint64 block_file_size;
+
+ if (ioctl (tmp_fd, BLKGETSIZE64, &block_file_size) != 0)
+ {
+ set_error (self, _("Error attempting to read block device"));
+ return FALSE;
+ }
+ bytes = block_file_size;
+ }
+
+ self->payload = self->clean_bytes = bytes;
+
+ self->fd = tmp_fd;
+
return TRUE;
}
@@ -419,11 +470,46 @@ hex_buffer_direct_set_data (HexBuffer *buf,
{
HexBufferDirect *self = HEX_BUFFER_DIRECT (buf);
- g_warning ("%s: NOT IMPLEMENTED", __func__);
+ if (rep_len != len)
+ {
+ g_debug ("%s: rep_len != len; returning false", __func__);
+ return FALSE;
+ }
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ gboolean retval;
+ gint64 *ip = g_new (gint64, 1);
+ char *cp = g_new (char, 1);
+
+ *ip = offset + i;
+ *cp = data[i];
+
+ retval = g_hash_table_replace (self->changes, ip, cp);
- return FALSE;
+ // TEST
+ if (retval) /* key did not exist yet */
+ {
+ g_debug ("key did not exist yet");
+ }
+ else
+ {
+ char *tmp = NULL;
+
+ g_debug ("key already existed; replaced");
+
+ tmp = get_file_data (self, offset, 1);
+
+ if (*tmp == *cp)
+ {
+ g_debug ("key value back to what O.G. file was. Removing hash entry.");
+ g_hash_table_remove (self->changes, ip);
+ }
+ g_free (tmp);
+ }
+ }
-// return TRUE;
+ return TRUE;
}
static gboolean
@@ -431,12 +517,39 @@ hex_buffer_direct_write_to_file (HexBuffer *buf,
GFile *file)
{
HexBufferDirect *self = HEX_BUFFER_DIRECT (buf);
+ guint len;
+ gint64 **keys;
+ g_return_val_if_fail (self->fd != -1, FALSE);
g_return_val_if_fail (G_IS_FILE (file), FALSE);
- g_warning ("%s: NOT IMPLEMENTED", __func__);
+ keys = (gint64 **)g_hash_table_get_keys_as_array (self->changes, &len);
+
+ /* FIXME - very inefficient - we should at least implement a sorter
+ * function that puts the changes in order, and merges changes that
+ * are adjacent to one another.
+ */
+ for (guint i = 0; i < len; ++i)
+ {
+ ssize_t nwritten;
+ char *cp = g_hash_table_lookup (self->changes, keys[i]);
+ off_t offset, new_offset;
+
+ offset = *keys[i];
+ new_offset = lseek (self->fd, offset, SEEK_SET);
+ g_assert (offset == new_offset);
+ g_debug ("%u: offset %ld: switch with: %c", i, offset, *cp);
- return FALSE;
+ errno = 0;
+ nwritten = write (self->fd, cp, 1);
+ if (nwritten != 1)
+ {
+ set_error (self, _("Error writing changes to file"));
+ return FALSE;
+ }
+ }
+ g_hash_table_remove_all (self->changes);
+ return TRUE;
}
static gboolean
diff --git a/src/hex-buffer-direct.h b/src/hex-buffer-direct.h
index e794f10..e59e876 100644
--- a/src/hex-buffer-direct.h
+++ b/src/hex-buffer-direct.h
@@ -32,6 +32,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
G_BEGIN_DECLS
diff --git a/src/hex-document.c b/src/hex-document.c
index 83e1235..2d3afa1 100644
--- a/src/hex-document.c
+++ b/src/hex-document.c
@@ -358,6 +358,8 @@ hex_document_init (HexDocument *doc)
{
#ifdef BACKEND_MMAP
doc->buffer = hex_buffer_util_new ("mmap", NULL);
+#elif defined BACKEND_DIRECT
+ doc->buffer = hex_buffer_util_new ("direct", NULL);
#else
doc->buffer = hex_buffer_util_new (NULL, NULL);
#endif
diff --git a/src/meson.build b/src/meson.build
index 4091859..80a37b4 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -102,6 +102,16 @@ if mmap_backend
)
endif
+if direct_backend
+ shared_module('hex-buffer-direct',
+ sources: 'hex-buffer-direct.c',
+ c_args: libgtkhex_c_args,
+ dependencies: libgtkhex_dep,
+ install_dir: ghex_plugindir,
+ install: true,
+ )
+endif
+
ghex_sources = [
'chartable.c',
'common-ui.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]