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 33 errcode_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 43 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 44 45 /* 46 * Allocate an inode, if necessary 47 */ 48 if (!ino) { 49 retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 50 0, &ino); 51 if (retval) 52 goto cleanup; 53 } 54 55 /* 56 * Allocate a data block for the directory 57 */ 58 retval = ext2fs_new_block(fs, 0, 0, &blk); 59 if (retval) 60 goto cleanup; 61 62 /* 63 * Create a scratch template for the directory 64 */ 65 retval = ext2fs_new_dir_block(fs, ino, parent, &block); 66 if (retval) 67 goto cleanup; 68 69 /* 70 * Get the parent's inode, if necessary 71 */ 72 if (parent != ino) { 73 retval = ext2fs_read_inode(fs, parent, &parent_inode); 74 if (retval) 75 goto cleanup; 76 } else 77 memset(&parent_inode, 0, sizeof(parent_inode)); 78 79 /* 80 * Create the inode structure.... 81 */ 82 memset(&inode, 0, sizeof(struct ext2_inode)); 83 inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); 84 inode.i_uid = inode.i_gid = 0; 85 ext2fs_iblk_set(fs, &inode, 1); 86 inode.i_block[0] = blk; 87 inode.i_links_count = 2; 88 inode.i_size = fs->blocksize; 89 90 /* 91 * Write out the inode and inode data block 92 */ 93 retval = ext2fs_write_dir_block(fs, blk, block); 94 if (retval) 95 goto cleanup; 96 retval = ext2fs_write_new_inode(fs, ino, &inode); 97 if (retval) 98 goto cleanup; 99 100 /* 101 * Link the directory into the filesystem hierarchy 102 */ 103 if (name) { 104 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 105 &scratch_ino); 106 if (!retval) { 107 retval = EXT2_ET_DIR_EXISTS; 108 name = 0; 109 goto cleanup; 110 } 111 if (retval != EXT2_ET_FILE_NOT_FOUND) 112 goto cleanup; 113 retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); 114 if (retval) 115 goto cleanup; 116 } 117 118 /* 119 * Update parent inode's counts 120 */ 121 if (parent != ino) { 122 parent_inode.i_links_count++; 123 retval = ext2fs_write_inode(fs, parent, &parent_inode); 124 if (retval) 125 goto cleanup; 126 } 127 128 /* 129 * Update accounting.... 130 */ 131 ext2fs_block_alloc_stats(fs, blk, +1); 132 ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 133 134 cleanup: 135 if (block) 136 ext2fs_free_mem(&block); 137 return retval; 138 139 } 140 141 142