add support for extended attributes in ext2fs for ext3/ext4; read-only for nowdiff -r1.42 -r1.43 src/sys/ufs/files.ufs
(jdolecek)
--- src/sys/ufs/files.ufs 2016/06/24 17:21:56 1.42
+++ src/sys/ufs/files.ufs 2016/08/12 19:04:03 1.43
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | # $NetBSD: files.ufs,v 1.42 2016/06/24 17:21:56 christos Exp $ | 1 | # $NetBSD: files.ufs,v 1.43 2016/08/12 19:04:03 jdolecek Exp $ | |
2 | 2 | |||
3 | deffs FFS | 3 | deffs FFS | |
4 | deffs EXT2FS | 4 | deffs EXT2FS | |
5 | deffs MFS | 5 | deffs MFS | |
6 | deffs LFS | 6 | deffs LFS | |
7 | deffs CHFS | 7 | deffs CHFS | |
8 | 8 | |||
9 | defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS | 9 | defflag opt_ffs.h FFS_EI FFS_NO_SNAPSHOT APPLE_UFS | |
10 | UFS_DIRHASH UFS_EXTATTR | 10 | UFS_DIRHASH UFS_EXTATTR | |
11 | 11 | |||
12 | defflag opt_lfs.h LFS_EI LFS_KERNEL_RFW | 12 | defflag opt_lfs.h LFS_EI LFS_KERNEL_RFW | |
13 | LFS_DIRHASH LFS_EXTATTR | 13 | LFS_DIRHASH LFS_EXTATTR | |
14 | LFS_QUOTA LFS_QUOTA2 | 14 | LFS_QUOTA LFS_QUOTA2 | |
@@ -18,26 +18,27 @@ file ufs/ext2fs/ext2fs_alloc.c ext2fs | @@ -18,26 +18,27 @@ file ufs/ext2fs/ext2fs_alloc.c ext2fs | |||
18 | file ufs/ext2fs/ext2fs_balloc.c ext2fs | 18 | file ufs/ext2fs/ext2fs_balloc.c ext2fs | |
19 | file ufs/ext2fs/ext2fs_bmap.c ext2fs | 19 | file ufs/ext2fs/ext2fs_bmap.c ext2fs | |
20 | file ufs/ext2fs/ext2fs_bswap.c ext2fs | 20 | file ufs/ext2fs/ext2fs_bswap.c ext2fs | |
21 | file ufs/ext2fs/ext2fs_hash.c ext2fs | 21 | file ufs/ext2fs/ext2fs_hash.c ext2fs | |
22 | file ufs/ext2fs/ext2fs_htree.c ext2fs | 22 | file ufs/ext2fs/ext2fs_htree.c ext2fs | |
23 | file ufs/ext2fs/ext2fs_extents.c ext2fs | 23 | file ufs/ext2fs/ext2fs_extents.c ext2fs | |
24 | file ufs/ext2fs/ext2fs_inode.c ext2fs | 24 | file ufs/ext2fs/ext2fs_inode.c ext2fs | |
25 | file ufs/ext2fs/ext2fs_lookup.c ext2fs | 25 | file ufs/ext2fs/ext2fs_lookup.c ext2fs | |
26 | file ufs/ext2fs/ext2fs_readwrite.c ext2fs | 26 | file ufs/ext2fs/ext2fs_readwrite.c ext2fs | |
27 | file ufs/ext2fs/ext2fs_rename.c ext2fs | 27 | file ufs/ext2fs/ext2fs_rename.c ext2fs | |
28 | file ufs/ext2fs/ext2fs_subr.c ext2fs | 28 | file ufs/ext2fs/ext2fs_subr.c ext2fs | |
29 | file ufs/ext2fs/ext2fs_vfsops.c ext2fs | 29 | file ufs/ext2fs/ext2fs_vfsops.c ext2fs | |
30 | file ufs/ext2fs/ext2fs_vnops.c ext2fs | 30 | file ufs/ext2fs/ext2fs_vnops.c ext2fs | |
31 | file ufs/ext2fs/ext2fs_xattr.c ext2fs | |||
31 | 32 | |||
32 | define chfs: vfs, ffs | 33 | define chfs: vfs, ffs | |
33 | file ufs/chfs/ebh.c chfs | 34 | file ufs/chfs/ebh.c chfs | |
34 | file ufs/chfs/chfs_scan.c chfs | 35 | file ufs/chfs/chfs_scan.c chfs | |
35 | file ufs/chfs/chfs_write.c chfs | 36 | file ufs/chfs/chfs_write.c chfs | |
36 | file ufs/chfs/chfs_vnode_cache.c chfs | 37 | file ufs/chfs/chfs_vnode_cache.c chfs | |
37 | file ufs/chfs/chfs_erase.c chfs | 38 | file ufs/chfs/chfs_erase.c chfs | |
38 | file ufs/chfs/chfs_build.c chfs | 39 | file ufs/chfs/chfs_build.c chfs | |
39 | file ufs/chfs/chfs_wbuf.c chfs | 40 | file ufs/chfs/chfs_wbuf.c chfs | |
40 | file ufs/chfs/chfs_vnops.c chfs | 41 | file ufs/chfs/chfs_vnops.c chfs | |
41 | file ufs/chfs/chfs_gc.c chfs | 42 | file ufs/chfs/chfs_gc.c chfs | |
42 | file ufs/chfs/chfs_nodeops.c chfs | 43 | file ufs/chfs/chfs_nodeops.c chfs | |
43 | file ufs/chfs/chfs_malloc.c chfs | 44 | file ufs/chfs/chfs_malloc.c chfs |
--- src/sys/ufs/ext2fs/ext2fs.h 2016/08/05 21:22:06 1.41
+++ src/sys/ufs/ext2fs/ext2fs.h 2016/08/12 19:04:03 1.42
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ext2fs.h,v 1.41 2016/08/05 21:22:06 jdolecek Exp $ */ | 1 | /* $NetBSD: ext2fs.h,v 1.42 2016/08/12 19:04:03 jdolecek Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1986, 1993 | 4 | * Copyright (c) 1982, 1986, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -331,26 +331,34 @@ struct m_ext2fs { | @@ -331,26 +331,34 @@ struct m_ext2fs { | |||
331 | "\015INCOMPAT_DIRDATA" \ | 331 | "\015INCOMPAT_DIRDATA" \ | |
332 | "\014" \ | 332 | "\014" \ | |
333 | "\013INCOMPAT_EA_INODE" \ | 333 | "\013INCOMPAT_EA_INODE" \ | |
334 | "\012INCOMPAT_FLEX_BG" \ | 334 | "\012INCOMPAT_FLEX_BG" \ | |
335 | "\011INCOMPAT_MMP" \ | 335 | "\011INCOMPAT_MMP" \ | |
336 | "\010INCOMPAT_64BIT" \ | 336 | "\010INCOMPAT_64BIT" \ | |
337 | "\07INCOMPAT_EXTENTS" \ | 337 | "\07INCOMPAT_EXTENTS" \ | |
338 | "\05INCOMPAT_META_BG" \ | 338 | "\05INCOMPAT_META_BG" \ | |
339 | "\04INCOMPAT_USES_JOURNAL" \ | 339 | "\04INCOMPAT_USES_JOURNAL" \ | |
340 | "\03INCOMPAT_REPLAY_JOURNAL" \ | 340 | "\03INCOMPAT_REPLAY_JOURNAL" \ | |
341 | "\02INCOMPAT_FTYPE" \ | 341 | "\02INCOMPAT_FTYPE" \ | |
342 | "\01INCOMPAT_COMP" | 342 | "\01INCOMPAT_COMP" | |
343 | 343 | |||
344 | #define EXT2F_HAS_COMPAT_FEATURE(ip, feature) \ | |||
345 | (ip)->i_e2fs->e2fs.e2fs_rev >= E2FS_REV1 && \ | |||
346 | ((ip)->i_e2fs->e2fs.e2fs_features_compat & (feature)) != 0 | |||
347 | ||||
348 | #define EXT2F_HAS_INCOMPAT_FEATURE(ip, feature) \ | |||
349 | (ip)->i_e2fs->e2fs.e2fs_rev >= E2FS_REV1 && \ | |||
350 | ((ip)->i_e2fs->e2fs.e2fs_features_incompat & (feature)) != 0 | |||
351 | ||||
344 | /* | 352 | /* | |
345 | * Features supported in this implementation | 353 | * Features supported in this implementation | |
346 | * | 354 | * | |
347 | * We support the following REV1 features: | 355 | * We support the following REV1 features: | |
348 | * - EXT2F_ROCOMPAT_SPARSESUPER | 356 | * - EXT2F_ROCOMPAT_SPARSESUPER | |
349 | * superblock backups stored only in cg_has_sb(bno) groups | 357 | * superblock backups stored only in cg_has_sb(bno) groups | |
350 | * - EXT2F_ROCOMPAT_LARGEFILE | 358 | * - EXT2F_ROCOMPAT_LARGEFILE | |
351 | * use e2di_size_high in struct ext2fs_dinode to store | 359 | * use e2di_size_high in struct ext2fs_dinode to store | |
352 | * upper 32bit of size for >2GB files | 360 | * upper 32bit of size for >2GB files | |
353 | * - EXT2F_INCOMPAT_FTYPE | 361 | * - EXT2F_INCOMPAT_FTYPE | |
354 | * store file type to e2d_type in struct ext2fs_direct | 362 | * store file type to e2d_type in struct ext2fs_direct | |
355 | * (on REV0 e2d_namlen is uint16_t and no e2d_type, like ffs) | 363 | * (on REV0 e2d_namlen is uint16_t and no e2d_type, like ffs) | |
356 | */ | 364 | */ |
--- src/sys/ufs/ext2fs/ext2fs_dinode.h 2016/08/06 09:29:28 1.35
+++ src/sys/ufs/ext2fs/ext2fs_dinode.h 2016/08/12 19:04:03 1.36
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ext2fs_dinode.h,v 1.35 2016/08/06 09:29:28 jdolecek Exp $ */ | 1 | /* $NetBSD: ext2fs_dinode.h,v 1.36 2016/08/12 19:04:03 jdolecek Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1989, 1993 | 4 | * Copyright (c) 1982, 1989, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * (c) UNIX System Laboratories, Inc. | 6 | * (c) UNIX System Laboratories, Inc. | |
7 | * All or some portions of this file are derived from material licensed | 7 | * All or some portions of this file are derived from material licensed | |
8 | * to the University of California by American Telephone and Telegraph | 8 | * to the University of California by American Telephone and Telegraph | |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
10 | * the permission of UNIX System Laboratories, Inc. | 10 | * the permission of UNIX System Laboratories, Inc. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -113,31 +113,31 @@ struct ext2fs_dinode { | @@ -113,31 +113,31 @@ struct ext2fs_dinode { | |||
113 | uint32_t e2di_size; /* 4: Size (in bytes) */ | 113 | uint32_t e2di_size; /* 4: Size (in bytes) */ | |
114 | uint32_t e2di_atime; /* 8: Access time */ | 114 | uint32_t e2di_atime; /* 8: Access time */ | |
115 | uint32_t e2di_ctime; /* 12: Create time */ | 115 | uint32_t e2di_ctime; /* 12: Create time */ | |
116 | uint32_t e2di_mtime; /* 16: Modification time */ | 116 | uint32_t e2di_mtime; /* 16: Modification time */ | |
117 | uint32_t e2di_dtime; /* 20: Deletion time */ | 117 | uint32_t e2di_dtime; /* 20: Deletion time */ | |
118 | uint16_t e2di_gid; /* 24: Owner GID */ | 118 | uint16_t e2di_gid; /* 24: Owner GID */ | |
119 | uint16_t e2di_nlink; /* 26: File link count */ | 119 | uint16_t e2di_nlink; /* 26: File link count */ | |
120 | uint32_t e2di_nblock; /* 28: Blocks count */ | 120 | uint32_t e2di_nblock; /* 28: Blocks count */ | |
121 | uint32_t e2di_flags; /* 32: Status flags (chflags) */ | 121 | uint32_t e2di_flags; /* 32: Status flags (chflags) */ | |
122 | uint32_t e2di_version; /* 36: was reserved1 */ | 122 | uint32_t e2di_version; /* 36: was reserved1 */ | |
123 | uint32_t e2di_blocks[EXT2FS_NDADDR+EXT2FS_NIADDR]; | 123 | uint32_t e2di_blocks[EXT2FS_NDADDR+EXT2FS_NIADDR]; | |
124 | /* 40: disk blocks */ | 124 | /* 40: disk blocks */ | |
125 | uint32_t e2di_gen; /* 100: generation number */ | 125 | uint32_t e2di_gen; /* 100: generation number */ | |
126 | uint32_t e2di_facl; /* 104: file ACL (not implemented) (ext3) */ | 126 | uint32_t e2di_facl; /* 104: file ACL (ext3) */ | |
127 | uint32_t e2di_size_high; /* 108: Size (in bytes) high */ | 127 | uint32_t e2di_size_high; /* 108: Size (in bytes) high */ | |
128 | uint32_t e2di_obso_faddr;/* 112: obsolete fragment address (ext2) */ | 128 | uint32_t e2di_obso_faddr;/* 112: obsolete fragment address (ext2) */ | |
129 | uint16_t e2di_nblock_high; /* 116: Blocks count bits 47:32 (ext4) */ | 129 | uint16_t e2di_nblock_high; /* 116: Blocks count bits 47:32 (ext4) */ | |
130 | uint16_t e2di_facl_high; /* 118: file ACL bits 47:32 (ext4) */ | 130 | uint16_t e2di_facl_high; /* 118: file ACL bits 47:32 (ext4/64bit) */ | |
131 | uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits (ext4) */ | 131 | uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits (ext4) */ | |
132 | uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits (ext4) */ | 132 | uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits (ext4) */ | |
133 | uint16_t e2di_checksum_low; /* 124: crc LE (not implemented) (ext4) */ | 133 | uint16_t e2di_checksum_low; /* 124: crc LE (not implemented) (ext4) */ | |
134 | uint16_t e2di_reserved; /* 126: reserved */ | 134 | uint16_t e2di_reserved; /* 126: reserved */ | |
135 | uint16_t e2di_extra_isize; /* 128: inode extra size (over 128) actually used (ext4) */ | 135 | uint16_t e2di_extra_isize; /* 128: inode extra size (over 128) actually used (ext4) */ | |
136 | uint16_t e2di_checksum_high; /* 130: crc BE (not implemented) (ext4) */ | 136 | uint16_t e2di_checksum_high; /* 130: crc BE (not implemented) (ext4) */ | |
137 | uint32_t e2di_ctime_extra; /* 132: ctime (nsec << 2 | high epoch) (ext4) */ | 137 | uint32_t e2di_ctime_extra; /* 132: ctime (nsec << 2 | high epoch) (ext4) */ | |
138 | uint32_t e2di_mtime_extra; /* 136: mtime (nsec << 2 | high epoch) (ext4) */ | 138 | uint32_t e2di_mtime_extra; /* 136: mtime (nsec << 2 | high epoch) (ext4) */ | |
139 | uint32_t e2di_atime_extra; /* 140: atime (nsec << 2 | high epoch) (ext4) */ | 139 | uint32_t e2di_atime_extra; /* 140: atime (nsec << 2 | high epoch) (ext4) */ | |
140 | uint32_t e2di_crtime; /* 144: creation time (epoch) (ext4) */ | 140 | uint32_t e2di_crtime; /* 144: creation time (epoch) (ext4) */ | |
141 | uint32_t e2di_crtime_extra; /* 148: creation time (nsec << 2 | high epoch) (ext4) */ | 141 | uint32_t e2di_crtime_extra; /* 148: creation time (nsec << 2 | high epoch) (ext4) */ | |
142 | uint32_t e2di_version_high; /* 152: version high (ext4) */ | 142 | uint32_t e2di_version_high; /* 152: version high (ext4) */ | |
143 | uint32_t e2di_projid; /* 156: project id (not implemented) (ext4) */ | 143 | uint32_t e2di_projid; /* 156: project id (not implemented) (ext4) */ |
--- src/sys/ufs/ext2fs/ext2fs_vnops.c 2016/08/05 20:15:41 1.120
+++ src/sys/ufs/ext2fs/ext2fs_vnops.c 2016/08/12 19:04:03 1.121
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ext2fs_vnops.c,v 1.120 2016/08/05 20:15:41 jdolecek Exp $ */ | 1 | /* $NetBSD: ext2fs_vnops.c,v 1.121 2016/08/12 19:04:03 jdolecek Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1986, 1989, 1993 | 4 | * Copyright (c) 1982, 1986, 1989, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * (c) UNIX System Laboratories, Inc. | 6 | * (c) UNIX System Laboratories, Inc. | |
7 | * All or some portions of this file are derived from material licensed | 7 | * All or some portions of this file are derived from material licensed | |
8 | * to the University of California by American Telephone and Telegraph | 8 | * to the University of California by American Telephone and Telegraph | |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
10 | * the permission of UNIX System Laboratories, Inc. | 10 | * the permission of UNIX System Laboratories, Inc. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -55,27 +55,27 @@ | @@ -55,27 +55,27 @@ | |||
55 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 55 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
56 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 56 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
57 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 57 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
58 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 58 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
59 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 59 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
60 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 60 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
61 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 61 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
62 | * | 62 | * | |
63 | * @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94 | 63 | * @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94 | |
64 | * Modified for ext2fs by Manuel Bouyer. | 64 | * Modified for ext2fs by Manuel Bouyer. | |
65 | */ | 65 | */ | |
66 | 66 | |||
67 | #include <sys/cdefs.h> | 67 | #include <sys/cdefs.h> | |
68 | __KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.120 2016/08/05 20:15:41 jdolecek Exp $"); | 68 | __KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.121 2016/08/12 19:04:03 jdolecek Exp $"); | |
69 | 69 | |||
70 | #include <sys/param.h> | 70 | #include <sys/param.h> | |
71 | #include <sys/systm.h> | 71 | #include <sys/systm.h> | |
72 | #include <sys/resourcevar.h> | 72 | #include <sys/resourcevar.h> | |
73 | #include <sys/kernel.h> | 73 | #include <sys/kernel.h> | |
74 | #include <sys/file.h> | 74 | #include <sys/file.h> | |
75 | #include <sys/stat.h> | 75 | #include <sys/stat.h> | |
76 | #include <sys/buf.h> | 76 | #include <sys/buf.h> | |
77 | #include <sys/proc.h> | 77 | #include <sys/proc.h> | |
78 | #include <sys/mount.h> | 78 | #include <sys/mount.h> | |
79 | #include <sys/namei.h> | 79 | #include <sys/namei.h> | |
80 | #include <sys/vnode.h> | 80 | #include <sys/vnode.h> | |
81 | #include <sys/lockf.h> | 81 | #include <sys/lockf.h> | |
@@ -84,26 +84,27 @@ __KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops | @@ -84,26 +84,27 @@ __KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops | |||
84 | #include <sys/kauth.h> | 84 | #include <sys/kauth.h> | |
85 | 85 | |||
86 | #include <miscfs/fifofs/fifo.h> | 86 | #include <miscfs/fifofs/fifo.h> | |
87 | #include <miscfs/genfs/genfs.h> | 87 | #include <miscfs/genfs/genfs.h> | |
88 | #include <miscfs/specfs/specdev.h> | 88 | #include <miscfs/specfs/specdev.h> | |
89 | 89 | |||
90 | #include <ufs/ufs/inode.h> | 90 | #include <ufs/ufs/inode.h> | |
91 | #include <ufs/ufs/ufs_extern.h> | 91 | #include <ufs/ufs/ufs_extern.h> | |
92 | #include <ufs/ufs/ufsmount.h> | 92 | #include <ufs/ufs/ufsmount.h> | |
93 | 93 | |||
94 | #include <ufs/ext2fs/ext2fs.h> | 94 | #include <ufs/ext2fs/ext2fs.h> | |
95 | #include <ufs/ext2fs/ext2fs_extern.h> | 95 | #include <ufs/ext2fs/ext2fs_extern.h> | |
96 | #include <ufs/ext2fs/ext2fs_dir.h> | 96 | #include <ufs/ext2fs/ext2fs_dir.h> | |
97 | #include <ufs/ext2fs/ext2fs_xattr.h> | |||
97 | 98 | |||
98 | extern int prtactive; | 99 | extern int prtactive; | |
99 | 100 | |||
100 | static int ext2fs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *); | 101 | static int ext2fs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *); | |
101 | static int ext2fs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, | 102 | static int ext2fs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, | |
102 | struct lwp *); | 103 | struct lwp *); | |
103 | 104 | |||
104 | union _qcvt { | 105 | union _qcvt { | |
105 | int64_t qcvt; | 106 | int64_t qcvt; | |
106 | int32_t val[2]; | 107 | int32_t val[2]; | |
107 | }; | 108 | }; | |
108 | 109 | |||
109 | #define SETHIGH(q, h) { \ | 110 | #define SETHIGH(q, h) { \ | |
@@ -1172,26 +1173,30 @@ const struct vnodeopv_entry_desc ext2fs_ | @@ -1172,26 +1173,30 @@ const struct vnodeopv_entry_desc ext2fs_ | |||
1172 | { &vop_inactive_desc, ext2fs_inactive }, /* inactive */ | 1173 | { &vop_inactive_desc, ext2fs_inactive }, /* inactive */ | |
1173 | { &vop_reclaim_desc, ext2fs_reclaim }, /* reclaim */ | 1174 | { &vop_reclaim_desc, ext2fs_reclaim }, /* reclaim */ | |
1174 | { &vop_lock_desc, ufs_lock }, /* lock */ | 1175 | { &vop_lock_desc, ufs_lock }, /* lock */ | |
1175 | { &vop_unlock_desc, ufs_unlock }, /* unlock */ | 1176 | { &vop_unlock_desc, ufs_unlock }, /* unlock */ | |
1176 | { &vop_bmap_desc, ext2fs_bmap }, /* bmap */ | 1177 | { &vop_bmap_desc, ext2fs_bmap }, /* bmap */ | |
1177 | { &vop_strategy_desc, ufs_strategy }, /* strategy */ | 1178 | { &vop_strategy_desc, ufs_strategy }, /* strategy */ | |
1178 | { &vop_print_desc, ufs_print }, /* print */ | 1179 | { &vop_print_desc, ufs_print }, /* print */ | |
1179 | { &vop_islocked_desc, ufs_islocked }, /* islocked */ | 1180 | { &vop_islocked_desc, ufs_islocked }, /* islocked */ | |
1180 | { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ | 1181 | { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ | |
1181 | { &vop_advlock_desc, ext2fs_advlock }, /* advlock */ | 1182 | { &vop_advlock_desc, ext2fs_advlock }, /* advlock */ | |
1182 | { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ | 1183 | { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ | |
1183 | { &vop_getpages_desc, genfs_getpages }, /* getpages */ | 1184 | { &vop_getpages_desc, genfs_getpages }, /* getpages */ | |
1184 | { &vop_putpages_desc, genfs_putpages }, /* putpages */ | 1185 | { &vop_putpages_desc, genfs_putpages }, /* putpages */ | |
1186 | { &vop_getextattr_desc, ext2fs_getextattr }, /* getextattr */ | |||
1187 | { &vop_setextattr_desc, ext2fs_setextattr }, /* setextattr */ | |||
1188 | { &vop_listextattr_desc, ext2fs_listextattr }, /* listextattr */ | |||
1189 | { &vop_deleteextattr_desc, ext2fs_deleteextattr },/* deleteextattr */ | |||
1185 | { NULL, NULL } | 1190 | { NULL, NULL } | |
1186 | }; | 1191 | }; | |
1187 | const struct vnodeopv_desc ext2fs_vnodeop_opv_desc = | 1192 | const struct vnodeopv_desc ext2fs_vnodeop_opv_desc = | |
1188 | { &ext2fs_vnodeop_p, ext2fs_vnodeop_entries }; | 1193 | { &ext2fs_vnodeop_p, ext2fs_vnodeop_entries }; | |
1189 | 1194 | |||
1190 | int (**ext2fs_specop_p)(void *); | 1195 | int (**ext2fs_specop_p)(void *); | |
1191 | const struct vnodeopv_entry_desc ext2fs_specop_entries[] = { | 1196 | const struct vnodeopv_entry_desc ext2fs_specop_entries[] = { | |
1192 | { &vop_default_desc, vn_default_error }, | 1197 | { &vop_default_desc, vn_default_error }, | |
1193 | { &vop_lookup_desc, spec_lookup }, /* lookup */ | 1198 | { &vop_lookup_desc, spec_lookup }, /* lookup */ | |
1194 | { &vop_create_desc, spec_create }, /* create */ | 1199 | { &vop_create_desc, spec_create }, /* create */ | |
1195 | { &vop_mknod_desc, spec_mknod }, /* mknod */ | 1200 | { &vop_mknod_desc, spec_mknod }, /* mknod */ | |
1196 | { &vop_open_desc, spec_open }, /* open */ | 1201 | { &vop_open_desc, spec_open }, /* open */ | |
1197 | { &vop_close_desc, ufsspec_close }, /* close */ | 1202 | { &vop_close_desc, ufsspec_close }, /* close */ | |
@@ -1222,26 +1227,30 @@ const struct vnodeopv_entry_desc ext2fs_ | @@ -1222,26 +1227,30 @@ const struct vnodeopv_entry_desc ext2fs_ | |||
1222 | { &vop_inactive_desc, ext2fs_inactive }, /* inactive */ | 1227 | { &vop_inactive_desc, ext2fs_inactive }, /* inactive */ | |
1223 | { &vop_reclaim_desc, ext2fs_reclaim }, /* reclaim */ | 1228 | { &vop_reclaim_desc, ext2fs_reclaim }, /* reclaim */ | |
1224 | { &vop_lock_desc, ufs_lock }, /* lock */ | 1229 | { &vop_lock_desc, ufs_lock }, /* lock */ | |
1225 | { &vop_unlock_desc, ufs_unlock }, /* unlock */ | 1230 | { &vop_unlock_desc, ufs_unlock }, /* unlock */ | |
1226 | { &vop_bmap_desc, spec_bmap }, /* bmap */ | 1231 | { &vop_bmap_desc, spec_bmap }, /* bmap */ | |
1227 | { &vop_strategy_desc, spec_strategy }, /* strategy */ | 1232 | { &vop_strategy_desc, spec_strategy }, /* strategy */ | |
1228 | { &vop_print_desc, ufs_print }, /* print */ | 1233 | { &vop_print_desc, ufs_print }, /* print */ | |
1229 | { &vop_islocked_desc, ufs_islocked }, /* islocked */ | 1234 | { &vop_islocked_desc, ufs_islocked }, /* islocked */ | |
1230 | { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ | 1235 | { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ | |
1231 | { &vop_advlock_desc, spec_advlock }, /* advlock */ | 1236 | { &vop_advlock_desc, spec_advlock }, /* advlock */ | |
1232 | { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ | 1237 | { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ | |
1233 | { &vop_getpages_desc, spec_getpages }, /* getpages */ | 1238 | { &vop_getpages_desc, spec_getpages }, /* getpages */ | |
1234 | { &vop_putpages_desc, spec_putpages }, /* putpages */ | 1239 | { &vop_putpages_desc, spec_putpages }, /* putpages */ | |
1240 | { &vop_getextattr_desc, ext2fs_getextattr }, /* getextattr */ | |||
1241 | { &vop_setextattr_desc, ext2fs_setextattr }, /* setextattr */ | |||
1242 | { &vop_listextattr_desc, ext2fs_listextattr }, /* listextattr */ | |||
1243 | { &vop_deleteextattr_desc, ext2fs_deleteextattr },/* deleteextattr */ | |||
1235 | { NULL, NULL } | 1244 | { NULL, NULL } | |
1236 | }; | 1245 | }; | |
1237 | const struct vnodeopv_desc ext2fs_specop_opv_desc = | 1246 | const struct vnodeopv_desc ext2fs_specop_opv_desc = | |
1238 | { &ext2fs_specop_p, ext2fs_specop_entries }; | 1247 | { &ext2fs_specop_p, ext2fs_specop_entries }; | |
1239 | 1248 | |||
1240 | int (**ext2fs_fifoop_p)(void *); | 1249 | int (**ext2fs_fifoop_p)(void *); | |
1241 | const struct vnodeopv_entry_desc ext2fs_fifoop_entries[] = { | 1250 | const struct vnodeopv_entry_desc ext2fs_fifoop_entries[] = { | |
1242 | { &vop_default_desc, vn_default_error }, | 1251 | { &vop_default_desc, vn_default_error }, | |
1243 | { &vop_lookup_desc, vn_fifo_bypass }, /* lookup */ | 1252 | { &vop_lookup_desc, vn_fifo_bypass }, /* lookup */ | |
1244 | { &vop_create_desc, vn_fifo_bypass }, /* create */ | 1253 | { &vop_create_desc, vn_fifo_bypass }, /* create */ | |
1245 | { &vop_mknod_desc, vn_fifo_bypass }, /* mknod */ | 1254 | { &vop_mknod_desc, vn_fifo_bypass }, /* mknod */ | |
1246 | { &vop_open_desc, vn_fifo_bypass }, /* open */ | 1255 | { &vop_open_desc, vn_fifo_bypass }, /* open */ | |
1247 | { &vop_close_desc, ufsfifo_close }, /* close */ | 1256 | { &vop_close_desc, ufsfifo_close }, /* close */ | |
@@ -1271,17 +1280,21 @@ const struct vnodeopv_entry_desc ext2fs_ | @@ -1271,17 +1280,21 @@ const struct vnodeopv_entry_desc ext2fs_ | |||
1271 | { &vop_abortop_desc, vn_fifo_bypass }, /* abortop */ | 1280 | { &vop_abortop_desc, vn_fifo_bypass }, /* abortop */ | |
1272 | { &vop_inactive_desc, ext2fs_inactive }, /* inactive */ | 1281 | { &vop_inactive_desc, ext2fs_inactive }, /* inactive */ | |
1273 | { &vop_reclaim_desc, ext2fs_reclaim }, /* reclaim */ | 1282 | { &vop_reclaim_desc, ext2fs_reclaim }, /* reclaim */ | |
1274 | { &vop_lock_desc, ufs_lock }, /* lock */ | 1283 | { &vop_lock_desc, ufs_lock }, /* lock */ | |
1275 | { &vop_unlock_desc, ufs_unlock }, /* unlock */ | 1284 | { &vop_unlock_desc, ufs_unlock }, /* unlock */ | |
1276 | { &vop_bmap_desc, vn_fifo_bypass }, /* bmap */ | 1285 | { &vop_bmap_desc, vn_fifo_bypass }, /* bmap */ | |
1277 | { &vop_strategy_desc, vn_fifo_bypass }, /* strategy */ | 1286 | { &vop_strategy_desc, vn_fifo_bypass }, /* strategy */ | |
1278 | { &vop_print_desc, ufs_print }, /* print */ | 1287 | { &vop_print_desc, ufs_print }, /* print */ | |
1279 | { &vop_islocked_desc, ufs_islocked }, /* islocked */ | 1288 | { &vop_islocked_desc, ufs_islocked }, /* islocked */ | |
1280 | { &vop_pathconf_desc, vn_fifo_bypass }, /* pathconf */ | 1289 | { &vop_pathconf_desc, vn_fifo_bypass }, /* pathconf */ | |
1281 | { &vop_advlock_desc, vn_fifo_bypass }, /* advlock */ | 1290 | { &vop_advlock_desc, vn_fifo_bypass }, /* advlock */ | |
1282 | { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ | 1291 | { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ | |
1283 | { &vop_putpages_desc, vn_fifo_bypass }, /* putpages */ | 1292 | { &vop_putpages_desc, vn_fifo_bypass }, /* putpages */ | |
1293 | { &vop_getextattr_desc, ext2fs_getextattr }, /* getextattr */ | |||
1294 | { &vop_setextattr_desc, ext2fs_setextattr }, /* setextattr */ | |||
1295 | { &vop_listextattr_desc, ext2fs_listextattr }, /* listextattr */ | |||
1296 | { &vop_deleteextattr_desc, ext2fs_deleteextattr },/* deleteextattr */ | |||
1284 | { NULL, NULL } | 1297 | { NULL, NULL } | |
1285 | }; | 1298 | }; | |
1286 | const struct vnodeopv_desc ext2fs_fifoop_opv_desc = | 1299 | const struct vnodeopv_desc ext2fs_fifoop_opv_desc = | |
1287 | { &ext2fs_fifoop_p, ext2fs_fifoop_entries }; | 1300 | { &ext2fs_fifoop_p, ext2fs_fifoop_entries }; |
/* $NetBSD: ext2fs_xattr.c,v 1.1 2016/08/12 19:04:03 jdolecek Exp $ */
/*-
* Copyright (c) 2016 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jaromir Dolecek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_xattr.c,v 1.1 2016/08/12 19:04:03 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/kernel.h>
#include <sys/kmem.h>
#include <sys/trace.h>
#include <sys/resourcevar.h>
#include <sys/kauth.h>
#include <sys/extattr.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ext2fs/ext2fs_extern.h>
#include <ufs/ext2fs/ext2fs_xattr.h>
static const char * const xattr_prefix_index[] = {
"",
"user.",
"system.posix_acl_access",
"system.posix_acl_default",
"trusted.",
"", /* unused */
"security",
"system.",
"system.richacl",
"c",
};
static int
ext2fs_find_xattr(struct ext2fs_xattr_entry *e, uint8_t *start, uint8_t *end, int attrnamespace, struct uio *uio, size_t *size, uint8_t name_index, const char *name)
{
uint8_t *value;
int error;
size_t value_offs, value_len, len, old_len;
/*
* Individual entries follow the header. Each is aligned on 4-byte
* boundary.
*/
for(; !EXT2FS_XATTR_IS_LAST_ENTRY(e, end); e = EXT2FS_XATTR_NEXT(e)) {
/*
* Only EXT2FS_XATTR_PREFIX_USER is USER, anything else
* is considered SYSTEM.
*/
if ((attrnamespace == EXTATTR_NAMESPACE_USER && e->e_name_index != EXT2FS_XATTR_PREFIX_USER) ||
(attrnamespace == EXTATTR_NAMESPACE_SYSTEM && e->e_name_index == EXT2FS_XATTR_PREFIX_USER)) {
continue;
}
if (e->e_name_index != name_index ||
e->e_name_len != strlen(name) ||
strncmp(e->e_name, name, e->e_name_len) != 0)
continue;
value_offs = fs2h32(e->e_value_offs);
value_len = fs2h32(e->e_value_size);
value = &start[value_offs];
/* make sure the value offset are sane */
if (&value[value_len] > end)
return (EINVAL);
if (uio != NULL) {
/*
* Figure out maximum to transfer -- use buffer size and
* local data limit.
*/
len = MIN(uio->uio_resid, value_len);
old_len = uio->uio_resid;
uio->uio_resid = len;
uio->uio_resid = old_len - (len - uio->uio_resid);
error = uiomove(value, value_len, uio);
if (error)
return error;
}
/* full data size */
*size += value_len;
goto found;
}
/* requested attribute not found */
return (ENODATA);
found:
return (0);
}
static int
ext2fs_get_inode_xattr(struct inode *ip, int attrnamespace, struct uio *uio, size_t *size, uint8_t name_index, const char *name)
{
struct ext2fs_dinode *di = ip->i_din.e2fs_din;
struct ext2fs_xattr_ibody_header *h;
uint8_t *start, *end;
start = &((uint8_t *)di)[EXT2_REV0_DINODE_SIZE + di->e2di_extra_isize];
h = (struct ext2fs_xattr_ibody_header *)start;
end = &((uint8_t *)di)[EXT2_DINODE_SIZE(ip->i_e2fs)];
if (end <= start || fs2h32(h->h_magic) != EXT2FS_XATTR_MAGIC)
return (ENODATA);
return ext2fs_find_xattr(EXT2FS_XATTR_IFIRST(h), start, end, attrnamespace, uio, size, name_index, name);
}
static int
ext2fs_get_block_xattr(struct inode *ip, int attrnamespace, struct uio *uio, size_t *size, uint8_t name_index, const char *name)
{
struct ext2fs_dinode *di = ip->i_din.e2fs_din;
uint8_t *start, *end;
struct ext2fs_xattr_header *h;
int error = 0;
struct buf *bp = NULL;
daddr_t xblk;
xblk = di->e2di_facl;
if (EXT2F_HAS_INCOMPAT_FEATURE(ip, EXT2F_INCOMPAT_64BIT))
xblk |= (((daddr_t)di->e2di_facl_high) << 32);
/* don't do anything if no attr block was allocated */
if (xblk == 0)
return (0);
error = bread(ip->i_devvp, fsbtodb(ip->i_e2fs, xblk), (int)ip->i_e2fs->e2fs_bsize, 0, &bp);
if (error)
goto out;
start = (uint8_t *)bp->b_data;
h = (struct ext2fs_xattr_header *)start;
end = &((uint8_t *)bp->b_data)[bp->b_bcount];
if (end <= start || fs2h32(h->h_magic) != EXT2FS_XATTR_MAGIC)
goto out;
error = ext2fs_find_xattr(EXT2FS_XATTR_BFIRST(h), start, end, attrnamespace, uio, size, name_index, name);
out:
if (bp)
brelse(bp, 0);
return (error);
}
int
ext2fs_getextattr(void *v)
{
struct vop_getextattr_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
int a_attrnamespace;
const char *a_name;
struct uio *a_uio;
size_t *a_size;
kauth_cred_t a_cred;
} */ *ap = v;
struct inode *ip = VTOI(ap->a_vp);
char namebuf[EXT2FS_XATTR_NAME_LEN_MAX + 1];
int error, i;
const char *prefix, *name;
uint8_t name_index;
size_t name_match, valuesize = 0;
if (ap->a_attrnamespace == EXTATTR_NAMESPACE_USER)
prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_USER];
else
prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_SYSTEM];
snprintf(namebuf, sizeof(namebuf), "%s%s", prefix, ap->a_name);
error = extattr_check_cred(ap->a_vp, namebuf, ap->a_cred, VREAD);
if (error)
return (error);
/*
* Allow only offsets of zero to encourage the read/replace
* extended attribute semantic. Otherwise we can't guarantee
* atomicity, as we don't provide locks for extended attributes.
*/
if (ap->a_uio != NULL && ap->a_uio->uio_offset != 0)
return (ENXIO);
/* figure out the name index */
name = ap->a_name;
name_index = 0;
name_match = 0;
for(i=0; i < sizeof(xattr_prefix_index)/sizeof(void *); i++) {
prefix = xattr_prefix_index[i];
if (strlen(prefix) > 0 &&
strncmp(ap->a_name, prefix, strlen(prefix)) == 0 &&
name_match < strlen(prefix)) {
name = &ap->a_name[strlen(prefix)];
name_index = i;
name_match = strlen(prefix);
continue;
}
}
/* fetch the xattr */
error = ext2fs_get_inode_xattr(ip, ap->a_attrnamespace, ap->a_uio, &valuesize, name_index, name);
if (error == ENODATA) {
/* not found in inode, try facl */
error = ext2fs_get_block_xattr(ip, ap->a_attrnamespace, ap->a_uio, &valuesize, name_index, name);
}
if (ap->a_size != NULL)
*ap->a_size = valuesize;
return (error);
}
int
ext2fs_setextattr(void *v)
{
#if 0
struct vop_setextattr_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
int a_attrnamespace;
const char *a_name;
struct uio *a_uio;
kauth_cred_t a_cred;
} */ *ap = v;
/* XXX set EXT2F_COMPAT_EXTATTR in superblock after successful set */
#endif
/* XXX Not implemented */
return (EOPNOTSUPP);
}
static int
ext2fs_list_xattr(struct ext2fs_xattr_entry *e, uint8_t *end, int attrnamespace, int flags, struct uio *uio, size_t *size)
{
char name[EXT2FS_XATTR_NAME_LEN_MAX + 1];
uint8_t len;
int error;
const char *prefix;
/*
* Individual entries follow the header. Each is aligned on 4-byte
* boundary.
*/
for(; !EXT2FS_XATTR_IS_LAST_ENTRY(e, end); e = EXT2FS_XATTR_NEXT(e)) {
/*
* Only EXT2FS_XATTR_PREFIX_USER is USER, anything else
* is considered SYSTEM.
*/
if ((attrnamespace == EXTATTR_NAMESPACE_USER && e->e_name_index != EXT2FS_XATTR_PREFIX_USER) ||
(attrnamespace == EXTATTR_NAMESPACE_SYSTEM && e->e_name_index == EXT2FS_XATTR_PREFIX_USER)) {
continue;
}
if (e->e_name_index <= sizeof(xattr_prefix_index)/sizeof(void *))
prefix = xattr_prefix_index[e->e_name_index];
else
prefix = "";
len = snprintf(name, sizeof(name), "%s%.*s",
prefix,
e->e_name_len, e->e_name);
if (uio != NULL) {
if (flags & EXTATTR_LIST_LENPREFIX) {
/* write name length */
uiomove(&len, sizeof(uint8_t), uio);
} else {
/* include trailing NUL */
len++;
}
error = uiomove(name, len, uio);
if (error)
return error;
*size += len;
}
}
return (0);
}
static int
ext2fs_list_inode_xattr(struct inode *ip, int attrnamespace, int flags, struct uio *uio, size_t *size)
{
struct ext2fs_dinode *di = ip->i_din.e2fs_din;
void *start, *end;
struct ext2fs_xattr_ibody_header *h;
start = &((uint8_t *)di)[EXT2_REV0_DINODE_SIZE + di->e2di_extra_isize];
h = start;
end = &((uint8_t *)di)[EXT2_DINODE_SIZE(ip->i_e2fs)];
if (end <= start || fs2h32(h->h_magic) != EXT2FS_XATTR_MAGIC)
return (0);
return ext2fs_list_xattr(EXT2FS_XATTR_IFIRST(h), end, attrnamespace, flags, uio, size);
}
static int
ext2fs_list_block_xattr(struct inode *ip, int attrnamespace, int flags, struct uio *uio, size_t *size)
{
struct ext2fs_dinode *di = ip->i_din.e2fs_din;
void *end;
struct ext2fs_xattr_header *h;
int error = 0;
struct buf *bp = NULL;
daddr_t xblk;
xblk = di->e2di_facl;
if (EXT2F_HAS_INCOMPAT_FEATURE(ip, EXT2F_INCOMPAT_64BIT))
xblk |= (((daddr_t)di->e2di_facl_high) << 32);
/* don't do anything if no attr block was allocated */
if (xblk == 0)
return (0);
error = bread(ip->i_devvp, fsbtodb(ip->i_e2fs, xblk), (int)ip->i_e2fs->e2fs_bsize, 0, &bp);
if (error)
goto out;
h = (struct ext2fs_xattr_header *)bp->b_data;
end = &((uint8_t *)bp->b_data)[bp->b_bcount];
if (end <= (void *)h || fs2h32(h->h_magic) != EXT2FS_XATTR_MAGIC)
goto out;
error = ext2fs_list_xattr(EXT2FS_XATTR_BFIRST(h), end, attrnamespace, flags, uio, size);
out:
if (bp)
brelse(bp, 0);
return (error);
}
int
ext2fs_listextattr(void *v)
{
struct vop_listextattr_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
int a_attrnamespace;
struct uio *a_uio;
size_t *a_size;
int a_flag;
kauth_cred_t a_cred;
} */ *ap = v;
struct inode *ip = VTOI(ap->a_vp);
int error;
const char *prefix;
size_t listsize = 0;
if (!EXT2F_HAS_COMPAT_FEATURE(ip, EXT2F_COMPAT_EXTATTR)) {
/* no EA on the filesystem */
goto out;
}
/*
* XXX: We can move this inside the loop and iterate on individual
* attributes.
*/
if (ap->a_attrnamespace == EXTATTR_NAMESPACE_USER)
prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_USER];
else
prefix = xattr_prefix_index[EXT2FS_XATTR_PREFIX_SYSTEM];
error = extattr_check_cred(ap->a_vp, prefix, ap->a_cred, VREAD);
if (error)
return (error);
/*
* Allow only offsets of zero to encourage the read/replace
* extended attribute semantic. Otherwise we can't guarantee
* atomicity, as we don't provide locks for extended attributes.
* XXX revisit - vnode lock enough?
*/
if (ap->a_uio != NULL && ap->a_uio->uio_offset != 0)
return (ENXIO);
/* fetch inode xattrs */
error = ext2fs_list_inode_xattr(ip, ap->a_attrnamespace, ap->a_flag, ap->a_uio, &listsize);
if (error)
return (error);
error = ext2fs_list_block_xattr(ip, ap->a_attrnamespace, ap->a_flag, ap->a_uio, &listsize);
if (error)
return (error);
out:
if (ap->a_size != NULL)
*ap->a_size = listsize;
return (0);
}
int
ext2fs_deleteextattr(void *v)
{
#if 0
struct vop_deleteextattr_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
int a_attrnamespace;
const char *a_name;
kauth_cred_t a_cred;
} */ *ap = v;
#endif
/* XXX Not implemented */
return (EOPNOTSUPP);
}
/* $NetBSD: ext2fs_xattr.h,v 1.1 2016/08/12 19:04:03 jdolecek Exp $ */
/*-
* Copyright (c) 2016 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jaromir Dolecek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UFS_EXT2FS_EXT2FS_XATTR_H_
#define _UFS_EXT2FS_EXT2FS_XATTR_H_
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_xattr.h,v 1.1 2016/08/12 19:04:03 jdolecek Exp $");
#ifdef _KERNEL
#define EXT2FS_XATTR_MAGIC 0xEA020000
#define EXT2FS_XATTR_NAME_LEN_MAX 255
#define EXT2FS_XATTR_REFCOUNT_MAX 1024
/*
* This is used as header for extended attribute block within inode
*/
struct ext2fs_xattr_ibody_header {
uint32_t h_magic; /* Magic number - 0xEA020000 */
};
/*
* This is used as header for extended attribute on separate disk block
*/
struct ext2fs_xattr_header {
uint32_t h_magic; /* Magic number - 0xEA020000 */
uint32_t h_refcount; /* Reference count */
uint32_t h_blocks; /* Number of blocks - only 1 supported */
uint32_t h_hash; /* Hash of all attributes */
uint32_t h_checksum; /* Checksum of the extended attribute block */
uint32_t h_reserved[3];
};
/*
* Extended attribute on-disk header structure
*/
struct ext2fs_xattr_entry {
uint8_t e_name_len; /* Name length */
uint8_t e_name_index; /* Name prefix index (see below) */
uint16_t e_value_offs; /* Offset of value within block */
uint32_t e_value_block; /* Value block - not supported (always zero) */
uint32_t e_value_size; /* Length of value */
uint32_t e_hash; /* Hash (not supported) */
char e_name[0]; /* Name string (e_name_len bytes) */
};
/*
* Linux kernel checks only the 0, we also check that the current entry
* doesn't overflow past end.
*/
#define EXT2FS_XATTR_IS_LAST_ENTRY(entry, end) \
*((uint32_t *)(entry)) == 0 || EXT2FS_XATTR_NEXT(entry) > end
/*
* Each ext2fs_xattr_entry starts on next 4-byte boundary, pad if necessary.
*/
#define EXT2FS_XATTR_PAD 4
#define EXT2FS_XATTR_ROUND (EXT2FS_XATTR_PAD - 1)
#define EXT2FS_XATTR_LEN(name_len) \
(((name_len) + EXT2FS_XATTR_ROUND + \
sizeof(struct ext2fs_xattr_entry)) & ~EXT2FS_XATTR_ROUND)
#define EXT2FS_XATTR_NEXT(entry) \
(struct ext2fs_xattr_entry *)(((uint8_t *)(entry)) + EXT2FS_XATTR_LEN((entry)->e_name_len))
#define EXT2FS_XATTR_IFIRST(h) (void *)&(h)[1]
#define EXT2FS_XATTR_BFIRST(h) EXT2FS_XATTR_IFIRST(h)
/*
* Name prefixes
*/
#define EXT2FS_XATTR_PREFIX_NONE 0 /* no prefix */
#define EXT2FS_XATTR_PREFIX_USER 1 /* "user." */
#define EXT2FS_XATTR_PREFIX_POSIX_ACCESS 2 /* "system.posix_acl_access" */
#define EXT2FS_XATTR_PREFIX_POSIX_DEFAULT1 3 /* "system.posix_acl_default" */
#define EXT2FS_XATTR_PREFIX_TRUSTED 4 /* "trusted." */
#define EXT2FS_XATTR_PREFIX_SECURITY 6 /* "security." */
#define EXT2FS_XATTR_PREFIX_SYSTEM 7 /* "system." */
#define EXT2FS_XATTR_PREFIX_SYSTEM_RICHACL 8 /* "system.richacl" */
#define EXT2FS_XATTR_PREFIX_ENCRYPTION 9 /* "c" */
int ext2fs_getextattr(void *);
int ext2fs_setextattr(void *);
int ext2fs_listextattr(void *);
int ext2fs_deleteextattr(void *);
#endif /* _KERNEL */
#endif /* _UFS_EXT2FS_EXT2FS_XATTR_H_ */