2 * Squashfs - a compressed read only filesystem for Linux
5 * Phillip Lougher <phillip@squashfs.org.uk>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/string.h>
28 #include <linux/vfs.h>
29 #include <linux/xattr.h>
30 #include <linux/slab.h>
32 #include "squashfs_fs.h"
33 #include "squashfs_fs_sb.h"
34 #include "squashfs_fs_i.h"
37 static const struct xattr_handler
*squashfs_xattr_handler(int);
39 ssize_t
squashfs_listxattr(struct dentry
*d
, char *buffer
,
42 struct inode
*inode
= d_inode(d
);
43 struct super_block
*sb
= inode
->i_sb
;
44 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
45 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
47 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
48 int count
= squashfs_i(inode
)->xattr_count
;
49 size_t rest
= buffer_size
;
52 /* check that the file system has xattrs */
53 if (msblk
->xattr_id_table
== NULL
)
56 /* loop reading each xattr name */
58 struct squashfs_xattr_entry entry
;
59 struct squashfs_xattr_val val
;
60 const struct xattr_handler
*handler
;
61 int name_size
, prefix_size
= 0;
63 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
68 name_size
= le16_to_cpu(entry
.size
);
69 handler
= squashfs_xattr_handler(le16_to_cpu(entry
.type
));
71 prefix_size
= handler
->list(handler
, d
, buffer
, rest
,
75 if (prefix_size
+ name_size
+ 1 > rest
) {
79 buffer
+= prefix_size
;
81 err
= squashfs_read_metadata(sb
, buffer
, &start
,
86 buffer
[name_size
] = '\0';
87 buffer
+= name_size
+ 1;
89 rest
-= prefix_size
+ name_size
+ 1;
91 /* no handler or insuffficient privileges, so skip */
92 err
= squashfs_read_metadata(sb
, NULL
, &start
,
99 /* skip remaining xattr entry */
100 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
105 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
106 le32_to_cpu(val
.vsize
));
110 err
= buffer_size
- rest
;
117 static int squashfs_xattr_get(struct inode
*inode
, int name_index
,
118 const char *name
, void *buffer
, size_t buffer_size
)
120 struct super_block
*sb
= inode
->i_sb
;
121 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
122 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
123 + msblk
->xattr_table
;
124 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
125 int count
= squashfs_i(inode
)->xattr_count
;
126 int name_len
= strlen(name
);
128 char *target
= kmalloc(name_len
, GFP_KERNEL
);
133 /* loop reading each xattr name */
134 for (; count
; count
--) {
135 struct squashfs_xattr_entry entry
;
136 struct squashfs_xattr_val val
;
137 int type
, prefix
, name_size
;
139 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
144 name_size
= le16_to_cpu(entry
.size
);
145 type
= le16_to_cpu(entry
.type
);
146 prefix
= type
& SQUASHFS_XATTR_PREFIX_MASK
;
148 if (prefix
== name_index
&& name_size
== name_len
)
149 err
= squashfs_read_metadata(sb
, target
, &start
,
152 err
= squashfs_read_metadata(sb
, NULL
, &start
,
157 if (prefix
== name_index
&& name_size
== name_len
&&
158 strncmp(target
, name
, name_size
) == 0) {
160 if (type
& SQUASHFS_XATTR_VALUE_OOL
) {
163 /* val is a reference to the real location */
164 err
= squashfs_read_metadata(sb
, &val
, &start
,
165 &offset
, sizeof(val
));
168 err
= squashfs_read_metadata(sb
, &xattr_val
,
169 &start
, &offset
, sizeof(xattr_val
));
172 xattr
= le64_to_cpu(xattr_val
);
173 start
= SQUASHFS_XATTR_BLK(xattr
) +
175 offset
= SQUASHFS_XATTR_OFFSET(xattr
);
177 /* read xattr value */
178 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
183 vsize
= le32_to_cpu(val
.vsize
);
185 if (vsize
> buffer_size
) {
189 err
= squashfs_read_metadata(sb
, buffer
, &start
,
197 /* no match, skip remaining xattr entry */
198 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
202 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
203 le32_to_cpu(val
.vsize
));
207 err
= count
? vsize
: -ENODATA
;
215 static size_t squashfs_xattr_handler_list(const struct xattr_handler
*handler
,
216 struct dentry
*d
, char *list
,
217 size_t list_size
, const char *name
,
220 int len
= strlen(handler
->prefix
);
222 if (list
&& len
<= list_size
)
223 memcpy(list
, handler
->prefix
, len
);
227 static int squashfs_xattr_handler_get(const struct xattr_handler
*handler
,
228 struct dentry
*d
, const char *name
,
229 void *buffer
, size_t size
)
234 return squashfs_xattr_get(d_inode(d
), handler
->flags
, name
,
239 * User namespace support
241 static const struct xattr_handler squashfs_xattr_user_handler
= {
242 .prefix
= XATTR_USER_PREFIX
,
243 .flags
= SQUASHFS_XATTR_USER
,
244 .list
= squashfs_xattr_handler_list
,
245 .get
= squashfs_xattr_handler_get
249 * Trusted namespace support
251 static size_t squashfs_trusted_xattr_handler_list(const struct xattr_handler
*handler
,
252 struct dentry
*d
, char *list
,
253 size_t list_size
, const char *name
,
256 if (!capable(CAP_SYS_ADMIN
))
258 return squashfs_xattr_handler_list(handler
, d
, list
, list_size
, name
,
262 static const struct xattr_handler squashfs_xattr_trusted_handler
= {
263 .prefix
= XATTR_TRUSTED_PREFIX
,
264 .flags
= SQUASHFS_XATTR_TRUSTED
,
265 .list
= squashfs_trusted_xattr_handler_list
,
266 .get
= squashfs_xattr_handler_get
270 * Security namespace support
272 static const struct xattr_handler squashfs_xattr_security_handler
= {
273 .prefix
= XATTR_SECURITY_PREFIX
,
274 .flags
= SQUASHFS_XATTR_SECURITY
,
275 .list
= squashfs_xattr_handler_list
,
276 .get
= squashfs_xattr_handler_get
279 static const struct xattr_handler
*squashfs_xattr_handler(int type
)
281 if (type
& ~(SQUASHFS_XATTR_PREFIX_MASK
| SQUASHFS_XATTR_VALUE_OOL
))
282 /* ignore unrecognised type */
285 switch (type
& SQUASHFS_XATTR_PREFIX_MASK
) {
286 case SQUASHFS_XATTR_USER
:
287 return &squashfs_xattr_user_handler
;
288 case SQUASHFS_XATTR_TRUSTED
:
289 return &squashfs_xattr_trusted_handler
;
290 case SQUASHFS_XATTR_SECURITY
:
291 return &squashfs_xattr_security_handler
;
293 /* ignore unrecognised type */
298 const struct xattr_handler
*squashfs_xattr_handlers
[] = {
299 &squashfs_xattr_user_handler
,
300 &squashfs_xattr_trusted_handler
,
301 &squashfs_xattr_security_handler
,