expanddir.c revision 5be8dc2143c7b3b21a9b8fb56797dd855ee87560
1/* 2 * expand.c --- expand an ext2fs directory 3 * 4 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12#include <stdio.h> 13#include <string.h> 14#if HAVE_UNISTD_H 15#include <unistd.h> 16#endif 17 18#include <linux/ext2_fs.h> 19 20#include "ext2fs.h" 21 22struct expand_dir_struct { 23 int done; 24 errcode_t err; 25}; 26 27static int expand_dir_proc(ext2_filsys fs, 28 blk_t *blocknr, 29 int blockcnt, 30 void *private) 31{ 32 struct expand_dir_struct *es = (struct expand_dir_struct *) private; 33 blk_t new_blk; 34 static blk_t last_blk = 0; 35 char *block; 36 errcode_t retval; 37 int group; 38 39 if (*blocknr) { 40 last_blk = *blocknr; 41 return 0; 42 } 43 retval = ext2fs_new_block(fs, last_blk, 0, &new_blk); 44 if (retval) { 45 es->err = retval; 46 return BLOCK_ABORT; 47 } 48 if (blockcnt > 0) { 49 retval = ext2fs_new_dir_block(fs, 0, 0, &block); 50 if (retval) { 51 es->err = retval; 52 return BLOCK_ABORT; 53 } 54 es->done = 1; 55 retval = ext2fs_write_dir_block(fs, new_blk, block); 56 } else { 57 retval = ext2fs_get_mem(fs->blocksize, (void **) &block); 58 if (retval) { 59 es->err = retval; 60 return BLOCK_ABORT; 61 } 62 memset(block, 0, fs->blocksize); 63 retval = io_channel_write_blk(fs->io, new_blk, 1, block); 64 } 65 if (retval) { 66 es->err = retval; 67 return BLOCK_ABORT; 68 } 69 ext2fs_free_mem((void **) &block); 70 *blocknr = new_blk; 71 ext2fs_mark_block_bitmap(fs->block_map, new_blk); 72 ext2fs_mark_bb_dirty(fs); 73 group = ext2fs_group_of_blk(fs, new_blk); 74 fs->group_desc[group].bg_free_blocks_count--; 75 fs->super->s_free_blocks_count--; 76 ext2fs_mark_super_dirty(fs); 77 if (es->done) 78 return (BLOCK_CHANGED | BLOCK_ABORT); 79 else 80 return BLOCK_CHANGED; 81} 82 83errcode_t ext2fs_expand_dir(ext2_filsys fs, ino_t dir) 84{ 85 errcode_t retval; 86 struct expand_dir_struct es; 87 struct ext2_inode inode; 88 89 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 90 91 if (!(fs->flags & EXT2_FLAG_RW)) 92 return EXT2_ET_RO_FILSYS; 93 94 if (!fs->block_map) 95 return EXT2_ET_NO_BLOCK_BITMAP; 96 97 retval = ext2fs_check_directory(fs, dir); 98 if (retval) 99 return retval; 100 101 es.done = 0; 102 es.err = 0; 103 104 retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND, 105 0, expand_dir_proc, &es); 106 107 if (es.err) 108 return es.err; 109 if (!es.done) 110 return EXT2_ET_EXPAND_DIR_ERR; 111 112 /* 113 * Update the size and block count fields in the inode. 114 */ 115 retval = ext2fs_read_inode(fs, dir, &inode); 116 if (retval) 117 return retval; 118 119 inode.i_size += fs->blocksize; 120 inode.i_blocks += fs->blocksize / 512; 121 122 retval = ext2fs_write_inode(fs, dir, &inode); 123 if (retval) 124 return retval; 125 126 return 0; 127} 128