1/* vi: set sw=4 ts=4: */ 2/* 3 * mkdir.c --- make a directory in the filesystem 4 * 5 * Copyright (C) 1994, 1995 Theodore Ts'o. 6 * 7 * %Begin-Header% 8 * This file may be redistributed under the terms of the GNU Public 9 * License. 10 * %End-Header% 11 */ 12 13#include <stdio.h> 14#include <string.h> 15#if HAVE_UNISTD_H 16#include <unistd.h> 17#endif 18#include <fcntl.h> 19#include <time.h> 20#if HAVE_SYS_STAT_H 21#include <sys/stat.h> 22#endif 23#if HAVE_SYS_TYPES_H 24#include <sys/types.h> 25#endif 26 27#include "ext2_fs.h" 28#include "ext2fs.h" 29 30#ifndef EXT2_FT_DIR 31#define EXT2_FT_DIR 2 32#endif 33 34errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, 35 const char *name) 36{ 37 errcode_t retval; 38 struct ext2_inode parent_inode, inode; 39 ext2_ino_t ino = inum; 40 ext2_ino_t scratch_ino; 41 blk_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_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_new_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_block_alloc_stats(fs, blk, +1); 134 ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 135 136cleanup: 137 ext2fs_free_mem(&block); 138 return retval; 139 140} 141