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 Library 8 * General Public License, version 2. 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 ext2_extent_handle_t handle; 37 errcode_t retval; 38 struct ext2_inode parent_inode, inode; 39 ext2_ino_t ino = inum; 40 ext2_ino_t scratch_ino; 41 blk64_t blk; 42 char *block = 0; 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_block2(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 ext2fs_iblk_set(fs, &inode, 1); 87 if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) 88 inode.i_flags |= EXT4_EXTENTS_FL; 89 else 90 inode.i_block[0] = blk; 91 inode.i_links_count = 2; 92 inode.i_size = fs->blocksize; 93 94 /* 95 * Write out the inode and inode data block 96 */ 97 retval = ext2fs_write_dir_block(fs, blk, block); 98 if (retval) 99 goto cleanup; 100 retval = ext2fs_write_new_inode(fs, ino, &inode); 101 if (retval) 102 goto cleanup; 103 104 if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { 105 retval = ext2fs_extent_open2(fs, ino, &inode, &handle); 106 if (retval) 107 goto cleanup; 108 retval = ext2fs_extent_set_bmap(handle, 0, blk, 0); 109 ext2fs_extent_free(handle); 110 if (retval) 111 goto cleanup; 112 } 113 114 /* 115 * Link the directory into the filesystem hierarchy 116 */ 117 if (name) { 118 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 119 &scratch_ino); 120 if (!retval) { 121 retval = EXT2_ET_DIR_EXISTS; 122 name = 0; 123 goto cleanup; 124 } 125 if (retval != EXT2_ET_FILE_NOT_FOUND) 126 goto cleanup; 127 retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); 128 if (retval) 129 goto cleanup; 130 } 131 132 /* 133 * Update parent inode's counts 134 */ 135 if (parent != ino) { 136 parent_inode.i_links_count++; 137 retval = ext2fs_write_inode(fs, parent, &parent_inode); 138 if (retval) 139 goto cleanup; 140 } 141 142 /* 143 * Update accounting.... 144 */ 145 ext2fs_block_alloc_stats2(fs, blk, +1); 146 ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 147 148cleanup: 149 if (block) 150 ext2fs_free_mem(&block); 151 return retval; 152 153} 154 155 156