Whamcloud - gitweb
e2fsck: fix incorrect interior node logical start values
[tools/e2fsprogs.git] / lib / ext2fs / mkdir.c
1 /*
2  * mkdir.c --- make a directory in the filesystem
3  *
4  * Copyright (C) 1994, 1995 Theodore Ts'o.
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the GNU Library
8  * General Public License, version 2.
9  * %End-Header%
10  */
11
12 #include "config.h"
13 #include <stdio.h>
14 #include <string.h>
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #include <fcntl.h>
19 #include <time.h>
20 #if HAVE_SYS_STAT_H
21 #include <sys/stat.h>
22 #endif
23 #if HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26
27 #include "ext2_fs.h"
28 #include "ext2fs.h"
29
30 #ifndef EXT2_FT_DIR
31 #define EXT2_FT_DIR             2
32 #endif
33
34 errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
35                        const char *name)
36 {
37         ext2_extent_handle_t    handle;
38         errcode_t               retval;
39         struct ext2_inode       parent_inode, inode;
40         ext2_ino_t              ino = inum;
41         ext2_ino_t              scratch_ino;
42         blk64_t                 blk;
43         char                    *block = 0;
44
45         EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
46
47         /*
48          * Allocate an inode, if necessary
49          */
50         if (!ino) {
51                 retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
52                                           0, &ino);
53                 if (retval)
54                         goto cleanup;
55         }
56
57         /*
58          * Allocate a data block for the directory
59          */
60         retval = ext2fs_new_block2(fs, 0, 0, &blk);
61         if (retval)
62                 goto cleanup;
63
64         /*
65          * Create a scratch template for the directory
66          */
67         retval = ext2fs_new_dir_block(fs, ino, parent, &block);
68         if (retval)
69                 goto cleanup;
70
71         /*
72          * Get the parent's inode, if necessary
73          */
74         if (parent != ino) {
75                 retval = ext2fs_read_inode(fs, parent, &parent_inode);
76                 if (retval)
77                         goto cleanup;
78         } else
79                 memset(&parent_inode, 0, sizeof(parent_inode));
80
81         /*
82          * Create the inode structure....
83          */
84         memset(&inode, 0, sizeof(struct ext2_inode));
85         inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
86         inode.i_uid = inode.i_gid = 0;
87         ext2fs_iblk_set(fs, &inode, 1);
88         if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)
89                 inode.i_flags |= EXT4_EXTENTS_FL;
90         else
91                 inode.i_block[0] = blk;
92         inode.i_links_count = 2;
93         inode.i_size = fs->blocksize;
94
95         /*
96          * Write out the inode and inode data block
97          */
98         retval = ext2fs_write_dir_block(fs, blk, block);
99         if (retval)
100                 goto cleanup;
101         retval = ext2fs_write_new_inode(fs, ino, &inode);
102         if (retval)
103                 goto cleanup;
104
105         if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
106                 retval = ext2fs_extent_open2(fs, ino, &inode, &handle);
107                 if (retval)
108                         goto cleanup;
109                 retval = ext2fs_extent_set_bmap(handle, 0, blk, 0);
110                 ext2fs_extent_free(handle);
111                 if (retval)
112                         goto cleanup;
113         }
114
115         /*
116          * Link the directory into the filesystem hierarchy
117          */
118         if (name) {
119                 retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
120                                        &scratch_ino);
121                 if (!retval) {
122                         retval = EXT2_ET_DIR_EXISTS;
123                         name = 0;
124                         goto cleanup;
125                 }
126                 if (retval != EXT2_ET_FILE_NOT_FOUND)
127                         goto cleanup;
128                 retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
129                 if (retval)
130                         goto cleanup;
131         }
132
133         /*
134          * Update parent inode's counts
135          */
136         if (parent != ino) {
137                 parent_inode.i_links_count++;
138                 retval = ext2fs_write_inode(fs, parent, &parent_inode);
139                 if (retval)
140                         goto cleanup;
141         }
142
143         /*
144          * Update accounting....
145          */
146         ext2fs_block_alloc_stats2(fs, blk, +1);
147         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
148
149 cleanup:
150         if (block)
151                 ext2fs_free_mem(&block);
152         return retval;
153
154 }
155
156