/src/e2fsprogs/lib/ext2fs/newdir.c
Line | Count | Source |
1 | | /* |
2 | | * newdir.c --- create a new directory block |
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 | | |
19 | | #include "ext2_fs.h" |
20 | | #include "ext2fs.h" |
21 | | |
22 | | #ifndef EXT2_FT_DIR |
23 | | #define EXT2_FT_DIR 2 |
24 | | #endif |
25 | | |
26 | | /* |
27 | | * Create new directory block |
28 | | */ |
29 | | errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, |
30 | | ext2_ino_t parent_ino, char **block) |
31 | 0 | { |
32 | 0 | struct ext2_dir_entry *dir = NULL; |
33 | 0 | errcode_t retval; |
34 | 0 | char *buf; |
35 | 0 | int rec_len; |
36 | 0 | int filetype = 0; |
37 | 0 | struct ext2_dir_entry_tail *t; |
38 | 0 | int csum_size = 0; |
39 | |
|
40 | 0 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); |
41 | | |
42 | 0 | retval = ext2fs_get_mem(fs->blocksize, &buf); |
43 | 0 | if (retval) |
44 | 0 | return retval; |
45 | 0 | memset(buf, 0, fs->blocksize); |
46 | 0 | dir = (struct ext2_dir_entry *) buf; |
47 | |
|
48 | 0 | if (ext2fs_has_feature_metadata_csum(fs->super)) |
49 | 0 | csum_size = sizeof(struct ext2_dir_entry_tail); |
50 | |
|
51 | 0 | retval = ext2fs_set_rec_len(fs, fs->blocksize - csum_size, dir); |
52 | 0 | if (retval) { |
53 | 0 | ext2fs_free_mem(&buf); |
54 | 0 | return retval; |
55 | 0 | } |
56 | | |
57 | 0 | if (dir_ino) { |
58 | 0 | if (ext2fs_has_feature_filetype(fs->super)) |
59 | 0 | filetype = EXT2_FT_DIR; |
60 | | /* |
61 | | * Set up entry for '.' |
62 | | */ |
63 | 0 | dir->inode = dir_ino; |
64 | 0 | ext2fs_dirent_set_name_len(dir, 1); |
65 | 0 | ext2fs_dirent_set_file_type(dir, filetype); |
66 | 0 | dir->name[0] = '.'; |
67 | 0 | rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1); |
68 | 0 | dir->rec_len = EXT2_DIR_REC_LEN(1); |
69 | | |
70 | | /* |
71 | | * Set up entry for '..' |
72 | | */ |
73 | 0 | dir = (struct ext2_dir_entry *) (buf + dir->rec_len); |
74 | 0 | retval = ext2fs_set_rec_len(fs, rec_len, dir); |
75 | 0 | if (retval) { |
76 | 0 | ext2fs_free_mem(&buf); |
77 | 0 | return retval; |
78 | 0 | } |
79 | 0 | dir->inode = parent_ino; |
80 | 0 | ext2fs_dirent_set_name_len(dir, 2); |
81 | 0 | ext2fs_dirent_set_file_type(dir, filetype); |
82 | 0 | dir->name[0] = '.'; |
83 | 0 | dir->name[1] = '.'; |
84 | |
|
85 | 0 | } |
86 | | |
87 | 0 | if (csum_size) { |
88 | 0 | t = EXT2_DIRENT_TAIL(buf, fs->blocksize); |
89 | 0 | ext2fs_initialize_dirent_tail(fs, t); |
90 | 0 | } |
91 | 0 | *block = buf; |
92 | 0 | return 0; |
93 | 0 | } |
94 | | |
95 | | /* |
96 | | * Create new directory on inline data |
97 | | */ |
98 | | errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, |
99 | | ext2_ino_t dir_ino EXT2FS_ATTR((unused)), |
100 | | ext2_ino_t parent_ino, __u32 *iblock) |
101 | 0 | { |
102 | 0 | struct ext2_dir_entry *dir = NULL; |
103 | 0 | errcode_t retval; |
104 | 0 | int rec_len; |
105 | |
|
106 | 0 | EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); |
107 | | |
108 | 0 | iblock[0] = ext2fs_cpu_to_le32(parent_ino); |
109 | |
|
110 | 0 | dir = (struct ext2_dir_entry *)((char *)iblock + |
111 | 0 | EXT4_INLINE_DATA_DOTDOT_SIZE); |
112 | 0 | dir->inode = 0; |
113 | 0 | rec_len = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE; |
114 | 0 | retval = ext2fs_set_rec_len(fs, rec_len, dir); |
115 | 0 | if (retval) |
116 | 0 | goto errout; |
117 | | |
118 | | #ifdef WORDS_BIGENDIAN |
119 | | retval = ext2fs_dirent_swab_out2(fs, (char *)dir, rec_len, 0); |
120 | | if (retval) |
121 | | goto errout; |
122 | | #endif |
123 | | |
124 | 0 | errout: |
125 | 0 | return retval; |
126 | 0 | } |