2 * Copyright (c) 2017, Fedor Uporov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/types.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/vnode.h>
37 #include <sys/endian.h>
39 #include <sys/extattr.h>
41 #include <fs/ext2fs/fs.h>
42 #include <fs/ext2fs/ext2fs.h>
43 #include <fs/ext2fs/inode.h>
44 #include <fs/ext2fs/ext2_dinode.h>
45 #include <fs/ext2fs/ext2_mount.h>
46 #include <fs/ext2fs/ext2_extattr.h>
50 ext2_extattr_index_to_bsd(int index)
53 case EXT4_XATTR_INDEX_USER:
54 return EXTATTR_NAMESPACE_USER;
56 case EXT4_XATTR_INDEX_SYSTEM:
57 return EXTATTR_NAMESPACE_SYSTEM;
60 return EXTATTR_NAMESPACE_EMPTY;
65 ext2_extattr_inode_list(struct inode *ip, int attrnamespace,
66 struct uio *uio, size_t *size)
70 struct ext2fs_extattr_dinode_header *header;
71 struct ext2fs_extattr_entry *entry;
72 struct ext2fs_extattr_entry *next;
78 if ((error = bread(ip->i_devvp,
79 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
80 (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
85 struct ext2fs_dinode *dinode = (struct ext2fs_dinode *)
87 EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number));
89 /* Check attributes magic value */
90 header = (struct ext2fs_extattr_dinode_header *)((char *)dinode +
91 E2FS_REV0_INODE_SIZE + dinode->e2di_extra_isize);
93 if (header->h_magic != EXTATTR_MAGIC) {
98 /* Check attributes integrity */
99 entry = EXT2_IFIRST(header);
100 end = (char *)dinode + EXT2_INODE_SIZE(fs);
101 while (!EXT2_IS_LAST_ENTRY(entry)) {
102 next = EXT2_EXTATTR_NEXT(entry);
103 if ((char *)next >= end) {
111 for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry);
112 entry = EXT2_EXTATTR_NEXT(entry)) {
113 if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
117 *size += entry->e_name_len + 1;
119 char *attr_name = malloc(entry->e_name_len + 1, M_TEMP, M_WAITOK);
120 attr_name[0] = entry->e_name_len;
121 memcpy(&attr_name[1], entry->e_name, entry->e_name_len);
122 error = uiomove(attr_name, entry->e_name_len + 1, uio);
123 free(attr_name, M_TEMP);
133 ext2_extattr_block_list(struct inode *ip, int attrnamespace,
134 struct uio *uio, size_t *size)
138 struct ext2fs_extattr_header *header;
139 struct ext2fs_extattr_entry *entry;
140 struct ext2fs_extattr_entry *next;
146 error = bread(ip->i_devvp, fsbtodb(fs, ip->i_facl),
147 fs->e2fs_bsize, NOCRED, &bp);
153 /* Check attributes magic value */
154 header = EXT2_HDR(bp);
155 if (header->h_magic != EXTATTR_MAGIC || header->h_blocks != 1) {
160 /* Check attributes integrity */
161 end = bp->b_data + bp->b_bufsize;
162 entry = EXT2_FIRST_ENTRY(bp);
163 while (!EXT2_IS_LAST_ENTRY(entry)) {
164 next = EXT2_EXTATTR_NEXT(entry);
165 if ((char *)next >= end) {
173 for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry);
174 entry = EXT2_EXTATTR_NEXT(entry)) {
175 if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
179 *size += entry->e_name_len + 1;
181 char *attr_name = malloc(entry->e_name_len + 1, M_TEMP, M_WAITOK);
182 attr_name[0] = entry->e_name_len;
183 memcpy(&attr_name[1], entry->e_name, entry->e_name_len);
184 error = uiomove(attr_name, entry->e_name_len + 1, uio);
185 free(attr_name, M_TEMP);
195 ext2_extattr_inode_get(struct inode *ip, int attrnamespace,
196 const char *name, struct uio *uio, size_t *size)
200 struct ext2fs_extattr_dinode_header *header;
201 struct ext2fs_extattr_entry *entry;
202 struct ext2fs_extattr_entry *next;
208 if ((error = bread(ip->i_devvp,
209 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
210 (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
215 struct ext2fs_dinode *dinode = (struct ext2fs_dinode *)
216 ((char *)bp->b_data +
217 EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number));
219 /* Check attributes magic value */
220 header = (struct ext2fs_extattr_dinode_header *)((char *)dinode +
221 E2FS_REV0_INODE_SIZE + dinode->e2di_extra_isize);
223 if (header->h_magic != EXTATTR_MAGIC) {
228 /* Check attributes integrity */
229 entry = EXT2_IFIRST(header);
230 end = (char *)dinode + EXT2_INODE_SIZE(fs);
231 while (!EXT2_IS_LAST_ENTRY(entry)) {
232 next = EXT2_EXTATTR_NEXT(entry);
233 if ((char *)next >= end) {
241 for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry);
242 entry = EXT2_EXTATTR_NEXT(entry)) {
243 if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
246 if (strlen(name) == entry->e_name_len &&
247 0 == strncmp(entry->e_name, name, entry->e_name_len)) {
249 *size += entry->e_value_size;
251 error = uiomove(((char *)EXT2_IFIRST(header)) + entry->e_value_offs,
252 entry->e_value_size, uio);
267 ext2_extattr_block_get(struct inode *ip, int attrnamespace,
268 const char *name, struct uio *uio, size_t *size)
272 struct ext2fs_extattr_header *header;
273 struct ext2fs_extattr_entry *entry;
274 struct ext2fs_extattr_entry *next;
280 error = bread(ip->i_devvp, fsbtodb(fs, ip->i_facl),
281 fs->e2fs_bsize, NOCRED, &bp);
287 /* Check attributes magic value */
288 header = EXT2_HDR(bp);
289 if (header->h_magic != EXTATTR_MAGIC || header->h_blocks != 1) {
294 /* Check attributes integrity */
295 end = bp->b_data + bp->b_bufsize;
296 entry = EXT2_FIRST_ENTRY(bp);
297 while (!EXT2_IS_LAST_ENTRY(entry)) {
298 next = EXT2_EXTATTR_NEXT(entry);
299 if ((char *)next >= end) {
307 for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry);
308 entry = EXT2_EXTATTR_NEXT(entry)) {
309 if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
312 if (strlen(name) == entry->e_name_len &&
313 0 == strncmp(entry->e_name, name, entry->e_name_len)) {
315 *size += entry->e_value_size;
317 error = uiomove(bp->b_data + entry->e_value_offs,
318 entry->e_value_size, uio);