blob: bcdb011716707440fc7d42d3215491c2976438c3
1 | /* |
2 | * attrib.h - Exports for attribute handling. Originated from the Linux-NTFS project. |
3 | * |
4 | * Copyright (c) 2000-2004 Anton Altaparmakov |
5 | * Copyright (c) 2004-2005 Yura Pakhuchiy |
6 | * Copyright (c) 2006-2007 Szabolcs Szakacsits |
7 | * |
8 | * This program/include file is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as published |
10 | * by the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * This program/include file is distributed in the hope that it will be |
14 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program (in the main directory of the NTFS-3G |
20 | * distribution in the file COPYING); if not, write to the Free Software |
21 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
22 | */ |
23 | |
24 | #ifndef _NTFS_ATTRIB_H |
25 | #define _NTFS_ATTRIB_H |
26 | |
27 | /* Forward declarations */ |
28 | typedef struct _ntfs_attr ntfs_attr; |
29 | typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx; |
30 | |
31 | #include "types.h" |
32 | #include "inode.h" |
33 | #include "unistr.h" |
34 | #include "runlist.h" |
35 | #include "volume.h" |
36 | #include "debug.h" |
37 | #include "logging.h" |
38 | |
39 | extern ntfschar AT_UNNAMED[]; |
40 | extern ntfschar STREAM_SDS[]; |
41 | |
42 | /* The little endian Unicode string $TXF_DATA as a global constant. */ |
43 | extern ntfschar TXF_DATA[10]; |
44 | |
45 | /** |
46 | * enum ntfs_lcn_special_values - special return values for ntfs_*_vcn_to_lcn() |
47 | * |
48 | * Special return values for ntfs_rl_vcn_to_lcn() and ntfs_attr_vcn_to_lcn(). |
49 | * |
50 | * TODO: Describe them. |
51 | */ |
52 | typedef enum { |
53 | LCN_HOLE = -1, /* Keep this as highest value or die! */ |
54 | LCN_RL_NOT_MAPPED = -2, |
55 | LCN_ENOENT = -3, |
56 | LCN_EINVAL = -4, |
57 | LCN_EIO = -5, |
58 | } ntfs_lcn_special_values; |
59 | |
60 | /** |
61 | * struct ntfs_attr_search_ctx - search context used in attribute search functions |
62 | * @mrec: buffer containing mft record to search |
63 | * @attr: attribute record in @mrec where to begin/continue search |
64 | * @is_first: if true lookup_attr() begins search with @attr, else after @attr |
65 | * |
66 | * Structure must be initialized to zero before the first call to one of the |
67 | * attribute search functions. Initialize @mrec to point to the mft record to |
68 | * search, and @attr to point to the first attribute within @mrec (not necessary |
69 | * if calling the _first() functions), and set @is_first to TRUE (not necessary |
70 | * if calling the _first() functions). |
71 | * |
72 | * If @is_first is TRUE, the search begins with @attr. If @is_first is FALSE, |
73 | * the search begins after @attr. This is so that, after the first call to one |
74 | * of the search attribute functions, we can call the function again, without |
75 | * any modification of the search context, to automagically get the next |
76 | * matching attribute. |
77 | */ |
78 | struct _ntfs_attr_search_ctx { |
79 | MFT_RECORD *mrec; |
80 | ATTR_RECORD *attr; |
81 | BOOL is_first; |
82 | ntfs_inode *ntfs_ino; |
83 | ATTR_LIST_ENTRY *al_entry; |
84 | ntfs_inode *base_ntfs_ino; |
85 | MFT_RECORD *base_mrec; |
86 | ATTR_RECORD *base_attr; |
87 | }; |
88 | |
89 | extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx); |
90 | extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, |
91 | MFT_RECORD *mrec); |
92 | extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx); |
93 | |
94 | extern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name, |
95 | const u32 name_len, const IGNORE_CASE_BOOL ic, |
96 | const VCN lowest_vcn, const u8 *val, const u32 val_len, |
97 | ntfs_attr_search_ctx *ctx); |
98 | |
99 | extern int ntfs_attr_position(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx); |
100 | |
101 | extern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol, |
102 | const ATTR_TYPES type); |
103 | |
104 | /** |
105 | * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode |
106 | * @ctx: initialised attribute search context |
107 | * |
108 | * Syntactic sugar for walking attributes in an inode. |
109 | * |
110 | * Return 0 on success and -1 on error with errno set to the error code from |
111 | * ntfs_attr_lookup(). |
112 | * |
113 | * Example: When you want to enumerate all attributes in an open ntfs inode |
114 | * @ni, you can simply do: |
115 | * |
116 | * int err; |
117 | * ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL); |
118 | * if (!ctx) |
119 | * // Error code is in errno. Handle this case. |
120 | * while (!(err = ntfs_attrs_walk(ctx))) { |
121 | * ATTR_RECORD *attr = ctx->attr; |
122 | * // attr now contains the next attribute. Do whatever you want |
123 | * // with it and then just continue with the while loop. |
124 | * } |
125 | * if (err && errno != ENOENT) |
126 | * // Ooops. An error occurred! You should handle this case. |
127 | * // Now finished with all attributes in the inode. |
128 | */ |
129 | static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx) |
130 | { |
131 | return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0, |
132 | NULL, 0, ctx); |
133 | } |
134 | |
135 | /** |
136 | * struct ntfs_attr - ntfs in memory non-resident attribute structure |
137 | * @rl: if not NULL, the decompressed runlist |
138 | * @ni: base ntfs inode to which this attribute belongs |
139 | * @type: attribute type |
140 | * @name: Unicode name of the attribute |
141 | * @name_len: length of @name in Unicode characters |
142 | * @state: NTFS attribute specific flags describing this attribute |
143 | * @allocated_size: copy from the attribute record |
144 | * @data_size: copy from the attribute record |
145 | * @initialized_size: copy from the attribute record |
146 | * @compressed_size: copy from the attribute record |
147 | * @compression_block_size: size of a compression block (cb) |
148 | * @compression_block_size_bits: log2 of the size of a cb |
149 | * @compression_block_clusters: number of clusters per cb |
150 | * |
151 | * This structure exists purely to provide a mechanism of caching the runlist |
152 | * of an attribute. If you want to operate on a particular attribute extent, |
153 | * you should not be using this structure at all. If you want to work with a |
154 | * resident attribute, you should not be using this structure at all. As a |
155 | * fail-safe check make sure to test NAttrNonResident() and if it is false, you |
156 | * know you shouldn't be using this structure. |
157 | * |
158 | * If you want to work on a resident attribute or on a specific attribute |
159 | * extent, you should use ntfs_lookup_attr() to retrieve the attribute (extent) |
160 | * record, edit that, and then write back the mft record (or set the |
161 | * corresponding ntfs inode dirty for delayed write back). |
162 | * |
163 | * @rl is the decompressed runlist of the attribute described by this |
164 | * structure. Obviously this only makes sense if the attribute is not resident, |
165 | * i.e. NAttrNonResident() is true. If the runlist hasn't been decompressed yet |
166 | * @rl is NULL, so be prepared to cope with @rl == NULL. |
167 | * |
168 | * @ni is the base ntfs inode of the attribute described by this structure. |
169 | * |
170 | * @type is the attribute type (see layout.h for the definition of ATTR_TYPES), |
171 | * @name and @name_len are the little endian Unicode name and the name length |
172 | * in Unicode characters of the attribute, respectively. |
173 | * |
174 | * @state contains NTFS attribute specific flags describing this attribute |
175 | * structure. See ntfs_attr_state_bits above. |
176 | */ |
177 | struct _ntfs_attr { |
178 | runlist_element *rl; |
179 | ntfs_inode *ni; |
180 | ATTR_TYPES type; |
181 | ATTR_FLAGS data_flags; |
182 | ntfschar *name; |
183 | u32 name_len; |
184 | unsigned long state; |
185 | s64 allocated_size; |
186 | s64 data_size; |
187 | s64 initialized_size; |
188 | s64 compressed_size; |
189 | u32 compression_block_size; |
190 | u8 compression_block_size_bits; |
191 | u8 compression_block_clusters; |
192 | }; |
193 | |
194 | /** |
195 | * enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr |
196 | * structure |
197 | */ |
198 | typedef enum { |
199 | NA_Initialized, /* 1: structure is initialized. */ |
200 | NA_NonResident, /* 1: Attribute is not resident. */ |
201 | } ntfs_attr_state_bits; |
202 | |
203 | #define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state) |
204 | #define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state) |
205 | #define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state) |
206 | |
207 | #define NAttrInitialized(na) test_nattr_flag(na, Initialized) |
208 | #define NAttrSetInitialized(na) set_nattr_flag(na, Initialized) |
209 | #define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized) |
210 | |
211 | #define NAttrNonResident(na) test_nattr_flag(na, NonResident) |
212 | #define NAttrSetNonResident(na) set_nattr_flag(na, NonResident) |
213 | #define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident) |
214 | |
215 | #define GenNAttrIno(func_name, flag) \ |
216 | extern int NAttr##func_name(ntfs_attr *na); \ |
217 | extern void NAttrSet##func_name(ntfs_attr *na); \ |
218 | extern void NAttrClear##func_name(ntfs_attr *na); |
219 | |
220 | GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED) |
221 | GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED) |
222 | GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE) |
223 | #undef GenNAttrIno |
224 | |
225 | /** |
226 | * union attr_val - Union of all known attribute values |
227 | * |
228 | * For convenience. Used in the attr structure. |
229 | */ |
230 | typedef union { |
231 | u8 _default; /* Unnamed u8 to serve as default when just using |
232 | a_val without specifying any of the below. */ |
233 | STANDARD_INFORMATION std_inf; |
234 | ATTR_LIST_ENTRY al_entry; |
235 | FILE_NAME_ATTR filename; |
236 | OBJECT_ID_ATTR obj_id; |
237 | SECURITY_DESCRIPTOR_ATTR sec_desc; |
238 | VOLUME_NAME vol_name; |
239 | VOLUME_INFORMATION vol_inf; |
240 | DATA_ATTR data; |
241 | INDEX_ROOT index_root; |
242 | INDEX_BLOCK index_blk; |
243 | BITMAP_ATTR bmp; |
244 | REPARSE_POINT reparse; |
245 | EA_INFORMATION ea_inf; |
246 | EA_ATTR ea; |
247 | PROPERTY_SET property_set; |
248 | LOGGED_UTILITY_STREAM logged_util_stream; |
249 | EFS_ATTR_HEADER efs; |
250 | } attr_val; |
251 | |
252 | extern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, |
253 | const ATTR_FLAGS data_flags, const BOOL encrypted, |
254 | const BOOL sparse, |
255 | const s64 allocated_size, const s64 data_size, |
256 | const s64 initialized_size, const s64 compressed_size, |
257 | const u8 compression_unit); |
258 | |
259 | /* warning : in the following "name" has to be freeable */ |
260 | /* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */ |
261 | extern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, |
262 | ntfschar *name, u32 name_len); |
263 | extern void ntfs_attr_close(ntfs_attr *na); |
264 | |
265 | extern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, |
266 | void *b); |
267 | extern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, |
268 | const void *b); |
269 | extern int ntfs_attr_pclose(ntfs_attr *na); |
270 | |
271 | extern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, |
272 | ntfschar *name, u32 name_len, s64 *data_size); |
273 | |
274 | extern s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, |
275 | const s64 bk_cnt, const u32 bk_size, void *dst); |
276 | extern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, |
277 | s64 bk_cnt, const u32 bk_size, void *src); |
278 | |
279 | extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn); |
280 | extern int ntfs_attr_map_whole_runlist(ntfs_attr *na); |
281 | |
282 | extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn); |
283 | extern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn); |
284 | |
285 | extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol, |
286 | const ATTR_TYPES type, const s64 size); |
287 | extern int ntfs_attr_can_be_resident(const ntfs_volume *vol, |
288 | const ATTR_TYPES type); |
289 | int ntfs_attr_make_non_resident(ntfs_attr *na, |
290 | ntfs_attr_search_ctx *ctx); |
291 | extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size); |
292 | |
293 | extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, |
294 | ntfschar *name, u8 name_len, u8 *val, u32 size, |
295 | ATTR_FLAGS flags); |
296 | extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, |
297 | ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, |
298 | ATTR_FLAGS flags); |
299 | extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx); |
300 | |
301 | extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, |
302 | ntfschar *name, u8 name_len, u8 *val, s64 size); |
303 | extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, |
304 | ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask); |
305 | extern int ntfs_attr_rm(ntfs_attr *na); |
306 | |
307 | extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size); |
308 | |
309 | extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, |
310 | const u32 new_size); |
311 | |
312 | extern int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni); |
313 | extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra); |
314 | |
315 | extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn); |
316 | |
317 | extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize); |
318 | |
319 | /** |
320 | * get_attribute_value_length - return the length of the value of an attribute |
321 | * @a: pointer to a buffer containing the attribute record |
322 | * |
323 | * Return the byte size of the attribute value of the attribute @a (as it |
324 | * would be after eventual decompression and filling in of holes if sparse). |
325 | * If we return 0, check errno. If errno is 0 the actual length was 0, |
326 | * otherwise errno describes the error. |
327 | * |
328 | * FIXME: Describe possible errnos. |
329 | */ |
330 | extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a); |
331 | |
332 | /** |
333 | * get_attribute_value - return the attribute value of an attribute |
334 | * @vol: volume on which the attribute is present |
335 | * @a: attribute to get the value of |
336 | * @b: destination buffer for the attribute value |
337 | * |
338 | * Make a copy of the attribute value of the attribute @a into the destination |
339 | * buffer @b. Note, that the size of @b has to be at least equal to the value |
340 | * returned by get_attribute_value_length(@a). |
341 | * |
342 | * Return number of bytes copied. If this is zero check errno. If errno is 0 |
343 | * then nothing was read due to a zero-length attribute value, otherwise |
344 | * errno describes the error. |
345 | */ |
346 | extern s64 ntfs_get_attribute_value(const ntfs_volume *vol, |
347 | const ATTR_RECORD *a, u8 *b); |
348 | |
349 | extern void ntfs_attr_name_free(char **name); |
350 | extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len); |
351 | extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, |
352 | ntfschar *name, u32 name_len); |
353 | extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, |
354 | ntfschar *name, u32 name_len); |
355 | extern s64 ntfs_attr_get_free_bits(ntfs_attr *na); |
356 | |
357 | #endif /* defined _NTFS_ATTRIB_H */ |
358 | |
359 |