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