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 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 inode.i_blocks = fs->blocksize / 512; 86 inode.i_block[0] = blk; 87 inode.i_links_count = 2; 88 inode.i_ctime = inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(NULL); 89 inode.i_size = fs->blocksize; 90 91 /* 92 * Write out the inode and inode data block 93 */ 94 retval = ext2fs_write_dir_block(fs, blk, block); 95 if (retval) 96 goto cleanup; 97 retval = ext2fs_write_new_inode(fs, ino, &inode); 98 if (retval) 99 goto cleanup; 100 101 /* 102 * Link the directory into the filesystem hierarchy 103 */ 104 if (name) { 105 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 106 &scratch_ino); 107 if (!retval) { 108 retval = EXT2_ET_DIR_EXISTS; 109 name = 0; 110 goto cleanup; 111 } 112 if (retval != EXT2_ET_FILE_NOT_FOUND) 113 goto cleanup; 114 retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); 115 if (retval) 116 goto cleanup; 117 } 118 119 /* 120 * Update parent inode's counts 121 */ 122 if (parent != ino) { 123 parent_inode.i_links_count++; 124 retval = ext2fs_write_inode(fs, parent, &parent_inode); 125 if (retval) 126 goto cleanup; 127 } 128 129 /* 130 * Update accounting.... 131 */ 132 ext2fs_block_alloc_stats(fs, blk, +1); 133 ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 134 135 cleanup: 136 if (block) 137 ext2fs_free_mem(&block); 138 return retval; 139 140 } 141 142 143