expanddir.c revision 6d8b37fa7661484ca50a4951cffbf531ab1bccbb
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * expand.c --- expand an ext2fs directory 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 43a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. 519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 144cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 164cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 17f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 18b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "ext2fs.h" 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct expand_dir_struct { 223a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o int done; 233a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o int newblocks; 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t err; 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 27544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int expand_dir_proc(ext2_filsys fs, 286d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson blk64_t *blocknr, 29544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt, 306d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson blk64_t ref_block EXT2FS_ATTR((unused)), 31544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 32544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 34b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; 356d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson blk64_t new_blk; 366d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson static blk64_t last_blk = 0; 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block; 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 39efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*blocknr) { 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o last_blk = *blocknr; 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 446d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson retval = ext2fs_new_block2(fs, last_blk, 0, &new_blk); 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (blockcnt > 0) { 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, 0, 0, &block); 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->done = 1; 5689270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o retval = ext2fs_write_dir_block(fs, new_blk, block); 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else { 58c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize, &block); 597b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) { 607b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o es->err = retval; 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(block, 0, fs->blocksize); 6424a117abd0340d247befbf7687ffb70547fdf218Valerie Aurora Henson retval = io_channel_write_blk64(fs->io, new_blk, 1, block); 65efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 70c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *blocknr = new_blk; 7248f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_block_alloc_stats2(fs, new_blk, +1); 733a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o es->newblocks++; 743a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es->done) 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return (BLOCK_CHANGED | BLOCK_ABORT); 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_CHANGED; 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct expand_dir_struct es; 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 86efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 87f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 88f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!(fs->flags & EXT2_FLAG_RW)) 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_RO_FILSYS; 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9289270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o if (!fs->block_map) 9389270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o return EXT2_ET_NO_BLOCK_BITMAP; 9489270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_check_directory(fs, dir); 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 98efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.done = 0; 1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.err = 0; 1013a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o es.newblocks = 0; 102efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1036d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND, 10436a43d675ef61d0f5d5b2ad62d2e670c408d14acTheodore Ts'o 0, expand_dir_proc, &es); 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es.err) 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return es.err; 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!es.done) 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_EXPAND_DIR_ERR; 1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update the size and block count fields in the inode. 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, dir, &inode); 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 117efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size += fs->blocksize; 1191ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_write_inode(fs, dir, &inode); 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 127