119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * fileio.c --- Simple file I/O routines
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1997 Theodore Ts'o.
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library
88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2.
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h"
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs.h"
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct ext2_file {
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t		magic;
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys 		fs;
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t		ino;
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode	inode;
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int 			flags;
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u64			pos;
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t			blockno;
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t			physblock;
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char 			*buf;
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define BMAP_BUFFER (file->buf + fs->blocksize)
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    struct ext2_inode *inode,
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    int flags, ext2_file_t *ret)
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_file_t 	file;
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Don't let caller create or open a file for writing if the
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * filesystem is read-only.
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !(fs->flags & EXT2_FLAG_RW))
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_RO_FILSYS;
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	memset(file, 0, sizeof(struct ext2_file));
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->magic = EXT2_ET_MAGIC_EXT2_FILE;
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->fs = fs;
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->ino = ino;
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->flags = flags & EXT2_FILE_MASK;
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode) {
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		memcpy(&file->inode, inode, sizeof(struct ext2_inode));
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_read_inode(fs, ino, &file->inode);
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto fail;
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto fail;
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*ret = file;
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectfail:
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (file->buf)
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_mem(&file->buf);
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&file);
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   int flags, ext2_file_t *ret)
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ext2fs_file_open2(fs, ino, NULL, flags, ret);
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function returns the filesystem handle of a file from the structure
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectext2_filsys ext2fs_file_get_fs(ext2_file_t file)
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return file->fs;
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function flushes the dirty block buffer out to disk if
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * necessary.
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_flush(ext2_file_t file)
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs;
1063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs = file->fs;
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(file->flags & EXT2_FILE_BUF_VALID) ||
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !(file->flags & EXT2_FILE_BUF_DIRTY))
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * OK, the physical block hasn't been allocated yet.
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Allocate it.
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!file->physblock) {
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_bmap(fs, file->ino, &file->inode,
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				     BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				     file->blockno, &file->physblock);
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = io_channel_write_blk(fs->io, file->physblock,
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				      1, file->buf);
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->flags &= ~EXT2_FILE_BUF_DIRTY;
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function synchronizes the file's block buffer and the current
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * file position, possibly invalidating block buffer if necessary
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t sync_buffer_position(ext2_file_t file)
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	b;
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	b = file->pos / file->fs->blocksize;
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (b != file->blockno) {
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_file_flush(file);
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->flags &= ~EXT2_FILE_BUF_VALID;
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->blockno = b;
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function loads the file's block buffer with valid data from
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the disk as necessary.
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If dontfill is true, then skip initializing the buffer since we're
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * going to be replacing its entire contents anyway.  If set, then the
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define DONTFILL 1
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t load_buffer(ext2_file_t file, int dontfill)
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys	fs = file->fs;
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(file->flags & EXT2_FILE_BUF_VALID)) {
17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_bmap(fs, file->ino, &file->inode,
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				     BMAP_BUFFER, 0, file->blockno,
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				     &file->physblock);
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!dontfill) {
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (file->physblock) {
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				retval = io_channel_read_blk(fs->io,
1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							     file->physblock,
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							     1, file->buf);
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (retval)
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					return retval;
18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				memset(file->buf, 0, fs->blocksize);
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->flags |= EXT2_FILE_BUF_VALID;
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_close(ext2_file_t file)
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_file_flush(file);
1993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (file->buf)
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_mem(&file->buf);
20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&file);
20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_read(ext2_file_t file, void *buf,
20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   unsigned int wanted, unsigned int *got)
21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys	fs;
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval = 0;
21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	start, c, count = 0;
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u64		left;
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char		*ptr = (char *) buf;
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs = file->fs;
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = sync_buffer_position(file);
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto fail;
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = load_buffer(file, 0);
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto fail;
22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		start = file->pos % fs->blocksize;
22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		c = fs->blocksize - start;
23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (c > wanted)
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			c = wanted;
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		left = EXT2_I_SIZE(&file->inode) - file->pos ;
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (c > left)
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			c = left;
2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		memcpy(ptr, file->buf+start, c);
23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->pos += c;
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ptr += c;
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		count += c;
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		wanted -= c;
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectfail:
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (got)
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*got = count;
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    unsigned int nbytes, unsigned int *written)
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys	fs;
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval = 0;
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	start, c, count = 0;
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	const char	*ptr = (const char *) buf;
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs = file->fs;
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(file->flags & EXT2_FILE_WRITE))
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_FILE_RO;
26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (nbytes > 0) {
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = sync_buffer_position(file);
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto fail;
2683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		start = file->pos % fs->blocksize;
27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		c = fs->blocksize - start;
27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (c > nbytes)
27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			c = nbytes;
27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * We only need to do a read-modify-update cycle if
27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * we're doing a partial write.
27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = load_buffer(file, (c == fs->blocksize));
27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto fail;
28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->flags |= EXT2_FILE_BUF_DIRTY;
28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		memcpy(file->buf+start, ptr, c);
28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->pos += c;
28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ptr += c;
28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		count += c;
28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		nbytes -= c;
28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
2893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectfail:
29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (written)
29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*written = count;
29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    int whence, __u64 *ret_pos)
29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (whence == EXT2_SEEK_SET)
30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->pos = offset;
30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (whence == EXT2_SEEK_CUR)
30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->pos += offset;
30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else if (whence == EXT2_SEEK_END)
30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		file->pos = EXT2_I_SIZE(&file->inode) + offset;
30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else
30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_INVALID_ARGUMENT;
30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ret_pos)
31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*ret_pos = file->pos;
31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    int whence, ext2_off_t *ret_pos)
31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u64		loffset, ret_loffset;
32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
3213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	loffset = offset;
32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ret_pos)
32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*ret_pos = (ext2_off_t) ret_loffset;
32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
32719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function returns the size of the file, according to the inode
33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_MAGIC_EXT2_FILE;
33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*ret_size = EXT2_I_SIZE(&file->inode);
33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function returns the size of the file, according to the inode
34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectext2_off_t ext2fs_file_get_size(ext2_file_t file)
34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u64	size;
34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_file_get_lsize(file, &size))
34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((size >> 32) != 0)
35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return size;
35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function sets the size of the file, truncating it if necessary
3573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * XXX still need to call truncate
35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
3643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->inode.i_size = size;
36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	file->inode.i_size_high = 0;
36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (file->ino) {
36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * XXX truncate inode if necessary
37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
379