blob: 03e49d8ffd4e93a61ab759f5f2c6f59dd3fab6c9 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * mkdir.c --- make a directory in the filesystem
3 *
4 * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
5 * under the terms of the GNU Public License.
6 */
7
8#include <stdio.h>
9#include <string.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <fcntl.h>
13#include <time.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16
17#include <linux/fs.h>
18#include <linux/ext2_fs.h>
19
20#include "ext2fs.h"
21
22errcode_t ext2fs_mkdir(ext2_filsys fs, ino_t parent, ino_t inum,
23 const char *name)
24{
25 errcode_t retval;
26 struct ext2_inode inode;
27 ino_t ino = inum;
28 ino_t scratch_ino;
29 blk_t blk;
30 char *block = 0;
31 int group;
32
33 /*
34 * Allocate an inode, if necessary
35 */
36 if (!ino) {
37 retval = ext2fs_new_inode(fs, parent, S_IFDIR | 0755, 0, &ino);
38 if (retval)
39 goto cleanup;
40 }
41
42 /*
43 * Allocate a data block for the directory
44 */
45 retval = ext2fs_new_block(fs, 0, 0, &blk);
46 if (retval)
47 goto cleanup;
48
49 /*
50 * Create a scratch template for the directory
51 */
52 retval = ext2fs_new_dir_block(fs, ino, parent, &block);
53 if (retval)
54 goto cleanup;
55
56 /*
57 * Create the inode structure....
58 */
59 memset(&inode, 0, sizeof(struct ext2_inode));
60 inode.i_mode = S_IFDIR | 0755;
61 inode.i_uid = inode.i_gid = 0;
62 inode.i_blocks = fs->blocksize / 512;
63 inode.i_block[0] = blk;
64 inode.i_links_count = 2;
65 inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
66 inode.i_size = fs->blocksize;
67
68 /*
69 * Write out the inode and inode data block
70 */
71 retval = io_channel_write_blk(fs->io, blk, 1, block);
72 if (retval)
73 goto cleanup;
74 retval = ext2fs_write_inode(fs, ino, &inode);
75 if (retval)
76 goto cleanup;
77
78 /*
79 * Update parent inode's counts
80 */
81 if (parent != ino) {
82 retval = ext2fs_read_inode(fs, parent, &inode);
83 if (retval)
84 goto cleanup;
85 inode.i_links_count++;
86 retval = ext2fs_write_inode(fs, parent, &inode);
87 if (retval)
88 goto cleanup;
89 }
90
91 /*
92 * Link the directory into the filesystem hierarchy
93 */
94 if (name) {
95 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
96 &scratch_ino);
97 if (!retval) {
98 retval = EEXIST;
99 name = 0;
100 goto cleanup;
101 }
102 if (retval != ENOENT)
103 goto cleanup;
104 retval = ext2fs_link(fs, parent, name, ino, 0);
105 if (retval)
106 goto cleanup;
107 }
108
109 /*
110 * Update accounting....
111 */
112 ext2fs_mark_block_bitmap(fs, fs->block_map, blk);
113 ext2fs_mark_bb_dirty(fs);
114 ext2fs_mark_inode_bitmap(fs, fs->inode_map, ino);
115 ext2fs_mark_ib_dirty(fs);
116
117 group = ext2fs_group_of_blk(fs, blk);
118 fs->group_desc[group].bg_free_blocks_count--;
119 group = ext2fs_group_of_ino(fs, ino);
120 fs->group_desc[group].bg_free_inodes_count--;
121 fs->group_desc[group].bg_used_dirs_count++;
122 fs->super->s_free_blocks_count--;
123 fs->super->s_free_inodes_count--;
124 ext2fs_mark_super_dirty(fs);
125
126cleanup:
127 if (block)
128 free(block);
129 return retval;
130
131}
132
133