unix_io.c revision 1d2ff46ae7533ffd038534b189f272d2a4122e4e
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 2850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#if HAVE_ERRNO_H 2950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 3050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 3350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include "ext2fs/ext2_err.h" 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "io.h" 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/* 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * For checking structure magic numbers... 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \ 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if ((struct)->magic != (code)) return (code) 42f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct unix_private_data { 44f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int magic; 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int flags; 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *buf; 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int buf_block_nr; 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel); 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel); 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize); 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *data); 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *data); 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel); 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 60f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic struct struct_io_manager struct_unix_manager = { 61f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_ET_MAGIC_IO_MANAGER, 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "Unix I/O Manager", 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_open, 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_close, 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_set_blksize, 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_read_blk, 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_write_blk, 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_flush 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oio_manager unix_io_manager = &struct_unix_manager; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel) 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel io = NULL; 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data = NULL; 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (name == 0) 8050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return EXT2_ET_BAD_DEVICE_NAME; 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io = (io_channel) malloc(sizeof(struct struct_io_channel)); 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!io) 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ENOMEM; 84f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o memset(io, 0, sizeof(struct struct_io_channel)); 85f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o malloc(sizeof(struct unix_private_data)); 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!data) { 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ENOMEM; 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->manager = unix_io_manager; 933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->name = malloc(strlen(name)+1); 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!io->name) { 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ENOMEM; 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o strcpy(io->name, name); 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->private_data = data; 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->block_size = 1024; 101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->read_error = 0; 102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->write_error = 0; 103a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o io->refcount = 1; 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(data, 0, sizeof(struct unix_private_data)); 106f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf = malloc(io->block_size); 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!data->buf) { 1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ENOMEM; 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY); 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->dev < 0) { 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *channel = io; 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (io) 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(io); 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data) { 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data->buf); 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data); 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel) 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval = 0; 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 139f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 140a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 141a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (--channel->refcount > 0) 142a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 143f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (close(data->dev) < 0) 1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data->buf); 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->private_data) 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(channel->private_data); 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->name) 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(channel->name); 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(channel); 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize) 1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 160f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 162f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 163f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->block_size != blksize) { 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o channel->block_size = blksize; 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data->buf); 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf = malloc(blksize); 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!data->buf) 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ENOMEM; 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *buf) 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 182f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 185f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 187f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If it's in the cache, use it! 1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) { 1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(buf, data->buf, channel->block_size); 1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 196f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#if 0 197f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("read_block %lu (%d)\n", block, count); 198f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif 1993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = (count < 0) ? -count : count * channel->block_size; 200f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 20119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 202a1230b1376dc5514a260134f53c23f8d2d1e61ceTheodore Ts'o retval = errno ? errno : EXT2_IO_LLSEEK_FAILED; 2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = read(data->dev, buf, size); 2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual < 0) 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = 0; 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_READ; 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) { 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = block; 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset((char *) buf+actual, 0, size-actual); 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->read_error) 2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->read_error)(channel, block, count, buf, 2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *buf) 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 231f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 235f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 237f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = channel->block_size; 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else { 2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; /* Invalidate the cache */ 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count < 0) 2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = -count; 2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = count * channel->block_size; 2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 248f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 249f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 25019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 251a1230b1376dc5514a260134f53c23f8d2d1e61ceTheodore Ts'o retval = errno ? errno : EXT2_IO_LLSEEK_FAILED; 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = write(data->dev, buf, size); 2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_WRITE; 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->write_error) 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->write_error)(channel, block, count, buf, 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 27436f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o * Flush data buffers to disk. 2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel) 2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 278f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct unix_private_data *data; 279f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 280f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 281f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 282f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 283f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 28436f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o fsync(data->dev); 2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 288