1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Defines for attribute handling in NTFS Linux kernel driver.
4 *
5 * Copyright (c) 2001-2005 Anton Altaparmakov
6 * Copyright (c) 2002 Richard Russon
7 * Copyright (c) 2025 LG Electronics Co., Ltd.
8 */
9
10 #ifndef _LINUX_NTFS_ATTRIB_H
11 #define _LINUX_NTFS_ATTRIB_H
12
13 #include "ntfs.h"
14 #include "dir.h"
15
16 extern __le16 AT_UNNAMED[];
17
18 /*
19 * ntfs_attr_search_ctx - used in attribute search functions
20 * @mrec: buffer containing mft record to search
21 * @mapped_mrec: true if @mrec was mapped by the search functions
22 * @attr: attribute record in @mrec where to begin/continue search
23 * @is_first: if true ntfs_attr_lookup() begins search with @attr, else after
24 * @ntfs_ino: Inode owning this attribute search
25 * @al_entry: Current attribute list entry
26 * @base_ntfs_ino: Base inode
27 * @mapped_base_mrec: true if @base_mrec was mapped by the search
28 * @base_attr: Base attribute record pointer
29 *
30 * Structure must be initialized to zero before the first call to one of the
31 * attribute search functions. Initialize @mrec to point to the mft record to
32 * search, and @attr to point to the first attribute within @mrec (not necessary
33 * if calling the _first() functions), and set @is_first to 'true' (not necessary
34 * if calling the _first() functions).
35 *
36 * If @is_first is 'true', the search begins with @attr. If @is_first is 'false',
37 * the search begins after @attr. This is so that, after the first call to one
38 * of the search attribute functions, we can call the function again, without
39 * any modification of the search context, to automagically get the next
40 * matching attribute.
41 */
42 struct ntfs_attr_search_ctx {
43 struct mft_record *mrec;
44 bool mapped_mrec;
45 struct attr_record *attr;
46 bool is_first;
47 struct ntfs_inode *ntfs_ino;
48 struct attr_list_entry *al_entry;
49 struct ntfs_inode *base_ntfs_ino;
50 struct mft_record *base_mrec;
51 bool mapped_base_mrec;
52 struct attr_record *base_attr;
53 };
54
55 enum { /* ways of processing holes when expanding */
56 HOLES_NO,
57 HOLES_OK,
58 };
59
60 int ntfs_map_runlist_nolock(struct ntfs_inode *ni, s64 vcn,
61 struct ntfs_attr_search_ctx *ctx);
62 int ntfs_map_runlist(struct ntfs_inode *ni, s64 vcn);
63 s64 ntfs_attr_vcn_to_lcn_nolock(struct ntfs_inode *ni, const s64 vcn,
64 const bool write_locked);
65 struct runlist_element *ntfs_attr_find_vcn_nolock(struct ntfs_inode *ni,
66 const s64 vcn, struct ntfs_attr_search_ctx *ctx);
67 struct runlist_element *__ntfs_attr_find_vcn_nolock(struct runlist *runlist,
68 const s64 vcn);
69 int ntfs_attr_map_whole_runlist(struct ntfs_inode *ni);
70 int ntfs_attr_lookup(const __le32 type, const __le16 *name,
71 const u32 name_len, const u32 ic,
72 const s64 lowest_vcn, const u8 *val, const u32 val_len,
73 struct ntfs_attr_search_ctx *ctx);
74 bool ntfs_attr_list_entry_is_valid(const struct attr_list_entry *ale,
75 const u8 *al_end);
76 bool ntfs_attr_list_is_valid(const u8 *al_start, s64 size);
77
78 int load_attribute_list(struct ntfs_inode *base_ni,
79 u8 *al_start, const s64 size);
80
ntfs_attr_size(const struct attr_record * a)81 static inline s64 ntfs_attr_size(const struct attr_record *a)
82 {
83 if (!a->non_resident)
84 return (s64)le32_to_cpu(a->data.resident.value_length);
85 return le64_to_cpu(a->data.non_resident.data_size);
86 }
87
88 void ntfs_attr_reinit_search_ctx(struct ntfs_attr_search_ctx *ctx);
89 struct ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(struct ntfs_inode *ni,
90 struct mft_record *mrec);
91 void ntfs_attr_put_search_ctx(struct ntfs_attr_search_ctx *ctx);
92 int ntfs_attr_size_bounds_check(const struct ntfs_volume *vol,
93 const __le32 type, const s64 size);
94 int ntfs_attr_can_be_resident(const struct ntfs_volume *vol,
95 const __le32 type);
96 int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
97 s64 *lcn_count, s64 max_clu_count, bool *balloc, bool update_mp, bool skip_holes);
98 int ntfs_attr_record_resize(struct mft_record *m, struct attr_record *a, u32 new_size);
99 int ntfs_resident_attr_value_resize(struct mft_record *m, struct attr_record *a,
100 const u32 new_size);
101 int ntfs_attr_make_non_resident(struct ntfs_inode *ni, const u32 data_size);
102 int ntfs_attr_set(struct ntfs_inode *ni, const s64 ofs, const s64 cnt,
103 const u8 val);
104 int ntfs_attr_set_initialized_size(struct ntfs_inode *ni, loff_t new_size);
105 int ntfs_attr_open(struct ntfs_inode *ni, const __le32 type,
106 __le16 *name, u32 name_len);
107 void ntfs_attr_close(struct ntfs_inode *n);
108 int ntfs_attr_fallocate(struct ntfs_inode *ni, loff_t start, loff_t byte_len, bool keep_size);
109 int ntfs_non_resident_attr_insert_range(struct ntfs_inode *ni, s64 start_vcn, s64 len);
110 int ntfs_non_resident_attr_collapse_range(struct ntfs_inode *ni, s64 start_vcn, s64 len);
111 int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64 len);
112 int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,
113 const s64 i_size);
114 int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloc_size);
115 int ntfs_attr_expand_locked(struct ntfs_inode *ni, const s64 newsize,
116 const s64 prealloc_size,
117 struct ntfs_inode *locked_ni);
118 int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned int holes);
119 int ntfs_attr_truncate_i_locked(struct ntfs_inode *ni, const s64 newsize,
120 unsigned int holes,
121 struct ntfs_inode *locked_ni);
122 int ntfs_attr_truncate(struct ntfs_inode *ni, const s64 newsize);
123 int ntfs_attr_rm(struct ntfs_inode *ni);
124 int ntfs_attr_exist(struct ntfs_inode *ni, const __le32 type, __le16 *name,
125 u32 name_len);
126 int ntfs_attr_remove(struct ntfs_inode *ni, const __le32 type, __le16 *name,
127 u32 name_len);
128 int ntfs_attr_record_rm(struct ntfs_attr_search_ctx *ctx);
129 int ntfs_attr_record_move_to(struct ntfs_attr_search_ctx *ctx, struct ntfs_inode *ni);
130 int ntfs_attr_add(struct ntfs_inode *ni, __le32 type,
131 __le16 *name, u8 name_len, u8 *val, s64 size);
132 int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra);
133 char *ntfs_attr_name_get(const struct ntfs_volume *vol, const __le16 *uname,
134 const int uname_len);
135 void ntfs_attr_name_free(unsigned char **name);
136 void *ntfs_attr_readall(struct ntfs_inode *ni, const __le32 type,
137 __le16 *name, u32 name_len, s64 *data_size);
138 int ntfs_resident_attr_record_add(struct ntfs_inode *ni, __le32 type,
139 __le16 *name, u8 name_len, u8 *val, u32 size,
140 __le16 flags);
141 int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn);
142 int ntfs_attr_update_mapping_pairs_locked(struct ntfs_inode *ni,
143 s64 from_vcn,
144 struct ntfs_inode *locked_ni);
145 struct runlist_element *ntfs_attr_vcn_to_rl(struct ntfs_inode *ni, s64 vcn, s64 *lcn);
146
147 /*
148 * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
149 * @ctx: initialised attribute search context
150 *
151 * Syntactic sugar for walking attributes in an inode.
152 *
153 * Return 0 on success and -1 on error with errno set to the error code from
154 * ntfs_attr_lookup().
155 *
156 * Example: When you want to enumerate all attributes in an open ntfs inode
157 * @ni, you can simply do:
158 *
159 * int err;
160 * struct ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL);
161 * if (!ctx)
162 * // Error code is in errno. Handle this case.
163 * while (!(err = ntfs_attrs_walk(ctx))) {
164 * struct attr_record *attr = ctx->attr;
165 * // attr now contains the next attribute. Do whatever you want
166 * // with it and then just continue with the while loop.
167 * }
168 * if (err && errno != ENOENT)
169 * // Ooops. An error occurred! You should handle this case.
170 * // Now finished with all attributes in the inode.
171 */
ntfs_attrs_walk(struct ntfs_attr_search_ctx * ctx)172 static inline int ntfs_attrs_walk(struct ntfs_attr_search_ctx *ctx)
173 {
174 return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
175 NULL, 0, ctx);
176 }
177 #endif /* _LINUX_NTFS_ATTRIB_H */
178