summaryrefslogtreecommitdiff
path: root/sbin/pdisk/deblock_media.c
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2001-03-24 00:14:39 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2001-03-24 00:14:39 +0000
commitffb72f990c9933280de104024acf91acee02c1a5 (patch)
tree8312fd465c763b17886e6e1795ab48bde45c2381 /sbin/pdisk/deblock_media.c
parentfa5275b22eb94a7d990e643d54768420845d618c (diff)
Import of pdisk from apple, BSD licensed code. Archive dated Feb 18 1998
This is a HFS partition editing tool.
Diffstat (limited to 'sbin/pdisk/deblock_media.c')
-rw-r--r--sbin/pdisk/deblock_media.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/sbin/pdisk/deblock_media.c b/sbin/pdisk/deblock_media.c
new file mode 100644
index 00000000000..cb752d70554
--- /dev/null
+++ b/sbin/pdisk/deblock_media.c
@@ -0,0 +1,334 @@
+/*
+ * deblock_media.c -
+ *
+ * Written by Eryk Vershen (eryk@apple.com)
+ */
+
+/*
+ * Copyright 1997,1998 by Apple Computer, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+// for malloc() & free()
+#include <stdlib.h>
+// for memcpy()
+#include <string.h>
+
+#include "deblock_media.h"
+
+
+/*
+ * Defines
+ */
+
+
+/*
+ * Types
+ */
+typedef struct deblock_media *DEBLOCK_MEDIA;
+
+struct deblock_media {
+ struct media m;
+ long need_filtering;
+ MEDIA next_media;
+ unsigned long next_block_size;
+ unsigned char *buffer;
+};
+
+struct deblock_globals {
+ long exists;
+ long kind;
+};
+
+
+/*
+ * Global Constants
+ */
+
+
+/*
+ * Global Variables
+ */
+static long deblock_inited = 0;
+static struct deblock_globals deblock_info;
+
+/*
+ * Forward declarations
+ */
+void deblock_init(void);
+DEBLOCK_MEDIA new_deblock_media(void);
+long read_deblock_media(MEDIA m, long long offset, unsigned long count, void *address);
+long write_deblock_media(MEDIA m, long long offset, unsigned long count, void *address);
+long close_deblock_media(MEDIA m);
+long os_reload_deblock_media(MEDIA m);
+
+
+/*
+ * Routines
+ */
+void
+deblock_init(void)
+{
+ if (deblock_inited != 0) {
+ return;
+ }
+ deblock_inited = 1;
+
+ deblock_info.kind = allocate_media_kind();
+}
+
+
+DEBLOCK_MEDIA
+new_deblock_media(void)
+{
+ return (DEBLOCK_MEDIA) new_media(sizeof(struct deblock_media));
+}
+
+
+MEDIA
+open_deblock_media(long new_block_size, MEDIA m)
+{
+ DEBLOCK_MEDIA a;
+ unsigned long block_size;
+
+ if (deblock_inited == 0) {
+ deblock_init();
+ }
+
+ a = 0;
+ if (m != 0) {
+ block_size = media_granularity(m);
+
+ if (new_block_size == block_size) {
+ return m;
+
+ } else if (new_block_size > block_size) {
+ if ((new_block_size % block_size) == 0) {
+ /* no filtering necessary */
+ a = new_deblock_media();
+ if (a != 0) {
+ a->need_filtering = 0;
+ a->next_block_size = block_size;
+ a->buffer = 0;
+ }
+ } else {
+ /* too hard to bother with */
+ }
+ } else /* new_block_size < block_size */ {
+ if ((block_size % new_block_size) == 0) {
+ /* block & unblock */
+ a = new_deblock_media();
+ if (a != 0) {
+ a->need_filtering = 1;
+ a->next_block_size = block_size;
+ a->buffer = malloc(block_size);
+ }
+ } else {
+ /* too hard to bother with */
+ }
+ }
+ if (a != 0) {
+ a->m.kind = deblock_info.kind;
+ a->m.grain = new_block_size;
+ a->m.size_in_bytes = media_total_size(m);
+ a->m.do_read = read_deblock_media;
+ a->m.do_write = write_deblock_media;
+ a->m.do_close = close_deblock_media;
+ a->m.do_os_reload = os_reload_deblock_media;
+ a->next_media = m;
+ }
+ }
+ return (MEDIA) a;
+}
+
+
+long
+read_deblock_media(MEDIA m, long long offset, unsigned long count, void *address)
+{
+ DEBLOCK_MEDIA a;
+ long rtn_value;
+ unsigned long next_size;
+ unsigned long partial_offset;
+ unsigned long partial_count;
+ long long cur_offset;
+ unsigned long remainder;
+ unsigned char *addr;
+
+ a = (DEBLOCK_MEDIA) m;
+ rtn_value = 0;
+ if (a == 0) {
+ /* no media */
+ } else if (a->m.kind != deblock_info.kind) {
+ /* wrong kind - XXX need to error here - this is an internal problem */
+ } else if (count <= 0 || count % a->m.grain != 0) {
+ /* can't handle size */
+ } else if (offset < 0 || offset % a->m.grain != 0) {
+ /* can't handle offset */
+ } else if (a->need_filtering == 0) {
+ rtn_value = read_media(a->next_media, offset, count, address);
+ } else {
+ next_size = a->next_block_size;
+ addr = address;
+ cur_offset = offset;
+ remainder = count;
+ rtn_value = 1;
+
+ /* read partial */
+ partial_offset = cur_offset % next_size;
+ if (partial_offset != 0) {
+ partial_count = next_size - partial_offset;
+ if (partial_count > remainder) {
+ partial_count = remainder;
+ }
+ rtn_value = read_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
+ if (rtn_value != 0) {
+ memcpy (addr, a->buffer + partial_offset, partial_count);
+ addr += partial_count;
+ cur_offset += partial_count;
+ remainder -= partial_count;
+ }
+ }
+ /* read fulls as long as needed */
+ if (rtn_value != 0 && remainder > next_size) {
+ partial_count = remainder - (remainder % next_size);
+ rtn_value = read_media(a->next_media, cur_offset, partial_count, addr);
+ addr += partial_count;
+ cur_offset += partial_count;
+ remainder -= partial_count;
+ }
+ /* read partial */
+ if (rtn_value != 0 && remainder > 0) {
+ partial_count = remainder;
+ rtn_value = read_media(a->next_media, cur_offset, next_size, a->buffer);
+ if (rtn_value != 0) {
+ memcpy (addr, a->buffer, partial_count);
+ }
+ }
+ }
+ return rtn_value;
+}
+
+
+long
+write_deblock_media(MEDIA m, long long offset, unsigned long count, void *address)
+{
+ DEBLOCK_MEDIA a;
+ long rtn_value;
+ unsigned long next_size;
+ unsigned long partial_offset;
+ unsigned long partial_count;
+ long long cur_offset;
+ unsigned long remainder;
+ unsigned char *addr;
+
+ a = (DEBLOCK_MEDIA) m;
+ rtn_value = 0;
+ if (a == 0) {
+ /* no media */
+ } else if (a->m.kind != deblock_info.kind) {
+ /* wrong kind - XXX need to error here - this is an internal problem */
+ } else if (count <= 0 || count % a->m.grain != 0) {
+ /* can't handle size */
+ } else if (offset < 0 || offset % a->m.grain != 0) {
+ /* can't handle offset */
+ } else if (a->need_filtering == 0) {
+ rtn_value = write_media(a->next_media, offset, count, address);
+ } else {
+ next_size = a->next_block_size;
+ addr = address;
+ cur_offset = offset;
+ remainder = count;
+ rtn_value = 1;
+
+ /* write partial */
+ partial_offset = cur_offset % next_size;
+ if (partial_offset != 0) {
+ partial_count = next_size - partial_offset;
+ if (partial_count > remainder) {
+ partial_count = remainder;
+ }
+ rtn_value = read_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
+ if (rtn_value != 0) {
+ memcpy (a->buffer + partial_offset, addr, partial_count);
+ rtn_value = write_media(a->next_media, cur_offset - partial_offset, next_size, a->buffer);
+ addr += partial_count;
+ cur_offset += partial_count;
+ remainder -= partial_count;
+ }
+ }
+ /* write fulls as long as needed */
+ if (rtn_value != 0 && remainder > next_size) {
+ partial_count = remainder - (remainder % next_size);
+ rtn_value = write_media(a->next_media, cur_offset, partial_count, addr);
+ addr += partial_count;
+ cur_offset += partial_count;
+ remainder -= partial_count;
+ }
+ /* write partial */
+ if (rtn_value != 0 && remainder > 0) {
+ partial_count = remainder;
+ rtn_value = read_media(a->next_media, cur_offset, next_size, a->buffer);
+ if (rtn_value != 0) {
+ memcpy (a->buffer, addr, partial_count);
+ rtn_value = write_media(a->next_media, cur_offset, next_size, a->buffer);
+ }
+ }
+ }
+ /* recompute size to handle file media */
+ a->m.size_in_bytes = media_total_size(a->next_media);
+ return rtn_value;
+}
+
+
+long
+close_deblock_media(MEDIA m)
+{
+ DEBLOCK_MEDIA a;
+
+ a = (DEBLOCK_MEDIA) m;
+ if (a == 0) {
+ return 0;
+ } else if (a->m.kind != deblock_info.kind) {
+ /* XXX need to error here - this is an internal problem */
+ return 0;
+ }
+
+ close_media(a->next_media);
+ free(a->buffer);
+ return 1;
+}
+
+
+long
+os_reload_deblock_media(MEDIA m)
+{
+ DEBLOCK_MEDIA a;
+
+ a = (DEBLOCK_MEDIA) m;
+ if (a == 0) {
+ return 0;
+ } else if (a->m.kind != deblock_info.kind) {
+ /* XXX need to error here - this is an internal problem */
+ return 0;
+ }
+
+ os_reload_media(a->next_media);
+ return 1;
+}