summaryrefslogtreecommitdiff
path: root/fs/ntfs/attrib.h
blob: f7acc7986b090d58bb6aec84bf6c751bf378e6a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Defines for attribute handling in NTFS Linux kernel driver.
 *
 * Copyright (c) 2001-2005 Anton Altaparmakov
 * Copyright (c) 2002 Richard Russon
 * Copyright (c) 2025 LG Electronics Co., Ltd.
 */

#ifndef _LINUX_NTFS_ATTRIB_H
#define _LINUX_NTFS_ATTRIB_H

#include "ntfs.h"
#include "dir.h"

extern __le16 AT_UNNAMED[];

/*
 * ntfs_attr_search_ctx - used in attribute search functions
 * @mrec: buffer containing mft record to search
 * @mapped_mrec: true if @mrec was mapped by the search functions
 * @attr: attribute record in @mrec where to begin/continue search
 * @is_first: if true ntfs_attr_lookup() begins search with @attr, else after
 * @ntfs_ino: Inode owning this attribute search
 * @al_entry: Current attribute list entry
 * @base_ntfs_ino: Base inode
 * @mapped_base_mrec: true if @base_mrec was mapped by the search
 * @base_attr: Base attribute record pointer
 *
 * Structure must be initialized to zero before the first call to one of the
 * attribute search functions. Initialize @mrec to point to the mft record to
 * search, and @attr to point to the first attribute within @mrec (not necessary
 * if calling the _first() functions), and set @is_first to 'true' (not necessary
 * if calling the _first() functions).
 *
 * If @is_first is 'true', the search begins with @attr. If @is_first is 'false',
 * the search begins after @attr. This is so that, after the first call to one
 * of the search attribute functions, we can call the function again, without
 * any modification of the search context, to automagically get the next
 * matching attribute.
 */
struct ntfs_attr_search_ctx {
	struct mft_record *mrec;
	bool mapped_mrec;
	struct attr_record *attr;
	bool is_first;
	struct ntfs_inode *ntfs_ino;
	struct attr_list_entry *al_entry;
	struct ntfs_inode *base_ntfs_ino;
	struct mft_record *base_mrec;
	bool mapped_base_mrec;
	struct attr_record *base_attr;
};

enum {                  /* ways of processing holes when expanding */
	HOLES_NO,
	HOLES_OK,
};

int ntfs_map_runlist_nolock(struct ntfs_inode *ni, s64 vcn,
		struct ntfs_attr_search_ctx *ctx);
int ntfs_map_runlist(struct ntfs_inode *ni, s64 vcn);
s64 ntfs_attr_vcn_to_lcn_nolock(struct ntfs_inode *ni, const s64 vcn,
		const bool write_locked);
struct runlist_element *ntfs_attr_find_vcn_nolock(struct ntfs_inode *ni,
		const s64 vcn, struct ntfs_attr_search_ctx *ctx);
struct runlist_element *__ntfs_attr_find_vcn_nolock(struct runlist *runlist,
		const s64 vcn);
int ntfs_attr_map_whole_runlist(struct ntfs_inode *ni);
int ntfs_attr_lookup(const __le32 type, const __le16 *name,
		const u32 name_len, const u32 ic,
		const s64 lowest_vcn, const u8 *val, const u32 val_len,
		struct ntfs_attr_search_ctx *ctx);
int load_attribute_list(struct ntfs_inode *base_ni,
			       u8 *al_start, const s64 size);

static inline s64 ntfs_attr_size(const struct attr_record *a)
{
	if (!a->non_resident)
		return (s64)le32_to_cpu(a->data.resident.value_length);
	return le64_to_cpu(a->data.non_resident.data_size);
}

void ntfs_attr_reinit_search_ctx(struct ntfs_attr_search_ctx *ctx);
struct ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(struct ntfs_inode *ni,
		struct mft_record *mrec);
void ntfs_attr_put_search_ctx(struct ntfs_attr_search_ctx *ctx);
int ntfs_attr_size_bounds_check(const struct ntfs_volume *vol,
		const __le32 type, const s64 size);
int ntfs_attr_can_be_resident(const struct ntfs_volume *vol,
		const __le32 type);
int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
		s64 *lcn_count, s64 max_clu_count, bool *balloc, bool update_mp, bool skip_holes);
int ntfs_attr_record_resize(struct mft_record *m, struct attr_record *a, u32 new_size);
int ntfs_resident_attr_value_resize(struct mft_record *m, struct attr_record *a,
		const u32 new_size);
int ntfs_attr_make_non_resident(struct ntfs_inode *ni, const u32 data_size);
int ntfs_attr_set(struct ntfs_inode *ni, const s64 ofs, const s64 cnt,
		const u8 val);
int ntfs_attr_set_initialized_size(struct ntfs_inode *ni, loff_t new_size);
int ntfs_attr_open(struct ntfs_inode *ni, const __le32 type,
		__le16 *name, u32 name_len);
void ntfs_attr_close(struct ntfs_inode *n);
int ntfs_attr_fallocate(struct ntfs_inode *ni, loff_t start, loff_t byte_len, bool keep_size);
int ntfs_non_resident_attr_insert_range(struct ntfs_inode *ni, s64 start_vcn, s64 len);
int ntfs_non_resident_attr_collapse_range(struct ntfs_inode *ni, s64 start_vcn, s64 len);
int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64 len);
int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,
		const s64 i_size);
int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloc_size);
int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned int holes);
int ntfs_attr_truncate(struct ntfs_inode *ni, const s64 newsize);
int ntfs_attr_rm(struct ntfs_inode *ni);
int ntfs_attr_exist(struct ntfs_inode *ni, const __le32 type, __le16 *name,
		u32 name_len);
int ntfs_attr_remove(struct ntfs_inode *ni, const __le32 type, __le16 *name,
		u32 name_len);
int ntfs_attr_record_rm(struct ntfs_attr_search_ctx *ctx);
int ntfs_attr_record_move_to(struct ntfs_attr_search_ctx *ctx, struct ntfs_inode *ni);
int ntfs_attr_add(struct ntfs_inode *ni, __le32 type,
		__le16 *name, u8 name_len, u8 *val, s64 size);
int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra);
char *ntfs_attr_name_get(const struct ntfs_volume *vol, const __le16 *uname,
		const int uname_len);
void ntfs_attr_name_free(unsigned char **name);
void *ntfs_attr_readall(struct ntfs_inode *ni, const __le32 type,
		__le16 *name, u32 name_len, s64 *data_size);
int ntfs_resident_attr_record_add(struct ntfs_inode *ni, __le32 type,
		__le16 *name, u8 name_len, u8 *val, u32 size,
		__le16 flags);
int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn);
struct runlist_element *ntfs_attr_vcn_to_rl(struct ntfs_inode *ni, s64 vcn, s64 *lcn);

/*
 * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
 * @ctx:	initialised attribute search context
 *
 * Syntactic sugar for walking attributes in an inode.
 *
 * Return 0 on success and -1 on error with errno set to the error code from
 * ntfs_attr_lookup().
 *
 * Example: When you want to enumerate all attributes in an open ntfs inode
 *	    @ni, you can simply do:
 *
 *	int err;
 *	struct ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL);
 *	if (!ctx)
 *		// Error code is in errno. Handle this case.
 *	while (!(err = ntfs_attrs_walk(ctx))) {
 *		struct attr_record *attr = ctx->attr;
 *		// attr now contains the next attribute. Do whatever you want
 *		// with it and then just continue with the while loop.
 *	}
 *	if (err && errno != ENOENT)
 *		// Ooops. An error occurred! You should handle this case.
 *	// Now finished with all attributes in the inode.
 */
static inline int ntfs_attrs_walk(struct ntfs_attr_search_ctx *ctx)
{
	return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
			NULL, 0, ctx);
}
#endif /* _LINUX_NTFS_ATTRIB_H */