unix_io.c revision 7b4e4534f9361b21d3fafdd88a58f133decee38c
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * unix_io.c --- This is the Unix I/O interface to the I/O manager. 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Implements a one-block write-through cache. 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. 719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 164cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 184cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 221d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_STAT_H 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 241d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 251d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 271d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 297b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o#include <linux/ext2_fs.h> 307b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 317b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o#include "ext2fs.h" 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 33f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/* 34f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * For checking structure magic numbers... 35f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \ 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if ((struct)->magic != (code)) return (code) 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct unix_private_data { 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int magic; 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int flags; 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *buf; 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int buf_block_nr; 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel); 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel); 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize); 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *data); 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *data); 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel); 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 57f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic struct struct_io_manager struct_unix_manager = { 58f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_ET_MAGIC_IO_MANAGER, 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "Unix I/O Manager", 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_open, 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_close, 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_set_blksize, 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_read_blk, 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_write_blk, 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_flush 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oio_manager unix_io_manager = &struct_unix_manager; 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel) 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel io = NULL; 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data = NULL; 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (name == 0) 7750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return EXT2_ET_BAD_DEVICE_NAME; 787b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct struct_io_channel), 797b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &io); 807b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 817b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 82f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o memset(io, 0, sizeof(struct struct_io_channel)); 83f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 847b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct unix_private_data), 857b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &data); 867b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 887b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->manager = unix_io_manager; 907b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name); 917b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 937b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o strcpy(io->name, name); 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->private_data = data; 96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->block_size = 1024; 97f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->read_error = 0; 98f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->write_error = 0; 99a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o io->refcount = 1; 1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(data, 0, sizeof(struct unix_private_data)); 102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 1037b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(io->block_size, (void **) &data->buf); 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1057b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1077b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY); 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->dev < 0) { 1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *channel = io; 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (io) 1187b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &io); 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data) { 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1217b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data->buf); 1227b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data); 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel) 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval = 0; 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 132f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 134f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 135a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 136a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (--channel->refcount > 0) 137a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 138f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (close(data->dev) < 0) 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1427b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data->buf); 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->private_data) 1447b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &channel->private_data); 1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->name) 1467b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &channel->name); 1477b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &channel); 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize) 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1547b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 156f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 158f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 159f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->block_size != blksize) { 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o channel->block_size = blksize; 1627b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data->buf); 1637b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(blksize, (void **) &data->buf); 1647b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1657b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *buf) 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 178f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 181f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 183f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If it's in the cache, use it! 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) { 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(buf, data->buf, channel->block_size); 1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 192f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#if 0 193f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("read_block %lu (%d)\n", block, count); 194f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif 1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = (count < 0) ? -count : count * channel->block_size; 196f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 19719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 198a1230b1376dc5514a260134f53c23f8d2d1e61ceTheodore Ts'o retval = errno ? errno : EXT2_IO_LLSEEK_FAILED; 1993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = read(data->dev, buf, size); 2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual < 0) 2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = 0; 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_READ; 2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) { 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = block; 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset((char *) buf+actual, 0, size-actual); 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->read_error) 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->read_error)(channel, block, count, buf, 2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *buf) 2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 227f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 231f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 233f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) 2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = channel->block_size; 2373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else { 2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; /* Invalidate the cache */ 2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count < 0) 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = -count; 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = count * channel->block_size; 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 244f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 245f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 24619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 247a1230b1376dc5514a260134f53c23f8d2d1e61ceTheodore Ts'o retval = errno ? errno : EXT2_IO_LLSEEK_FAILED; 2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = write(data->dev, buf, size); 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_WRITE; 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->write_error) 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->write_error)(channel, block, count, buf, 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 27036f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o * Flush data buffers to disk. 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel) 2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 274f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct unix_private_data *data; 275f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 276f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 277f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 278f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 279f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 28036f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o fsync(data->dev); 2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 284