expanddir.c revision 81683c6a32045cf04d76a024e6f1753535b97c22
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 12d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 154cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 174cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 19b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "ext2fs.h" 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct expand_dir_struct { 233a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o int done; 243a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o int newblocks; 254a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o blk64_t goal; 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t err; 2781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong ext2_ino_t dir; 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 30544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int expand_dir_proc(ext2_filsys fs, 316d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson blk64_t *blocknr, 32544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt, 336d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson blk64_t ref_block EXT2FS_ATTR((unused)), 34544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 35544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 37b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; 386d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson blk64_t new_blk; 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block; 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 41efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*blocknr) { 434a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o if (blockcnt >= 0) 444a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o es->goal = *blocknr; 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 474a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o if (blockcnt && 484a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o (EXT2FS_B2C(fs, es->goal) == EXT2FS_B2C(fs, es->goal+1))) 494a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o new_blk = es->goal+1; 504a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o else { 514a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o es->goal &= ~EXT2FS_CLUSTER_MASK(fs); 524a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk); 534a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o if (retval) { 544a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o es->err = retval; 554a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o return BLOCK_ABORT; 564a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o } 57b2e6c86d61fccc39956c0cb8a8333f42d1569e8dTheodore Ts'o es->newblocks++; 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (blockcnt > 0) { 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, 0, 0, &block); 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->done = 1; 6681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_write_dir_block4(fs, new_blk, block, 0, 6781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong es->dir); 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else { 69c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize, &block); 707b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) { 717b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o es->err = retval; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(block, 0, fs->blocksize); 7524a117abd0340d247befbf7687ffb70547fdf218Valerie Aurora Henson retval = io_channel_write_blk64(fs->io, new_blk, 1, block); 76efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } 774a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o if (blockcnt >= 0) 784a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o es->goal = new_blk; 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 83c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *blocknr = new_blk; 8548f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_block_alloc_stats2(fs, new_blk, +1); 863a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es->done) 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return (BLOCK_CHANGED | BLOCK_ABORT); 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_CHANGED; 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct expand_dir_struct es; 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 98efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 99f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!(fs->flags & EXT2_FLAG_RW)) 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_RO_FILSYS; 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 10489270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o if (!fs->block_map) 10589270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o return EXT2_ET_NO_BLOCK_BITMAP; 10689270b5531516cf80498ad67809c1f09ce476568Theodore Ts'o 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_check_directory(fs, dir); 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 110efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.done = 0; 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.err = 0; 1134a2a9b70c89891a146bcb9cee3f29572ca2e1370Theodore Ts'o es.goal = 0; 1143a5f8eaa9741f6f14520ddd263a996e2764dd437Theodore Ts'o es.newblocks = 0; 11581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong es.dir = dir; 116efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1176d8b37fa7661484ca50a4951cffbf531ab1bccbbValerie Aurora Henson retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND, 11836a43d675ef61d0f5d5b2ad62d2e670c408d14acTheodore Ts'o 0, expand_dir_proc, &es); 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es.err) 1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return es.err; 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!es.done) 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_EXPAND_DIR_ERR; 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update the size and block count fields in the inode. 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, dir, &inode); 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 131efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size += fs->blocksize; 1331ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_write_inode(fs, dir, &inode); 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 141