mkdir.c revision 19c78dc07fce2d6f39b5e541562afc3ca1ea38ff
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * mkdir.c --- make a directory in the filesystem 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1994, 1995 Theodore Ts'o. 519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 2050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#if HAVE_ERRNO_H 2150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 2250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/ext2_fs.h> 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "ext2fs.h" 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerrcode_t ext2fs_mkdir(ext2_filsys fs, ino_t parent, ino_t inum, 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o const char *name) 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ino_t ino = inum; 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ino_t scratch_ino; 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t blk; 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block = 0; 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int group; 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Allocate an inode, if necessary 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!ino) { 4550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 4650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 0, &ino); 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Allocate a data block for the directory 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_block(fs, 0, 0, &blk); 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Create a scratch template for the directory 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, ino, parent, &block); 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Create the inode structure.... 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(&inode, 0, sizeof(struct ext2_inode)); 6950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o inode.i_mode = LINUX_S_IFDIR | 0755; 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_uid = inode.i_gid = 0; 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_blocks = fs->blocksize / 512; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_block[0] = blk; 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 2; 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL); 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size = fs->blocksize; 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Write out the inode and inode data block 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 8050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o retval = ext2fs_write_dir_block(fs, blk, block); 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_write_inode(fs, ino, &inode); 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update parent inode's counts 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (parent != ino) { 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, parent, &inode); 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count++; 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_write_inode(fs, parent, &inode); 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Link the directory into the filesystem hierarchy 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (name) { 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o &scratch_ino); 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!retval) { 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EEXIST; 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o name = 0; 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval != ENOENT) 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_link(fs, parent, name, ino, 0); 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update accounting.... 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 121f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_bb_dirty(fs); 123f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(fs->inode_map, ino); 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_ib_dirty(fs); 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o group = ext2fs_group_of_blk(fs, blk); 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->group_desc[group].bg_free_blocks_count--; 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o group = ext2fs_group_of_ino(fs, ino); 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->group_desc[group].bg_free_inodes_count--; 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->group_desc[group].bg_used_dirs_count++; 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->super->s_free_blocks_count--; 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->super->s_free_inodes_count--; 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_super_dirty(fs); 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (block) 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(block); 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 143