mkdir.c revision 6a525069a99787ef3ae1156f12230044b3568f4b
1/* 2 * mkdir.c --- make a directory in the filesystem 3 * 4 * Copyright (C) 1994, 1995 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#include <fcntl.h> 18#include <time.h> 19#if HAVE_SYS_STAT_H 20#include <sys/stat.h> 21#endif 22#if HAVE_SYS_TYPES_H 23#include <sys/types.h> 24#endif 25 26#include "ext2_fs.h" 27#include "ext2fs.h" 28 29#ifndef EXT2_FT_DIR 30#define EXT2_FT_DIR 2 31#endif 32 33errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, 34 const char *name) 35{ 36 errcode_t retval; 37 struct ext2_inode parent_inode, inode; 38 ext2_ino_t ino = inum; 39 ext2_ino_t scratch_ino; 40 blk_t blk; 41 char *block = 0; 42 int group; 43 44 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 45 46 /* 47 * Allocate an inode, if necessary 48 */ 49 if (!ino) { 50 retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 51 0, &ino); 52 if (retval) 53 goto cleanup; 54 } 55 56 /* 57 * Allocate a data block for the directory 58 */ 59 retval = ext2fs_new_block(fs, 0, 0, &blk); 60 if (retval) 61 goto cleanup; 62 63 /* 64 * Create a scratch template for the directory 65 */ 66 retval = ext2fs_new_dir_block(fs, ino, parent, &block); 67 if (retval) 68 goto cleanup; 69 70 /* 71 * Get the parent's inode, if necessary 72 */ 73 if (parent != ino) { 74 retval = ext2fs_read_inode(fs, parent, &parent_inode); 75 if (retval) 76 goto cleanup; 77 } else 78 memset(&parent_inode, 0, sizeof(parent_inode)); 79 80 /* 81 * Create the inode structure.... 82 */ 83 memset(&inode, 0, sizeof(struct ext2_inode)); 84 inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); 85 inode.i_uid = inode.i_gid = 0; 86 inode.i_blocks = fs->blocksize / 512; 87 inode.i_block[0] = blk; 88 inode.i_links_count = 2; 89 inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL); 90 inode.i_size = fs->blocksize; 91 92 /* 93 * Write out the inode and inode data block 94 */ 95 retval = ext2fs_write_dir_block(fs, blk, block); 96 if (retval) 97 goto cleanup; 98 retval = ext2fs_write_inode(fs, ino, &inode); 99 if (retval) 100 goto cleanup; 101 102 /* 103 * Link the directory into the filesystem hierarchy 104 */ 105 if (name) { 106 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 107 &scratch_ino); 108 if (!retval) { 109 retval = EXT2_ET_DIR_EXISTS; 110 name = 0; 111 goto cleanup; 112 } 113 if (retval != EXT2_ET_FILE_NOT_FOUND) 114 goto cleanup; 115 retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); 116 if (retval) 117 goto cleanup; 118 } 119 120 /* 121 * Update parent inode's counts 122 */ 123 if (parent != ino) { 124 parent_inode.i_links_count++; 125 retval = ext2fs_write_inode(fs, parent, &parent_inode); 126 if (retval) 127 goto cleanup; 128 } 129 130 /* 131 * Update accounting.... 132 */ 133 ext2fs_mark_block_bitmap(fs->block_map, blk); 134 ext2fs_mark_bb_dirty(fs); 135 ext2fs_mark_inode_bitmap(fs->inode_map, ino); 136 ext2fs_mark_ib_dirty(fs); 137 138 group = ext2fs_group_of_blk(fs, blk); 139 fs->group_desc[group].bg_free_blocks_count--; 140 group = ext2fs_group_of_ino(fs, ino); 141 fs->group_desc[group].bg_free_inodes_count--; 142 fs->group_desc[group].bg_used_dirs_count++; 143 fs->super->s_free_blocks_count--; 144 fs->super->s_free_inodes_count--; 145 ext2fs_mark_super_dirty(fs); 146 147cleanup: 148 if (block) 149 ext2fs_free_mem((void **) &block); 150 return retval; 151 152} 153 154 155