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