13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * mkdir.c --- make a directory in the filesystem 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1994, 1995 Theodore Ts'o. 519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 144cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 164cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 191d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_STAT_H 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 211d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 221d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 241d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 26b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "ext2fs.h" 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 29e6198e5a0191b2cbbf9765c4e4df11c7929279e6Theodore Ts'o#ifndef EXT2_FT_DIR 30e6198e5a0191b2cbbf9765c4e4df11c7929279e6Theodore Ts'o#define EXT2_FT_DIR 2 31e6198e5a0191b2cbbf9765c4e4df11c7929279e6Theodore Ts'o#endif 32e6198e5a0191b2cbbf9765c4e4df11c7929279e6Theodore Ts'o 3331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o const char *name) 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_extent_handle_t handle; 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 382e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o struct ext2_inode parent_inode, inode; 3931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino = inum; 4031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t scratch_ino; 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block = 0; 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 44f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 45f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Allocate an inode, if necessary 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!ino) { 5050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 5150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 0, &ino); 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Allocate a data block for the directory 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_new_block2(fs, 0, 0, &blk); 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Create a scratch template for the directory 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, ino, parent, &block); 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 712e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o * Get the parent's inode, if necessary 722e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o */ 732e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (parent != ino) { 742e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o retval = ext2fs_read_inode(fs, parent, &parent_inode); 752e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (retval) 762e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto cleanup; 772e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } else 782e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o memset(&parent_inode, 0, sizeof(parent_inode)); 792e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 802e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o /* 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Create the inode structure.... 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(&inode, 0, sizeof(struct ext2_inode)); 846a525069a99787ef3ae1156f12230044b3568f4bTheodore Ts'o inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_uid = inode.i_gid = 0; 861ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_set(fs, &inode, 1); 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_flags |= EXT4_EXTENTS_FL; 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_block[0] = blk; 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 2; 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size = fs->blocksize; 933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Write out the inode and inode data block 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 9750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o retval = ext2fs_write_dir_block(fs, blk, block); 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = ext2fs_write_new_inode(fs, ino, &inode); 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_open2(fs, ino, &inode, &handle); 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_set_bmap(handle, 0, blk, 0); 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_extent_free(handle); 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Link the directory into the filesystem hierarchy 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (name) { 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o &scratch_ino); 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!retval) { 1211f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o retval = EXT2_ET_DIR_EXISTS; 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o name = 0; 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1251f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o if (retval != EXT2_ET_FILE_NOT_FOUND) 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 127e6198e5a0191b2cbbf9765c4e4df11c7929279e6Theodore Ts'o retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 133dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o * Update parent inode's counts 134dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o */ 135dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o if (parent != ino) { 1362e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o parent_inode.i_links_count++; 1372e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o retval = ext2fs_write_inode(fs, parent, &parent_inode); 138dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o if (retval) 139dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o goto cleanup; 140dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o } 141efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 142dab278af8180bc85783da0b908e2a1af1388522dTheodore Ts'o /* 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update accounting.... 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, +1); 1467f961d424b1ba527e835d01ad24e0e4c3f4088c5Theodore Ts'o ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 1478bd0c95908baa3af706b9e731daff9472bec74c9Theodore Ts'o 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (block) 150c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 156