blob: 67a2046d0ad26a6429cf1054c9bbc60bbd29cc15 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * mkdir.c --- make a directory in the filesystem
3 *
Theodore Ts'o19c78dc1997-04-29 16:17:09 +00004 * 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%
Theodore Ts'o3839e651997-04-26 13:21:57 +000010 */
11
12#include <stdio.h>
13#include <string.h>
14#include <unistd.h>
15#include <stdlib.h>
16#include <fcntl.h>
17#include <time.h>
18#include <sys/stat.h>
19#include <sys/types.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000020#if HAVE_ERRNO_H
21#include <errno.h>
22#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000023
Theodore Ts'o3839e651997-04-26 13:21:57 +000024#include <linux/ext2_fs.h>
25
26#include "ext2fs.h"
27
28errcode_t ext2fs_mkdir(ext2_filsys fs, ino_t parent, ino_t inum,
29 const char *name)
30{
31 errcode_t retval;
32 struct ext2_inode inode;
33 ino_t ino = inum;
34 ino_t scratch_ino;
35 blk_t blk;
36 char *block = 0;
37 int group;
38
Theodore Ts'of3db3561997-04-26 13:34:30 +000039 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
40
Theodore Ts'o3839e651997-04-26 13:21:57 +000041 /*
42 * Allocate an inode, if necessary
43 */
44 if (!ino) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +000045 retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
46 0, &ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +000047 if (retval)
48 goto cleanup;
49 }
50
51 /*
52 * Allocate a data block for the directory
53 */
54 retval = ext2fs_new_block(fs, 0, 0, &blk);
55 if (retval)
56 goto cleanup;
57
58 /*
59 * Create a scratch template for the directory
60 */
61 retval = ext2fs_new_dir_block(fs, ino, parent, &block);
62 if (retval)
63 goto cleanup;
64
65 /*
66 * Create the inode structure....
67 */
68 memset(&inode, 0, sizeof(struct ext2_inode));
Theodore Ts'o50e1e101997-04-26 13:58:21 +000069 inode.i_mode = LINUX_S_IFDIR | 0755;
Theodore Ts'o3839e651997-04-26 13:21:57 +000070 inode.i_uid = inode.i_gid = 0;
71 inode.i_blocks = fs->blocksize / 512;
72 inode.i_block[0] = blk;
73 inode.i_links_count = 2;
74 inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
75 inode.i_size = fs->blocksize;
76
77 /*
78 * Write out the inode and inode data block
79 */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000080 retval = ext2fs_write_dir_block(fs, blk, block);
Theodore Ts'o3839e651997-04-26 13:21:57 +000081 if (retval)
82 goto cleanup;
83 retval = ext2fs_write_inode(fs, ino, &inode);
84 if (retval)
85 goto cleanup;
86
87 /*
88 * Update parent inode's counts
89 */
90 if (parent != ino) {
91 retval = ext2fs_read_inode(fs, parent, &inode);
92 if (retval)
93 goto cleanup;
94 inode.i_links_count++;
95 retval = ext2fs_write_inode(fs, parent, &inode);
96 if (retval)
97 goto cleanup;
98 }
99
100 /*
101 * Link the directory into the filesystem hierarchy
102 */
103 if (name) {
104 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
105 &scratch_ino);
106 if (!retval) {
107 retval = EEXIST;
108 name = 0;
109 goto cleanup;
110 }
111 if (retval != ENOENT)
112 goto cleanup;
113 retval = ext2fs_link(fs, parent, name, ino, 0);
114 if (retval)
115 goto cleanup;
116 }
117
118 /*
119 * Update accounting....
120 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000121 ext2fs_mark_block_bitmap(fs->block_map, blk);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000122 ext2fs_mark_bb_dirty(fs);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000123 ext2fs_mark_inode_bitmap(fs->inode_map, ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000124 ext2fs_mark_ib_dirty(fs);
125
126 group = ext2fs_group_of_blk(fs, blk);
127 fs->group_desc[group].bg_free_blocks_count--;
128 group = ext2fs_group_of_ino(fs, ino);
129 fs->group_desc[group].bg_free_inodes_count--;
130 fs->group_desc[group].bg_used_dirs_count++;
131 fs->super->s_free_blocks_count--;
132 fs->super->s_free_inodes_count--;
133 ext2fs_mark_super_dirty(fs);
134
135cleanup:
136 if (block)
137 free(block);
138 return retval;
139
140}
141
142