blob: a86ac8e9385a1690c82b110abbb82d31cd36e04f
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * mkdir.c --- make a directory in the filesystem |
4 | * |
5 | * Copyright (C) 1994, 1995 Theodore Ts'o. |
6 | * |
7 | * %Begin-Header% |
8 | * This file may be redistributed under the terms of the GNU Public |
9 | * License. |
10 | * %End-Header% |
11 | */ |
12 | |
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 | errcode_t retval; |
38 | struct ext2_inode parent_inode, inode; |
39 | ext2_ino_t ino = inum; |
40 | ext2_ino_t scratch_ino; |
41 | blk_t blk; |
42 | char *block = NULL; |
43 | |
44 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); |
45 | |
46 | /* |
47 | * Allocate an inode, if necessary |
48 | */ |
49 | if (!ino) { |
50 | retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, |
51 | 0, &ino); |
52 | if (retval) |
53 | goto cleanup; |
54 | } |
55 | |
56 | /* |
57 | * Allocate a data block for the directory |
58 | */ |
59 | retval = ext2fs_new_block(fs, 0, 0, &blk); |
60 | if (retval) |
61 | goto cleanup; |
62 | |
63 | /* |
64 | * Create a scratch template for the directory |
65 | */ |
66 | retval = ext2fs_new_dir_block(fs, ino, parent, &block); |
67 | if (retval) |
68 | goto cleanup; |
69 | |
70 | /* |
71 | * Get the parent's inode, if necessary |
72 | */ |
73 | if (parent != ino) { |
74 | retval = ext2fs_read_inode(fs, parent, &parent_inode); |
75 | if (retval) |
76 | goto cleanup; |
77 | } else |
78 | memset(&parent_inode, 0, sizeof(parent_inode)); |
79 | |
80 | /* |
81 | * Create the inode structure.... |
82 | */ |
83 | memset(&inode, 0, sizeof(struct ext2_inode)); |
84 | inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); |
85 | inode.i_uid = inode.i_gid = 0; |
86 | inode.i_blocks = fs->blocksize / 512; |
87 | inode.i_block[0] = blk; |
88 | inode.i_links_count = 2; |
89 | inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL); |
90 | inode.i_size = fs->blocksize; |
91 | |
92 | /* |
93 | * Write out the inode and inode data block |
94 | */ |
95 | retval = ext2fs_write_dir_block(fs, blk, block); |
96 | if (retval) |
97 | goto cleanup; |
98 | retval = ext2fs_write_new_inode(fs, ino, &inode); |
99 | if (retval) |
100 | goto cleanup; |
101 | |
102 | /* |
103 | * Link the directory into the filesystem hierarchy |
104 | */ |
105 | if (name) { |
106 | retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, |
107 | &scratch_ino); |
108 | if (!retval) { |
109 | retval = EXT2_ET_DIR_EXISTS; |
110 | name = 0; |
111 | goto cleanup; |
112 | } |
113 | if (retval != EXT2_ET_FILE_NOT_FOUND) |
114 | goto cleanup; |
115 | retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); |
116 | if (retval) |
117 | goto cleanup; |
118 | } |
119 | |
120 | /* |
121 | * Update parent inode's counts |
122 | */ |
123 | if (parent != ino) { |
124 | parent_inode.i_links_count++; |
125 | retval = ext2fs_write_inode(fs, parent, &parent_inode); |
126 | if (retval) |
127 | goto cleanup; |
128 | } |
129 | |
130 | /* |
131 | * Update accounting.... |
132 | */ |
133 | ext2fs_block_alloc_stats(fs, blk, +1); |
134 | ext2fs_inode_alloc_stats2(fs, ino, +1, 1); |
135 | |
136 | cleanup: |
137 | ext2fs_free_mem(&block); |
138 | return retval; |
139 | } |
140 |