12e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o/*
22e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o * io_manager.c --- the I/O manager abstraction
32e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o */
42e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
52e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <stdio.h>
62e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <string.h>
72e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#if HAVE_UNISTD_H
82e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <unistd.h>
92e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#endif
102e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <fcntl.h>
112e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <time.h>
122e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#if HAVE_SYS_STAT_H
132e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <sys/stat.h>
142e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#endif
152e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#if HAVE_SYS_TYPES_H
162e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include <sys/types.h>
172e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#endif
182e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
192e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include "ext2_fs.h"
202e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o#include "ext2fs.h"
212e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
222e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'oerrcode_t io_channel_set_options(io_channel channel, const char *opts)
232e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o{
242e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	errcode_t retval = 0;
252e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	char *next, *ptr, *options, *arg;
262e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
272e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
282e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
292e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	if (!opts)
302e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		return 0;
312e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
322e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	if (!channel->manager->set_option)
332e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		return EXT2_ET_INVALID_ARGUMENT;
342e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
352e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	options = malloc(strlen(opts)+1);
362e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	if (!options)
372e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		return EXT2_ET_NO_MEMORY;
382e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	strcpy(options, opts);
392e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	ptr = options;
402e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
412e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	while (ptr && *ptr) {
422e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		next = strchr(ptr, '&');
432e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		if (next)
442e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o			*next++ = 0;
452e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
462e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		arg = strchr(ptr, '=');
472e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		if (arg)
482e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o			*arg++ = 0;
492e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
502e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		retval = (channel->manager->set_option)(channel, ptr, arg);
512e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		if (retval)
522e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o			break;
532e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o		ptr = next;
542e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	}
552e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	free(options);
562e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	return retval;
572e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o}
582e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
592e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'oerrcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
602e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o				int count, const void *data)
612e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o{
622e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
632e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
64efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (channel->manager->write_byte)
65efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		return channel->manager->write_byte(channel, offset,
662e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o						    count, data);
672e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o
682e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o	return EXT2_ET_UNIMPLEMENTED;
692e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o}
704690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
714690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'oerrcode_t io_channel_read_blk64(io_channel channel, unsigned long long block,
724690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o				 int count, void *data)
734690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o{
744690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
754690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
764690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	if (channel->manager->read_blk64)
774690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o		return (channel->manager->read_blk64)(channel, block,
784690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o						      count, data);
794690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
804690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	if ((block >> 32) != 0)
814690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o		return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64;
824690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
834690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	return (channel->manager->read_blk)(channel, (unsigned long) block,
844690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o					     count, data);
854690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o}
864690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
874690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'oerrcode_t io_channel_write_blk64(io_channel channel, unsigned long long block,
884690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o				 int count, const void *data)
894690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o{
904690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
914690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
924690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	if (channel->manager->write_blk64)
934690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o		return (channel->manager->write_blk64)(channel, block,
944690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o						       count, data);
954690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
964690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	if ((block >> 32) != 0)
974690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o		return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64;
984690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o
994690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o	return (channel->manager->write_blk)(channel, (unsigned long) block,
1004690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o					     count, data);
1014690e621acd4579dae60b6f55f58284ee805e86dTheodore Ts'o}
102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t io_channel_discard(io_channel channel, unsigned long long block,
104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     unsigned long long count)
105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (channel->manager->discard)
109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return (channel->manager->discard)(channel, block, count);
110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return EXT2_ET_UNIMPLEMENTED;
112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr)
115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	size_t	size;
117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (count == 0)
119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		size = io->block_size;
120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	else if (count > 0)
121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		size = io->block_size * count;
122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	else
123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		size = -count;
124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (io->align)
126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return ext2fs_get_memalign(size, io->align, ptr);
127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	else
128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return ext2fs_get_mem(size, ptr);
129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
130