diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 13:08:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 13:08:45 -0400 |
commit | ba5a2655c270f59dea2d9b4d764aec2f6e7f5f41 (patch) | |
tree | 72b60e6899dfd156b2e9033818f894381da9355c /fs/jfs | |
parent | 8908c94d6cd7513ba4512295abc945a6ff7f979c (diff) | |
parent | e0d46f5c6e0ba3a79e64cd60e62b7b7191ed93f3 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull remaining vfs xattr work from Al Viro:
"The rest of work.xattr (non-cifs conversions)"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
btrfs: Switch to generic xattr handlers
ubifs: Switch to generic xattr handlers
jfs: Switch to generic xattr handlers
jfs: Clean up xattr name mapping
gfs2: Switch to generic xattr handlers
ceph: kill __ceph_removexattr()
ceph: Switch to generic xattr handlers
ceph: Get rid of d_find_alias in ceph_set_acl
Diffstat (limited to 'fs/jfs')
-rw-r--r-- | fs/jfs/file.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_xattr.h | 6 | ||||
-rw-r--r-- | fs/jfs/namei.c | 6 | ||||
-rw-r--r-- | fs/jfs/symlink.c | 12 | ||||
-rw-r--r-- | fs/jfs/xattr.c | 224 |
5 files changed, 96 insertions, 158 deletions
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 4ce7735dd042..7f1a585a0a94 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
@@ -140,10 +140,10 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | const struct inode_operations jfs_file_inode_operations = { | 142 | const struct inode_operations jfs_file_inode_operations = { |
143 | .setxattr = jfs_setxattr, | 143 | .setxattr = generic_setxattr, |
144 | .getxattr = jfs_getxattr, | 144 | .getxattr = generic_getxattr, |
145 | .listxattr = jfs_listxattr, | 145 | .listxattr = jfs_listxattr, |
146 | .removexattr = jfs_removexattr, | 146 | .removexattr = generic_removexattr, |
147 | .setattr = jfs_setattr, | 147 | .setattr = jfs_setattr, |
148 | #ifdef CONFIG_JFS_POSIX_ACL | 148 | #ifdef CONFIG_JFS_POSIX_ACL |
149 | .get_acl = jfs_get_acl, | 149 | .get_acl = jfs_get_acl, |
diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h index e69e14f3777b..561f6af46288 100644 --- a/fs/jfs/jfs_xattr.h +++ b/fs/jfs/jfs_xattr.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #ifndef H_JFS_XATTR | 19 | #ifndef H_JFS_XATTR |
20 | #define H_JFS_XATTR | 20 | #define H_JFS_XATTR |
21 | 21 | ||
22 | #include <linux/xattr.h> | ||
23 | |||
22 | /* | 24 | /* |
23 | * jfs_ea_list describe the on-disk format of the extended attributes. | 25 | * jfs_ea_list describe the on-disk format of the extended attributes. |
24 | * I know the null-terminator is redundant since namelen is stored, but | 26 | * I know the null-terminator is redundant since namelen is stored, but |
@@ -54,12 +56,8 @@ struct jfs_ea_list { | |||
54 | 56 | ||
55 | extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *, | 57 | extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *, |
56 | size_t, int); | 58 | size_t, int); |
57 | extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, | ||
58 | int); | ||
59 | extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); | 59 | extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); |
60 | extern ssize_t jfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); | ||
61 | extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); | 60 | extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); |
62 | extern int jfs_removexattr(struct dentry *, const char *); | ||
63 | 61 | ||
64 | extern const struct xattr_handler *jfs_xattr_handlers[]; | 62 | extern const struct xattr_handler *jfs_xattr_handlers[]; |
65 | 63 | ||
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index ff671edcf4f0..539deddecbb0 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -1537,10 +1537,10 @@ const struct inode_operations jfs_dir_inode_operations = { | |||
1537 | .rmdir = jfs_rmdir, | 1537 | .rmdir = jfs_rmdir, |
1538 | .mknod = jfs_mknod, | 1538 | .mknod = jfs_mknod, |
1539 | .rename = jfs_rename, | 1539 | .rename = jfs_rename, |
1540 | .setxattr = jfs_setxattr, | 1540 | .setxattr = generic_setxattr, |
1541 | .getxattr = jfs_getxattr, | 1541 | .getxattr = generic_getxattr, |
1542 | .listxattr = jfs_listxattr, | 1542 | .listxattr = jfs_listxattr, |
1543 | .removexattr = jfs_removexattr, | 1543 | .removexattr = generic_removexattr, |
1544 | .setattr = jfs_setattr, | 1544 | .setattr = jfs_setattr, |
1545 | #ifdef CONFIG_JFS_POSIX_ACL | 1545 | #ifdef CONFIG_JFS_POSIX_ACL |
1546 | .get_acl = jfs_get_acl, | 1546 | .get_acl = jfs_get_acl, |
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index f8db4fde0b0b..c94c7e4a1323 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c | |||
@@ -25,19 +25,19 @@ const struct inode_operations jfs_fast_symlink_inode_operations = { | |||
25 | .readlink = generic_readlink, | 25 | .readlink = generic_readlink, |
26 | .get_link = simple_get_link, | 26 | .get_link = simple_get_link, |
27 | .setattr = jfs_setattr, | 27 | .setattr = jfs_setattr, |
28 | .setxattr = jfs_setxattr, | 28 | .setxattr = generic_setxattr, |
29 | .getxattr = jfs_getxattr, | 29 | .getxattr = generic_getxattr, |
30 | .listxattr = jfs_listxattr, | 30 | .listxattr = jfs_listxattr, |
31 | .removexattr = jfs_removexattr, | 31 | .removexattr = generic_removexattr, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | const struct inode_operations jfs_symlink_inode_operations = { | 34 | const struct inode_operations jfs_symlink_inode_operations = { |
35 | .readlink = generic_readlink, | 35 | .readlink = generic_readlink, |
36 | .get_link = page_get_link, | 36 | .get_link = page_get_link, |
37 | .setattr = jfs_setattr, | 37 | .setattr = jfs_setattr, |
38 | .setxattr = jfs_setxattr, | 38 | .setxattr = generic_setxattr, |
39 | .getxattr = jfs_getxattr, | 39 | .getxattr = generic_getxattr, |
40 | .listxattr = jfs_listxattr, | 40 | .listxattr = jfs_listxattr, |
41 | .removexattr = jfs_removexattr, | 41 | .removexattr = generic_removexattr, |
42 | }; | 42 | }; |
43 | 43 | ||
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 5becc6a3ff8c..beb182b503b3 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c | |||
@@ -86,6 +86,14 @@ struct ea_buffer { | |||
86 | #define EA_MALLOC 0x0008 | 86 | #define EA_MALLOC 0x0008 |
87 | 87 | ||
88 | 88 | ||
89 | /* | ||
90 | * Mapping of on-disk attribute names: for on-disk attribute names with an | ||
91 | * unknown prefix (not "system.", "user.", "security.", or "trusted."), the | ||
92 | * prefix "os2." is prepended. On the way back to disk, "os2." prefixes are | ||
93 | * stripped and we make sure that the remaining name does not start with one | ||
94 | * of the know prefixes. | ||
95 | */ | ||
96 | |||
89 | static int is_known_namespace(const char *name) | 97 | static int is_known_namespace(const char *name) |
90 | { | 98 | { |
91 | if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) && | 99 | if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) && |
@@ -97,29 +105,19 @@ static int is_known_namespace(const char *name) | |||
97 | return true; | 105 | return true; |
98 | } | 106 | } |
99 | 107 | ||
100 | /* | ||
101 | * These three routines are used to recognize on-disk extended attributes | ||
102 | * that are in a recognized namespace. If the attribute is not recognized, | ||
103 | * "os2." is prepended to the name | ||
104 | */ | ||
105 | static int is_os2_xattr(struct jfs_ea *ea) | ||
106 | { | ||
107 | return !is_known_namespace(ea->name); | ||
108 | } | ||
109 | |||
110 | static inline int name_size(struct jfs_ea *ea) | 108 | static inline int name_size(struct jfs_ea *ea) |
111 | { | 109 | { |
112 | if (is_os2_xattr(ea)) | 110 | if (is_known_namespace(ea->name)) |
113 | return ea->namelen + XATTR_OS2_PREFIX_LEN; | ||
114 | else | ||
115 | return ea->namelen; | 111 | return ea->namelen; |
112 | else | ||
113 | return ea->namelen + XATTR_OS2_PREFIX_LEN; | ||
116 | } | 114 | } |
117 | 115 | ||
118 | static inline int copy_name(char *buffer, struct jfs_ea *ea) | 116 | static inline int copy_name(char *buffer, struct jfs_ea *ea) |
119 | { | 117 | { |
120 | int len = ea->namelen; | 118 | int len = ea->namelen; |
121 | 119 | ||
122 | if (is_os2_xattr(ea)) { | 120 | if (!is_known_namespace(ea->name)) { |
123 | memcpy(buffer, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN); | 121 | memcpy(buffer, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN); |
124 | buffer += XATTR_OS2_PREFIX_LEN; | 122 | buffer += XATTR_OS2_PREFIX_LEN; |
125 | len += XATTR_OS2_PREFIX_LEN; | 123 | len += XATTR_OS2_PREFIX_LEN; |
@@ -665,35 +663,6 @@ static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf, | |||
665 | return 0; | 663 | return 0; |
666 | } | 664 | } |
667 | 665 | ||
668 | /* | ||
669 | * Most of the permission checking is done by xattr_permission in the vfs. | ||
670 | * We also need to verify that this is a namespace that we recognize. | ||
671 | */ | ||
672 | static int can_set_xattr(struct inode *inode, const char *name, | ||
673 | const void *value, size_t value_len) | ||
674 | { | ||
675 | if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) { | ||
676 | /* | ||
677 | * This makes sure that we aren't trying to set an | ||
678 | * attribute in a different namespace by prefixing it | ||
679 | * with "os2." | ||
680 | */ | ||
681 | if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN)) | ||
682 | return -EOPNOTSUPP; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | /* | ||
687 | * Don't allow setting an attribute in an unknown namespace. | ||
688 | */ | ||
689 | if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) && | ||
690 | strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) && | ||
691 | strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) | ||
692 | return -EOPNOTSUPP; | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, | 666 | int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, |
698 | const void *value, size_t value_len, int flags) | 667 | const void *value, size_t value_len, int flags) |
699 | { | 668 | { |
@@ -704,21 +673,10 @@ int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, | |||
704 | int xattr_size; | 673 | int xattr_size; |
705 | int new_size; | 674 | int new_size; |
706 | int namelen = strlen(name); | 675 | int namelen = strlen(name); |
707 | char *os2name = NULL; | ||
708 | int found = 0; | 676 | int found = 0; |
709 | int rc; | 677 | int rc; |
710 | int length; | 678 | int length; |
711 | 679 | ||
712 | if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { | ||
713 | os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, | ||
714 | GFP_KERNEL); | ||
715 | if (!os2name) | ||
716 | return -ENOMEM; | ||
717 | strcpy(os2name, name + XATTR_OS2_PREFIX_LEN); | ||
718 | name = os2name; | ||
719 | namelen -= XATTR_OS2_PREFIX_LEN; | ||
720 | } | ||
721 | |||
722 | down_write(&JFS_IP(inode)->xattr_sem); | 680 | down_write(&JFS_IP(inode)->xattr_sem); |
723 | 681 | ||
724 | xattr_size = ea_get(inode, &ea_buf, 0); | 682 | xattr_size = ea_get(inode, &ea_buf, 0); |
@@ -841,44 +799,6 @@ int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, | |||
841 | out: | 799 | out: |
842 | up_write(&JFS_IP(inode)->xattr_sem); | 800 | up_write(&JFS_IP(inode)->xattr_sem); |
843 | 801 | ||
844 | kfree(os2name); | ||
845 | |||
846 | return rc; | ||
847 | } | ||
848 | |||
849 | int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, | ||
850 | size_t value_len, int flags) | ||
851 | { | ||
852 | struct inode *inode = d_inode(dentry); | ||
853 | struct jfs_inode_info *ji = JFS_IP(inode); | ||
854 | int rc; | ||
855 | tid_t tid; | ||
856 | |||
857 | /* | ||
858 | * If this is a request for a synthetic attribute in the system.* | ||
859 | * namespace use the generic infrastructure to resolve a handler | ||
860 | * for it via sb->s_xattr. | ||
861 | */ | ||
862 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
863 | return generic_setxattr(dentry, name, value, value_len, flags); | ||
864 | |||
865 | if ((rc = can_set_xattr(inode, name, value, value_len))) | ||
866 | return rc; | ||
867 | |||
868 | if (value == NULL) { /* empty EA, do not remove */ | ||
869 | value = ""; | ||
870 | value_len = 0; | ||
871 | } | ||
872 | |||
873 | tid = txBegin(inode->i_sb, 0); | ||
874 | mutex_lock(&ji->commit_mutex); | ||
875 | rc = __jfs_setxattr(tid, d_inode(dentry), name, value, value_len, | ||
876 | flags); | ||
877 | if (!rc) | ||
878 | rc = txCommit(tid, 1, &inode, 0); | ||
879 | txEnd(tid); | ||
880 | mutex_unlock(&ji->commit_mutex); | ||
881 | |||
882 | return rc; | 802 | return rc; |
883 | } | 803 | } |
884 | 804 | ||
@@ -933,37 +853,6 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, | |||
933 | return size; | 853 | return size; |
934 | } | 854 | } |
935 | 855 | ||
936 | ssize_t jfs_getxattr(struct dentry *dentry, struct inode *inode, | ||
937 | const char *name, void *data, size_t buf_size) | ||
938 | { | ||
939 | int err; | ||
940 | |||
941 | /* | ||
942 | * If this is a request for a synthetic attribute in the system.* | ||
943 | * namespace use the generic infrastructure to resolve a handler | ||
944 | * for it via sb->s_xattr. | ||
945 | */ | ||
946 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
947 | return generic_getxattr(dentry, inode, name, data, buf_size); | ||
948 | |||
949 | if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { | ||
950 | /* | ||
951 | * skip past "os2." prefix | ||
952 | */ | ||
953 | name += XATTR_OS2_PREFIX_LEN; | ||
954 | /* | ||
955 | * Don't allow retrieving properly prefixed attributes | ||
956 | * by prepending them with "os2." | ||
957 | */ | ||
958 | if (is_known_namespace(name)) | ||
959 | return -EOPNOTSUPP; | ||
960 | } | ||
961 | |||
962 | err = __jfs_getxattr(inode, name, data, buf_size); | ||
963 | |||
964 | return err; | ||
965 | } | ||
966 | |||
967 | /* | 856 | /* |
968 | * No special permissions are needed to list attributes except for trusted.* | 857 | * No special permissions are needed to list attributes except for trusted.* |
969 | */ | 858 | */ |
@@ -1027,27 +916,16 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) | |||
1027 | return size; | 916 | return size; |
1028 | } | 917 | } |
1029 | 918 | ||
1030 | int jfs_removexattr(struct dentry *dentry, const char *name) | 919 | static int __jfs_xattr_set(struct inode *inode, const char *name, |
920 | const void *value, size_t size, int flags) | ||
1031 | { | 921 | { |
1032 | struct inode *inode = d_inode(dentry); | ||
1033 | struct jfs_inode_info *ji = JFS_IP(inode); | 922 | struct jfs_inode_info *ji = JFS_IP(inode); |
1034 | int rc; | ||
1035 | tid_t tid; | 923 | tid_t tid; |
1036 | 924 | int rc; | |
1037 | /* | ||
1038 | * If this is a request for a synthetic attribute in the system.* | ||
1039 | * namespace use the generic infrastructure to resolve a handler | ||
1040 | * for it via sb->s_xattr. | ||
1041 | */ | ||
1042 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
1043 | return generic_removexattr(dentry, name); | ||
1044 | |||
1045 | if ((rc = can_set_xattr(inode, name, NULL, 0))) | ||
1046 | return rc; | ||
1047 | 925 | ||
1048 | tid = txBegin(inode->i_sb, 0); | 926 | tid = txBegin(inode->i_sb, 0); |
1049 | mutex_lock(&ji->commit_mutex); | 927 | mutex_lock(&ji->commit_mutex); |
1050 | rc = __jfs_setxattr(tid, d_inode(dentry), name, NULL, 0, XATTR_REPLACE); | 928 | rc = __jfs_setxattr(tid, inode, name, value, size, flags); |
1051 | if (!rc) | 929 | if (!rc) |
1052 | rc = txCommit(tid, 1, &inode, 0); | 930 | rc = txCommit(tid, 1, &inode, 0); |
1053 | txEnd(tid); | 931 | txEnd(tid); |
@@ -1056,15 +934,77 @@ int jfs_removexattr(struct dentry *dentry, const char *name) | |||
1056 | return rc; | 934 | return rc; |
1057 | } | 935 | } |
1058 | 936 | ||
1059 | /* | 937 | static int jfs_xattr_get(const struct xattr_handler *handler, |
1060 | * List of handlers for synthetic system.* attributes. All real ondisk | 938 | struct dentry *unused, struct inode *inode, |
1061 | * attributes are handled directly. | 939 | const char *name, void *value, size_t size) |
1062 | */ | 940 | { |
941 | name = xattr_full_name(handler, name); | ||
942 | return __jfs_getxattr(inode, name, value, size); | ||
943 | } | ||
944 | |||
945 | static int jfs_xattr_set(const struct xattr_handler *handler, | ||
946 | struct dentry *dentry, const char *name, | ||
947 | const void *value, size_t size, int flags) | ||
948 | { | ||
949 | struct inode *inode = d_inode(dentry); | ||
950 | |||
951 | name = xattr_full_name(handler, name); | ||
952 | return __jfs_xattr_set(inode, name, value, size, flags); | ||
953 | } | ||
954 | |||
955 | static int jfs_xattr_get_os2(const struct xattr_handler *handler, | ||
956 | struct dentry *unused, struct inode *inode, | ||
957 | const char *name, void *value, size_t size) | ||
958 | { | ||
959 | if (is_known_namespace(name)) | ||
960 | return -EOPNOTSUPP; | ||
961 | return __jfs_getxattr(inode, name, value, size); | ||
962 | } | ||
963 | |||
964 | static int jfs_xattr_set_os2(const struct xattr_handler *handler, | ||
965 | struct dentry *dentry, const char *name, | ||
966 | const void *value, size_t size, int flags) | ||
967 | { | ||
968 | struct inode *inode = d_inode(dentry); | ||
969 | |||
970 | if (is_known_namespace(name)) | ||
971 | return -EOPNOTSUPP; | ||
972 | return __jfs_xattr_set(inode, name, value, size, flags); | ||
973 | } | ||
974 | |||
975 | static const struct xattr_handler jfs_user_xattr_handler = { | ||
976 | .prefix = XATTR_USER_PREFIX, | ||
977 | .get = jfs_xattr_get, | ||
978 | .set = jfs_xattr_set, | ||
979 | }; | ||
980 | |||
981 | static const struct xattr_handler jfs_os2_xattr_handler = { | ||
982 | .prefix = XATTR_OS2_PREFIX, | ||
983 | .get = jfs_xattr_get_os2, | ||
984 | .set = jfs_xattr_set_os2, | ||
985 | }; | ||
986 | |||
987 | static const struct xattr_handler jfs_security_xattr_handler = { | ||
988 | .prefix = XATTR_SECURITY_PREFIX, | ||
989 | .get = jfs_xattr_get, | ||
990 | .set = jfs_xattr_set, | ||
991 | }; | ||
992 | |||
993 | static const struct xattr_handler jfs_trusted_xattr_handler = { | ||
994 | .prefix = XATTR_TRUSTED_PREFIX, | ||
995 | .get = jfs_xattr_get, | ||
996 | .set = jfs_xattr_set, | ||
997 | }; | ||
998 | |||
1063 | const struct xattr_handler *jfs_xattr_handlers[] = { | 999 | const struct xattr_handler *jfs_xattr_handlers[] = { |
1064 | #ifdef CONFIG_JFS_POSIX_ACL | 1000 | #ifdef CONFIG_JFS_POSIX_ACL |
1065 | &posix_acl_access_xattr_handler, | 1001 | &posix_acl_access_xattr_handler, |
1066 | &posix_acl_default_xattr_handler, | 1002 | &posix_acl_default_xattr_handler, |
1067 | #endif | 1003 | #endif |
1004 | &jfs_os2_xattr_handler, | ||
1005 | &jfs_user_xattr_handler, | ||
1006 | &jfs_security_xattr_handler, | ||
1007 | &jfs_trusted_xattr_handler, | ||
1068 | NULL, | 1008 | NULL, |
1069 | }; | 1009 | }; |
1070 | 1010 | ||