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