]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/ext2fs/ext2_extattr.c
Merge llvm, clang, lld and lldb trunk r300890, and update build glue.
[FreeBSD/FreeBSD.git] / sys / fs / ext2fs / ext2_extattr.c
1 /*-
2  * Copyright (c) 2017, Fedor Uporov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
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>
35 #include <sys/bio.h>
36 #include <sys/buf.h>
37 #include <sys/endian.h>
38 #include <sys/conf.h>
39 #include <sys/extattr.h>
40
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>
47
48
49 static int
50 ext2_extattr_index_to_bsd(int index)
51 {
52         switch (index) {
53                 case EXT4_XATTR_INDEX_USER:
54                         return EXTATTR_NAMESPACE_USER;
55
56                 case EXT4_XATTR_INDEX_SYSTEM:
57                         return EXTATTR_NAMESPACE_SYSTEM;
58
59                 default:
60                         return EXTATTR_NAMESPACE_EMPTY;
61         }
62 }
63
64 int
65 ext2_extattr_inode_list(struct inode *ip, int attrnamespace,
66     struct uio *uio, size_t *size)
67 {
68         struct m_ext2fs *fs;
69         struct buf *bp;
70         struct ext2fs_extattr_dinode_header *header;
71         struct ext2fs_extattr_entry *entry;
72         struct ext2fs_extattr_entry *next;
73         char *end;
74         int error;
75
76         fs = ip->i_e2fs;
77
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) {
81                 brelse(bp);
82                 return (error);
83         }
84
85         struct ext2fs_dinode *dinode = (struct ext2fs_dinode *)
86             ((char *)bp->b_data +
87             EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number));
88
89         /* Check attributes magic value */
90         header = (struct ext2fs_extattr_dinode_header *)((char *)dinode +
91             E2FS_REV0_INODE_SIZE + dinode->e2di_extra_isize);
92
93         if (header->h_magic != EXTATTR_MAGIC) {
94                 brelse(bp);
95                 return (0);
96         }
97
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) {
104                         brelse(bp);
105                         return (EIO);
106                 }
107
108                 entry = next;
109         }
110
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)
114                         continue;
115
116                 if (uio == NULL)
117                         *size += entry->e_name_len + 1;
118                 else {
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);
124                 }
125         }
126
127         brelse(bp);
128
129         return (0);
130 }
131
132 int
133 ext2_extattr_block_list(struct inode *ip, int attrnamespace,
134     struct uio *uio, size_t *size)
135 {
136         struct m_ext2fs *fs;
137         struct buf *bp;
138         struct ext2fs_extattr_header *header;
139         struct ext2fs_extattr_entry *entry;
140         struct ext2fs_extattr_entry *next;
141         char *end;
142         int error;
143
144         fs = ip->i_e2fs;
145
146         error = bread(ip->i_devvp, fsbtodb(fs, ip->i_facl),
147             fs->e2fs_bsize, NOCRED, &bp);
148         if (error) {
149                 brelse(bp);
150                 return (error);
151         }
152
153         /* Check attributes magic value */
154         header = EXT2_HDR(bp);
155         if (header->h_magic != EXTATTR_MAGIC || header->h_blocks != 1) {
156                 brelse(bp);
157                 return (EINVAL);
158         }
159
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) {
166                         brelse(bp);
167                         return (EIO);
168                 }
169
170                 entry = next;
171         }
172
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)
176                         continue;
177
178                 if (uio == NULL)
179                         *size += entry->e_name_len + 1;
180                 else {
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);
186                 }
187         }
188
189         brelse(bp);
190
191         return (0);
192 }
193
194 int
195 ext2_extattr_inode_get(struct inode *ip, int attrnamespace,
196     const char *name, struct uio *uio, size_t *size)
197 {
198         struct m_ext2fs *fs;
199         struct buf *bp;
200         struct ext2fs_extattr_dinode_header *header;
201         struct ext2fs_extattr_entry *entry;
202         struct ext2fs_extattr_entry *next;
203         char *end;
204         int error;
205
206         fs = ip->i_e2fs;
207
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) {
211                 brelse(bp);
212                 return (error);
213         }
214
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));
218
219         /* Check attributes magic value */
220         header = (struct ext2fs_extattr_dinode_header *)((char *)dinode +
221             E2FS_REV0_INODE_SIZE + dinode->e2di_extra_isize);
222
223         if (header->h_magic != EXTATTR_MAGIC) {
224                 brelse(bp);
225                 return (0);
226         }
227
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) {
234                         brelse(bp);
235                         return (EIO);
236                 }
237
238                 entry = next;
239         }
240
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)
244                         continue;
245
246                 if (strlen(name) == entry->e_name_len &&
247                     0 == strncmp(entry->e_name, name, entry->e_name_len)) {
248                         if (uio == NULL)
249                                 *size += entry->e_value_size;
250                         else {
251                                 error = uiomove(((char *)EXT2_IFIRST(header)) + entry->e_value_offs,
252                                     entry->e_value_size, uio);
253                                 if (error) {
254                                         brelse(bp);
255                                         return (error);
256                                 }
257                         }
258                 }
259          }
260
261         brelse(bp);
262
263         return (0);
264 }
265
266 int
267 ext2_extattr_block_get(struct inode *ip, int attrnamespace,
268     const char *name, struct uio *uio, size_t *size)
269 {
270         struct m_ext2fs *fs;
271         struct buf *bp;
272         struct ext2fs_extattr_header *header;
273         struct ext2fs_extattr_entry *entry;
274         struct ext2fs_extattr_entry *next;
275         char *end;
276         int error;
277
278         fs = ip->i_e2fs;
279
280         error = bread(ip->i_devvp, fsbtodb(fs, ip->i_facl),
281             fs->e2fs_bsize, NOCRED, &bp);
282         if (error) {
283                 brelse(bp);
284                 return (error);
285         }
286
287         /* Check attributes magic value */
288         header = EXT2_HDR(bp);
289         if (header->h_magic != EXTATTR_MAGIC || header->h_blocks != 1) {
290                 brelse(bp);
291                 return (EINVAL);
292         }
293
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) {
300                         brelse(bp);
301                         return (EIO);
302                 }
303
304                 entry = next;
305         }
306
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)
310                         continue;
311
312                 if (strlen(name) == entry->e_name_len &&
313                     0 == strncmp(entry->e_name, name, entry->e_name_len)) {
314                         if (uio == NULL)
315                                 *size += entry->e_value_size;
316                         else {
317                                 error = uiomove(bp->b_data + entry->e_value_offs,
318                                     entry->e_value_size, uio);
319                                 if (error) {
320                                         brelse(bp);
321                                         return (error);
322                                 }
323                         }
324                 }
325          }
326
327         brelse(bp);
328
329         return (0);
330 }