fileio.c revision 546a1ff18cc912003883ff67ba3e87c69f700fc4
1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * fileio.c --- Simple file I/O routines 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * Copyright (C) 1997 Theodore Ts'o. 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * %Begin-Header% 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * This file may be redistributed under the terms of the GNU Public 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * License. 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * %End-Header% 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 11e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include <stdio.h> 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include <string.h> 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#if HAVE_UNISTD_H 15e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include <unistd.h> 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "ext2_fs.h" 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "ext2fs.h" 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstruct ext2_file { 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t magic; 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_filsys fs; 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_ino_t ino; 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org struct ext2_inode inode; 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int flags; 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_off_t pos; 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org blk_t blockno; 29885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org blk_t physblock; 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org char *buf; 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 33e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#define BMAP_BUFFER (file->buf + fs->blocksize) 34885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 35885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgerrcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, 363c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com int flags, ext2_file_t *ret) 37885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_file_t file; 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval; 40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * Don't let caller create or open a file for writing if the 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * filesystem is read-only. 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) && 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org !(fs->flags & EXT2_FLAG_RW)) 47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return EXT2_ET_RO_FILSYS; 48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_get_mem(sizeof(struct ext2_file), (void **) &file); 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 53885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org memset(file, 0, sizeof(struct ext2_file)); 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->magic = EXT2_ET_MAGIC_EXT2_FILE; 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->fs = fs; 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->ino = ino; 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->flags = flags & EXT2_FILE_MASK; 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_read_inode(fs, ino, &file->inode); 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org goto fail; 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_get_mem(fs->blocksize * 3, (void **) &file->buf); 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org goto fail; 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *ret = file; 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgfail: 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (file->buf) 72885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2fs_free_mem((void **) &file->buf); 73885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2fs_free_mem((void **) &file); 74885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 75885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* 78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * This function returns the filesystem handle of a file from the structure 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgext2_filsys ext2fs_file_get_fs(ext2_file_t file) 81885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return file->fs; 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 86e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 87e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* 88e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org * This function flushes the dirty block buffer out to disk if 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * necessary. 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 91e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgerrcode_t ext2fs_file_flush(ext2_file_t file) 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval; 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_filsys fs; 95e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org fs = file->fs; 98e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!(file->flags & EXT2_FILE_BUF_VALID) || 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org !(file->flags & EXT2_FILE_BUF_DIRTY)) 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * OK, the physical block hasn't been allocated yet. 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * Allocate it. 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!file->physblock) { 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_bmap(fs, file->ino, &file->inode, 109e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org BMAP_BUFFER, BMAP_ALLOC, 110e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org file->blockno, &file->physblock); 111e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (retval) 112e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return retval; 113e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 114e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 115e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org retval = io_channel_write_blk(fs->io, file->physblock, 116e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 1, file->buf); 117e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (retval) 118e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return retval; 119e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 120e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org file->flags &= ~EXT2_FILE_BUF_DIRTY; 121e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 122e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return retval; 123e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} 124e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 125e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* 126e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org * This function synchronizes the file's block buffer and the current 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * file position, possibly invalidating block buffer if necessary 128e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org */ 129e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgstatic errcode_t sync_buffer_position(ext2_file_t file) 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org blk_t b; 132e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org errcode_t retval; 133e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org b = file->pos / file->fs->blocksize; 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (b != file->blockno) { 136e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org retval = ext2fs_file_flush(file); 137e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (retval) 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->flags &= ~EXT2_FILE_BUF_VALID; 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->blockno = b; 142e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return 0; 143e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org} 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 145e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org/* 146e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org * This function loads the file's block buffer with valid data from 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * the disk as necessary. 148e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org * 149885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * If dontfill is true, then skip initializing the buffer since we're 150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * going to be replacing its entire contents anyway. If set, then the 151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * function basically only sets file->physblock and EXT2_FILE_BUF_VALID 152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#define DONTFILL 1 154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic errcode_t load_buffer(ext2_file_t file, int dontfill) 155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_filsys fs = file->fs; 157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval; 158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!(file->flags & EXT2_FILE_BUF_VALID)) { 160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_bmap(fs, file->ino, &file->inode, 161885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org BMAP_BUFFER, 0, file->blockno, 162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org &file->physblock); 163885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!dontfill) { 166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (file->physblock) { 167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = io_channel_read_blk(fs->io, 168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->physblock, 169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 1, file->buf); 170e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (retval) 171e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return retval; 172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else 173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org memset(file->buf, 0, fs->blocksize); 174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->flags |= EXT2_FILE_BUF_VALID; 176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgerrcode_t ext2fs_file_close(ext2_file_t file) 182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval; 184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); 186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_file_flush(file); 188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 189885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (file->buf) 190885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2fs_free_mem((void **) &file->buf); 191885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2fs_free_mem((void **) &file); 192885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 193885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 194885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 195885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 196885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 197885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgerrcode_t ext2fs_file_read(ext2_file_t file, void *buf, 198885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org unsigned int wanted, unsigned int *got) 199885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 200885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_filsys fs; 201885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval = 0; 202885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org unsigned int start, left, c, count = 0; 203885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org char *ptr = (char *) buf; 204885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 205885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); 206885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org fs = file->fs; 207885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 208885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org while ((file->pos < file->inode.i_size) && (wanted > 0)) { 209885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = sync_buffer_position(file); 210885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 211885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org goto fail; 212885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = load_buffer(file, 0); 213885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 214885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org goto fail; 215885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 216885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org start = file->pos % fs->blocksize; 217885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org c = fs->blocksize - start; 218885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (c > wanted) 219885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org c = wanted; 220885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org left = file->inode.i_size - file->pos ; 221885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (c > left) 222885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org c = left; 223885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 224885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org memcpy(ptr, file->buf+start, c); 225885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->pos += c; 226885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ptr += c; 227885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org count += c; 228885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org wanted -= c; 229885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 230885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 231885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgfail: 232885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (got) 233885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *got = count; 234885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 235885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 236885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 237885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 238885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgerrcode_t ext2fs_file_write(ext2_file_t file, const void *buf, 239885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org unsigned int nbytes, unsigned int *written) 240885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 241885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ext2_filsys fs; 242885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval = 0; 243885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org unsigned int start, c, count = 0; 244885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const char *ptr = (const char *) buf; 245885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 246885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); 247885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org fs = file->fs; 248885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 249885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!(file->flags & EXT2_FILE_WRITE)) 250885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return EXT2_ET_FILE_RO; 251885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 252885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org while (nbytes > 0) { 253885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = sync_buffer_position(file); 254885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 255885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org goto fail; 256885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 257885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org start = file->pos % fs->blocksize; 258885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org c = fs->blocksize - start; 259885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (c > nbytes) 260885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org c = nbytes; 261885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 262885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 263885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * We only need to do a read-modify-update cycle if 264885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * we're doing a partial write. 265885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 266885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = load_buffer(file, (c == fs->blocksize)); 267885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 268885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org goto fail; 269885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 270885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->flags |= EXT2_FILE_BUF_DIRTY; 271885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org memcpy(file->buf+start, ptr, c); 272885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->pos += c; 273885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ptr += c; 274885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org count += c; 275885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nbytes -= c; 276885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 277885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 278885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgfail: 279885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (written) 280885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *written = count; 281885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 282885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 283885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 284885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgerrcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, 285885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int whence, ext2_off_t *ret_pos) 286885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 287885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); 288885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 289885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (whence == EXT2_SEEK_SET) 290885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->pos = offset; 291885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (whence == EXT2_SEEK_CUR) 292e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org file->pos += offset; 293885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (whence == EXT2_SEEK_END) 294885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->pos = file->inode.i_size + offset; 295885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 296885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return EXT2_ET_INVALID_ARGUMENT; 297885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 298885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ret_pos) 2993c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com *ret_pos = file->pos; 300885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 301885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 302885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 303885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 304885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* 305885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * This function returns the size of the file, according to the inode 306885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 307885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgext2_off_t ext2fs_file_get_size(ext2_file_t file) 308885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 309885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) 310885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 311885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return file->inode.i_size; 312885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 313885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 314885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* 315885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * This function sets the size of the file, truncating it if necessary 316885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * 317885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * XXX still need to call truncate 318885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 319885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgerrcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size) 320885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 321885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org errcode_t retval; 322885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); 323885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 324885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org file->inode.i_size = size; 325885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org retval = ext2fs_write_inode(file->fs, file->ino, &file->inode); 326885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (retval) 327885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return retval; 328885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 329885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 330885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org * XXX truncate inode if necessary 331885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org */ 332885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 333885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 334885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 335885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org