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