1 /**
2 * attrib.c - Attribute handling code. Part of the Linux-NTFS project.
3 *
4 * Copyright (c) 2000-2006 Anton Altaparmakov
5 * Copyright (c) 2002-2005 Richard Russon
6 * Copyright (c) 2002-2006 Szabolcs Szakacsits
7 * Copyright (c) 2004-2007 Yura Pakhuchiy
8 *
9 * This program/include file is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program/include file is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the Linux-NTFS
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #ifdef HAVE_STDIO_H
30 #include <stdio.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38 #ifdef HAVE_ERRNO_H
39 #include <errno.h>
40 #endif
41
42 #include "compat.h"
43 #include "attrib.h"
44 #include "attrlist.h"
45 #include "device.h"
46 #include "mft.h"
47 #include "debug.h"
48 #include "mst.h"
49 #include "volume.h"
50 #include "types.h"
51 #include "layout.h"
52 #include "inode.h"
53 #include "runlist.h"
54 #include "lcnalloc.h"
55 #include "dir.h"
56 #include "compress.h"
57 #include "bitmap.h"
58 #include "logging.h"
59 #include "support.h"
60 #include "crypto.h"
61
62 ntfschar AT_UNNAMED[] = { const_cpu_to_le16('\0') };
63
64 /**
65 * ntfs_get_attribute_value_length - Find the length of an attribute
66 * @a:
67 *
68 * Description...
69 *
70 * Returns:
71 */
ntfs_get_attribute_value_length(const ATTR_RECORD * a)72 s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a)
73 {
74 if (!a) {
75 errno = EINVAL;
76 return 0;
77 }
78 errno = 0;
79 if (a->non_resident)
80 return sle64_to_cpu(a->u.nonres.data_size);
81 return (s64)le32_to_cpu(a->u.res.value_length);
82 }
83
84 /**
85 * ntfs_get_attribute_value - Get a copy of an attribute
86 * @vol:
87 * @a:
88 * @b:
89 *
90 * Description...
91 *
92 * Returns:
93 */
ntfs_get_attribute_value(const ntfs_volume * vol,const ATTR_RECORD * a,u8 * b)94 s64 ntfs_get_attribute_value(const ntfs_volume *vol,
95 const ATTR_RECORD *a, u8 *b)
96 {
97 runlist *rl;
98 s64 total, r;
99 int i;
100
101 /* Sanity checks. */
102 if (!vol || !a || !b) {
103 errno = EINVAL;
104 return 0;
105 }
106 /* Complex attribute? */
107 /*
108 * Ignore the flags in case they are not zero for an attribute list
109 * attribute. Windows does not complain about invalid flags and chkdsk
110 * does not detect or fix them so we need to cope with it, too.
111 */
112 if (a->type != AT_ATTRIBUTE_LIST && a->flags) {
113 ntfs_log_error("Non-zero (%04x) attribute flags. Cannot handle "
114 "this yet.\n", le16_to_cpu(a->flags));
115 errno = EOPNOTSUPP;
116 return 0;
117 }
118 if (!a->non_resident) {
119 /* Attribute is resident. */
120
121 /* Sanity check. */
122 if (le32_to_cpu(a->u.res.value_length) + le16_to_cpu(a->u.res.value_offset)
123 > le32_to_cpu(a->length)) {
124 return 0;
125 }
126
127 memcpy(b, (const char*)a + le16_to_cpu(a->u.res.value_offset),
128 le32_to_cpu(a->u.res.value_length));
129 errno = 0;
130 return (s64)le32_to_cpu(a->u.res.value_length);
131 }
132
133 /* Attribute is not resident. */
134
135 /* If no data, return 0. */
136 if (!(a->u.nonres.data_size)) {
137 errno = 0;
138 return 0;
139 }
140 /*
141 * FIXME: What about attribute lists?!? (AIA)
142 */
143 /* Decompress the mapping pairs array into a runlist. */
144 rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
145 if (!rl) {
146 errno = EINVAL;
147 return 0;
148 }
149 /*
150 * FIXED: We were overflowing here in a nasty fashion when we
151 * reach the last cluster in the runlist as the buffer will
152 * only be big enough to hold data_size bytes while we are
153 * reading in allocated_size bytes which is usually larger
154 * than data_size, since the actual data is unlikely to have a
155 * size equal to a multiple of the cluster size!
156 * FIXED2: We were also overflowing here in the same fashion
157 * when the data_size was more than one run smaller than the
158 * allocated size which happens with Windows XP sometimes.
159 */
160 /* Now load all clusters in the runlist into b. */
161 for (i = 0, total = 0; rl[i].length; i++) {
162 if (total + (rl[i].length << vol->cluster_size_bits) >=
163 sle64_to_cpu(a->u.nonres.data_size)) {
164 unsigned char *intbuf = NULL;
165 /*
166 * We have reached the last run so we were going to
167 * overflow when executing the ntfs_pread() which is
168 * BAAAAAAAD!
169 * Temporary fix:
170 * Allocate a new buffer with size:
171 * rl[i].length << vol->cluster_size_bits, do the
172 * read into our buffer, then memcpy the correct
173 * amount of data into the caller supplied buffer,
174 * free our buffer, and continue.
175 * We have reached the end of data size so we were
176 * going to overflow in the same fashion.
177 * Temporary fix: same as above.
178 */
179 intbuf = ntfs_malloc(rl[i].length <<
180 vol->cluster_size_bits);
181 if (!intbuf) {
182 int eo = errno;
183 free(rl);
184 errno = eo;
185 return 0;
186 }
187 /*
188 * FIXME: If compressed file: Only read if lcn != -1.
189 * Otherwise, we are dealing with a sparse run and we
190 * just memset the user buffer to 0 for the length of
191 * the run, which should be 16 (= compression unit
192 * size).
193 * FIXME: Really only when file is compressed, or can
194 * we have sparse runs in uncompressed files as well?
195 * - Yes we can, in sparse files! But not necessarily
196 * size of 16, just run length.
197 */
198 r = ntfs_pread(vol->u.dev, rl[i].lcn <<
199 vol->cluster_size_bits, rl[i].length <<
200 vol->cluster_size_bits, intbuf);
201 if (r != rl[i].length << vol->cluster_size_bits) {
202 #define ESTR "Error reading attribute value"
203 if (r == -1) {
204 int eo = errno;
205 ntfs_log_perror(ESTR);
206 errno = eo;
207 } else if (r < rl[i].length <<
208 vol->cluster_size_bits) {
209 ntfs_log_debug(ESTR": Ran out of "
210 "input data.\n");
211 errno = EIO;
212 } else {
213 ntfs_log_debug(ESTR": unknown error\n");
214 errno = EIO;
215 }
216 #undef ESTR
217 free(rl);
218 free(intbuf);
219 return 0;
220 }
221 memcpy(b + total, intbuf, sle64_to_cpu(a->u.nonres.data_size) -
222 total);
223 free(intbuf);
224 total = sle64_to_cpu(a->u.nonres.data_size);
225 break;
226 }
227 /*
228 * FIXME: If compressed file: Only read if lcn != -1.
229 * Otherwise, we are dealing with a sparse run and we just
230 * memset the user buffer to 0 for the length of the run, which
231 * should be 16 (= compression unit size).
232 * FIXME: Really only when file is compressed, or can
233 * we have sparse runs in uncompressed files as well?
234 * - Yes we can, in sparse files! But not necessarily size of
235 * 16, just run length.
236 */
237 r = ntfs_pread(vol->u.dev, rl[i].lcn << vol->cluster_size_bits,
238 rl[i].length << vol->cluster_size_bits,
239 b + total);
240 if (r != rl[i].length << vol->cluster_size_bits) {
241 #define ESTR "Error reading attribute value"
242 if (r == -1) {
243 int eo = errno;
244 ntfs_log_perror(ESTR);
245 errno = eo;
246 } else if (r < rl[i].length << vol->cluster_size_bits) {
247 ntfs_log_debug(ESTR ": Ran out of "
248 "input data.\n");
249 errno = EIO;
250 } else {
251 ntfs_log_debug(ESTR ": unknown error\n");
252 errno = EIO;
253 }
254 #undef ESTR
255 free(rl);
256 return 0;
257 }
258 total += r;
259 }
260 free(rl);
261 return total;
262 }
263
264 /* Already cleaned up code below, but still look for FIXME:... */
265
266 /**
267 * __ntfs_attr_init - primary initialization of an ntfs attribute structure
268 * @na: ntfs attribute to initialize
269 * @ni: ntfs inode with which to initialize the ntfs attribute
270 * @type: attribute type
271 * @name: attribute name in little endian Unicode or NULL
272 * @name_len: length of attribute @name in Unicode characters (if @name given)
273 *
274 * Initialize the ntfs attribute @na with @ni, @type, @name, and @name_len.
275 */
__ntfs_attr_init(ntfs_attr * na,ntfs_inode * ni,const ATTR_TYPES type,ntfschar * name,const u32 name_len)276 static void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni,
277 const ATTR_TYPES type, ntfschar *name, const u32 name_len)
278 {
279 na->rl = NULL;
280 na->ni = ni;
281 na->type = type;
282 na->name = name;
283 if (name)
284 na->name_len = name_len;
285 else
286 na->name_len = 0;
287 }
288
289 /**
290 * ntfs_attr_init - initialize an ntfs_attr with data sizes and status
291 * @na:
292 * @non_resident:
293 * @compressed:
294 * @encrypted:
295 * @sparse:
296 * @allocated_size:
297 * @data_size:
298 * @initialized_size:
299 * @compressed_size:
300 * @compression_unit:
301 *
302 * Final initialization for an ntfs attribute.
303 */
ntfs_attr_init(ntfs_attr * na,const BOOL non_resident,const BOOL compressed,const BOOL encrypted,const BOOL sparse,const s64 allocated_size,const s64 data_size,const s64 initialized_size,const s64 compressed_size,const u8 compression_unit)304 void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
305 const BOOL compressed, const BOOL encrypted, const BOOL sparse,
306 const s64 allocated_size, const s64 data_size,
307 const s64 initialized_size, const s64 compressed_size,
308 const u8 compression_unit)
309 {
310 if (!NAttrInitialized(na)) {
311 if (non_resident)
312 NAttrSetNonResident(na);
313 if (compressed)
314 NAttrSetCompressed(na);
315 if (encrypted)
316 NAttrSetEncrypted(na);
317 if (sparse)
318 NAttrSetSparse(na);
319 na->allocated_size = allocated_size;
320 na->data_size = data_size;
321 na->initialized_size = initialized_size;
322 if (compressed || sparse) {
323 ntfs_volume *vol = na->ni->vol;
324
325 na->compressed_size = compressed_size;
326 na->compression_block_clusters = 1 << compression_unit;
327 na->compression_block_size = 1 << (compression_unit +
328 vol->cluster_size_bits);
329 na->compression_block_size_bits = ffs(
330 na->compression_block_size) - 1;
331 }
332 NAttrSetInitialized(na);
333 }
334 }
335
336 /**
337 * ntfs_attr_open - open an ntfs attribute for access
338 * @ni: open ntfs inode in which the ntfs attribute resides
339 * @type: attribute type
340 * @name: attribute name in little endian Unicode or AT_UNNAMED or NULL
341 * @name_len: length of attribute @name in Unicode characters (if @name given)
342 *
343 * Allocate a new ntfs attribute structure, initialize it with @ni, @type,
344 * @name, and @name_len, then return it. Return NULL on error with
345 * errno set to the error code.
346 *
347 * If @name is AT_UNNAMED look specifically for an unnamed attribute. If you
348 * do not care whether the attribute is named or not set @name to NULL. In
349 * both those cases @name_len is not used at all.
350 */
ntfs_attr_open(ntfs_inode * ni,const ATTR_TYPES type,ntfschar * name,u32 name_len)351 ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
352 ntfschar *name, u32 name_len)
353 {
354 ntfs_attr_search_ctx *ctx;
355 ntfs_attr *na;
356 ATTR_RECORD *a;
357 struct list_head *pos;
358 int err;
359 BOOL cs;
360
361 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
362 (unsigned long long)ni->mft_no, type);
363 if (!ni || !ni->vol || !ni->mrec) {
364 errno = EINVAL;
365 return NULL;
366 }
367 /* Check cache, maybe this attribute already opened? */
368 list_for_each(pos, &ni->attr_cache) {
369 ntfs_attr *tmp_na;
370
371 tmp_na = list_entry(pos, ntfs_attr, list_entry);
372 if (tmp_na->type == type && tmp_na->name_len == name_len &&
373 !ntfs_ucsncmp(tmp_na->name, name, name_len)) {
374 ntfs_log_trace("Found this attribute in cache, "
375 "increment reference count and "
376 "return it.\n");
377 tmp_na->nr_references++;
378 return tmp_na;
379 }
380 }
381 /* Search failed. Properly open attrbute. */
382 na = calloc(sizeof(ntfs_attr), 1);
383 if (!na)
384 return NULL;
385 if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) {
386 name = ntfs_ucsndup(name, name_len);
387 if (!name) {
388 err = errno;
389 free(na);
390 errno = err;
391 return NULL;
392 }
393 }
394
395 ctx = ntfs_attr_get_search_ctx(ni, NULL);
396 if (!ctx) {
397 err = errno;
398 goto err_out;
399 }
400 if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx)) {
401 err = errno;
402 goto put_err_out;
403 }
404
405 a = ctx->attr;
406 /*
407 * Wipe the flags in case they are not zero for an attribute list
408 * attribute. Windows does not complain about invalid flags and chkdsk
409 * does not detect or fix them so we need to cope with it, too.
410 */
411 if (type == AT_ATTRIBUTE_LIST)
412 a->flags = 0;
413 cs = (a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ? 1 : 0;
414 if (!name) {
415 if (a->name_length) {
416 name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu(
417 a->name_offset)), a->name_length);
418 if (!name) {
419 err = errno;
420 goto put_err_out;
421 }
422 name_len = a->name_length;
423 } else {
424 name = AT_UNNAMED;
425 name_len = 0;
426 }
427 }
428 __ntfs_attr_init(na, ni, type, name, name_len);
429 if (a->non_resident) {
430 ntfs_attr_init(na, TRUE, (a->flags & ATTR_IS_COMPRESSED)? 1 : 0,
431 (a->flags & ATTR_IS_ENCRYPTED) ? 1 : 0,
432 (a->flags & ATTR_IS_SPARSE) ? 1 : 0,
433 sle64_to_cpu(a->u.nonres.allocated_size),
434 sle64_to_cpu(a->u.nonres.data_size),
435 sle64_to_cpu(a->u.nonres.initialized_size),
436 cs ? sle64_to_cpu(a->u.nonres.compressed_size) : 0,
437 cs ? a->u.nonres.compression_unit : 0);
438 } else {
439 s64 l = le32_to_cpu(a->u.res.value_length);
440 ntfs_attr_init(na, FALSE, (a->flags & ATTR_IS_COMPRESSED) ? 1:0,
441 (a->flags & ATTR_IS_ENCRYPTED) ? 1 : 0,
442 (a->flags & ATTR_IS_SPARSE) ? 1 : 0,
443 (l + 7) & ~7, l, l, cs ? (l + 7) & ~7 : 0, 0);
444 }
445 ntfs_attr_put_search_ctx(ctx);
446 if (NAttrEncrypted(na))
447 ntfs_crypto_attr_open(na);
448 list_add_tail(&na->list_entry, &ni->attr_cache);
449 na->nr_references = 1;
450 return na;
451 put_err_out:
452 ntfs_attr_put_search_ctx(ctx);
453 err_out:
454 free(na);
455 errno = err;
456 return NULL;
457 }
458
459 /**
460 * ntfs_attr_close - free an ntfs attribute structure
461 * @na: ntfs attribute structure to free
462 *
463 * Release all memory associated with the ntfs attribute @na and then release
464 * @na itself.
465 */
ntfs_attr_close(ntfs_attr * na)466 void ntfs_attr_close(ntfs_attr *na)
467 {
468 if (!na)
469 return;
470 na->nr_references--;
471 if (na->nr_references) {
472 ntfs_log_trace("There are %d more references left to "
473 "this attribute.\n", na->nr_references);
474 return;
475 }
476 ntfs_log_trace("There are no more references left to this attribute\n");
477 list_del(&na->list_entry);
478 if (NAttrEncrypted(na))
479 ntfs_crypto_attr_close(na);
480 if (NAttrNonResident(na) && na->rl)
481 free(na->rl);
482 /* Don't release if using an internal constant. */
483 if (na->name != AT_UNNAMED && na->name != NTFS_INDEX_I30)
484 free(na->name);
485 free(na);
486 }
487
488 /**
489 * ntfs_attr_map_runlist - map (a part of) a runlist of an ntfs attribute
490 * @na: ntfs attribute for which to map (part of) a runlist
491 * @vcn: map runlist part containing this vcn
492 *
493 * Map the part of a runlist containing the @vcn of the ntfs attribute @na.
494 *
495 * Return 0 on success and -1 on error with errno set to the error code.
496 */
ntfs_attr_map_runlist(ntfs_attr * na,VCN vcn)497 int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
498 {
499 LCN lcn;
500 ntfs_attr_search_ctx *ctx;
501
502 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n",
503 (unsigned long long)na->ni->mft_no, na->type, (long long)vcn);
504
505 lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
506 if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
507 return 0;
508
509 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
510 if (!ctx)
511 return -1;
512
513 /* Find the attribute in the mft record. */
514 if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
515 vcn, NULL, 0, ctx)) {
516 runlist_element *rl;
517
518 /* Decode the runlist. */
519 rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr,
520 na->rl);
521 if (rl) {
522 na->rl = rl;
523 ntfs_attr_put_search_ctx(ctx);
524 return 0;
525 }
526 }
527 ntfs_attr_put_search_ctx(ctx);
528 return -1;
529 }
530
531 /**
532 * ntfs_attr_map_runlist_range - map (a part of) a runlist of an ntfs attribute
533 * @na: ntfs attribute for which to map (part of) a runlist
534 * @from_vcn: map runlist part starting this vcn
535 * @to_vcn: map runlist part ending this vcn
536 *
537 * Map the part of a runlist from containing the @from_vcn to containing the
538 * @to_vcn of an ntfs attribute @na. It is OK for @to_vcn to be beyond last run.
539 *
540 * Return 0 on success and -1 on error with errno set to the error code.
541 */
ntfs_attr_map_runlist_range(ntfs_attr * na,VCN from_vcn,VCN to_vcn)542 int ntfs_attr_map_runlist_range(ntfs_attr *na, VCN from_vcn, VCN to_vcn)
543 {
544 ntfs_attr_search_ctx *ctx = NULL;
545 runlist *rl;
546
547 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, "
548 "from_vcn 0x%llx, to_vcn 0x%llx.\n",
549 (unsigned long long)na->ni->mft_no, na->type,
550 (long long)from_vcn, (long long)to_vcn);
551
552 /* Map extent with @from_vcn. */
553 if (ntfs_attr_map_runlist(na, from_vcn))
554 goto err_out;
555
556 for (rl = na->rl; rl->vcn <= to_vcn;) {
557 /* Skip not interesting to us runs. */
558 if (rl->lcn >= 0 || rl->lcn == LCN_HOLE || (rl->vcn +
559 rl->length < from_vcn &&
560 rl->lcn == LCN_RL_NOT_MAPPED)) {
561 rl++;
562 continue;
563 }
564
565 /* We reached the end of runlist, just exit. */
566 if (rl->lcn == LCN_ENOENT)
567 break;
568
569 /* Check for errors. */
570 if (rl->lcn < 0 && rl->lcn != LCN_RL_NOT_MAPPED) {
571 errno = EIO;
572 goto err_out;
573 }
574
575 /* Runlist is not mapped here. */
576 if (!ctx) {
577 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
578 if (!ctx)
579 goto err_out;
580 }
581 /* Find the attribute in the mft record. */
582 if (ntfs_attr_lookup(na->type, na->name, na->name_len,
583 CASE_SENSITIVE, rl->vcn, NULL, 0,
584 ctx))
585 goto err_out;
586
587 /* Decode the runlist. */
588 rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr,
589 na->rl);
590 if (!rl)
591 goto err_out;
592 na->rl = rl;
593 }
594
595 ntfs_attr_put_search_ctx(ctx);
596 ntfs_log_trace("Done.\n");
597 return 0;
598 err_out:
599 ntfs_attr_put_search_ctx(ctx);
600 ntfs_log_trace("Failed.\n");
601 return -1;
602 }
603
604 /**
605 * ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
606 * @na: ntfs attribute for which to map the runlist
607 *
608 * Map the whole runlist of the ntfs attribute @na. For an attribute made up
609 * of only one attribute extent this is the same as calling
610 * ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this
611 * will map the runlist fragments from each of the extents thus giving access
612 * to the entirety of the disk allocation of an attribute.
613 *
614 * Return 0 on success and -1 on error with errno set to the error code.
615 */
ntfs_attr_map_whole_runlist(ntfs_attr * na)616 int ntfs_attr_map_whole_runlist(ntfs_attr *na)
617 {
618 VCN next_vcn, last_vcn, highest_vcn;
619 ntfs_attr_search_ctx *ctx;
620 ntfs_volume *vol = na->ni->vol;
621 ATTR_RECORD *a;
622 int err;
623
624 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
625 (unsigned long long)na->ni->mft_no, na->type);
626
627 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
628 if (!ctx)
629 return -1;
630
631 /* Map all attribute extents one by one. */
632 next_vcn = last_vcn = highest_vcn = 0;
633 a = NULL;
634 while (1) {
635 runlist_element *rl;
636
637 int not_mapped = 0;
638 if (ntfs_rl_vcn_to_lcn(na->rl, next_vcn) == LCN_RL_NOT_MAPPED)
639 not_mapped = 1;
640
641 if (ntfs_attr_lookup(na->type, na->name, na->name_len,
642 CASE_SENSITIVE, next_vcn, NULL, 0, ctx))
643 break;
644
645 a = ctx->attr;
646
647 if (not_mapped) {
648 /* Decode the runlist. */
649 rl = ntfs_mapping_pairs_decompress(na->ni->vol,
650 a, na->rl);
651 if (!rl)
652 goto err_out;
653 na->rl = rl;
654 }
655
656 /* Are we in the first extent? */
657 if (!next_vcn) {
658 if (a->u.nonres.lowest_vcn) {
659 ntfs_log_trace("First extent of attribute has "
660 "non zero lowest_vcn. "
661 "Inode is corrupt.\n");
662 errno = EIO;
663 goto err_out;
664 }
665 /* Get the last vcn in the attribute. */
666 last_vcn = sle64_to_cpu(a->u.nonres.allocated_size) >>
667 vol->cluster_size_bits;
668 }
669
670 /* Get the lowest vcn for the next extent. */
671 highest_vcn = sle64_to_cpu(a->u.nonres.highest_vcn);
672 next_vcn = highest_vcn + 1;
673
674 /* Only one extent or error, which we catch below. */
675 if (next_vcn <= 0) {
676 errno = ENOENT;
677 break;
678 }
679
680 /* Avoid endless loops due to corruption. */
681 if (next_vcn < sle64_to_cpu(a->u.nonres.lowest_vcn)) {
682 ntfs_log_trace("Inode has corrupt attribute list "
683 "attribute.\n");
684 errno = EIO;
685 goto err_out;
686 }
687 }
688 if (!a) {
689 if (errno == ENOENT)
690 ntfs_log_trace("Attribute not found. "
691 "Inode is corrupt.\n");
692 else
693 ntfs_log_trace("Inode is corrupt.\n");
694 goto err_out;
695 }
696 if (highest_vcn && highest_vcn != last_vcn - 1) {
697 ntfs_log_trace("Failed to load the complete run list for the "
698 "attribute. Bug or corrupt inode.\n");
699 ntfs_log_trace("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n",
700 (long long)highest_vcn,
701 (long long)last_vcn - 1);
702 errno = EIO;
703 goto err_out;
704 }
705 err = errno;
706 ntfs_attr_put_search_ctx(ctx);
707 if (err == ENOENT)
708 return 0;
709 out_now:
710 errno = err;
711 return -1;
712 err_out:
713 err = errno;
714 ntfs_attr_put_search_ctx(ctx);
715 goto out_now;
716 }
717
718 /**
719 * ntfs_attr_vcn_to_lcn - convert a vcn into a lcn given an ntfs attribute
720 * @na: ntfs attribute whose runlist to use for conversion
721 * @vcn: vcn to convert
722 *
723 * Convert the virtual cluster number @vcn of an attribute into a logical
724 * cluster number (lcn) of a device using the runlist @na->rl to map vcns to
725 * their corresponding lcns.
726 *
727 * If the @vcn is not mapped yet, attempt to map the attribute extent
728 * containing the @vcn and retry the vcn to lcn conversion.
729 *
730 * Since lcns must be >= 0, we use negative return values with special meaning:
731 *
732 * Return value Meaning / Description
733 * ==========================================
734 * -1 = LCN_HOLE Hole / not allocated on disk.
735 * -3 = LCN_ENOENT There is no such vcn in the attribute.
736 * -4 = LCN_EINVAL Input parameter error.
737 * -5 = LCN_EIO Corrupt fs, disk i/o error, or not enough memory.
738 */
ntfs_attr_vcn_to_lcn(ntfs_attr * na,const VCN vcn)739 LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn)
740 {
741 LCN lcn;
742 BOOL is_retry = FALSE;
743
744 if (!na || !NAttrNonResident(na) || vcn < 0)
745 return (LCN)LCN_EINVAL;
746
747 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
748 long)na->ni->mft_no, na->type);
749 retry:
750 /* Convert vcn to lcn. If that fails map the runlist and retry once. */
751 lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
752 if (lcn >= 0)
753 return lcn;
754 if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
755 is_retry = TRUE;
756 goto retry;
757 }
758 /*
759 * If the attempt to map the runlist failed, or we are getting
760 * LCN_RL_NOT_MAPPED despite having mapped the attribute extent
761 * successfully, something is really badly wrong...
762 */
763 if (!is_retry || lcn == (LCN)LCN_RL_NOT_MAPPED)
764 return (LCN)LCN_EIO;
765 /* lcn contains the appropriate error code. */
766 return lcn;
767 }
768
769 /**
770 * ntfs_attr_find_vcn - find a vcn in the runlist of an ntfs attribute
771 * @na: ntfs attribute whose runlist to search
772 * @vcn: vcn to find
773 *
774 * Find the virtual cluster number @vcn in the runlist of the ntfs attribute
775 * @na and return the the address of the runlist element containing the @vcn.
776 *
777 * Note you need to distinguish between the lcn of the returned runlist
778 * element being >= 0 and LCN_HOLE. In the later case you have to return zeroes
779 * on read and allocate clusters on write. You need to update the runlist, the
780 * attribute itself as well as write the modified mft record to disk.
781 *
782 * If there is an error return NULL with errno set to the error code. The
783 * following error codes are defined:
784 * EINVAL Input parameter error.
785 * ENOENT There is no such vcn in the runlist.
786 * ENOMEM Not enough memory.
787 * EIO I/O error or corrupt metadata.
788 */
ntfs_attr_find_vcn(ntfs_attr * na,const VCN vcn)789 runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn)
790 {
791 runlist_element *rl;
792 BOOL is_retry = FALSE;
793
794 if (!na || !NAttrNonResident(na) || vcn < 0) {
795 errno = EINVAL;
796 return NULL;
797 }
798
799 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn %llx\n",
800 (unsigned long long)na->ni->mft_no, na->type,
801 (long long)vcn);
802 retry:
803 rl = na->rl;
804 if (!rl)
805 goto map_rl;
806 if (vcn < rl[0].vcn)
807 goto map_rl;
808 while (rl->length) {
809 if (vcn < rl[1].vcn) {
810 if (rl->lcn >= (LCN)LCN_HOLE)
811 return rl;
812 break;
813 }
814 rl++;
815 }
816 switch (rl->lcn) {
817 case (LCN)LCN_RL_NOT_MAPPED:
818 goto map_rl;
819 case (LCN)LCN_ENOENT:
820 errno = ENOENT;
821 break;
822 case (LCN)LCN_EINVAL:
823 errno = EINVAL;
824 break;
825 default:
826 errno = EIO;
827 break;
828 }
829 return NULL;
830 map_rl:
831 /* The @vcn is in an unmapped region, map the runlist and retry. */
832 if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
833 is_retry = TRUE;
834 goto retry;
835 }
836 /*
837 * If we already retried or the mapping attempt failed something has
838 * gone badly wrong. EINVAL and ENOENT coming from a failed mapping
839 * attempt are equivalent to errors for us as they should not happen
840 * in our code paths.
841 */
842 if (is_retry || errno == EINVAL || errno == ENOENT)
843 errno = EIO;
844 return NULL;
845 }
846
847 /**
848 * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
849 * @na: ntfs attribute to read from
850 * @pos: byte position in the attribute to begin reading from
851 * @count: number of bytes to read
852 * @b: output data buffer
853 *
854 * This function will read @count bytes starting at offset @pos from the ntfs
855 * attribute @na into the data buffer @b.
856 *
857 * On success, return the number of successfully read bytes. If this number is
858 * lower than @count this means that the read reached end of file or that an
859 * error was encountered during the read so that the read is partial. 0 means
860 * end of file or nothing was read (also return 0 when @count is 0).
861 *
862 * On error and nothing has been read, return -1 with errno set appropriately
863 * to the return code of ntfs_pread(), or to EINVAL in case of invalid
864 * arguments.
865 */
ntfs_attr_pread(ntfs_attr * na,const s64 pos,s64 count,void * b)866 s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
867 {
868 s64 br, to_read, ofs, total, total2;
869 ntfs_volume *vol;
870 runlist_element *rl;
871
872 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, "
873 "count 0x%llx.\n", (unsigned long long)na->ni->mft_no,
874 na->type, (long long)pos, (long long)count);
875 if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
876 errno = EINVAL;
877 return -1;
878 }
879 /*
880 * If this is a compressed attribute it needs special treatment, but
881 * only if it is non-resident.
882 */
883 if (NAttrCompressed(na) && NAttrNonResident(na))
884 return ntfs_compressed_attr_pread(na, pos, count, b);
885 /*
886 * Encrypted non-resident attributes are not supported. We return
887 * access denied, which is what Windows NT4 does, too.
888 */
889 if (NAttrEncrypted(na) && NAttrNonResident(na))
890 return ntfs_crypto_attr_pread(na, pos, count, b);
891
892 vol = na->ni->vol;
893 if (!count)
894 return 0;
895 /* Truncate reads beyond end of attribute. */
896 if (pos + count > na->data_size) {
897 if (pos >= na->data_size)
898 return 0;
899 count = na->data_size - pos;
900 }
901 /* If it is a resident attribute, get the value from the mft record. */
902 if (!NAttrNonResident(na)) {
903 ntfs_attr_search_ctx *ctx;
904 char *val;
905
906 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
907 if (!ctx)
908 return -1;
909 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
910 0, NULL, 0, ctx)) {
911 int eo;
912 res_err_out:
913 eo = errno;
914 ntfs_attr_put_search_ctx(ctx);
915 errno = eo;
916 return -1;
917 }
918 val = (char*)ctx->attr + le16_to_cpu(ctx->attr->u.res.value_offset);
919 if (val < (char*)ctx->attr || val +
920 le32_to_cpu(ctx->attr->u.res.value_length) >
921 (char*)ctx->mrec + vol->mft_record_size) {
922 errno = EIO;
923 goto res_err_out;
924 }
925 memcpy(b, val + pos, count);
926 ntfs_attr_put_search_ctx(ctx);
927 return count;
928 }
929 total = total2 = 0;
930 /* Zero out reads beyond initialized size. */
931 if (pos + count > na->initialized_size) {
932 if (pos >= na->initialized_size) {
933 memset(b, 0, count);
934 return count;
935 }
936 total2 = pos + count - na->initialized_size;
937 count -= total2;
938 memset((u8*)b + count, 0, total2);
939 }
940 /* Find the runlist element containing the vcn. */
941 rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
942 if (!rl) {
943 /*
944 * If the vcn is not present it is an out of bounds read.
945 * However, we already truncated the read to the data_size,
946 * so getting this here is an error.
947 */
948 if (errno == ENOENT)
949 errno = EIO;
950 return -1;
951 }
952 /*
953 * Gather the requested data into the linear destination buffer. Note,
954 * a partial final vcn is taken care of by the @count capping of read
955 * length.
956 */
957 ofs = pos - (rl->vcn << vol->cluster_size_bits);
958 for (; count; rl++, ofs = 0) {
959 if (rl->lcn == LCN_RL_NOT_MAPPED) {
960 rl = ntfs_attr_find_vcn(na, rl->vcn);
961 if (!rl) {
962 if (errno == ENOENT)
963 errno = EIO;
964 goto rl_err_out;
965 }
966 /* Needed for case when runs merged. */
967 ofs = pos + total - (rl->vcn << vol->cluster_size_bits);
968 }
969 if (!rl->length)
970 goto rl_err_out;
971 if (rl->lcn < (LCN)0) {
972 if (rl->lcn != (LCN)LCN_HOLE)
973 goto rl_err_out;
974 /* It is a hole, just zero the matching @b range. */
975 to_read = min(count, (rl->length <<
976 vol->cluster_size_bits) - ofs);
977 memset(b, 0, to_read);
978 /* Update progress counters. */
979 total += to_read;
980 count -= to_read;
981 b = (u8*)b + to_read;
982 continue;
983 }
984 /* It is a real lcn, read it into @dst. */
985 to_read = min(count, (rl->length << vol->cluster_size_bits) -
986 ofs);
987 retry:
988 ntfs_log_trace("Reading 0x%llx bytes from vcn 0x%llx, "
989 "lcn 0x%llx, ofs 0x%llx.\n", to_read, rl->vcn,
990 rl->lcn, ofs);
991 br = ntfs_pread(vol->u.dev, (rl->lcn << vol->cluster_size_bits) +
992 ofs, to_read, b);
993 /* If everything ok, update progress counters and continue. */
994 if (br > 0) {
995 total += br;
996 count -= br;
997 b = (u8*)b + br;
998 continue;
999 }
1000 /* If the syscall was interrupted, try again. */
1001 if (br == (s64)-1 && errno == EINTR)
1002 goto retry;
1003 if (total)
1004 return total;
1005 if (!br)
1006 errno = EIO;
1007 return -1;
1008 }
1009 /* Finally, return the number of bytes read. */
1010 return total + total2;
1011 rl_err_out:
1012 if (total)
1013 return total;
1014 errno = EIO;
1015 return -1;
1016 }
1017
1018 /**
1019 * ntfs_attr_pwrite - positioned write to an ntfs attribute
1020 * @na: ntfs attribute to write to
1021 * @pos: position in the attribute to write to
1022 * @count: number of bytes to write
1023 * @b: data buffer to write to disk
1024 *
1025 * This function will write @count bytes from data buffer @b to ntfs attribute
1026 * @na at position @pos.
1027 *
1028 * On success, return the number of successfully written bytes. If this number
1029 * is lower than @count this means that an error was encountered during the
1030 * write so that the write is partial. 0 means nothing was written (also return
1031 * 0 when @count is 0).
1032 *
1033 * On error and nothing has been written, return -1 with errno set
1034 * appropriately to the return code of ntfs_pwrite(), or to EINVAL in case of
1035 * invalid arguments.
1036 */
ntfs_attr_pwrite(ntfs_attr * na,const s64 pos,s64 count,const void * b)1037 s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
1038 {
1039 s64 written, to_write, ofs, total, old_initialized_size, old_data_size;
1040 VCN update_from = -1;
1041 ntfs_volume *vol;
1042 ntfs_attr_search_ctx *ctx = NULL;
1043 runlist_element *rl;
1044 int eo;
1045 struct {
1046 unsigned int undo_initialized_size : 1;
1047 unsigned int undo_data_size : 1;
1048 unsigned int update_mapping_pairs : 1;
1049 } need_to = { 0, 0, 0 };
1050
1051 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, "
1052 "count 0x%llx.\n", na->ni->mft_no, na->type,
1053 (long long)pos, (long long)count);
1054 if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
1055 errno = EINVAL;
1056 return -1;
1057 }
1058 vol = na->ni->vol;
1059 /*
1060 * Encrypted non-resident attributes are not supported. We return
1061 * access denied, which is what Windows NT4 does, too.
1062 */
1063 if (NAttrEncrypted(na) && NAttrNonResident(na)) {
1064 errno = EACCES;
1065 return -1;
1066 }
1067 /* If this is a compressed attribute it needs special treatment. */
1068 if (NAttrCompressed(na)) {
1069 // TODO: Implement writing compressed attributes! (AIA)
1070 // return ntfs_attr_pwrite_compressed(ntfs_attr *na,
1071 // const s64 pos, s64 count, void *b);
1072 errno = EOPNOTSUPP;
1073 return -1;
1074 }
1075 if (!count)
1076 return 0;
1077 /* If the write reaches beyond the end, extend the attribute. */
1078 old_data_size = na->data_size;
1079 if (pos + count > na->data_size) {
1080 if (__ntfs_attr_truncate(na, pos + count, FALSE)) {
1081 eo = errno;
1082 ntfs_log_trace("Attribute extend failed.\n");
1083 errno = eo;
1084 return -1;
1085 }
1086 need_to.undo_data_size = 1;
1087 }
1088 old_initialized_size = na->initialized_size;
1089 /* If it is a resident attribute, write the data to the mft record. */
1090 if (!NAttrNonResident(na)) {
1091 char *val;
1092
1093 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
1094 if (!ctx)
1095 goto err_out;
1096 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
1097 0, NULL, 0, ctx))
1098 goto err_out;
1099 val = (char*)ctx->attr + le16_to_cpu(ctx->attr->u.res.value_offset);
1100 if (val < (char*)ctx->attr || val +
1101 le32_to_cpu(ctx->attr->u.res.value_length) >
1102 (char*)ctx->mrec + vol->mft_record_size) {
1103 errno = EIO;
1104 goto err_out;
1105 }
1106 memcpy(val + pos, b, count);
1107 if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
1108 ctx->mrec)) {
1109 /*
1110 * NOTE: We are in a bad state at this moment. We have
1111 * dirtied the mft record but we failed to commit it to
1112 * disk. Since we have read the mft record ok before,
1113 * it is unlikely to fail writing it, so is ok to just
1114 * return error here... (AIA)
1115 */
1116 goto err_out;
1117 }
1118 ntfs_attr_put_search_ctx(ctx);
1119 return count;
1120 }
1121 total = 0;
1122 /* Handle writes beyond initialized_size. */
1123 if (pos + count > na->initialized_size) {
1124 /*
1125 * Map runlist between initialized size and place we start
1126 * writing at.
1127 */
1128 if (ntfs_attr_map_runlist_range(na, na->initialized_size >>
1129 vol->cluster_size_bits,
1130 pos >> vol->cluster_size_bits))
1131 goto err_out;
1132 /* Set initialized_size to @pos + @count. */
1133 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
1134 if (!ctx)
1135 goto err_out;
1136 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
1137 0, NULL, 0, ctx))
1138 goto err_out;
1139 /* If write starts beyond initialized_size, zero the gap. */
1140 if (pos > na->initialized_size && ntfs_rl_fill_zero(vol,
1141 na->rl, na->initialized_size,
1142 pos - na->initialized_size))
1143 goto err_out;
1144
1145 ctx->attr->u.nonres.initialized_size = cpu_to_sle64(pos + count);
1146 if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
1147 ctx->mrec)) {
1148 /*
1149 * Undo the change in the in-memory copy and send it
1150 * back for writing.
1151 */
1152 ctx->attr->u.nonres.initialized_size =
1153 cpu_to_sle64(old_initialized_size);
1154 ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
1155 ctx->mrec);
1156 goto err_out;
1157 }
1158 na->initialized_size = pos + count;
1159 ntfs_attr_put_search_ctx(ctx);
1160 ctx = NULL;
1161 /*
1162 * NOTE: At this point the initialized_size in the mft record
1163 * has been updated BUT there is random data on disk thus if
1164 * we decide to abort, we MUST change the initialized_size
1165 * again.
1166 */
1167 need_to.undo_initialized_size = 1;
1168 }
1169 /* Find the runlist element containing the vcn. */
1170 rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
1171 if (!rl) {
1172 /*
1173 * If the vcn is not present it is an out of bounds write.
1174 * However, we already extended the size of the attribute,
1175 * so getting this here must be an error of some kind.
1176 */
1177 if (errno == ENOENT)
1178 errno = EIO;
1179 goto err_out;
1180 }
1181 /*
1182 * Scatter the data from the linear data buffer to the volume. Note, a
1183 * partial final vcn is taken care of by the @count capping of write
1184 * length.
1185 */
1186 ofs = pos - (rl->vcn << vol->cluster_size_bits);
1187 for (; count; rl++, ofs = 0) {
1188 if (rl->lcn == LCN_RL_NOT_MAPPED) {
1189 rl = ntfs_attr_find_vcn(na, rl->vcn);
1190 if (!rl) {
1191 if (errno == ENOENT)
1192 errno = EIO;
1193 goto rl_err_out;
1194 }
1195 /* Needed for case when runs merged. */
1196 ofs = pos + total - (rl->vcn << vol->cluster_size_bits);
1197 }
1198 if (!rl->length) {
1199 errno = EIO;
1200 goto rl_err_out;
1201 }
1202 if (rl->lcn < (LCN)0) {
1203 LCN lcn_seek_from = -1;
1204 runlist *rlc;
1205 VCN cur_vcn, from_vcn;
1206
1207 if (rl->lcn != (LCN)LCN_HOLE) {
1208 errno = EIO;
1209 goto rl_err_out;
1210 }
1211
1212 to_write = min(count, (rl->length <<
1213 vol->cluster_size_bits) - ofs);
1214
1215 /* Instantiate the hole. */
1216 cur_vcn = rl->vcn;
1217 from_vcn = rl->vcn + (ofs >> vol->cluster_size_bits);
1218 ntfs_log_trace("Instantiate hole with vcn 0x%llx.\n",
1219 cur_vcn);
1220 /*
1221 * Map whole runlist to be able update mapping pairs
1222 * later.
1223 */
1224 if (ntfs_attr_map_whole_runlist(na))
1225 goto err_out;
1226 /*
1227 * Restore @rl, it probably get lost during runlist
1228 * mapping.
1229 */
1230 rl = ntfs_attr_find_vcn(na, cur_vcn);
1231 if (!rl) {
1232 ntfs_log_error("BUG! Failed to find run after "
1233 "mapping whole runlist. Please "
1234 "report to the %s.\n",
1235 NTFS_DEV_LIST);
1236 errno = EIO;
1237 goto err_out;
1238 }
1239 /*
1240 * Search backwards to find the best lcn to start
1241 * seek from.
1242 */
1243 rlc = rl;
1244 while (rlc->vcn) {
1245 rlc--;
1246 if (rlc->lcn >= 0) {
1247 lcn_seek_from = rlc->lcn +
1248 (from_vcn - rlc->vcn);
1249 break;
1250 }
1251 }
1252 if (lcn_seek_from == -1) {
1253 /* Backwards search failed, search forwards. */
1254 rlc = rl;
1255 while (rlc->length) {
1256 rlc++;
1257 if (rlc->lcn >= 0) {
1258 lcn_seek_from = rlc->lcn -
1259 (rlc->vcn - from_vcn);
1260 if (lcn_seek_from < -1)
1261 lcn_seek_from = -1;
1262 break;
1263 }
1264 }
1265 }
1266 /* Allocate clusters to instantiate the hole. */
1267 rlc = ntfs_cluster_alloc(vol, from_vcn,
1268 ((ofs + to_write - 1) >>
1269 vol->cluster_size_bits) + 1 +
1270 rl->vcn - from_vcn,
1271 lcn_seek_from, DATA_ZONE);
1272 if (!rlc) {
1273 eo = errno;
1274 ntfs_log_trace("Failed to allocate clusters "
1275 "for hole instantiating.\n");
1276 errno = eo;
1277 goto err_out;
1278 }
1279 /* Merge runlists. */
1280 rl = ntfs_runlists_merge(na->rl, rlc);
1281 if (!rl) {
1282 eo = errno;
1283 ntfs_log_trace("Failed to merge runlists.\n");
1284 if (ntfs_cluster_free_from_rl(vol, rlc)) {
1285 ntfs_log_trace("Failed to free just "
1286 "allocated clusters. Leaving "
1287 "inconsistent metadata. "
1288 "Run chkdsk\n");
1289 }
1290 errno = eo;
1291 goto err_out;
1292 }
1293 na->rl = rl;
1294 need_to.update_mapping_pairs = 1;
1295 if (update_from == -1)
1296 update_from = from_vcn;
1297 rl = ntfs_attr_find_vcn(na, cur_vcn);
1298 if (!rl) {
1299 /*
1300 * It's definitely a BUG, if we failed to find
1301 * @cur_vcn, because we missed it during
1302 * instantiating of the hole.
1303 */
1304 ntfs_log_error("BUG! Failed to find run after "
1305 "instantiating. Please report "
1306 "to the %s.\n", NTFS_DEV_LIST);
1307 errno = EIO;
1308 goto err_out;
1309 }
1310 /* If leaved part of the hole go to the next run. */
1311 if (rl->lcn < 0)
1312 rl++;
1313 /* Now LCN shoudn't be less than 0. */
1314 if (rl->lcn < 0) {
1315 ntfs_log_error("BUG! LCN is lesser than 0. "
1316 "Please report to the %s.\n",
1317 NTFS_DEV_LIST);
1318 errno = EIO;
1319 goto err_out;
1320 }
1321 if (rl->vcn < cur_vcn) {
1322 /*
1323 * Clusters that replaced hole are merged with
1324 * previous run, so we need to update offset.
1325 */
1326 ofs += (cur_vcn - rl->vcn) <<
1327 vol->cluster_size_bits;
1328 }
1329 if (rl->vcn > cur_vcn) {
1330 /*
1331 * We left part of the hole, so update we need
1332 * to update offset
1333 */
1334 ofs -= (rl->vcn - cur_vcn) <<
1335 vol->cluster_size_bits;
1336 }
1337 /*
1338 * Clear region between start of @rl->vcn cluster and
1339 * @ofs if necessary.
1340 */
1341 if (ofs && ntfs_rl_fill_zero(vol, na->rl, rl->vcn <<
1342 vol->cluster_size_bits, ofs))
1343 goto err_out;
1344 }
1345 /* It is a real lcn, write it to the volume. */
1346 to_write = min(count, (rl->length << vol->cluster_size_bits) -
1347 ofs);
1348 retry:
1349 ntfs_log_trace("Writing 0x%llx bytes to vcn 0x%llx, lcn 0x%llx,"
1350 " ofs 0x%llx.\n", to_write, rl->vcn, rl->lcn,
1351 ofs);
1352 if (!NVolReadOnly(vol)) {
1353 s64 pos = (rl->lcn << vol->cluster_size_bits) + ofs;
1354 int bsize = 4096; /* FIXME: Test whether we need
1355 PAGE_SIZE here. Eg., on IA64. */
1356 /*
1357 * Write 4096 size blocks if it's possible. This will
1358 * cause the kernel not to seek and read disk blocks for
1359 * filling the end of the buffer which increases write
1360 * speed.
1361 */
1362 if (vol->cluster_size >= bsize && !(ofs % bsize) &&
1363 (to_write % bsize) && ofs + to_write ==
1364 na->initialized_size) {
1365 char *cb;
1366 s64 rounded = (to_write + bsize - 1) &
1367 ~(bsize - 1);
1368
1369 cb = ntfs_malloc(rounded);
1370 if (!cb)
1371 goto err_out;
1372 memcpy(cb, b, to_write);
1373 memset(cb + to_write, 0, rounded - to_write);
1374 written = ntfs_pwrite(vol->u.dev, pos, rounded,
1375 cb);
1376 if (written > to_write)
1377 written = to_write;
1378 free(cb);
1379 } else
1380 written = ntfs_pwrite(vol->u.dev, pos, to_write,
1381 b);
1382 } else
1383 written = to_write;
1384 /* If everything ok, update progress counters and continue. */
1385 if (written > 0) {
1386 total += written;
1387 count -= written;
1388 b = (const u8*)b + written;
1389 continue;
1390 }
1391 /* If the syscall was interrupted, try again. */
1392 if (written == (s64)-1 && errno == EINTR)
1393 goto retry;
1394 if (!written)
1395 errno = EIO;
1396 goto rl_err_out;
1397 }
1398 done:
1399 if (ctx)
1400 ntfs_attr_put_search_ctx(ctx);
1401 /* Update mapping pairs if needed. */
1402 if (need_to.update_mapping_pairs) {
1403 if (ntfs_attr_update_mapping_pairs(na, update_from)) {
1404 /* FIXME: We want rollback here. */
1405 ntfs_log_perror("%s(): Failed to update mapping pairs. "
1406 "Leaving inconsistent metadata. "
1407 "Run chkdsk!", "ntfs_attr_pwrite");
1408 errno = EIO;
1409 return -1;
1410 }
1411 }
1412 /* Finally, return the number of bytes written. */
1413 return total;
1414 rl_err_out:
1415 eo = errno;
1416 if (total) {
1417 if (need_to.undo_initialized_size) {
1418 if (pos + total > na->initialized_size)
1419 goto done;
1420 /*
1421 * TODO: Need to try to change initialized_size. If it
1422 * succeeds goto done, otherwise goto err_out. (AIA)
1423 */
1424 errno = EOPNOTSUPP;
1425 goto err_out;
1426 }
1427 goto done;
1428 }
1429 errno = eo;
1430 err_out:
1431 eo = errno;
1432 if (need_to.undo_initialized_size) {
1433 int err;
1434
1435 err = 0;
1436 if (!ctx) {
1437 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
1438 if (!ctx)
1439 err = 1;
1440 } else
1441 ntfs_attr_reinit_search_ctx(ctx);
1442 if (ctx) {
1443 err = ntfs_attr_lookup(na->type, na->name,
1444 na->name_len, 0, 0, NULL, 0, ctx);
1445 if (!err) {
1446 na->initialized_size = old_initialized_size;
1447 ctx->attr->u.nonres.initialized_size = cpu_to_sle64(
1448 old_initialized_size);
1449 err = ntfs_mft_record_write(vol,
1450 ctx->ntfs_ino->mft_no,
1451 ctx->mrec);
1452 }
1453 }
1454 if (err) {
1455 /*
1456 * FIXME: At this stage could try to recover by filling
1457 * old_initialized_size -> new_initialized_size with
1458 * data or at least zeroes. (AIA)
1459 */
1460 ntfs_log_error("Eeek! Failed to recover from error. "
1461 "Leaving metadata in inconsistent "
1462 "state! Run chkdsk!\n");
1463 }
1464 }
1465 if (ctx)
1466 ntfs_attr_put_search_ctx(ctx);
1467 /* Update mapping pairs if needed. */
1468 if (need_to.update_mapping_pairs)
1469 ntfs_attr_update_mapping_pairs(na, update_from);
1470 /* Restore original data_size if needed. */
1471 if (need_to.undo_data_size && ntfs_attr_truncate(na, old_data_size))
1472 ntfs_log_trace("Failed to restore data_size.\n");
1473 errno = eo;
1474 return -1;
1475 }
1476
1477 /**
1478 * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read
1479 * @na: multi sector transfer protected ntfs attribute to read from
1480 * @pos: byte position in the attribute to begin reading from
1481 * @bk_cnt: number of mst protected blocks to read
1482 * @bk_size: size of each mst protected block in bytes
1483 * @dst: output data buffer
1484 *
1485 * This function will read @bk_cnt blocks of size @bk_size bytes each starting
1486 * at offset @pos from the ntfs attribute @na into the data buffer @b.
1487 *
1488 * On success, the multi sector transfer fixups are applied and the number of
1489 * read blocks is returned. If this number is lower than @bk_cnt this means
1490 * that the read has either reached end of attribute or that an error was
1491 * encountered during the read so that the read is partial. 0 means end of
1492 * attribute or nothing to read (also return 0 when @bk_cnt or @bk_size are 0).
1493 *
1494 * On error and nothing has been read, return -1 with errno set appropriately
1495 * to the return code of ntfs_attr_pread() or to EINVAL in case of invalid
1496 * arguments.
1497 *
1498 * NOTE: If an incomplete multi sector transfer is detected the magic is
1499 * changed to BAAD but no error is returned, i.e. it is possible that any of
1500 * the returned blocks have multi sector transfer errors. This should be
1501 * detected by the caller by checking each block with is_baad_recordp(&block).
1502 * The reasoning is that we want to fixup as many blocks as possible and we
1503 * want to return even bad ones to the caller so, e.g. in case of ntfsck, the
1504 * errors can be repaired.
1505 */
ntfs_attr_mst_pread(ntfs_attr * na,const s64 pos,const s64 bk_cnt,const u32 bk_size,void * dst)1506 s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
1507 const u32 bk_size, void *dst)
1508 {
1509 s64 br;
1510 u8 *end;
1511
1512 ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, "
1513 "pos 0x%llx.\n", (unsigned long long)na->ni->mft_no,
1514 na->type, (long long)pos);
1515 if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
1516 errno = EINVAL;
1517 return -1;
1518 }
1519 br = ntfs_attr_pread(na, pos, bk_cnt * bk_size, dst);
1520 if (br <= 0)
1521 return br;
1522 br /= bk_size;
1523 for (end = (u8*)dst + br * bk_size; (u8*)dst < end; dst = (u8*)dst +
1524 bk_size)
1525 ntfs_mst_post_read_fixup((NTFS_RECORD*)dst, bk_size);
1526 /* Finally, return the number of blocks read. */
1527 return br;
1528 }
1529
1530 /**
1531 * ntfs_attr_mst_pwrite - multi sector transfer protected ntfs attribute write
1532 * @na: multi sector transfer protected ntfs attribute to write to
1533 * @pos: position in the attribute to write to
1534 * @bk_cnt: number of mst protected blocks to write
1535 * @bk_size: size of each mst protected block in bytes
1536 * @src: data buffer to write to disk
1537 *
1538 * This function will write @bk_cnt blocks of size @bk_size bytes each from
1539 * data buffer @b to multi sector transfer (mst) protected ntfs attribute @na
1540 * at position @pos.
1541 *
1542 * On success, return the number of successfully written blocks. If this number
1543 * is lower than @bk_cnt this means that an error was encountered during the
1544 * write so that the write is partial. 0 means nothing was written (also
1545 * return 0 when @bk_cnt or @bk_size are 0).
1546 *
1547 * On error and nothing has been written, return -1 with errno set
1548 * appropriately to the return code of ntfs_attr_pwrite(), or to EINVAL in case
1549 * of invalid arguments.
1550 *
1551 * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
1552 * deprotect algorithm (no checking). This saves us from making a copy before
1553 * the write and at the same time causes the usn to be incremented in the
1554 * buffer. This conceptually fits in better with the idea that cached data is
1555 * always deprotected and protection is performed when the data is actually
1556 * going to hit the disk and the cache is immediately deprotected again
1557 * simulating an mst read on the written data. This way cache coherency is
1558 * achieved.
1559 */
ntfs_attr_mst_pwrite(ntfs_attr * na,const s64 pos,s64 bk_cnt,const u32 bk_size,void * src)1560 s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, s64 bk_cnt,
1561 const u32 bk_size, void *src)
1562 {
1563 s64 written, i;
1564
1565 ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, "
1566 "pos 0x%llx.\n", (unsigned long long)na->ni->mft_no,
1567 na->type, (long long)pos);
1568 if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
1569 errno = EINVAL;
1570 return -1;
1571 }
1572 if (!bk_cnt)
1573 return 0;
1574 /* Prepare data for writing. */
1575 for (i = 0; i < bk_cnt; ++i) {
1576 int err;
1577
1578 err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
1579 ((u8*)src + i * bk_size), bk_size);
1580 if (err < 0) {
1581 /* Abort write at this position. */
1582 if (!i)
1583 return err;
1584 bk_cnt = i;
1585 break;
1586 }
1587 }
1588 /* Write the prepared data. */
1589 written = ntfs_attr_pwrite(na, pos, bk_cnt * bk_size, src);
1590 /* Quickly deprotect the data again. */
1591 for (i = 0; i < bk_cnt; ++i)
1592 ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)src + i *
1593 bk_size));
1594 if (written <= 0)
1595 return written;
1596 /* Finally, return the number of complete blocks written. */
1597 return written / bk_size;
1598 }
1599
1600 /**
1601 * ntfs_attr_find - find (next) attribute in mft record
1602 * @type: attribute type to find
1603 * @name: attribute name to find (optional, i.e. NULL means don't care)
1604 * @name_len: attribute name length (only needed if @name present)
1605 * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
1606 * @val: attribute value to find (optional, resident attributes only)
1607 * @val_len: attribute value length
1608 * @ctx: search context with mft record and attribute to search from
1609 *
1610 * You shouldn't need to call this function directly. Use lookup_attr() instead.
1611 *
1612 * ntfs_attr_find() takes a search context @ctx as parameter and searches the
1613 * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
1614 * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
1615 * returns 0 and @ctx->attr will point to the found attribute.
1616 *
1617 * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
1618 * @ctx->attr will point to the attribute before which the attribute being
1619 * searched for would need to be inserted if such an action were to be desired.
1620 *
1621 * On actual error, ntfs_attr_find() returns -1 with errno set to the error
1622 * code but not to ENOENT. In this case @ctx->attr is undefined and in
1623 * particular do not rely on it not changing.
1624 *
1625 * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
1626 * is FALSE, the search begins after @ctx->attr.
1627 *
1628 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
1629 * enumerate all attributes by setting @type to AT_UNUSED and then calling
1630 * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
1631 * indicate that there are no more entries. During the enumeration, each
1632 * successful call of ntfs_attr_find() will return the next attribute in the
1633 * mft record @ctx->mrec.
1634 *
1635 * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
1636 * AT_END is not a valid attribute, its length is zero for example, thus it is
1637 * safer to return error instead of success in this case. This also allows us
1638 * to interoperate cleanly with ntfs_external_attr_find().
1639 *
1640 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
1641 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
1642 * match both named and unnamed attributes.
1643 *
1644 * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
1645 * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
1646 * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
1647 * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
1648 * sensitive. When @name is present, @name_len is the @name length in Unicode
1649 * characters.
1650 *
1651 * If @name is not present (NULL), we assume that the unnamed attribute is
1652 * being searched for.
1653 *
1654 * Finally, the resident attribute value @val is looked for, if present.
1655 * If @val is not present (NULL), @val_len is ignored.
1656 *
1657 * ntfs_attr_find() only searches the specified mft record and it ignores the
1658 * presence of an attribute list attribute (unless it is the one being searched
1659 * for, obviously). If you need to take attribute lists into consideration, use
1660 * ntfs_attr_lookup() instead (see below). This also means that you cannot use
1661 * ntfs_attr_find() to search for extent records of non-resident attributes, as
1662 * extents with lowest_vcn != 0 are usually described by the attribute list
1663 * attribute only. - Note that it is possible that the first extent is only in
1664 * the attribute list while the last extent is in the base mft record, so don't
1665 * rely on being able to find the first extent in the base mft record.
1666 *
1667 * Warning: Never use @val when looking for attribute types which can be
1668 * non-resident as this most likely will result in a crash!
1669 */
ntfs_attr_find(const ATTR_TYPES type,const ntfschar * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const u8 * val,const u32 val_len,ntfs_attr_search_ctx * ctx)1670 static int ntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
1671 const u32 name_len, const IGNORE_CASE_BOOL ic,
1672 const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
1673 {
1674 ATTR_RECORD *a;
1675 ntfs_volume *vol;
1676 ntfschar *upcase;
1677 u32 upcase_len;
1678
1679 ntfs_log_trace("Entering for attribute type 0x%x.\n", type);
1680
1681 if (ctx->ntfs_ino) {
1682 vol = ctx->ntfs_ino->vol;
1683 upcase = vol->upcase;
1684 upcase_len = vol->upcase_len;
1685 } else {
1686 if (name && name != AT_UNNAMED) {
1687 errno = EINVAL;
1688 return -1;
1689 }
1690 vol = NULL;
1691 upcase = NULL;
1692 upcase_len = 0;
1693 }
1694 /*
1695 * Iterate over attributes in mft record starting at @ctx->attr, or the
1696 * attribute following that, if @ctx->is_first is TRUE.
1697 */
1698 if (ctx->is_first) {
1699 a = ctx->attr;
1700 ctx->is_first = FALSE;
1701 } else
1702 a = (ATTR_RECORD*)((char*)ctx->attr +
1703 le32_to_cpu(ctx->attr->length));
1704 for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
1705 if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
1706 le32_to_cpu(ctx->mrec->bytes_allocated))
1707 break;
1708 ctx->attr = a;
1709 if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
1710 le32_to_cpu(type))) ||
1711 (a->type == AT_END)) {
1712 errno = ENOENT;
1713 return -1;
1714 }
1715 if (!a->length)
1716 break;
1717 /* If this is an enumeration return this attribute. */
1718 if (type == AT_UNUSED)
1719 return 0;
1720 if (a->type != type)
1721 continue;
1722 /*
1723 * If @name is AT_UNNAMED we want an unnamed attribute.
1724 * If @name is present, compare the two names.
1725 * Otherwise, match any attribute.
1726 */
1727 if (name == AT_UNNAMED) {
1728 /* The search failed if the found attribute is named. */
1729 if (a->name_length) {
1730 errno = ENOENT;
1731 return -1;
1732 }
1733 } else if (name && !ntfs_names_are_equal(name, name_len,
1734 (ntfschar*)((char*)a + le16_to_cpu(a->name_offset)),
1735 a->name_length, ic, upcase, upcase_len)) {
1736 register int rc;
1737
1738 rc = ntfs_names_collate(name, name_len,
1739 (ntfschar*)((char*)a +
1740 le16_to_cpu(a->name_offset)),
1741 a->name_length, 1, IGNORE_CASE,
1742 upcase, upcase_len);
1743 /*
1744 * If @name collates before a->name, there is no
1745 * matching attribute.
1746 */
1747 if (rc == -1) {
1748 errno = ENOENT;
1749 return -1;
1750 }
1751 /* If the strings are not equal, continue search. */
1752 if (rc)
1753 continue;
1754 rc = ntfs_names_collate(name, name_len,
1755 (ntfschar*)((char*)a +
1756 le16_to_cpu(a->name_offset)),
1757 a->name_length, 1, CASE_SENSITIVE,
1758 upcase, upcase_len);
1759 if (rc == -1) {
1760 errno = ENOENT;
1761 return -1;
1762 }
1763 if (rc)
1764 continue;
1765 }
1766 /*
1767 * The names match or @name not present and attribute is
1768 * unnamed. If no @val specified, we have found the attribute
1769 * and are done.
1770 */
1771 if (!val)
1772 return 0;
1773 /* @val is present; compare values. */
1774 else {
1775 register int rc;
1776
1777 rc = memcmp(val, (char*)a +le16_to_cpu(a->u.res.value_offset),
1778 min(val_len,
1779 le32_to_cpu(a->u.res.value_length)));
1780 /*
1781 * If @val collates before the current attribute's
1782 * value, there is no matching attribute.
1783 */
1784 if (!rc) {
1785 register u32 avl;
1786 avl = le32_to_cpu(a->u.res.value_length);
1787 if (val_len == avl)
1788 return 0;
1789 if (val_len < avl) {
1790 errno = ENOENT;
1791 return -1;
1792 }
1793 } else if (rc < 0) {
1794 errno = ENOENT;
1795 return -1;
1796 }
1797 }
1798 }
1799 ntfs_log_debug("ntfs_attr_find(): File is corrupt. Run chkdsk.\n");
1800 errno = EIO;
1801 return -1;
1802 }
1803
1804 /**
1805 * ntfs_external_attr_find - find an attribute in the attribute list of an inode
1806 * @type: attribute type to find
1807 * @name: attribute name to find (optional, i.e. NULL means don't care)
1808 * @name_len: attribute name length (only needed if @name present)
1809 * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
1810 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
1811 * @val: attribute value to find (optional, resident attributes only)
1812 * @val_len: attribute value length
1813 * @ctx: search context with mft record and attribute to search from
1814 *
1815 * You shouldn't need to call this function directly. Use ntfs_attr_lookup()
1816 * instead.
1817 *
1818 * Find an attribute by searching the attribute list for the corresponding
1819 * attribute list entry. Having found the entry, map the mft record for read
1820 * if the attribute is in a different mft record/inode, find the attribute in
1821 * there and return it.
1822 *
1823 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
1824 * enumerate all attributes by setting @type to AT_UNUSED and then calling
1825 * ntfs_external_attr_find() repeatedly until it returns -1 with errno set to
1826 * ENOENT to indicate that there are no more entries. During the enumeration,
1827 * each successful call of ntfs_external_attr_find() will return the next
1828 * attribute described by the attribute list of the base mft record described
1829 * by the search context @ctx.
1830 *
1831 * If @type is AT_END, seek to the end of the base mft record ignoring the
1832 * attribute list completely and return -1 with errno set to ENOENT. AT_END is
1833 * not a valid attribute, its length is zero for example, thus it is safer to
1834 * return error instead of success in this case.
1835 *
1836 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
1837 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
1838 * match both named and unnamed attributes.
1839 *
1840 * On first search @ctx->ntfs_ino must be the inode of the base mft record and
1841 * @ctx must have been obtained from a call to ntfs_attr_get_search_ctx().
1842 * On subsequent calls, @ctx->ntfs_ino can be any extent inode, too
1843 * (@ctx->base_ntfs_ino is then the base inode).
1844 *
1845 * After finishing with the attribute/mft record you need to call
1846 * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
1847 * mapped extent inodes, etc).
1848 *
1849 * Return 0 if the search was successful and -1 if not, with errno set to the
1850 * error code.
1851 *
1852 * On success, @ctx->attr is the found attribute, it is in mft record
1853 * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
1854 * attribute with @ctx->base_* being the base mft record to which @ctx->attr
1855 * belongs.
1856 *
1857 * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
1858 * attribute which collates just after the attribute being searched for in the
1859 * base ntfs inode, i.e. if one wants to add the attribute to the mft record
1860 * this is the correct place to insert it into, and if there is not enough
1861 * space, the attribute should be placed in an extent mft record.
1862 * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
1863 * at which the new attribute's attribute list entry should be inserted. The
1864 * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
1865 * The only exception to this is when @type is AT_END, in which case
1866 * @ctx->al_entry is set to NULL also (see above).
1867 *
1868 * The following error codes are defined:
1869 * ENOENT Attribute not found, not an error as such.
1870 * EINVAL Invalid arguments.
1871 * EIO I/O error or corrupt data structures found.
1872 * ENOMEM Not enough memory to allocate necessary buffers.
1873 */
ntfs_external_attr_find(ATTR_TYPES type,const ntfschar * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const VCN lowest_vcn,const u8 * val,const u32 val_len,ntfs_attr_search_ctx * ctx)1874 static int ntfs_external_attr_find(ATTR_TYPES type, const ntfschar *name,
1875 const u32 name_len, const IGNORE_CASE_BOOL ic,
1876 const VCN lowest_vcn, const u8 *val, const u32 val_len,
1877 ntfs_attr_search_ctx *ctx)
1878 {
1879 ntfs_inode *base_ni, *ni;
1880 ntfs_volume *vol;
1881 ATTR_LIST_ENTRY *al_entry, *next_al_entry;
1882 u8 *al_start, *al_end;
1883 ATTR_RECORD *a;
1884 ntfschar *al_name;
1885 u32 al_name_len;
1886 BOOL is_first_search = FALSE;
1887
1888 ni = ctx->ntfs_ino;
1889 base_ni = ctx->base_ntfs_ino;
1890 ntfs_log_trace("Entering for inode 0x%llx, attribute type 0x%x.\n",
1891 (unsigned long long)ni->mft_no, type);
1892 if (!base_ni) {
1893 /* First call happens with the base mft record. */
1894 base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino;
1895 ctx->base_mrec = ctx->mrec;
1896 }
1897 if (ni == base_ni)
1898 ctx->base_attr = ctx->attr;
1899 if (type == AT_END)
1900 goto not_found;
1901 vol = base_ni->vol;
1902 al_start = base_ni->attr_list;
1903 al_end = al_start + base_ni->attr_list_size;
1904 if (!ctx->al_entry) {
1905 ctx->al_entry = (ATTR_LIST_ENTRY*)al_start;
1906 is_first_search = TRUE;
1907 }
1908 /*
1909 * Iterate over entries in attribute list starting at @ctx->al_entry,
1910 * or the entry following that, if @ctx->is_first is TRUE.
1911 */
1912 if (ctx->is_first) {
1913 al_entry = ctx->al_entry;
1914 ctx->is_first = FALSE;
1915 /*
1916 * If an enumeration and the first attribute is higher than
1917 * the attribute list itself, need to return the attribute list
1918 * attribute.
1919 */
1920 if ((type == AT_UNUSED) && is_first_search &&
1921 le32_to_cpu(al_entry->type) >
1922 le32_to_cpu(AT_ATTRIBUTE_LIST))
1923 goto find_attr_list_attr;
1924 } else {
1925 al_entry = (ATTR_LIST_ENTRY*)((char*)ctx->al_entry +
1926 le16_to_cpu(ctx->al_entry->length));
1927 /*
1928 * If this is an enumeration and the attribute list attribute
1929 * is the next one in the enumeration sequence, just return the
1930 * attribute list attribute from the base mft record as it is
1931 * not listed in the attribute list itself.
1932 */
1933 if ((type == AT_UNUSED) && le32_to_cpu(ctx->al_entry->type) <
1934 le32_to_cpu(AT_ATTRIBUTE_LIST) &&
1935 le32_to_cpu(al_entry->type) >
1936 le32_to_cpu(AT_ATTRIBUTE_LIST)) {
1937 int rc;
1938 find_attr_list_attr:
1939
1940 /* Check for bogus calls. */
1941 if (name || name_len || val || val_len || lowest_vcn) {
1942 errno = EINVAL;
1943 return -1;
1944 }
1945
1946 /* We want the base record. */
1947 ctx->ntfs_ino = base_ni;
1948 ctx->mrec = ctx->base_mrec;
1949 ctx->is_first = TRUE;
1950 /* Sanity checks are performed elsewhere. */
1951 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
1952 le16_to_cpu(ctx->mrec->attrs_offset));
1953
1954 /* Find the attribute list attribute. */
1955 rc = ntfs_attr_find(AT_ATTRIBUTE_LIST, NULL, 0,
1956 IGNORE_CASE, NULL, 0, ctx);
1957
1958 /*
1959 * Setup the search context so the correct
1960 * attribute is returned next time round.
1961 */
1962 ctx->al_entry = al_entry;
1963 ctx->is_first = TRUE;
1964
1965 /* Got it. Done. */
1966 if (!rc)
1967 return 0;
1968
1969 /* Error! If other than not found return it. */
1970 if (errno != ENOENT)
1971 return rc;
1972
1973 /* Not found?!? Absurd! Must be a bug... )-: */
1974 ntfs_log_trace("BUG! Attribute list attribute not "
1975 "found but it exists! "
1976 "Returning error (EINVAL).\n");
1977 errno = EINVAL;
1978 return -1;
1979 }
1980 }
1981 for (;; al_entry = next_al_entry) {
1982 /* Out of bounds check. */
1983 if ((u8*)al_entry < base_ni->attr_list ||
1984 (u8*)al_entry > al_end)
1985 break; /* Inode is corrupt. */
1986 ctx->al_entry = al_entry;
1987 /* Catch the end of the attribute list. */
1988 if ((u8*)al_entry == al_end)
1989 goto not_found;
1990 if (!al_entry->length)
1991 break;
1992 if ((u8*)al_entry + 6 > al_end || (u8*)al_entry +
1993 le16_to_cpu(al_entry->length) > al_end)
1994 break;
1995 next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
1996 le16_to_cpu(al_entry->length));
1997 if (type != AT_UNUSED) {
1998 if (le32_to_cpu(al_entry->type) > le32_to_cpu(type))
1999 goto not_found;
2000 if (type != al_entry->type)
2001 continue;
2002 }
2003 al_name_len = al_entry->name_length;
2004 al_name = (ntfschar*)((u8*)al_entry + al_entry->name_offset);
2005 /*
2006 * If !@type we want the attribute represented by this
2007 * attribute list entry.
2008 */
2009 if (type == AT_UNUSED)
2010 goto is_enumeration;
2011 /*
2012 * If @name is AT_UNNAMED we want an unnamed attribute.
2013 * If @name is present, compare the two names.
2014 * Otherwise, match any attribute.
2015 */
2016 if (name == AT_UNNAMED) {
2017 if (al_name_len)
2018 goto not_found;
2019 } else if (name && !ntfs_names_are_equal(al_name, al_name_len,
2020 name, name_len, ic, vol->upcase,
2021 vol->upcase_len)) {
2022 register int rc;
2023
2024 rc = ntfs_names_collate(name, name_len, al_name,
2025 al_name_len, 1, IGNORE_CASE,
2026 vol->upcase, vol->upcase_len);
2027 /*
2028 * If @name collates before al_name, there is no
2029 * matching attribute.
2030 */
2031 if (rc == -1)
2032 goto not_found;
2033 /* If the strings are not equal, continue search. */
2034 if (rc)
2035 continue;
2036 /*
2037 * FIXME: Reverse engineering showed 0, IGNORE_CASE but
2038 * that is inconsistent with ntfs_attr_find(). The
2039 * subsequent rc checks were also different. Perhaps I
2040 * made a mistake in one of the two. Need to recheck
2041 * which is correct or at least see what is going
2042 * on... (AIA)
2043 */
2044 rc = ntfs_names_collate(name, name_len, al_name,
2045 al_name_len, 1, CASE_SENSITIVE,
2046 vol->upcase, vol->upcase_len);
2047 if (rc == -1)
2048 goto not_found;
2049 if (rc)
2050 continue;
2051 }
2052 /*
2053 * The names match or @name not present and attribute is
2054 * unnamed. Now check @lowest_vcn. Continue search if the
2055 * next attribute list entry still fits @lowest_vcn. Otherwise
2056 * we have reached the right one or the search has failed.
2057 */
2058 if (lowest_vcn && (u8*)next_al_entry >= al_start &&
2059 (u8*)next_al_entry + 6 < al_end &&
2060 (u8*)next_al_entry + le16_to_cpu(
2061 next_al_entry->length) <= al_end &&
2062 sle64_to_cpu(next_al_entry->lowest_vcn) <=
2063 lowest_vcn &&
2064 next_al_entry->type == al_entry->type &&
2065 next_al_entry->name_length == al_name_len &&
2066 ntfs_names_are_equal((ntfschar*)((char*)
2067 next_al_entry +
2068 next_al_entry->name_offset),
2069 next_al_entry->name_length,
2070 al_name, al_name_len, CASE_SENSITIVE,
2071 vol->upcase, vol->upcase_len))
2072 continue;
2073 is_enumeration:
2074 if (MREF_LE(al_entry->mft_reference) == ni->mft_no) {
2075 if (MSEQNO_LE(al_entry->mft_reference) !=
2076 le16_to_cpu(
2077 ni->mrec->sequence_number)) {
2078 ntfs_log_debug("Found stale mft reference in "
2079 "attribute list!\n");
2080 break;
2081 }
2082 } else { /* Mft references do not match. */
2083 /* Do we want the base record back? */
2084 if (MREF_LE(al_entry->mft_reference) ==
2085 base_ni->mft_no) {
2086 ni = ctx->ntfs_ino = base_ni;
2087 ctx->mrec = ctx->base_mrec;
2088 } else {
2089 /* We want an extent record. */
2090 ni = ntfs_extent_inode_open(base_ni,
2091 al_entry->mft_reference);
2092 if (!ni) {
2093 ntfs_log_perror("Failed to map extent "
2094 "inode");
2095 break;
2096 }
2097 ctx->ntfs_ino = ni;
2098 ctx->mrec = ni->mrec;
2099 }
2100 }
2101 a = ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec +
2102 le16_to_cpu(ctx->mrec->attrs_offset));
2103 /*
2104 * ctx->ntfs_ino, ctx->mrec, and ctx->attr now point to the
2105 * mft record containing the attribute represented by the
2106 * current al_entry.
2107 *
2108 * We could call into ntfs_attr_find() to find the right
2109 * attribute in this mft record but this would be less
2110 * efficient and not quite accurate as ntfs_attr_find() ignores
2111 * the attribute instance numbers for example which become
2112 * important when one plays with attribute lists. Also, because
2113 * a proper match has been found in the attribute list entry
2114 * above, the comparison can now be optimized. So it is worth
2115 * re-implementing a simplified ntfs_attr_find() here.
2116 *
2117 * Use a manual loop so we can still use break and continue
2118 * with the same meanings as above.
2119 */
2120 do_next_attr_loop:
2121 if ((char*)a < (char*)ctx->mrec || (char*)a > (char*)ctx->mrec +
2122 le32_to_cpu(ctx->mrec->bytes_allocated))
2123 break;
2124 if (a->type == AT_END)
2125 continue;
2126 if (!a->length)
2127 break;
2128 if (al_entry->instance != a->instance)
2129 goto do_next_attr;
2130 /*
2131 * If the type and/or the name are/is mismatched between the
2132 * attribute list entry and the attribute record, there is
2133 * corruption so we break and return error EIO.
2134 */
2135 if (al_entry->type != a->type)
2136 break;
2137 if (!ntfs_names_are_equal((ntfschar*)((char*)a +
2138 le16_to_cpu(a->name_offset)),
2139 a->name_length, al_name,
2140 al_name_len, CASE_SENSITIVE,
2141 vol->upcase, vol->upcase_len))
2142 break;
2143 ctx->attr = a;
2144 /*
2145 * If no @val specified or @val specified and it matches, we
2146 * have found it! Also, if !@type, it is an enumeration, so we
2147 * want the current attribute.
2148 */
2149 if ((type == AT_UNUSED) || !val || (!a->non_resident &&
2150 le32_to_cpu(a->u.res.value_length) == val_len &&
2151 !memcmp((char*)a + le16_to_cpu(a->u.res.value_offset),
2152 val, val_len))) {
2153 return 0;
2154 }
2155 do_next_attr:
2156 /* Proceed to the next attribute in the current mft record. */
2157 a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
2158 goto do_next_attr_loop;
2159 }
2160 if (ni != base_ni) {
2161 ctx->ntfs_ino = base_ni;
2162 ctx->mrec = ctx->base_mrec;
2163 ctx->attr = ctx->base_attr;
2164 }
2165 ntfs_log_debug("Inode is corrupt.\n");
2166 errno = EIO;
2167 return -1;
2168 not_found:
2169 /*
2170 * If we were looking for AT_END or we were enumerating and reached the
2171 * end, we reset the search context @ctx and use ntfs_attr_find() to
2172 * seek to the end of the base mft record.
2173 */
2174 if (type == AT_UNUSED || type == AT_END) {
2175 ntfs_attr_reinit_search_ctx(ctx);
2176 return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len,
2177 ctx);
2178 }
2179 /*
2180 * The attribute wasn't found. Before we return, we want to ensure
2181 * @ctx->mrec and @ctx->attr indicate the position at which the
2182 * attribute should be inserted in the base mft record. Since we also
2183 * want to preserve @ctx->al_entry we cannot reinitialize the search
2184 * context using ntfs_attr_reinit_search_ctx() as this would set
2185 * @ctx->al_entry to NULL. Thus we do the necessary bits manually (see
2186 * ntfs_attr_init_search_ctx() below). Note, we _only_ preserve
2187 * @ctx->al_entry as the remaining fields (base_*) are identical to
2188 * their non base_ counterparts and we cannot set @ctx->base_attr
2189 * correctly yet as we do not know what @ctx->attr will be set to by
2190 * the call to ntfs_attr_find() below.
2191 */
2192 ctx->mrec = ctx->base_mrec;
2193 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
2194 le16_to_cpu(ctx->mrec->attrs_offset));
2195 ctx->is_first = TRUE;
2196 ctx->ntfs_ino = ctx->base_ntfs_ino;
2197 ctx->base_ntfs_ino = NULL;
2198 ctx->base_mrec = NULL;
2199 ctx->base_attr = NULL;
2200 /*
2201 * In case there are multiple matches in the base mft record, need to
2202 * keep enumerating until we get an attribute not found response (or
2203 * another error), otherwise we would keep returning the same attribute
2204 * over and over again and all programs using us for enumeration would
2205 * lock up in a tight loop.
2206 */
2207 {
2208 int ret;
2209
2210 do {
2211 ret = ntfs_attr_find(type, name, name_len, ic, val,
2212 val_len, ctx);
2213 } while (!ret);
2214 return ret;
2215 }
2216 }
2217
2218 /**
2219 * ntfs_attr_lookup - find an attribute in an ntfs inode
2220 * @type: attribute type to find
2221 * @name: attribute name to find (optional, i.e. NULL means don't care)
2222 * @name_len: attribute name length (only needed if @name present)
2223 * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
2224 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
2225 * @val: attribute value to find (optional, resident attributes only)
2226 * @val_len: attribute value length
2227 * @ctx: search context with mft record and attribute to search from
2228 *
2229 * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
2230 * be the base mft record and @ctx must have been obtained from a call to
2231 * ntfs_attr_get_search_ctx().
2232 *
2233 * This function transparently handles attribute lists and @ctx is used to
2234 * continue searches where they were left off at.
2235 *
2236 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
2237 * enumerate all attributes by setting @type to AT_UNUSED and then calling
2238 * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
2239 * to indicate that there are no more entries. During the enumeration, each
2240 * successful call of ntfs_attr_lookup() will return the next attribute, with
2241 * the current attribute being described by the search context @ctx.
2242 *
2243 * If @type is AT_END, seek to the end of the base mft record ignoring the
2244 * attribute list completely and return -1 with errno set to ENOENT. AT_END is
2245 * not a valid attribute, its length is zero for example, thus it is safer to
2246 * return error instead of success in this case. It should never be needed to
2247 * do this, but we implement the functionality because it allows for simpler
2248 * code inside ntfs_external_attr_find().
2249 *
2250 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
2251 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
2252 * match both named and unnamed attributes.
2253 *
2254 * After finishing with the attribute/mft record you need to call
2255 * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
2256 * mapped extent inodes, etc).
2257 *
2258 * Return 0 if the search was successful and -1 if not, with errno set to the
2259 * error code.
2260 *
2261 * On success, @ctx->attr is the found attribute, it is in mft record
2262 * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
2263 * attribute with @ctx->base_* being the base mft record to which @ctx->attr
2264 * belongs. If no attribute list attribute is present @ctx->al_entry and
2265 * @ctx->base_* are NULL.
2266 *
2267 * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
2268 * attribute which collates just after the attribute being searched for in the
2269 * base ntfs inode, i.e. if one wants to add the attribute to the mft record
2270 * this is the correct place to insert it into, and if there is not enough
2271 * space, the attribute should be placed in an extent mft record.
2272 * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
2273 * at which the new attribute's attribute list entry should be inserted. The
2274 * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
2275 * The only exception to this is when @type is AT_END, in which case
2276 * @ctx->al_entry is set to NULL also (see above).
2277 *
2278 *
2279 * The following error codes are defined:
2280 * ENOENT Attribute not found, not an error as such.
2281 * EINVAL Invalid arguments.
2282 * EIO I/O error or corrupt data structures found.
2283 * ENOMEM Not enough memory to allocate necessary buffers.
2284 */
ntfs_attr_lookup(const ATTR_TYPES type,const ntfschar * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const VCN lowest_vcn,const u8 * val,const u32 val_len,ntfs_attr_search_ctx * ctx)2285 int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
2286 const u32 name_len, const IGNORE_CASE_BOOL ic,
2287 const VCN lowest_vcn, const u8 *val, const u32 val_len,
2288 ntfs_attr_search_ctx *ctx)
2289 {
2290 ntfs_volume *vol;
2291 ntfs_inode *base_ni;
2292
2293 if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED &&
2294 (!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) ||
2295 !vol->upcase || !vol->upcase_len))) {
2296 errno = EINVAL;
2297 return -1;
2298 }
2299 if (ctx->base_ntfs_ino)
2300 base_ni = ctx->base_ntfs_ino;
2301 else
2302 base_ni = ctx->ntfs_ino;
2303 if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
2304 return ntfs_attr_find(type, name, name_len, ic, val, val_len,
2305 ctx);
2306 return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn,
2307 val, val_len, ctx);
2308 }
2309
2310 /**
2311 * ntfs_attr_init_search_ctx - initialize an attribute search context
2312 * @ctx: attribute search context to initialize
2313 * @ni: ntfs inode with which to initialize the search context
2314 * @mrec: mft record with which to initialize the search context
2315 *
2316 * Initialize the attribute search context @ctx with @ni and @mrec.
2317 */
ntfs_attr_init_search_ctx(ntfs_attr_search_ctx * ctx,ntfs_inode * ni,MFT_RECORD * mrec)2318 static void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
2319 ntfs_inode *ni, MFT_RECORD *mrec)
2320 {
2321 if (!mrec)
2322 mrec = ni->mrec;
2323 ctx->mrec = mrec;
2324 /* Sanity checks are performed elsewhere. */
2325 ctx->attr = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset));
2326 ctx->is_first = TRUE;
2327 ctx->ntfs_ino = ni;
2328 ctx->al_entry = NULL;
2329 ctx->base_ntfs_ino = NULL;
2330 ctx->base_mrec = NULL;
2331 ctx->base_attr = NULL;
2332 }
2333
2334 /**
2335 * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
2336 * @ctx: attribute search context to reinitialize
2337 *
2338 * Reinitialize the attribute search context @ctx.
2339 *
2340 * This is used when a search for a new attribute is being started to reset
2341 * the search context to the beginning.
2342 */
ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx * ctx)2343 void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
2344 {
2345 if (!ctx->base_ntfs_ino) {
2346 /* No attribute list. */
2347 ctx->is_first = TRUE;
2348 /* Sanity checks are performed elsewhere. */
2349 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
2350 le16_to_cpu(ctx->mrec->attrs_offset));
2351 /*
2352 * This needs resetting due to ntfs_external_attr_find() which
2353 * can leave it set despite having zeroed ctx->base_ntfs_ino.
2354 */
2355 ctx->al_entry = NULL;
2356 return;
2357 } /* Attribute list. */
2358 ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
2359 return;
2360 }
2361
2362 /**
2363 * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
2364 * @ni: ntfs inode with which to initialize the search context
2365 * @mrec: mft record with which to initialize the search context
2366 *
2367 * Allocate a new attribute search context, initialize it with @ni and @mrec,
2368 * and return it. Return NULL on error with errno set to ENOMEM.
2369 *
2370 * @mrec can be NULL, in which case the mft record is taken from @ni.
2371 *
2372 * Note: For low level utilities which know what they are doing we allow @ni to
2373 * be NULL and @mrec to be set. Do NOT do this unless you understand the
2374 * implications!!! For example it is no longer safe to call ntfs_attr_lookup()
2375 * if you
2376 */
ntfs_attr_get_search_ctx(ntfs_inode * ni,MFT_RECORD * mrec)2377 ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
2378 {
2379 ntfs_attr_search_ctx *ctx;
2380
2381 if (!ni && !mrec) {
2382 errno = EINVAL;
2383 return NULL;
2384 }
2385 ctx = ntfs_malloc(sizeof(ntfs_attr_search_ctx));
2386 if (ctx)
2387 ntfs_attr_init_search_ctx(ctx, ni, mrec);
2388 return ctx;
2389 }
2390
2391 /**
2392 * ntfs_attr_put_search_ctx - release an attribute search context
2393 * @ctx: attribute search context to free
2394 *
2395 * Release the attribute search context @ctx. This function does not change
2396 * errno and doing nothing if NULL passed to it.
2397 */
ntfs_attr_put_search_ctx(ntfs_attr_search_ctx * ctx)2398 void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
2399 {
2400 free(ctx);
2401 }
2402
2403 /**
2404 * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file
2405 * @vol: ntfs volume to which the attribute belongs
2406 * @type: attribute type which to find
2407 *
2408 * Search for the attribute definition record corresponding to the attribute
2409 * @type in the $AttrDef system file.
2410 *
2411 * Return the attribute type definition record if found and NULL if not found
2412 * or an error occurred. On error the error code is stored in errno. The
2413 * following error codes are defined:
2414 * ENOENT - The attribute @type is not specified in $AttrDef.
2415 * EINVAL - Invalid parameters (e.g. @vol is not valid).
2416 */
ntfs_attr_find_in_attrdef(const ntfs_volume * vol,const ATTR_TYPES type)2417 ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
2418 const ATTR_TYPES type)
2419 {
2420 ATTR_DEF *ad;
2421
2422 if (!vol || !vol->attrdef || !type) {
2423 errno = EINVAL;
2424 return NULL;
2425 }
2426 for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef <
2427 vol->attrdef_len && ad->type; ++ad) {
2428 /* We haven't found it yet, carry on searching. */
2429 if (le32_to_cpu(ad->type) < le32_to_cpu(type))
2430 continue;
2431 /* We found the attribute; return it. */
2432 if (ad->type == type)
2433 return ad;
2434 /* We have gone too far already. No point in continuing. */
2435 break;
2436 }
2437 /* Attribute not found?!? */
2438 errno = ENOENT;
2439 return NULL;
2440 }
2441
2442 /**
2443 * ntfs_attr_size_bounds_check - check a size of an attribute type for validity
2444 * @vol: ntfs volume to which the attribute belongs
2445 * @type: attribute type which to check
2446 * @size: size which to check
2447 *
2448 * Check whether the @size in bytes is valid for an attribute of @type on the
2449 * ntfs volume @vol. This information is obtained from $AttrDef system file.
2450 *
2451 * Return 0 if valid and -1 if not valid or an error occurred. On error the
2452 * error code is stored in errno. The following error codes are defined:
2453 * ERANGE - @size is not valid for the attribute @type.
2454 * ENOENT - The attribute @type is not specified in $AttrDef.
2455 * EINVAL - Invalid parameters (e.g. @size is < 0 or @vol is not valid).
2456 */
ntfs_attr_size_bounds_check(const ntfs_volume * vol,const ATTR_TYPES type,const s64 size)2457 int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
2458 const s64 size)
2459 {
2460 ATTR_DEF *ad;
2461
2462 if (size < 0) {
2463 errno = EINVAL;
2464 return -1;
2465 }
2466
2467 /*
2468 * $ATTRIBUTE_LIST should be not greater than 0x40000, but this is not
2469 * listed in the AttrDef.
2470 */
2471 if (type == AT_ATTRIBUTE_LIST && size > 0x40000) {
2472 errno = ERANGE;
2473 return -1;
2474 }
2475
2476 ad = ntfs_attr_find_in_attrdef(vol, type);
2477 if (!ad)
2478 return -1;
2479 /* We found the attribute. - Do the bounds check. */
2480 if ((sle64_to_cpu(ad->min_size) && size <
2481 sle64_to_cpu(ad->min_size)) ||
2482 ((sle64_to_cpu(ad->max_size) > 0) && size >
2483 sle64_to_cpu(ad->max_size))) {
2484 /* @size is out of range! */
2485 errno = ERANGE;
2486 return -1;
2487 }
2488 return 0;
2489 }
2490
2491 /**
2492 * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident
2493 * @vol: ntfs volume to which the attribute belongs
2494 * @type: attribute type which to check
2495 *
2496 * Check whether the attribute of @type on the ntfs volume @vol is allowed to
2497 * be non-resident. This information is obtained from $AttrDef system file.
2498 *
2499 * Return 0 if the attribute is allowed to be non-resident and -1 if not or an
2500 * error occurred. On error the error code is stored in errno. The following
2501 * error codes are defined:
2502 * EPERM - The attribute is not allowed to be non-resident.
2503 * ENOENT - The attribute @type is not specified in $AttrDef.
2504 * EINVAL - Invalid parameters (e.g. @vol is not valid).
2505 */
ntfs_attr_can_be_non_resident(const ntfs_volume * vol,const ATTR_TYPES type)2506 int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type)
2507 {
2508 ATTR_DEF *ad;
2509
2510 /* Find the attribute definition record in $AttrDef. */
2511 ad = ntfs_attr_find_in_attrdef(vol, type);
2512 if (!ad)
2513 return -1;
2514 /* Check the flags and return the result. */
2515 if (ad->flags & ATTR_DEF_RESIDENT) {
2516 ntfs_log_trace("Attribute can't be non-resident\n");
2517 errno = EPERM;
2518 return -1;
2519 }
2520 return 0;
2521 }
2522
2523 /**
2524 * ntfs_attr_can_be_resident - check if an attribute can be resident
2525 * @vol: ntfs volume to which the attribute belongs
2526 * @type: attribute type which to check
2527 *
2528 * Check whether the attribute of @type on the ntfs volume @vol is allowed to
2529 * be resident. This information is derived from our ntfs knowledge and may
2530 * not be completely accurate, especially when user defined attributes are
2531 * present. Basically we allow everything to be resident except for index
2532 * allocation and extended attribute attributes.
2533 *
2534 * Return 0 if the attribute is allowed to be resident and -1 if not or an
2535 * error occurred. On error the error code is stored in errno. The following
2536 * error codes are defined:
2537 * EPERM - The attribute is not allowed to be resident.
2538 * EINVAL - Invalid parameters (e.g. @vol is not valid).
2539 *
2540 * Warning: In the system file $MFT the attribute $Bitmap must be non-resident
2541 * otherwise windows will not boot (blue screen of death)! We cannot
2542 * check for this here as we don't know which inode's $Bitmap is being
2543 * asked about so the caller needs to special case this.
2544 */
ntfs_attr_can_be_resident(const ntfs_volume * vol,const ATTR_TYPES type)2545 int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPES type)
2546 {
2547 if (!vol || !vol->attrdef || !type) {
2548 errno = EINVAL;
2549 return -1;
2550 }
2551 if (type != AT_INDEX_ALLOCATION)
2552 return 0;
2553
2554 ntfs_log_trace("Attribute can't be resident\n");
2555 errno = EPERM;
2556 return -1;
2557 }
2558
2559 /**
2560 * ntfs_make_room_for_attr - make room for an attribute inside an mft record
2561 * @m: mft record
2562 * @pos: position at which to make space
2563 * @size: byte size to make available at this position
2564 *
2565 * @pos points to the attribute in front of which we want to make space.
2566 *
2567 * Return 0 on success or -1 on error. On error the error code is stored in
2568 * errno. Possible error codes are:
2569 * ENOSPC - There is not enough space available to complete operation. The
2570 * caller has to make space before calling this.
2571 * EINVAL - Input parameters were faulty.
2572 */
ntfs_make_room_for_attr(MFT_RECORD * m,u8 * pos,u32 size)2573 int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size)
2574 {
2575 u32 biu;
2576
2577 ntfs_log_trace("Entering for pos 0x%d, size %u.\n",
2578 (int)(pos - (u8*)m), (unsigned) size);
2579
2580 /* Make size 8-byte alignment. */
2581 size = (size + 7) & ~7;
2582
2583 /* Rigorous consistency checks. */
2584 if (!m || !pos || pos < (u8*)m || pos + size >
2585 (u8*)m + le32_to_cpu(m->bytes_allocated)) {
2586 errno = EINVAL;
2587 return -1;
2588 }
2589 /* The -8 is for the attribute terminator. */
2590 if (pos - (u8*)m > (int)le32_to_cpu(m->bytes_in_use) - 8) {
2591 errno = EINVAL;
2592 return -1;
2593 }
2594 /* Nothing to do. */
2595 if (!size)
2596 return 0;
2597
2598 biu = le32_to_cpu(m->bytes_in_use);
2599 /* Do we have enough space? */
2600 if (biu + size > le32_to_cpu(m->bytes_allocated)) {
2601 ntfs_log_trace("Not enough space in the MFT record\n");
2602 errno = ENOSPC;
2603 return -1;
2604 }
2605 /* Move everything after pos to pos + size. */
2606 memmove(pos + size, pos, biu - (pos - (u8*)m));
2607 /* Update mft record. */
2608 m->bytes_in_use = cpu_to_le32(biu + size);
2609 return 0;
2610 }
2611
2612 /**
2613 * ntfs_resident_attr_record_add - add resident attribute to inode
2614 * @ni: opened ntfs inode to which MFT record add attribute
2615 * @type: type of the new attribute
2616 * @name: name of the new attribute
2617 * @name_len: name length of the new attribute
2618 * @val: value of the new attribute
2619 * @size: size of new attribute (length of @val, if @val != NULL)
2620 * @flags: flags of the new attribute
2621 *
2622 * Return offset to attribute from the beginning of the mft record on success
2623 * and -1 on error. On error the error code is stored in errno.
2624 * Possible error codes are:
2625 * EINVAL - Invalid arguments passed to function.
2626 * EEXIST - Attribute of such type and with same name already exists.
2627 * EIO - I/O error occurred or damaged filesystem.
2628 */
ntfs_resident_attr_record_add(ntfs_inode * ni,ATTR_TYPES type,ntfschar * name,u8 name_len,u8 * val,u32 size,ATTR_FLAGS flags)2629 int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
2630 ntfschar *name, u8 name_len, u8 *val, u32 size,
2631 ATTR_FLAGS flags)
2632 {
2633 ntfs_attr_search_ctx *ctx;
2634 u32 length;
2635 ATTR_RECORD *a;
2636 MFT_RECORD *m;
2637 int err, offset;
2638 ntfs_inode *base_ni;
2639
2640 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, flags 0x%x.\n",
2641 (long long) ni->mft_no, le32_to_cpu(type), le16_to_cpu(flags));
2642
2643 if (!ni || (!name && name_len)) {
2644 errno = EINVAL;
2645 return -1;
2646 }
2647
2648 if (ntfs_attr_can_be_resident(ni->vol, type)) {
2649 if (errno == EPERM)
2650 ntfs_log_trace("Attribute can't be resident.\n");
2651 else
2652 ntfs_log_trace("ntfs_attr_can_be_resident failed.\n");
2653 return -1;
2654 }
2655
2656 /* Locate place where record should be. */
2657 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2658 if (!ctx)
2659 return -1;
2660 /*
2661 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
2662 * attribute in @ni->mrec, not any extent inode in case if @ni is base
2663 * file record.
2664 */
2665 if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, val, size,
2666 ctx)) {
2667 err = EEXIST;
2668 ntfs_log_trace("Attribute already present.\n");
2669 goto put_err_out;
2670 }
2671 if (errno != ENOENT) {
2672 err = EIO;
2673 goto put_err_out;
2674 }
2675 a = ctx->attr;
2676 m = ctx->mrec;
2677
2678 /* Make room for attribute. */
2679 length = offsetof(ATTR_RECORD, u.res.resident_end) +
2680 ((name_len * sizeof(ntfschar) + 7) & ~7) +
2681 ((size + 7) & ~7);
2682 if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) {
2683 err = errno;
2684 ntfs_log_trace("Failed to make room for attribute.\n");
2685 goto put_err_out;
2686 }
2687
2688 /* Setup record fields. */
2689 offset = ((u8*)a - (u8*)m);
2690 a->type = type;
2691 a->length = cpu_to_le32(length);
2692 a->non_resident = 0;
2693 a->name_length = name_len;
2694 a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, u.res.resident_end));
2695 a->flags = flags;
2696 a->instance = m->next_attr_instance;
2697 a->u.res.value_length = cpu_to_le32(size);
2698 a->u.res.value_offset = cpu_to_le16(length - ((size + 7) & ~7));
2699 if (val)
2700 memcpy((u8*)a + le16_to_cpu(a->u.res.value_offset), val, size);
2701 else
2702 memset((u8*)a + le16_to_cpu(a->u.res.value_offset), 0, size);
2703 if (type == AT_FILE_NAME)
2704 a->u.res.resident_flags = RESIDENT_ATTR_IS_INDEXED;
2705 else
2706 a->u.res.resident_flags = 0;
2707 if (name_len)
2708 memcpy((u8*)a + le16_to_cpu(a->name_offset),
2709 name, sizeof(ntfschar) * name_len);
2710 m->next_attr_instance =
2711 cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
2712 if (ni->nr_extents == -1)
2713 base_ni = ni->u.base_ni;
2714 else
2715 base_ni = ni;
2716 if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
2717 if (ntfs_attrlist_entry_add(ni, a)) {
2718 err = errno;
2719 ntfs_attr_record_resize(m, a, 0);
2720 ntfs_log_trace("Failed add attribute entry to "
2721 "ATTRIBUTE_LIST.\n");
2722 goto put_err_out;
2723 }
2724 }
2725 ntfs_inode_mark_dirty(ni);
2726 ntfs_attr_put_search_ctx(ctx);
2727 return offset;
2728 put_err_out:
2729 ntfs_attr_put_search_ctx(ctx);
2730 errno = err;
2731 return -1;
2732 }
2733
2734 /**
2735 * ntfs_non_resident_attr_record_add - add extent of non-resident attribute
2736 * @ni: opened ntfs inode to which MFT record add attribute
2737 * @type: type of the new attribute extent
2738 * @name: name of the new attribute extent
2739 * @name_len: name length of the new attribute extent
2740 * @lowest_vcn: lowest vcn of the new attribute extent
2741 * @dataruns_size: dataruns size of the new attribute extent
2742 * @flags: flags of the new attribute extent
2743 *
2744 * Return offset to attribute from the beginning of the mft record on success
2745 * and -1 on error. On error the error code is stored in errno.
2746 * Possible error codes are:
2747 * EINVAL - Invalid arguments passed to function.
2748 * EEXIST - Attribute of such type, with same lowest vcn and with same
2749 * name already exists.
2750 * EIO - I/O error occurred or damaged filesystem.
2751 */
ntfs_non_resident_attr_record_add(ntfs_inode * ni,ATTR_TYPES type,ntfschar * name,u8 name_len,VCN lowest_vcn,int dataruns_size,ATTR_FLAGS flags)2752 int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
2753 ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
2754 ATTR_FLAGS flags)
2755 {
2756 ntfs_attr_search_ctx *ctx;
2757 u32 length;
2758 ATTR_RECORD *a;
2759 MFT_RECORD *m;
2760 ntfs_inode *base_ni;
2761 int err, offset;
2762
2763 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld, "
2764 "dataruns_size %d, flags 0x%x.\n",
2765 (long long) ni->mft_no, le32_to_cpu(type),
2766 (long long) lowest_vcn, dataruns_size,
2767 le16_to_cpu(flags));
2768
2769 if (!ni || dataruns_size <= 0 || (!name && name_len)) {
2770 errno = EINVAL;
2771 return -1;
2772 }
2773
2774 if (ntfs_attr_can_be_non_resident(ni->vol, type)) {
2775 if (errno == EPERM)
2776 ntfs_log_trace("Attribute can't be non resident.\n");
2777 else
2778 ntfs_log_trace("ntfs_attr_can_be_non_resident() "
2779 "failed.\n");
2780 return -1;
2781 }
2782
2783 /* Locate place where record should be. */
2784 ctx = ntfs_attr_get_search_ctx(ni, NULL);
2785 if (!ctx)
2786 return -1;
2787 /*
2788 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
2789 * attribute in @ni->mrec, not any extent inode in case if @ni is base
2790 * file record.
2791 */
2792 if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, NULL, 0,
2793 ctx)) {
2794 err = EEXIST;
2795 ntfs_log_trace("Attribute already present.\n");
2796 goto put_err_out;
2797 }
2798 if (errno != ENOENT) {
2799 err = EIO;
2800 goto put_err_out;
2801 }
2802 a = ctx->attr;
2803 m = ctx->mrec;
2804
2805 /* Make room for attribute. */
2806 dataruns_size = (dataruns_size + 7) & ~7;
2807 length = offsetof(ATTR_RECORD, u.nonres.compressed_size) + ((sizeof(ntfschar) *
2808 name_len + 7) & ~7) + dataruns_size +
2809 ((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ?
2810 sizeof(a->u.nonres.compressed_size) : 0);
2811 if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) {
2812 err = errno;
2813 ntfs_log_trace("Failed to make room for attribute.\n");
2814 goto put_err_out;
2815 }
2816
2817 /* Setup record fields. */
2818 a->type = type;
2819 a->length = cpu_to_le32(length);
2820 a->non_resident = 1;
2821 a->name_length = name_len;
2822 a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, u.nonres.compressed_size) +
2823 ((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ?
2824 sizeof(a->u.nonres.compressed_size) : 0));
2825 a->flags = flags;
2826 a->instance = m->next_attr_instance;
2827 a->u.nonres.lowest_vcn = cpu_to_sle64(lowest_vcn);
2828 a->u.nonres.mapping_pairs_offset = cpu_to_le16(length - dataruns_size);
2829 a->u.nonres.compression_unit = (flags & ATTR_IS_COMPRESSED) ? 4 : 0;
2830 /* If @lowest_vcn == 0, than setup empty attribute. */
2831 if (!lowest_vcn) {
2832 a->u.nonres.highest_vcn = cpu_to_sle64(-1);
2833 a->u.nonres.allocated_size = 0;
2834 a->u.nonres.data_size = 0;
2835 a->u.nonres.initialized_size = 0;
2836 /* Set empty mapping pairs. */
2837 *((u8*)a + le16_to_cpu(a->u.nonres.mapping_pairs_offset)) = 0;
2838 }
2839 if (name_len)
2840 memcpy((u8*)a + le16_to_cpu(a->name_offset),
2841 name, sizeof(ntfschar) * name_len);
2842 m->next_attr_instance =
2843 cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
2844 if (ni->nr_extents == -1)
2845 base_ni = ni->u.base_ni;
2846 else
2847 base_ni = ni;
2848 if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
2849 if (ntfs_attrlist_entry_add(ni, a)) {
2850 err = errno;
2851 ntfs_attr_record_resize(m, a, 0);
2852 ntfs_log_trace("Failed add attribute entry to "
2853 "ATTRIBUTE_LIST.\n");
2854 goto put_err_out;
2855 }
2856 }
2857 ntfs_inode_mark_dirty(ni);
2858 /*
2859 * Locate offset from start of the MFT record where new attribute is
2860 * placed. We need relookup it, because record maybe moved during
2861 * update of attribute list.
2862 */
2863 ntfs_attr_reinit_search_ctx(ctx);
2864 if (ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE,
2865 lowest_vcn, NULL, 0, ctx)) {
2866 err = errno;
2867 ntfs_log_trace("Attribute lookup failed. Probably leaving "
2868 "inconsistent metadata.\n");
2869 ntfs_attr_put_search_ctx(ctx);
2870 errno = err;
2871 return -1;
2872 }
2873 offset = (u8*)ctx->attr - (u8*)ctx->mrec;
2874 ntfs_attr_put_search_ctx(ctx);
2875 return offset;
2876 put_err_out:
2877 ntfs_attr_put_search_ctx(ctx);
2878 errno = err;
2879 return -1;
2880 }
2881
2882 /**
2883 * ntfs_attr_record_rm - remove attribute extent
2884 * @ctx: search context describing the attribute which should be removed
2885 *
2886 * If this function succeed, user should reinit search context if he/she wants
2887 * use it anymore.
2888 *
2889 * Return 0 on success and -1 on error. On error the error code is stored in
2890 * errno. Possible error codes are:
2891 * EINVAL - Invalid arguments passed to function.
2892 * EIO - I/O error occurred or damaged filesystem.
2893 */
ntfs_attr_record_rm(ntfs_attr_search_ctx * ctx)2894 int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx)
2895 {
2896 ntfs_inode *base_ni, *ni;
2897 ATTR_TYPES type;
2898 int err;
2899
2900 if (!ctx || !ctx->ntfs_ino || !ctx->mrec || !ctx->attr) {
2901 errno = EINVAL;
2902 return -1;
2903 }
2904
2905 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
2906 (long long) ctx->ntfs_ino->mft_no,
2907 (unsigned) le32_to_cpu(ctx->attr->type));
2908 type = ctx->attr->type;
2909 ni = ctx->ntfs_ino;
2910 if (ctx->base_ntfs_ino)
2911 base_ni = ctx->base_ntfs_ino;
2912 else
2913 base_ni = ctx->ntfs_ino;
2914
2915 /* Remove attribute itself. */
2916 if (ntfs_attr_record_resize(ctx->mrec, ctx->attr, 0)) {
2917 ntfs_log_trace("Couldn't remove attribute record. "
2918 "Bug or damaged MFT record.\n");
2919 if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST)
2920 if (ntfs_attrlist_entry_add(ni, ctx->attr))
2921 ntfs_log_trace("Rollback failed. Leaving "
2922 "inconsistent metadata.\n");
2923 err = EIO;
2924 return -1;
2925 }
2926 ntfs_inode_mark_dirty(ni);
2927
2928 /*
2929 * Remove record from $ATTRIBUTE_LIST if present and we don't want
2930 * delete $ATTRIBUTE_LIST itself.
2931 */
2932 if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) {
2933 if (ntfs_attrlist_entry_rm(ctx)) {
2934 ntfs_log_trace("Couldn't delete record from "
2935 "$ATTRIBUTE_LIST.\n");
2936 return -1;
2937 }
2938 }
2939
2940 /* Post $ATTRIBUTE_LIST delete setup. */
2941 if (type == AT_ATTRIBUTE_LIST) {
2942 if (NInoAttrList(base_ni) && base_ni->attr_list)
2943 free(base_ni->attr_list);
2944 base_ni->attr_list = NULL;
2945 NInoClearAttrList(base_ni);
2946 NInoAttrListClearDirty(base_ni);
2947 }
2948
2949 /* Free MFT record, if it isn't contain attributes. */
2950 if (le32_to_cpu(ctx->mrec->bytes_in_use) -
2951 le16_to_cpu(ctx->mrec->attrs_offset) == 8) {
2952 if (ntfs_mft_record_free(ni->vol, ni)) {
2953 // FIXME: We need rollback here.
2954 ntfs_log_trace("Couldn't free MFT record.\n");
2955 errno = EIO;
2956 return -1;
2957 }
2958 /* Remove done if we freed base inode. */
2959 if (ni == base_ni)
2960 return 0;
2961 }
2962
2963 if (type == AT_ATTRIBUTE_LIST || !NInoAttrList(base_ni))
2964 return 0;
2965
2966 /* Remove attribute list if we don't need it any more. */
2967 if (!ntfs_attrlist_need(base_ni)) {
2968 ntfs_attr_reinit_search_ctx(ctx);
2969 if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, CASE_SENSITIVE,
2970 0, NULL, 0, ctx)) {
2971 /*
2972 * FIXME: Should we succeed here? Definitely something
2973 * goes wrong because NInoAttrList(base_ni) returned
2974 * that we have got attribute list.
2975 */
2976 ntfs_log_trace("Couldn't find attribute list. Succeed "
2977 "anyway.\n");
2978 return 0;
2979 }
2980 /* Deallocate clusters. */
2981 if (ctx->attr->non_resident) {
2982 runlist *al_rl;
2983
2984 al_rl = ntfs_mapping_pairs_decompress(base_ni->vol,
2985 ctx->attr, NULL);
2986 if (!al_rl) {
2987 ntfs_log_trace("Couldn't decompress attribute "
2988 "list runlist. Succeed "
2989 "anyway.\n");
2990 return 0;
2991 }
2992 if (ntfs_cluster_free_from_rl(base_ni->vol, al_rl)) {
2993 ntfs_log_trace("Leaking clusters! Run chkdsk. "
2994 "Couldn't free clusters from "
2995 "attribute list runlist.\n");
2996 }
2997 free(al_rl);
2998 }
2999 /* Remove attribute record itself. */
3000 if (ntfs_attr_record_rm(ctx)) {
3001 /*
3002 * FIXME: Should we succeed here? BTW, chkdsk doesn't
3003 * complain if it find MFT record with attribute list,
3004 * but without extents.
3005 */
3006 ntfs_log_trace("Couldn't remove attribute list. "
3007 "Succeed anyway.\n");
3008 return 0;
3009 }
3010 }
3011 return 0;
3012 }
3013
3014 /**
3015 * ntfs_attr_add - add attribute to inode
3016 * @ni: opened ntfs inode to which add attribute
3017 * @type: type of the new attribute
3018 * @name: name in unicode of the new attribute
3019 * @name_len: name length in unicode characters of the new attribute
3020 * @val: value of new attribute
3021 * @size: size of the new attribute / length of @val (if specified)
3022 *
3023 * @val should always be specified for always resident attributes (eg. FILE_NAME
3024 * attribute), for attributes that can become non-resident @val can be NULL
3025 * (eg. DATA attribute). @size can be specified even if @val is NULL, in this
3026 * case data size will be equal to @size and initialized size will be equal
3027 * to 0.
3028 *
3029 * If inode haven't got enough space to add attribute, add attribute to one of
3030 * it extents, if no extents present or no one of them have enough space, than
3031 * allocate new extent and add attribute to it.
3032 *
3033 * If on one of this steps attribute list is needed but not present, than it is
3034 * added transparently to caller. So, this function should not be called with
3035 * @type == AT_ATTRIBUTE_LIST, if you really need to add attribute list call
3036 * ntfs_inode_add_attrlist instead.
3037 *
3038 * On success return 0. On error return -1 with errno set to the error code.
3039 */
ntfs_attr_add(ntfs_inode * ni,ATTR_TYPES type,ntfschar * name,u8 name_len,u8 * val,s64 size)3040 int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
3041 ntfschar *name, u8 name_len, u8 *val, s64 size)
3042 {
3043 u32 attr_rec_size;
3044 int err, i, offset;
3045 BOOL is_resident = TRUE;
3046 BOOL always_non_resident = FALSE, always_resident = FALSE;
3047 ntfs_inode *attr_ni;
3048 ntfs_attr *na;
3049
3050 if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) {
3051 ntfs_log_trace("Invalid arguments passed.\n");
3052 errno = EINVAL;
3053 return -1;
3054 }
3055
3056 ntfs_log_trace("Entering for inode 0x%llx, attr %x, size %lld.\n",
3057 (long long) ni->mft_no, type, size);
3058
3059 if (ni->nr_extents == -1)
3060 ni = ni->u.base_ni;
3061
3062 /* Check the attribute type and the size. */
3063 if (ntfs_attr_size_bounds_check(ni->vol, type, size)) {
3064 if (errno == ERANGE) {
3065 ntfs_log_trace("Size bounds check failed.\n");
3066 } else if (errno == ENOENT) {
3067 ntfs_log_trace("Invalid attribute type. Aborting...\n");
3068 errno = EIO;
3069 }
3070 return -1;
3071 }
3072
3073 /* Sanity checks for always resident attributes. */
3074 if (ntfs_attr_can_be_non_resident(ni->vol, type)) {
3075 if (errno != EPERM) {
3076 err = errno;
3077 ntfs_log_trace("ntfs_attr_can_be_non_resident() "
3078 "failed.\n");
3079 goto err_out;
3080 }
3081 /* @val is mandatory. */
3082 if (!val) {
3083 ntfs_log_trace("@val is mandatory for always resident "
3084 "attributes.\n");
3085 errno = EINVAL;
3086 return -1;
3087 }
3088 if (size > ni->vol->mft_record_size) {
3089 ntfs_log_trace("Attribute is too big.\n");
3090 errno = ERANGE;
3091 return -1;
3092 }
3093 always_resident = TRUE;
3094 }
3095
3096 /* Check whether attribute can be resident. */
3097 if (ntfs_attr_can_be_resident(ni->vol, type)) {
3098 if (errno != EPERM) {
3099 err = errno;
3100 ntfs_log_trace("ntfs_attr_can_be_resident() failed.\n");
3101 goto err_out;
3102 }
3103 is_resident = FALSE;
3104 always_non_resident = TRUE;
3105 }
3106
3107 retry:
3108 /* Calculate attribute record size. */
3109 if (is_resident)
3110 attr_rec_size = offsetof(ATTR_RECORD, u.res.resident_end) +
3111 ROUND_UP(name_len * sizeof(ntfschar), 3) +
3112 ROUND_UP(size, 3);
3113 else /* We add 8 for space for mapping pairs. */
3114 attr_rec_size = offsetof(ATTR_RECORD, u.nonres.non_resident_end) +
3115 ROUND_UP(name_len * sizeof(ntfschar), 3) + 8;
3116
3117 /*
3118 * If we have enough free space for the new attribute in the base MFT
3119 * record, then add attribute to it.
3120 */
3121 if (le32_to_cpu(ni->mrec->bytes_allocated) -
3122 le32_to_cpu(ni->mrec->bytes_in_use) >= attr_rec_size) {
3123 attr_ni = ni;
3124 goto add_attr_record;
3125 }
3126
3127 /* Try to add to extent inodes. */
3128 if (ntfs_inode_attach_all_extents(ni)) {
3129 err = errno;
3130 ntfs_log_trace("Failed to attach all extents to inode.\n");
3131 goto err_out;
3132 }
3133 for (i = 0; i < ni->nr_extents; i++) {
3134 attr_ni = ni->u.extent_nis[i];
3135 if (le32_to_cpu(attr_ni->mrec->bytes_allocated) -
3136 le32_to_cpu(attr_ni->mrec->bytes_in_use) >=
3137 attr_rec_size)
3138 goto add_attr_record;
3139 }
3140
3141 /*
3142 * If failed to find space for resident attribute, then try to find
3143 * space for non resident one.
3144 */
3145 if (is_resident && !always_resident) {
3146 is_resident = FALSE;
3147 goto retry;
3148 }
3149
3150 /*
3151 * FIXME: Try to make other attributes non-resident here. Factor out
3152 * code from ntfs_resident_attr_resize.
3153 */
3154
3155 /* There is no extent that contain enough space for new attribute. */
3156 if (!NInoAttrList(ni)) {
3157 /* Add attribute list not present, add it and retry. */
3158 if (ntfs_inode_add_attrlist(ni)) {
3159 err = errno;
3160 ntfs_log_trace("Failed to add attribute list.\n");
3161 goto err_out;
3162 }
3163 return ntfs_attr_add(ni, type, name, name_len, val, size);
3164 }
3165 /* Allocate new extent for attribute. */
3166 attr_ni = ntfs_mft_record_alloc(ni->vol, ni);
3167 if (!attr_ni) {
3168 err = errno;
3169 ntfs_log_trace("Failed to allocate extent record.\n");
3170 goto err_out;
3171 }
3172
3173 /*
3174 * Determine resident or not will be attribute using heuristics and
3175 * calculate attribute record size. FIXME: small code duplication here.
3176 */
3177 if (always_resident || (!always_non_resident && size < 256)) {
3178 is_resident = TRUE;
3179 attr_rec_size = offsetof(ATTR_RECORD, u.res.resident_end) +
3180 ROUND_UP(name_len * sizeof(ntfschar), 3) +
3181 ROUND_UP(size, 3);
3182 } else { /* We add 8 for space for mapping pairs. */
3183 is_resident = FALSE;
3184 attr_rec_size = offsetof(ATTR_RECORD, u.nonres.non_resident_end) +
3185 ROUND_UP(name_len * sizeof(ntfschar), 3) + 8;
3186 }
3187
3188 add_attr_record:
3189 if (is_resident) {
3190 /* Add resident attribute. */
3191 offset = ntfs_resident_attr_record_add(attr_ni, type, name,
3192 name_len, val, size, 0);
3193 if (offset < 0) {
3194 err = errno;
3195 ntfs_log_trace("Failed to add resident attribute.\n");
3196 goto free_err_out;
3197 }
3198 return 0;
3199 }
3200
3201 /* Add non resident attribute. */
3202 offset = ntfs_non_resident_attr_record_add(attr_ni, type, name,
3203 name_len, 0, 8, 0);
3204 if (offset < 0) {
3205 err = errno;
3206 ntfs_log_trace("Failed to add non resident attribute.\n");
3207 goto free_err_out;
3208 }
3209
3210 /* If @size == 0, we are done. */
3211 if (!size)
3212 return 0;
3213
3214 /* Open new attribute and resize it. */
3215 na = ntfs_attr_open(ni, type, name, name_len);
3216 if (!na) {
3217 err = errno;
3218 ntfs_log_trace("Failed to open just added attribute.\n");
3219 goto rm_attr_err_out;
3220 }
3221 /* Resize and set attribute value. */
3222 if (ntfs_attr_truncate(na, size) ||
3223 (val && (ntfs_attr_pwrite(na, 0, size, val) != size))) {
3224 err = errno;
3225 ntfs_log_trace("Failed to initialize just added attribute.\n");
3226 if (ntfs_attr_rm(na))
3227 ntfs_log_trace("Failed to remove just added attribute. "
3228 "Probably leaving inconsistent "
3229 "metadata.\n");
3230 goto err_out;
3231 }
3232 ntfs_attr_close(na);
3233 /* Done !*/
3234 return 0;
3235
3236 rm_attr_err_out:
3237 /* Remove just added attribute. */
3238 if (ntfs_attr_record_resize(attr_ni->mrec,
3239 (ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0)) {
3240 ntfs_log_trace("Failed to remove just added attribute.\n");
3241 }
3242 free_err_out:
3243 /* Free MFT record, if it isn't contain attributes. */
3244 if (le32_to_cpu(attr_ni->mrec->bytes_in_use) -
3245 le16_to_cpu(attr_ni->mrec->attrs_offset) == 8) {
3246 if (ntfs_mft_record_free(attr_ni->vol, attr_ni)) {
3247 ntfs_log_trace("Failed to free MFT record. Leaving "
3248 "inconsistent metadata.\n");
3249 }
3250 }
3251 err_out:
3252 errno = err;
3253 return -1;
3254 }
3255
3256 /**
3257 * ntfs_attr_rm - remove attribute from ntfs inode
3258 * @na: opened ntfs attribute to delete
3259 *
3260 * Remove attribute and all it's extents from ntfs inode. If attribute was non
3261 * resident also free all clusters allocated by attribute. This function always
3262 * closes @na upon exit (both on success and failure).
3263 *
3264 * Return 0 on success or -1 on error with errno set to the error code.
3265 */
ntfs_attr_rm(ntfs_attr * na)3266 int ntfs_attr_rm(ntfs_attr *na)
3267 {
3268 ntfs_attr_search_ctx *ctx;
3269 int ret = 0;
3270
3271 if (!na) {
3272 ntfs_log_trace("Invalid arguments passed.\n");
3273 errno = EINVAL;
3274 return -1;
3275 }
3276
3277 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
3278 (long long) na->ni->mft_no, na->type);
3279
3280 /* Free cluster allocation. */
3281 if (NAttrNonResident(na)) {
3282 if (ntfs_attr_map_whole_runlist(na)) {
3283 ntfs_attr_close(na);
3284 return -1;
3285 }
3286 if (ntfs_cluster_free(na->ni->vol, na, 0, -1) < 0) {
3287 ntfs_log_trace("Failed to free cluster allocation. "
3288 "Leaving inconsistent metadata.\n");
3289 ret = -1;
3290 }
3291 }
3292
3293 /* Search for attribute extents and remove them all. */
3294 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
3295 if (!ctx) {
3296 ntfs_attr_close(na);
3297 return -1;
3298 }
3299 while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
3300 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
3301 if (ntfs_attr_record_rm(ctx)) {
3302 ntfs_log_trace("Failed to remove attribute extent. "
3303 "Leaving inconsistent metadata.\n");
3304 ret = -1;
3305 }
3306 ntfs_attr_reinit_search_ctx(ctx);
3307 }
3308 if (errno != ENOENT) {
3309 ntfs_log_trace("Attribute lookup failed. "
3310 "Probably leaving inconsistent metadata.\n");
3311 ret = -1;
3312 }
3313
3314 /* Throw away now non-exist attribute. */
3315 ntfs_attr_close(na);
3316 /* Done. */
3317 return ret;
3318 }
3319
3320 /**
3321 * ntfs_attr_record_resize - resize an attribute record
3322 * @m: mft record containing attribute record
3323 * @a: attribute record to resize
3324 * @new_size: new size in bytes to which to resize the attribute record @a
3325 *
3326 * Resize the attribute record @a, i.e. the resident part of the attribute, in
3327 * the mft record @m to @new_size bytes.
3328 *
3329 * Return 0 on success and -1 on error with errno set to the error code.
3330 * The following error codes are defined:
3331 * ENOSPC - Not enough space in the mft record @m to perform the resize.
3332 * Note that on error no modifications have been performed whatsoever.
3333 *
3334 * Warning: If you make a record smaller without having copied all the data you
3335 * are interested in the data may be overwritten!
3336 */
ntfs_attr_record_resize(MFT_RECORD * m,ATTR_RECORD * a,u32 new_size)3337 int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
3338 {
3339 ntfs_log_trace("Entering for new_size %u.\n", (unsigned) new_size);
3340 /* Align to 8 bytes, just in case the caller hasn't. */
3341 new_size = (new_size + 7) & ~7;
3342 /* If the actual attribute length has changed, move things around. */
3343 if (new_size != le32_to_cpu(a->length)) {
3344 u32 new_muse = le32_to_cpu(m->bytes_in_use) -
3345 le32_to_cpu(a->length) + new_size;
3346 /* Not enough space in this mft record. */
3347 if (new_muse > le32_to_cpu(m->bytes_allocated)) {
3348 errno = ENOSPC;
3349 return -1;
3350 }
3351 /* Move attributes following @a to their new location. */
3352 memmove((u8*)a + new_size, (u8*)a + le32_to_cpu(a->length),
3353 le32_to_cpu(m->bytes_in_use) - ((u8*)a -
3354 (u8*)m) - le32_to_cpu(a->length));
3355 /* Adjust @m to reflect the change in used space. */
3356 m->bytes_in_use = cpu_to_le32(new_muse);
3357 /* Adjust @a to reflect the new size. */
3358 if (new_size >= offsetof(ATTR_REC, length) + sizeof(a->length))
3359 a->length = cpu_to_le32(new_size);
3360 }
3361 return 0;
3362 }
3363
3364 /**
3365 * ntfs_resident_attr_value_resize - resize the value of a resident attribute
3366 * @m: mft record containing attribute record
3367 * @a: attribute record whose value to resize
3368 * @new_size: new size in bytes to which to resize the attribute value of @a
3369 *
3370 * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
3371 * If the value is made bigger, the newly "allocated" space is cleared.
3372 *
3373 * Return 0 on success and -1 on error with errno set to the error code.
3374 * The following error codes are defined:
3375 * ENOSPC - Not enough space in the mft record @m to perform the resize.
3376 * Note that on error no modifications have been performed whatsoever.
3377 */
ntfs_resident_attr_value_resize(MFT_RECORD * m,ATTR_RECORD * a,const u32 new_size)3378 int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
3379 const u32 new_size)
3380 {
3381 ntfs_log_trace("Entering for new size %u.\n", (unsigned)new_size);
3382
3383 /*
3384 * Check that the attribute name hasn't been placed after the
3385 * attribute value. Chkdsk treat this as corruption.
3386 */
3387 if (a->name_length && le16_to_cpu(a->name_offset) >=
3388 le16_to_cpu(a->u.res.value_offset)) {
3389 ntfs_log_trace("Name is placed after the attribute value. "
3390 "Corrupted inode. Run chkdsk. Aborting...\n");
3391 errno = EIO;
3392 return -1;
3393 }
3394 /* Resize the resident part of the attribute record. */
3395 if (ntfs_attr_record_resize(m, a, (le16_to_cpu(a->u.res.value_offset) +
3396 new_size + 7) & ~7) < 0) {
3397 if (errno != ENOSPC) {
3398 int eo = errno;
3399 ntfs_log_trace("Attribute record resize failed. "
3400 "Aborting...\n");
3401 errno = eo;
3402 }
3403 return -1;
3404 }
3405 /*
3406 * If we made the attribute value bigger, clear the area between the
3407 * old size and @new_size.
3408 */
3409 if (new_size > le32_to_cpu(a->u.res.value_length))
3410 memset((u8*)a + le16_to_cpu(a->u.res.value_offset) +
3411 le32_to_cpu(a->u.res.value_length), 0, new_size -
3412 le32_to_cpu(a->u.res.value_length));
3413 /* Finally update the length of the attribute value. */
3414 a->u.res.value_length = cpu_to_le32(new_size);
3415 return 0;
3416 }
3417
3418 /**
3419 * ntfs_attr_record_move_to - move attribute record to target inode
3420 * @ctx: attribute search context describing the attribute record
3421 * @ni: opened ntfs inode to which move attribute record
3422 *
3423 * If this function succeed, user should reinit search context if he/she wants
3424 * use it anymore.
3425 *
3426 * Return 0 on success and -1 on error with errno set to the error code.
3427 */
ntfs_attr_record_move_to(ntfs_attr_search_ctx * ctx,ntfs_inode * ni)3428 int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni)
3429 {
3430 ntfs_attr_search_ctx *nctx;
3431 ATTR_RECORD *a;
3432 int err;
3433
3434 if (!ctx || !ctx->attr || !ctx->ntfs_ino || !ni) {
3435 ntfs_log_trace("Invalid arguments passed.\n");
3436 errno = EINVAL;
3437 return -1;
3438 }
3439
3440 ntfs_log_trace("Entering for ctx->attr->type 0x%x, "
3441 "ctx->ntfs_ino->mft_no 0x%llx, ni->mft_no 0x%llx.\n",
3442 (unsigned) le32_to_cpu(ctx->attr->type),
3443 (long long) ctx->ntfs_ino->mft_no,
3444 (long long) ni->mft_no);
3445
3446 if (ctx->ntfs_ino == ni)
3447 return 0;
3448
3449 if (!ctx->al_entry) {
3450 ntfs_log_trace("Inode should contain attribute list to use "
3451 "this function.\n");
3452 errno = EINVAL;
3453 return -1;
3454 }
3455
3456 /* Find place in MFT record where attribute will be moved. */
3457 a = ctx->attr;
3458 nctx = ntfs_attr_get_search_ctx(ni, NULL);
3459 if (!nctx) {
3460 ntfs_log_trace("Couldn't obtain search context.\n");
3461 return -1;
3462 }
3463 /*
3464 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
3465 * attribute in @ni->mrec, not any extent inode in case if @ni is base
3466 * file record.
3467 */
3468 if (!ntfs_attr_find(a->type, (ntfschar*)((u8*)a + le16_to_cpu(
3469 a->name_offset)), a->name_length, CASE_SENSITIVE, NULL,
3470 0, nctx)) {
3471 ntfs_log_trace("Attribute of such type, with same name already "
3472 "present in this MFT record.\n");
3473 err = EEXIST;
3474 goto put_err_out;
3475 }
3476 if (errno != ENOENT) {
3477 err = errno;
3478 ntfs_log_debug("Attribute lookup failed.\n");
3479 goto put_err_out;
3480 }
3481
3482 /* Make space and move attribute. */
3483 if (ntfs_make_room_for_attr(ni->mrec, (u8*) nctx->attr,
3484 le32_to_cpu(a->length))) {
3485 err = errno;
3486 ntfs_log_trace("Couldn't make space for attribute.\n");
3487 goto put_err_out;
3488 }
3489 memcpy(nctx->attr, a, le32_to_cpu(a->length));
3490 nctx->attr->instance = nctx->mrec->next_attr_instance;
3491 nctx->mrec->next_attr_instance = cpu_to_le16(
3492 (le16_to_cpu(nctx->mrec->next_attr_instance) + 1) & 0xffff);
3493 ntfs_attr_record_resize(ctx->mrec, a, 0);
3494 ntfs_inode_mark_dirty(ctx->ntfs_ino);
3495 ntfs_inode_mark_dirty(ni);
3496
3497 /* Update attribute list. */
3498 ctx->al_entry->mft_reference =
3499 MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number));
3500 ctx->al_entry->instance = nctx->attr->instance;
3501 ntfs_attrlist_mark_dirty(ni);
3502
3503 ntfs_attr_put_search_ctx(nctx);
3504 return 0;
3505 put_err_out:
3506 ntfs_attr_put_search_ctx(nctx);
3507 errno = err;
3508 return -1;
3509 }
3510
3511 /**
3512 * ntfs_attr_record_move_away - move away attribute record from it's mft record
3513 * @ctx: attribute search context describing the attribute record
3514 * @extra: minimum amount of free space in the new holder of record
3515 *
3516 * New attribute record holder must have free @extra bytes after moving
3517 * attribute record to it.
3518 *
3519 * If this function succeed, user should reinit search context if he/she wants
3520 * use it anymore.
3521 *
3522 * Return 0 on success and -1 on error with errno set to the error code.
3523 */
ntfs_attr_record_move_away(ntfs_attr_search_ctx * ctx,int extra)3524 int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra)
3525 {
3526 ntfs_inode *base_ni, *ni;
3527 MFT_RECORD *m;
3528 int i;
3529
3530 if (!ctx || !ctx->attr || !ctx->ntfs_ino || extra < 0) {
3531 ntfs_log_trace("Invalid arguments passed.\n");
3532 errno = EINVAL;
3533 return -1;
3534 }
3535
3536 ntfs_log_trace("Entering for attr 0x%x, inode 0x%llx.\n",
3537 (unsigned) le32_to_cpu(ctx->attr->type),
3538 (long long) ctx->ntfs_ino->mft_no);
3539
3540 if (ctx->ntfs_ino->nr_extents == -1)
3541 base_ni = ctx->base_ntfs_ino;
3542 else
3543 base_ni = ctx->ntfs_ino;
3544
3545 if (!NInoAttrList(base_ni)) {
3546 ntfs_log_trace("Inode should contain attribute list to use "
3547 "this function.\n");
3548 errno = EINVAL;
3549 return -1;
3550 }
3551
3552 if (ntfs_inode_attach_all_extents(ctx->ntfs_ino)) {
3553 ntfs_log_trace("Couldn't attach extent inode.\n");
3554 return -1;
3555 }
3556
3557 /* Walk through all extents and try to move attribute to them. */
3558 for (i = 0; i < base_ni->nr_extents; i++) {
3559 ni = base_ni->u.extent_nis[i];
3560 m = ni->mrec;
3561
3562 if (ctx->ntfs_ino->mft_no == ni->mft_no)
3563 continue;
3564
3565 if (le32_to_cpu(m->bytes_allocated) -
3566 le32_to_cpu(m->bytes_in_use) <
3567 le32_to_cpu(ctx->attr->length) + extra)
3568 continue;
3569
3570 /*
3571 * ntfs_attr_record_move_to can fail if extent with other lowest
3572 * VCN already present in inode we trying move record to. So,
3573 * do not return error.
3574 */
3575 if (!ntfs_attr_record_move_to(ctx, ni))
3576 return 0;
3577 }
3578
3579 /*
3580 * Failed to move attribute to one of the current extents, so allocate
3581 * new extent and move attribute to it.
3582 */
3583 ni = ntfs_mft_record_alloc(base_ni->vol, base_ni);
3584 if (!ni) {
3585 ntfs_log_trace("Couldn't allocate new MFT record.\n");
3586 return -1;
3587 }
3588 if (ntfs_attr_record_move_to(ctx, ni)) {
3589 ntfs_log_trace("Couldn't move attribute to new MFT record.\n");
3590 return -1;
3591 }
3592 return 0;
3593 }
3594
3595 /**
3596 * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
3597 * @na: open ntfs attribute to make non-resident
3598 * @ctx: ntfs search context describing the attribute
3599 *
3600 * Convert a resident ntfs attribute to a non-resident one.
3601 *
3602 * Return 0 on success and -1 on error with errno set to the error code. The
3603 * following error codes are defined:
3604 * EPERM - The attribute is not allowed to be non-resident.
3605 * TODO: others...
3606 *
3607 * NOTE to self: No changes in the attribute list are required to move from
3608 * a resident to a non-resident attribute.
3609 *
3610 * Warning: We do not set the inode dirty and we do not write out anything!
3611 * We expect the caller to do this as this is a fairly low level
3612 * function and it is likely there will be further changes made.
3613 */
ntfs_attr_make_non_resident(ntfs_attr * na,ntfs_attr_search_ctx * ctx)3614 static int ntfs_attr_make_non_resident(ntfs_attr *na,
3615 ntfs_attr_search_ctx *ctx)
3616 {
3617 s64 new_allocated_size, bw;
3618 ntfs_volume *vol = na->ni->vol;
3619 ATTR_REC *a = ctx->attr;
3620 runlist *rl;
3621 int mp_size, mp_ofs, name_ofs, arec_size;
3622
3623 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
3624 long)na->ni->mft_no, na->type);
3625
3626 /* Some preliminary sanity checking. */
3627 if (NAttrNonResident(na)) {
3628 ntfs_log_trace("Eeek! Trying to make non-resident attribute "
3629 "non-resident. Aborting...\n");
3630 errno = EINVAL;
3631 return -1;
3632 }
3633
3634 /* Check that the attribute is allowed to be non-resident. */
3635 if (ntfs_attr_can_be_non_resident(vol, na->type))
3636 return -1;
3637
3638 /*
3639 * Check that the attribute name hasn't been placed after the
3640 * attribute value. Chkdsk treat this as corruption.
3641 */
3642 if (a->name_length && le16_to_cpu(a->name_offset) >=
3643 le16_to_cpu(a->u.res.value_offset)) {
3644 ntfs_log_trace("Name is placed after the attribute value. "
3645 "Corrupted inode. Run chkdsk. Aborting...\n");
3646 errno = EIO;
3647 return -1;
3648 }
3649
3650 new_allocated_size = (le32_to_cpu(a->u.res.value_length) + vol->cluster_size
3651 - 1) & ~(vol->cluster_size - 1);
3652
3653 if (new_allocated_size > 0) {
3654 /* Start by allocating clusters to hold the attribute value. */
3655 rl = ntfs_cluster_alloc(vol, 0, new_allocated_size >>
3656 vol->cluster_size_bits, -1, DATA_ZONE);
3657 if (!rl) {
3658 if (errno != ENOSPC) {
3659 ntfs_log_trace("Eeek! Failed to allocate "
3660 "cluster(s). Aborting...\n");
3661 }
3662 return -1;
3663 }
3664 } else
3665 rl = NULL;
3666 /*
3667 * Setup the in-memory attribute structure to be non-resident so that
3668 * we can use ntfs_attr_pwrite().
3669 */
3670 NAttrSetNonResident(na);
3671 na->rl = rl;
3672 na->allocated_size = new_allocated_size;
3673 na->data_size = na->initialized_size = le32_to_cpu(a->u.res.value_length);
3674 /*
3675 * FIXME: For now just clear all of these as we don't support them when
3676 * writing.
3677 */
3678 NAttrClearCompressed(na);
3679 NAttrClearSparse(na);
3680 NAttrClearEncrypted(na);
3681
3682 if (rl) {
3683 /* Now copy the attribute value to the allocated cluster(s). */
3684 bw = ntfs_attr_pwrite(na, 0, le32_to_cpu(a->u.res.value_length),
3685 (u8*)a + le16_to_cpu(a->u.res.value_offset));
3686 if (bw != le32_to_cpu(a->u.res.value_length)) {
3687 ntfs_log_debug("Failed to write out attribute value "
3688 "(bw = %lli, errno = %i). "
3689 "Aborting...\n", (long long)bw, errno);
3690 if (bw >= 0)
3691 errno = EIO;
3692 goto cluster_free_err_out;
3693 }
3694 }
3695 /* Determine the size of the mapping pairs array. */
3696 mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
3697 if (mp_size < 0) {
3698 ntfs_log_debug("Failed to get size for mapping pairs array. "
3699 "Aborting...\n");
3700 goto cluster_free_err_out;
3701 }
3702 /* Calculate new offsets for the name and the mapping pairs array. */
3703 name_ofs = (sizeof(ATTR_REC) - sizeof(a->u.nonres.compressed_size) + 7) & ~7;
3704 mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
3705 /*
3706 * Determine the size of the resident part of the non-resident
3707 * attribute record. (Not compressed thus no compressed_size element
3708 * present.)
3709 */
3710 arec_size = (mp_ofs + mp_size + 7) & ~7;
3711
3712 /* Resize the resident part of the attribute record. */
3713 if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
3714 if (errno != ENOSPC) {
3715 ntfs_log_trace("Failed to resize attribute record. "
3716 "Aborting...\n");
3717 }
3718 goto cluster_free_err_out;
3719 }
3720
3721 /*
3722 * Convert the resident part of the attribute record to describe a
3723 * non-resident attribute.
3724 */
3725 a->non_resident = 1;
3726
3727 /* Move the attribute name if it exists and update the offset. */
3728 if (a->name_length)
3729 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
3730 a->name_length * sizeof(ntfschar));
3731 a->name_offset = cpu_to_le16(name_ofs);
3732
3733 /* Update the flags to match the in-memory ones. */
3734 a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED |
3735 ATTR_COMPRESSION_MASK);
3736
3737 /* Setup the fields specific to non-resident attributes. */
3738 a->u.nonres.lowest_vcn = cpu_to_sle64(0);
3739 a->u.nonres.highest_vcn = cpu_to_sle64((new_allocated_size - 1) >>
3740 vol->cluster_size_bits);
3741
3742 a->u.nonres.mapping_pairs_offset = cpu_to_le16(mp_ofs);
3743
3744 a->u.nonres.compression_unit = 0;
3745
3746 memset(&a->u.nonres.reserved1, 0, sizeof(a->u.nonres.reserved1));
3747
3748 a->u.nonres.allocated_size = cpu_to_sle64(new_allocated_size);
3749 a->u.nonres.data_size = a->u.nonres.initialized_size = cpu_to_sle64(na->data_size);
3750
3751 /* Generate the mapping pairs array in the attribute record. */
3752 if (ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, arec_size - mp_ofs,
3753 rl, 0, NULL) < 0) {
3754 // FIXME: Eeek! We need rollback! (AIA)
3755 ntfs_log_trace("Eeek! Failed to build mapping pairs. Leaving "
3756 "corrupt attribute record on disk. In memory "
3757 "runlist is still intact! Error code is %i. "
3758 "FIXME: Need to rollback instead!\n", errno);
3759 return -1;
3760 }
3761
3762 /* Done! */
3763 return 0;
3764
3765 cluster_free_err_out:
3766 if (rl && ntfs_cluster_free(vol, na, 0, -1) < 0)
3767 ntfs_log_trace("Failed to release allocated clusters in error "
3768 "code path. Leaving inconsistent metadata...\n");
3769 NAttrClearNonResident(na);
3770 na->allocated_size = na->data_size;
3771 na->rl = NULL;
3772 free(rl);
3773 return -1;
3774 }
3775
3776 /**
3777 * ntfs_resident_attr_resize - resize a resident, open ntfs attribute
3778 * @na: resident ntfs attribute to resize
3779 * @newsize: new size (in bytes) to which to resize the attribute
3780 *
3781 * Change the size of a resident, open ntfs attribute @na to @newsize bytes.
3782 *
3783 * On success return 0 and on error return -1 with errno set to the error code.
3784 * The following error codes are defined:
3785 * ENOMEM - Not enough memory to complete operation.
3786 * ERANGE - @newsize is not valid for the attribute type of @na.
3787 * ENOSPC - There is no enough space on the volume to allocate
3788 * new clusters or in base mft to resize $ATTRIBUTE_LIST.
3789 * EOVERFLOW - Resident attribute can not become non resident and
3790 * already filled whole MFT record, but had not reached
3791 * @newsize bytes length.
3792 */
ntfs_resident_attr_resize(ntfs_attr * na,const s64 newsize)3793 static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
3794 {
3795 ntfs_attr_search_ctx *ctx;
3796 ntfs_volume *vol;
3797 ntfs_inode *ni;
3798 int err;
3799
3800 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, new size %lld.\n",
3801 (unsigned long long)na->ni->mft_no, na->type,
3802 (long long)newsize);
3803
3804 /* Get the attribute record that needs modification. */
3805 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
3806 if (!ctx)
3807 return -1;
3808 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, 0, NULL, 0,
3809 ctx)) {
3810 err = errno;
3811 goto put_err_out;
3812 }
3813 vol = na->ni->vol;
3814 /*
3815 * Check the attribute type and the corresponding minimum and maximum
3816 * sizes against @newsize and fail if @newsize is out of bounds.
3817 */
3818 if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
3819 err = errno;
3820 if (err == ERANGE) {
3821 ntfs_log_trace("Size bounds check failed. "
3822 "Aborting...\n");
3823 } else if (err == ENOENT)
3824 err = EIO;
3825 goto put_err_out;
3826 }
3827 /*
3828 * If @newsize is bigger than the MFT record we need to make the
3829 * attribute non-resident if the attribute type supports it. If it is
3830 * smaller we can go ahead and attempt the resize.
3831 */
3832 if (newsize < vol->mft_record_size) {
3833 /* Perform the resize of the attribute record. */
3834 if (!ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
3835 newsize)) {
3836 /* Update attribute size everywhere. */
3837 na->data_size = na->initialized_size = newsize;
3838 na->allocated_size = ROUND_UP(newsize, 3);
3839 if (NAttrCompressed(na) || NAttrSparse(na))
3840 na->compressed_size = na->allocated_size;
3841 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
3842 na->ni->data_size = na->data_size;
3843 na->ni->allocated_size = na->allocated_size;
3844 NInoFileNameSetDirty(na->ni);
3845 }
3846 goto resize_done;
3847 }
3848 /* Error! If not enough space, just continue. */
3849 if (errno != ENOSPC) {
3850 err = errno;
3851 ntfs_log_trace("Failed to resize resident part "
3852 "of attribute. Aborting...\n");
3853 goto put_err_out;
3854 }
3855 }
3856 /* There is not enough space in the MFT record to perform the resize. */
3857
3858 /* Make the attribute non-resident if possible. */
3859 if (!ntfs_attr_make_non_resident(na, ctx)) {
3860 ntfs_inode_mark_dirty(ctx->ntfs_ino);
3861 ntfs_attr_put_search_ctx(ctx);
3862 /* Resize non-resident attribute */
3863 return ntfs_attr_truncate(na, newsize);
3864 } else if (errno != ENOSPC && errno != EPERM) {
3865 err = errno;
3866 ntfs_log_trace("Failed to make attribute non-resident. "
3867 "Aborting...\n");
3868 goto put_err_out;
3869 }
3870
3871 /* Try to make other attributes non-resident and retry each time. */
3872 ntfs_attr_init_search_ctx(ctx, NULL, na->ni->mrec);
3873 while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
3874 ntfs_attr *tna;
3875 ATTR_RECORD *a;
3876
3877 a = ctx->attr;
3878 if (a->non_resident)
3879 continue;
3880
3881 /*
3882 * Check out whether convert is reasonable. Assume that mapping
3883 * pairs will take 8 bytes.
3884 */
3885 if (le32_to_cpu(a->length) <= offsetof(ATTR_RECORD,
3886 u.nonres.compressed_size) + ROUND_UP(a->name_length *
3887 sizeof(ntfschar), 3) + 8)
3888 continue;
3889
3890 tna = ntfs_attr_open(na->ni, a->type, (ntfschar*)((u8*)a +
3891 le16_to_cpu(a->name_offset)), a->name_length);
3892 if (!tna) {
3893 err = errno;
3894 ntfs_log_trace("Couldn't open attribute.\n");
3895 goto put_err_out;
3896 }
3897 if (ntfs_attr_make_non_resident(tna, ctx)) {
3898 ntfs_attr_close(tna);
3899 continue;
3900 }
3901 ntfs_inode_mark_dirty(tna->ni);
3902 ntfs_attr_close(tna);
3903 ntfs_attr_put_search_ctx(ctx);
3904 return ntfs_resident_attr_resize(na, newsize);
3905 }
3906 /* Check whether error occurred. */
3907 if (errno != ENOENT) {
3908 err = errno;
3909 ntfs_log_trace("Attribute lookup failed.\n");
3910 goto put_err_out;
3911 }
3912
3913 /* We can't move out attribute list, thus move out others. */
3914 if (na->type == AT_ATTRIBUTE_LIST) {
3915 ntfs_attr_put_search_ctx(ctx);
3916 if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD,
3917 u.nonres.non_resident_end) + 8)) {
3918 ntfs_log_trace("Couldn't free space in the MFT record "
3919 "to make attribute list non "
3920 "resident.\n");
3921 return -1;
3922 }
3923 return ntfs_resident_attr_resize(na, newsize);
3924 }
3925
3926 /*
3927 * Move the attribute to a new MFT record, creating an attribute list
3928 * attribute or modifying it if it is already present.
3929 */
3930
3931 /* Point search context back to attribute which we need resize. */
3932 ntfs_attr_init_search_ctx(ctx, na->ni, NULL);
3933 if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
3934 0, NULL, 0, ctx)) {
3935 ntfs_log_trace("Attribute lookup failed.\n");
3936 err = errno;
3937 goto put_err_out;
3938 }
3939
3940 /*
3941 * Force index allocation creation instead of moving out index root
3942 * from the base MFT record.
3943 */
3944 if (na->type == AT_INDEX_ROOT && na->data_size > sizeof(INDEX_ROOT) +
3945 sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN)) {
3946 INDEX_ROOT *ir;
3947
3948 ir = (INDEX_ROOT*)((u8*)ctx->attr +
3949 le16_to_cpu(ctx->attr->u.res.value_offset));
3950 if (!(ir->index.flags & LARGE_INDEX)) {
3951 err = EOVERFLOW;
3952 goto put_err_out;
3953 }
3954 }
3955
3956 /*
3957 * Check whether attribute is already single in the this MFT record.
3958 * 8 added for the attribute terminator.
3959 */
3960 if (le32_to_cpu(ctx->mrec->bytes_in_use) ==
3961 le16_to_cpu(ctx->mrec->attrs_offset) +
3962 le32_to_cpu(ctx->attr->length) + 8) {
3963 err = EOVERFLOW;
3964 goto put_err_out;
3965 }
3966
3967 /* Add attribute list if not present. */
3968 if (na->ni->nr_extents == -1)
3969 ni = na->ni->u.base_ni;
3970 else
3971 ni = na->ni;
3972 if (!NInoAttrList(ni)) {
3973 ntfs_attr_put_search_ctx(ctx);
3974 if (ntfs_inode_add_attrlist(ni))
3975 return -1;
3976 return ntfs_resident_attr_resize(na, newsize);
3977 }
3978 /* Allocate new MFT record. */
3979 ni = ntfs_mft_record_alloc(vol, ni);
3980 if (!ni) {
3981 err = errno;
3982 ntfs_log_trace("Couldn't allocate new MFT record.\n");
3983 goto put_err_out;
3984 }
3985 /* Move attribute to it. */
3986 if (ntfs_attr_record_move_to(ctx, ni)) {
3987 err = errno;
3988 ntfs_log_trace("Couldn't move attribute to new MFT record.\n");
3989 goto put_err_out;
3990 }
3991 /* Update ntfs attribute. */
3992 if (na->ni->nr_extents == -1)
3993 na->ni = ni;
3994
3995 ntfs_attr_put_search_ctx(ctx);
3996 /* Try to perform resize once again. */
3997 return ntfs_resident_attr_resize(na, newsize);
3998
3999 resize_done:
4000 /*
4001 * Set the inode (and its base inode if it exists) dirty so it is
4002 * written out later.
4003 */
4004 ntfs_inode_mark_dirty(ctx->ntfs_ino);
4005 /* Done! */
4006 ntfs_attr_put_search_ctx(ctx);
4007 return 0;
4008 put_err_out:
4009 ntfs_attr_put_search_ctx(ctx);
4010 errno = err;
4011 return -1;
4012 }
4013
4014 /**
4015 * ntfs_attr_make_resident - convert a non-resident to a resident attribute
4016 * @na: open ntfs attribute to make resident
4017 * @ctx: ntfs search context describing the attribute
4018 *
4019 * Convert a non-resident ntfs attribute to a resident one.
4020 *
4021 * Return 0 on success and -1 on error with errno set to the error code. The
4022 * following error codes are defined:
4023 * EINVAL - Invalid arguments passed.
4024 * EPERM - The attribute is not allowed to be resident.
4025 * EIO - I/O error, damaged inode or bug.
4026 * ENOSPC - There is no enough space to perform conversion.
4027 * EOPNOTSUPP - Requested conversion is not supported yet.
4028 *
4029 * Warning: We do not set the inode dirty and we do not write out anything!
4030 * We expect the caller to do this as this is a fairly low level
4031 * function and it is likely there will be further changes made.
4032 */
ntfs_attr_make_resident(ntfs_attr * na,ntfs_attr_search_ctx * ctx)4033 static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
4034 {
4035 ntfs_volume *vol = na->ni->vol;
4036 ATTR_REC *a = ctx->attr;
4037 int name_ofs, val_ofs;
4038 s64 arec_size, bytes_read;
4039
4040 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
4041 long)na->ni->mft_no, na->type);
4042
4043 /* Should be called for the first extent of the attribute. */
4044 if (sle64_to_cpu(a->u.nonres.lowest_vcn)) {
4045 ntfs_log_trace("Should be called for the first extent of the "
4046 "attribute. Aborting...\n");
4047 errno = EINVAL;
4048 return -1;
4049 }
4050
4051 /* Some preliminary sanity checking. */
4052 if (!NAttrNonResident(na)) {
4053 ntfs_log_trace("Trying to make resident attribute resident. "
4054 "Aborting...\n");
4055 errno = EINVAL;
4056 return -1;
4057 }
4058
4059 /* Make sure this is not $MFT/$BITMAP or Windows will not boot! */
4060 if (na->type == AT_BITMAP && na->ni->mft_no == FILE_MFT) {
4061 errno = EPERM;
4062 return -1;
4063 }
4064
4065 /* Check that the attribute is allowed to be resident. */
4066 if (ntfs_attr_can_be_resident(vol, na->type))
4067 return -1;
4068
4069 /*
4070 * Check that the attribute name hasn't been placed after the
4071 * mapping pairs array. Chkdsk treat this as corruption.
4072 */
4073 if (a->name_length && le16_to_cpu(a->name_offset) >=
4074 le16_to_cpu(a->u.nonres.mapping_pairs_offset)) {
4075 ntfs_log_trace("Damaged attribute. Name is placed after the "
4076 "mapping pairs array. Run chkdsk. Aborting.\n");
4077 errno = EIO;
4078 return -1;
4079 }
4080
4081 if (NAttrCompressed(na) || NAttrEncrypted(na)) {
4082 ntfs_log_trace("Making compressed or encrypted files resident "
4083 "is not implemented yet.\n");
4084 errno = EOPNOTSUPP;
4085 return -1;
4086 }
4087
4088 /* Work out offsets into and size of the resident attribute. */
4089 name_ofs = 24; /* = sizeof(resident_ATTR_REC); */
4090 val_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
4091 arec_size = (val_ofs + na->data_size + 7) & ~7;
4092
4093 /* Sanity check the size before we start modifying the attribute. */
4094 if (le32_to_cpu(ctx->mrec->bytes_in_use) - le32_to_cpu(a->length) +
4095 arec_size > le32_to_cpu(ctx->mrec->bytes_allocated)) {
4096 ntfs_log_trace("Not enough space to make attribute resident\n");
4097 errno = ENOSPC;
4098 return -1;
4099 }
4100
4101 /* Read and cache the whole runlist if not already done. */
4102 if (ntfs_attr_map_whole_runlist(na))
4103 return -1;
4104
4105 /* Move the attribute name if it exists and update the offset. */
4106 if (a->name_length) {
4107 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
4108 a->name_length * sizeof(ntfschar));
4109 }
4110 a->name_offset = cpu_to_le16(name_ofs);
4111
4112 /* Resize the resident part of the attribute record. */
4113 if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
4114 /*
4115 * Bug, because ntfs_attr_record_resize should not fail (we
4116 * already checked that attribute fits MFT record).
4117 */
4118 ntfs_log_error("BUG! Failed to resize attribute record. "
4119 "Please report to the %s. Aborting...\n",
4120 NTFS_DEV_LIST);
4121 errno = EIO;
4122 return -1;
4123 }
4124
4125 /* Convert the attribute record to describe a resident attribute. */
4126 a->non_resident = 0;
4127 a->flags = 0;
4128 a->u.res.value_length = cpu_to_le32(na->data_size);
4129 a->u.res.value_offset = cpu_to_le16(val_ofs);
4130 /*
4131 * File names cannot be non-resident so we would never see this here
4132 * but at least it serves as a reminder that there may be attributes
4133 * for which we do need to set this flag. (AIA)
4134 */
4135 if (a->type == AT_FILE_NAME)
4136 a->u.res.resident_flags = RESIDENT_ATTR_IS_INDEXED;
4137 else
4138 a->u.res.resident_flags = 0;
4139 a->u.res.reservedR = 0;
4140
4141 /* Sanity fixup... Shouldn't really happen. (AIA) */
4142 if (na->initialized_size > na->data_size)
4143 na->initialized_size = na->data_size;
4144
4145 /* Copy data from run list to resident attribute value. */
4146 bytes_read = ntfs_rl_pread(vol, na->rl, 0, na->initialized_size,
4147 (u8*)a + val_ofs);
4148 if (bytes_read != na->initialized_size) {
4149 if (bytes_read >= 0)
4150 errno = EIO;
4151 ntfs_log_trace("Eeek! Failed to read attribute data. Leaving "
4152 "inconsistent metadata. Run chkdsk. "
4153 "Aborting...\n");
4154 return -1;
4155 }
4156
4157 /* Clear memory in gap between initialized_size and data_size. */
4158 if (na->initialized_size < na->data_size)
4159 memset((u8*)a + val_ofs + na->initialized_size, 0,
4160 na->data_size - na->initialized_size);
4161
4162 /*
4163 * Deallocate clusters from the runlist.
4164 *
4165 * NOTE: We can use ntfs_cluster_free() because we have already mapped
4166 * the whole run list and thus it doesn't matter that the attribute
4167 * record is in a transiently corrupted state at this moment in time.
4168 */
4169 if (ntfs_cluster_free(vol, na, 0, -1) < 0) {
4170 ntfs_log_perror("Eeek! Failed to release allocated clusters");
4171 ntfs_log_trace("Ignoring error and leaving behind wasted "
4172 "clusters.\n");
4173 }
4174
4175 /* Throw away the now unused runlist. */
4176 free(na->rl);
4177 na->rl = NULL;
4178
4179 /* Update in-memory struct ntfs_attr. */
4180 NAttrClearNonResident(na);
4181 NAttrClearCompressed(na);
4182 NAttrClearSparse(na);
4183 NAttrClearEncrypted(na);
4184 na->initialized_size = na->data_size;
4185 na->allocated_size = na->compressed_size = (na->data_size + 7) & ~7;
4186 na->compression_block_size = 0;
4187 na->compression_block_size_bits = na->compression_block_clusters = 0;
4188 return 0;
4189 }
4190
4191 #define NTFS_VCN_DELETE_MARK -2
4192 /**
4193 * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute
4194 * @na: non-resident ntfs open attribute for which we need update
4195 * @from_vcn: update runlist starting this VCN
4196 *
4197 * Build mapping pairs from @na->rl and write them to the disk. Also, this
4198 * function updates sparse bit, allocated and compressed size (allocates/frees
4199 * space for this field if required).
4200 *
4201 * @na->allocated_size should be set to correct value for the new runlist before
4202 * call to this function. Vice-versa @na->compressed_size will be calculated and
4203 * set to correct value during this function.
4204 *
4205 * New runlist should be fully formed starting @from_vcn. Runs before @from_vcn
4206 * can be mapped or not, but on-disk structures should not be modified before
4207 * call to this function so they can be mapped if necessary.
4208 *
4209 * FIXME: Make it O(1) for sparse files too, not only for normal.
4210 *
4211 * FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define.
4212 *
4213 * NOTE: Be careful in the future with updating bits on compressed files (at
4214 * present assumed that on-disk flag is already set/cleared before call to
4215 * this function).
4216 *
4217 * On success return 0 and on error return -1 with errno set to the error code.
4218 * The following error codes are defined:
4219 * EINVAL - Invalid arguments passed.
4220 * ENOMEM - Not enough memory to complete operation.
4221 * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST
4222 * or there is no free MFT records left to allocate.
4223 */
ntfs_attr_update_mapping_pairs(ntfs_attr * na,VCN from_vcn)4224 int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
4225 {
4226 ntfs_attr_search_ctx *ctx;
4227 ntfs_inode *ni, *base_ni;
4228 MFT_RECORD *m;
4229 ATTR_RECORD *a;
4230 VCN stop_vcn;
4231 int err, mp_size, cur_max_mp_size, exp_max_mp_size;
4232 BOOL finished_build;
4233
4234 retry:
4235 if (!na || !na->rl) {
4236 ntfs_log_trace("Invalid parameters passed.\n");
4237 errno = EINVAL;
4238 return -1;
4239 }
4240
4241 if (!NAttrNonResident(na)) {
4242 ntfs_log_trace("Attribute should be non resident.\n");
4243 errno = EINVAL;
4244 return -1;
4245 }
4246
4247 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, from vcn 0x%lld."
4248 "\n", (unsigned long long)na->ni->mft_no, na->type,
4249 from_vcn);
4250
4251 if (na->ni->nr_extents == -1)
4252 base_ni = na->ni->u.base_ni;
4253 else
4254 base_ni = na->ni;
4255
4256 ctx = ntfs_attr_get_search_ctx(base_ni, NULL);
4257 if (!ctx) {
4258 ntfs_log_trace("Couldn't get search context.\n");
4259 return -1;
4260 }
4261
4262 /* Fill attribute records with new mapping pairs. */
4263 stop_vcn = 0;
4264 finished_build = FALSE;
4265 while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
4266 CASE_SENSITIVE, ctx->is_first ? 0 : from_vcn,
4267 NULL, 0, ctx)) {
4268 a = ctx->attr;
4269 m = ctx->mrec;
4270 /*
4271 * If runlist is updating not from the beginning, then set
4272 * @stop_vcn properly, i.e. to the lowest vcn of record that
4273 * contain @from_vcn. Also we do not need @from_vcn anymore,
4274 * set it to 0 to make ntfs_attr_lookup enumerate attributes.
4275 */
4276 if (from_vcn && a->u.nonres.lowest_vcn) {
4277 LCN first_lcn;
4278
4279 stop_vcn = sle64_to_cpu(a->u.nonres.lowest_vcn);
4280 from_vcn = 0;
4281 /*
4282 * Check whether the first run we need to update is
4283 * the last run in runlist, if so, then deallocate
4284 * all attribute extents starting this one.
4285 */
4286 first_lcn = ntfs_rl_vcn_to_lcn(na->rl, stop_vcn);
4287 if (first_lcn == LCN_EINVAL) {
4288 ntfs_log_trace("BUG! Incorrect runlist.\n");
4289 err = EIO;
4290 goto put_err_out;
4291 }
4292 if (first_lcn == LCN_ENOENT ||
4293 first_lcn == LCN_RL_NOT_MAPPED)
4294 finished_build = TRUE;
4295 }
4296
4297 /*
4298 * Check whether we finished mapping pairs build, if so mark
4299 * extent as need to delete (by setting highest vcn to
4300 * NTFS_VCN_DELETE_MARK (-2), we shall check it later and
4301 * delete extent) and continue search.
4302 */
4303 if (finished_build) {
4304 ntfs_log_trace("Mark attr 0x%x for delete in inode "
4305 "0x%llx.\n", (unsigned)le32_to_cpu(
4306 a->type), ctx->ntfs_ino->mft_no);
4307 a->u.nonres.highest_vcn = cpu_to_sle64(NTFS_VCN_DELETE_MARK);
4308 ntfs_inode_mark_dirty(ctx->ntfs_ino);
4309 continue;
4310 }
4311
4312 /*
4313 * Check that the attribute name hasn't been placed after the
4314 * mapping pairs array. Windows treat this as a corruption.
4315 */
4316 if (a->name_length) {
4317 if (le16_to_cpu(a->name_offset) >=
4318 le16_to_cpu(a->u.nonres.mapping_pairs_offset)) {
4319 ntfs_log_error("Damaged attribute. Name is "
4320 "placed after the mapping "
4321 "pairs array. Run chkdsk.\n");
4322 err = EIO;
4323 goto put_err_out;
4324 }
4325 }
4326 /*
4327 * If we in the first extent, then set/clean sparse bit,
4328 * update allocated and compressed size.
4329 */
4330 if (!a->u.nonres.lowest_vcn) {
4331 int sparse;
4332
4333 /* Update allocated size. */
4334 a->u.nonres.allocated_size = cpu_to_sle64(na->allocated_size);
4335 /*
4336 * Check whether part of runlist we are updating is
4337 * sparse.
4338 */
4339 sparse = ntfs_rl_sparse(na->rl);
4340 if (sparse == -1) {
4341 ntfs_log_trace("Bad runlist.\n");
4342 err = errno;
4343 goto put_err_out;
4344 }
4345 /*
4346 * If new part or on-disk attribute is not sparse, then
4347 * we should fully map runlist to make final decision.
4348 */
4349 if (sparse || (a->flags & ATTR_IS_SPARSE)) {
4350 if (from_vcn && ntfs_attr_map_runlist_range(na,
4351 0, from_vcn - 1)) {
4352 ntfs_log_trace("Failed to map runlist "
4353 "before @from_vcn.\n");
4354 err = errno;
4355 goto put_err_out;
4356 }
4357 /*
4358 * Reconsider whether whole runlist is sparse
4359 * if new part is not.
4360 */
4361 if (!sparse) {
4362 sparse = ntfs_rl_sparse(na->rl);
4363 if (sparse == -1) {
4364 ntfs_log_trace("Bad "
4365 "runlist.\n");
4366 err = errno;
4367 goto put_err_out;
4368 }
4369 }
4370 }
4371 /* Attribute becomes sparse/compressed. */
4372 if (sparse && !(a->flags & (ATTR_IS_SPARSE |
4373 ATTR_IS_COMPRESSED))) {
4374 /*
4375 * We need to move attribute to another mft
4376 * record, if attribute is to small to add
4377 * compressed_size field to it and we have no
4378 * free space in the current mft record.
4379 */
4380 if ((le32_to_cpu(a->length) - le16_to_cpu(
4381 a->u.nonres.mapping_pairs_offset)
4382 == 8) && !(le32_to_cpu(
4383 m->bytes_allocated) -
4384 le32_to_cpu(m->bytes_in_use))) {
4385 if (!NInoAttrList(na->ni)) {
4386 ntfs_attr_put_search_ctx(ctx);
4387 if (ntfs_inode_add_attrlist(
4388 na->ni))
4389 return -1;
4390 goto retry;
4391 }
4392 if (ntfs_attr_record_move_away(ctx,
4393 8)) {
4394 ntfs_log_trace("Failed to move "
4395 "attribute to another "
4396 "extent. Aborting..\n");
4397 err = errno;
4398 goto put_err_out;
4399 }
4400 ntfs_attr_put_search_ctx(ctx);
4401 goto retry;
4402 }
4403 if (!(le32_to_cpu(a->length) - le16_to_cpu(
4404 a->u.nonres.mapping_pairs_offset))) {
4405 ntfs_log_trace("Size of the space "
4406 "allocated for mapping "
4407 "pairs should not be 0."
4408 " Aborting ...\n");
4409 err = EIO;
4410 goto put_err_out;
4411 }
4412 NAttrSetSparse(na);
4413 a->flags |= ATTR_IS_SPARSE;
4414 a->u.nonres.compression_unit = 4; /* Windows set it so,
4415 even if attribute
4416 is not actually
4417 compressed. */
4418 memmove((u8*)a + le16_to_cpu(a->name_offset) +
4419 8, (u8*)a + le16_to_cpu(a->name_offset),
4420 a->name_length * sizeof(ntfschar));
4421 a->name_offset = cpu_to_le16(le16_to_cpu(
4422 a->name_offset) + 8);
4423 a->u.nonres.mapping_pairs_offset =
4424 cpu_to_le16(le16_to_cpu(
4425 a->u.nonres.mapping_pairs_offset) + 8);
4426 /*
4427 * We should update all mapping pairs, because
4428 * we shifted their starting position.
4429 */
4430 from_vcn = 0;
4431 }
4432 /* Attribute becomes normal. */
4433 if (!sparse && (a->flags & ATTR_IS_SPARSE) &&
4434 !(a->flags & ATTR_IS_COMPRESSED)) {
4435 NAttrClearSparse(na);
4436 a->flags &= ~ATTR_IS_SPARSE;
4437 a->u.nonres.compression_unit = 0;
4438 memmove((u8*)a + le16_to_cpu(a->name_offset) -
4439 8, (u8*)a + le16_to_cpu(a->name_offset),
4440 a->name_length * sizeof(ntfschar));
4441 /*
4442 * Windows defragmentation tool do not update
4443 * name offset correctly for unnamed
4444 * attributes, but chkdsk do not like when it
4445 * negative, so do not change it at all if it
4446 * would become negative.
4447 */
4448 if (le16_to_cpu(a->name_offset) >= 8)
4449 a->name_offset = cpu_to_le16(
4450 le16_to_cpu(
4451 a->name_offset) - 8);
4452 a->u.nonres.mapping_pairs_offset =
4453 cpu_to_le16(le16_to_cpu(
4454 a->u.nonres.mapping_pairs_offset) - 8);
4455 /*
4456 * We should update all mapping pairs, because
4457 * we shifted their starting position.
4458 */
4459 from_vcn = 0;
4460 }
4461 /* Update compressed size if required. */
4462 if (sparse || (a->flags & ATTR_IS_COMPRESSED)) {
4463 s64 new_compr_size;
4464
4465 new_compr_size = ntfs_rl_get_compressed_size(
4466 na->ni->vol, na->rl);
4467 if (new_compr_size == -1) {
4468 err = errno;
4469 ntfs_log_trace("BUG! Leaving "
4470 "inconsistent "
4471 "metadata.\n");
4472 goto put_err_out;
4473 }
4474 na->compressed_size = new_compr_size;
4475 a->u.nonres.compressed_size = cpu_to_sle64(
4476 new_compr_size);
4477 }
4478 /*
4479 * Set FILE_NAME dirty flag, to update sparse bit and
4480 * allocated size in the index.
4481 */
4482 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
4483 if (sparse)
4484 na->ni->allocated_size =
4485 na->compressed_size;
4486 else
4487 na->ni->allocated_size =
4488 na->allocated_size;
4489 NInoFileNameSetDirty(na->ni);
4490 }
4491
4492 /*
4493 * We do want to do anything for the first extent in
4494 * case we are updating mapping pairs not from the
4495 * begging.
4496 */
4497 if (!a->u.nonres.highest_vcn || from_vcn <=
4498 sle64_to_cpu(a->u.nonres.highest_vcn) + 1)
4499 from_vcn = 0;
4500 else {
4501 if (from_vcn)
4502 continue;
4503 }
4504 }
4505
4506 /* Get the size for the rest of mapping pairs array. */
4507 mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl,
4508 stop_vcn);
4509 if (mp_size <= 0) {
4510 err = errno;
4511 ntfs_log_trace("Get size for mapping pairs failed.\n");
4512 goto put_err_out;
4513 }
4514 /*
4515 * Determine maximum possible length of mapping pairs,
4516 * if we shall *not* expand space for mapping pairs.
4517 */
4518 cur_max_mp_size = le32_to_cpu(a->length) -
4519 le16_to_cpu(a->u.nonres.mapping_pairs_offset);
4520 /*
4521 * Determine maximum possible length of mapping pairs in the
4522 * current mft record, if we shall expand space for mapping
4523 * pairs.
4524 */
4525 exp_max_mp_size = le32_to_cpu(m->bytes_allocated) -
4526 le32_to_cpu(m->bytes_in_use) + cur_max_mp_size;
4527 /* Test mapping pairs for fitting in the current mft record. */
4528 if (mp_size > exp_max_mp_size) {
4529 /*
4530 * Mapping pairs of $ATTRIBUTE_LIST attribute must fit
4531 * in the base mft record. Try to move out other
4532 * attributes and try again.
4533 */
4534 if (na->type == AT_ATTRIBUTE_LIST) {
4535 ntfs_attr_put_search_ctx(ctx);
4536 if (ntfs_inode_free_space(na->ni, mp_size -
4537 cur_max_mp_size)) {
4538 if (errno != ENOSPC)
4539 return -1;
4540 ntfs_log_error("Attribute list mapping "
4541 "pairs size to big, "
4542 "can't fit them in the "
4543 "base MFT record. "
4544 "Defragment volume and "
4545 "try once again.\n");
4546 errno = ENOSPC;
4547 return -1;
4548 }
4549 goto retry;
4550 }
4551
4552 /* Add attribute list if it isn't present, and retry. */
4553 if (!NInoAttrList(base_ni)) {
4554 ntfs_attr_put_search_ctx(ctx);
4555 if (ntfs_inode_add_attrlist(base_ni)) {
4556 ntfs_log_trace("Couldn't add attribute "
4557 "list.\n");
4558 return -1;
4559 }
4560 goto retry;
4561 }
4562
4563 /*
4564 * Set mapping pairs size to maximum possible for this
4565 * mft record. We shall write the rest of mapping pairs
4566 * to another MFT records.
4567 */
4568 mp_size = exp_max_mp_size;
4569 }
4570
4571 /* Change space for mapping pairs if we need it. */
4572 if (((mp_size + 7) & ~7) != cur_max_mp_size) {
4573 if (ntfs_attr_record_resize(m, a,
4574 le16_to_cpu(a->u.nonres.mapping_pairs_offset) +
4575 mp_size)) {
4576 ntfs_log_error("BUG! Ran out of space in mft "
4577 "record. Please run chkdsk and "
4578 "if that doesn't find any "
4579 "errors please report you saw "
4580 "this message to %s.\n",
4581 NTFS_DEV_LIST);
4582 err = EIO;
4583 goto put_err_out;
4584 }
4585 }
4586
4587 /* Update lowest vcn. */
4588 a->u.nonres.lowest_vcn = cpu_to_sle64(stop_vcn);
4589 ntfs_inode_mark_dirty(ctx->ntfs_ino);
4590 if ((ctx->ntfs_ino->nr_extents == -1 ||
4591 NInoAttrList(ctx->ntfs_ino)) &&
4592 ctx->attr->type != AT_ATTRIBUTE_LIST) {
4593 ctx->al_entry->lowest_vcn = cpu_to_sle64(stop_vcn);
4594 ntfs_attrlist_mark_dirty(ctx->ntfs_ino);
4595 }
4596
4597 /*
4598 * Generate the new mapping pairs array directly into the
4599 * correct destination, i.e. the attribute record itself.
4600 */
4601 if (!ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu(
4602 a->u.nonres.mapping_pairs_offset), mp_size, na->rl,
4603 stop_vcn, &stop_vcn))
4604 finished_build = TRUE;
4605 if (!finished_build && errno != ENOSPC) {
4606 err = errno;
4607 ntfs_log_error("BUG! Mapping pairs build failed. "
4608 "Please run chkdsk and if that doesn't "
4609 "find any errors please report you saw "
4610 "this message to %s.\n", NTFS_DEV_LIST);
4611 goto put_err_out;
4612 }
4613 a->u.nonres.highest_vcn = cpu_to_sle64(stop_vcn - 1);
4614 }
4615 /* Check whether error occurred. */
4616 if (errno != ENOENT) {
4617 err = errno;
4618 ntfs_log_trace("Attribute lookup failed.\n");
4619 goto put_err_out;
4620 }
4621 /* Sanity check. */
4622 if (from_vcn) {
4623 err = ENOMSG;
4624 ntfs_log_error("Library BUG! @from_vcn is nonzero, please "
4625 "report to %s.\n", NTFS_DEV_LIST);
4626 goto put_err_out;
4627 }
4628
4629 /* Deallocate not used attribute extents and return with success. */
4630 if (finished_build) {
4631 ntfs_attr_reinit_search_ctx(ctx);
4632 ntfs_log_trace("Deallocate marked extents.\n");
4633 while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
4634 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
4635 if (sle64_to_cpu(ctx->attr->u.nonres.highest_vcn) !=
4636 NTFS_VCN_DELETE_MARK)
4637 continue;
4638 /* Remove unused attribute record. */
4639 if (ntfs_attr_record_rm(ctx)) {
4640 err = errno;
4641 ntfs_log_trace("Couldn't remove unused "
4642 "attribute record.\n");
4643 goto put_err_out;
4644 }
4645 ntfs_attr_reinit_search_ctx(ctx);
4646 }
4647 if (errno != ENOENT) {
4648 err = errno;
4649 ntfs_log_trace("Attribute lookup failed.\n");
4650 goto put_err_out;
4651 }
4652 ntfs_log_trace("Deallocate done.\n");
4653 ntfs_attr_put_search_ctx(ctx);
4654 ntfs_log_trace("Done!");
4655 return 0;
4656 }
4657 ntfs_attr_put_search_ctx(ctx);
4658 ctx = NULL;
4659
4660 /* Allocate new MFT records for the rest of mapping pairs. */
4661 while (1) {
4662 /* Calculate size of rest mapping pairs. */
4663 mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol,
4664 na->rl, stop_vcn);
4665 if (mp_size <= 0) {
4666 err = errno;
4667 ntfs_log_trace("Get size for mapping pairs failed.\n");
4668 goto put_err_out;
4669 }
4670 /* Allocate new mft record. */
4671 ni = ntfs_mft_record_alloc(na->ni->vol, base_ni);
4672 if (!ni) {
4673 err = errno;
4674 ntfs_log_trace("Couldn't allocate new MFT record.\n");
4675 goto put_err_out;
4676 }
4677 m = ni->mrec;
4678 /*
4679 * If mapping size exceed available space, set them to
4680 * possible maximum.
4681 */
4682 cur_max_mp_size = le32_to_cpu(m->bytes_allocated) -
4683 le32_to_cpu(m->bytes_in_use) -
4684 (offsetof(ATTR_RECORD, u.nonres.compressed_size) +
4685 ((NAttrCompressed(na) || NAttrSparse(na)) ?
4686 sizeof(a->u.nonres.compressed_size) : 0)) -
4687 ((sizeof(ntfschar) * na->name_len + 7) & ~7);
4688 if (mp_size > cur_max_mp_size)
4689 mp_size = cur_max_mp_size;
4690 /* Add attribute extent to new record. */
4691 err = ntfs_non_resident_attr_record_add(ni, na->type,
4692 na->name, na->name_len, stop_vcn, mp_size, 0);
4693 if (err == -1) {
4694 err = errno;
4695 ntfs_log_trace("Couldn't add attribute extent into the "
4696 "MFT record.\n");
4697 if (ntfs_mft_record_free(na->ni->vol, ni)) {
4698 ntfs_log_trace("Couldn't free MFT record.\n");
4699 }
4700 goto put_err_out;
4701 }
4702 a = (ATTR_RECORD*)((u8*)m + err);
4703
4704 err = ntfs_mapping_pairs_build(na->ni->vol, (u8*)a +
4705 le16_to_cpu(a->u.nonres.mapping_pairs_offset), mp_size, na->rl,
4706 stop_vcn, &stop_vcn);
4707 if (err < 0 && errno != ENOSPC) {
4708 err = errno;
4709 ntfs_log_error("BUG! Mapping pairs build failed. "
4710 "Please run chkdsk and if that doesn't "
4711 "find any errors please report you saw "
4712 "this message to %s.\n", NTFS_DEV_LIST);
4713 if (ntfs_mft_record_free(na->ni->vol, ni))
4714 ntfs_log_trace("Couldn't free MFT record.\n");
4715 goto put_err_out;
4716 }
4717 a->u.nonres.highest_vcn = cpu_to_sle64(stop_vcn - 1);
4718 ntfs_inode_mark_dirty(ni);
4719 /* All mapping pairs has been written. */
4720 if (!err)
4721 break;
4722 }
4723 ntfs_log_trace("Done!\n");
4724 return 0;
4725 put_err_out:
4726 if (ctx)
4727 ntfs_attr_put_search_ctx(ctx);
4728 errno = err;
4729 return -1;
4730 }
4731 #undef NTFS_VCN_DELETE_MARK
4732
4733 /**
4734 * ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute
4735 * @na: non-resident ntfs attribute to shrink
4736 * @newsize: new size (in bytes) to which to shrink the attribute
4737 *
4738 * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes.
4739 *
4740 * On success return 0 and on error return -1 with errno set to the error code.
4741 * The following error codes are defined:
4742 * ENOMEM - Not enough memory to complete operation.
4743 * ERANGE - @newsize is not valid for the attribute type of @na.
4744 */
ntfs_non_resident_attr_shrink(ntfs_attr * na,const s64 newsize)4745 static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize)
4746 {
4747 ntfs_volume *vol;
4748 ntfs_attr_search_ctx *ctx;
4749 VCN first_free_vcn;
4750 s64 nr_freed_clusters;
4751 int err;
4752
4753 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, newsize %lld.\n",
4754 (unsigned long long)na->ni->mft_no, na->type,
4755 (long long)newsize);
4756
4757 vol = na->ni->vol;
4758
4759 /*
4760 * Check the attribute type and the corresponding minimum size
4761 * against @newsize and fail if @newsize is too small.
4762 */
4763 if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
4764 if (errno == ERANGE) {
4765 ntfs_log_trace("Eeek! Size bounds check failed. "
4766 "Aborting...\n");
4767 } else if (errno == ENOENT)
4768 errno = EIO;
4769 return -1;
4770 }
4771
4772 /* The first cluster outside the new allocation. */
4773 first_free_vcn = (newsize + vol->cluster_size - 1) >>
4774 vol->cluster_size_bits;
4775 /*
4776 * Compare the new allocation with the old one and only deallocate
4777 * clusters if there is a change.
4778 */
4779 if ((na->allocated_size >> vol->cluster_size_bits) != first_free_vcn) {
4780 if (ntfs_attr_map_whole_runlist(na)) {
4781 ntfs_log_trace("Eeek! ntfs_attr_map_whole_runlist "
4782 "failed.\n");
4783 return -1;
4784 }
4785 /* Deallocate all clusters starting with the first free one. */
4786 nr_freed_clusters = ntfs_cluster_free(vol, na, first_free_vcn,
4787 -1);
4788 if (nr_freed_clusters < 0) {
4789 ntfs_log_trace("Eeek! Freeing of clusters failed. "
4790 "Aborting...\n");
4791 return -1;
4792 }
4793
4794 /* Truncate the runlist itself. */
4795 if (ntfs_rl_truncate(&na->rl, first_free_vcn)) {
4796 err = errno;
4797 /*
4798 * Failed to truncate the runlist, so just throw it
4799 * away, it will be mapped afresh on next use.
4800 */
4801 free(na->rl);
4802 na->rl = NULL;
4803 ntfs_log_trace("Eeek! Run list truncation failed.\n");
4804 errno = err;
4805 return -1;
4806 }
4807
4808 /* Prepare to mapping pairs update. */
4809 na->allocated_size = first_free_vcn << vol->cluster_size_bits;
4810 /* Write mapping pairs for new runlist. */
4811 if (ntfs_attr_update_mapping_pairs(na, first_free_vcn)) {
4812 ntfs_log_trace("Eeek! Mapping pairs update failed. "
4813 "Leaving inconsistent metadata. "
4814 "Run chkdsk.\n");
4815 return -1;
4816 }
4817 }
4818
4819 /* Get the first attribute record. */
4820 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
4821 if (!ctx) {
4822 ntfs_log_trace("Couldn't get attribute search context.\n");
4823 return -1;
4824 }
4825 if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
4826 0, NULL, 0, ctx)) {
4827 err = errno;
4828 if (err == ENOENT)
4829 err = EIO;
4830 ntfs_log_trace("Eeek! Lookup of first attribute extent failed. "
4831 "Leaving inconsistent metadata.\n");
4832 goto put_err_out;
4833 }
4834
4835 /* Update data and initialized size. */
4836 na->data_size = newsize;
4837 ctx->attr->u.nonres.data_size = cpu_to_sle64(newsize);
4838 if (newsize < na->initialized_size) {
4839 na->initialized_size = newsize;
4840 ctx->attr->u.nonres.initialized_size = cpu_to_sle64(newsize);
4841 }
4842 /* Update data size in the index. */
4843 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
4844 na->ni->data_size = na->data_size;
4845 NInoFileNameSetDirty(na->ni);
4846 }
4847
4848 /* If the attribute now has zero size, make it resident. */
4849 if (!newsize) {
4850 if (ntfs_attr_make_resident(na, ctx)) {
4851 /* If couldn't make resident, just continue. */
4852 if (errno != EPERM)
4853 ntfs_log_error("Failed to make attribute "
4854 "resident. Leaving as is...\n");
4855 }
4856 }
4857
4858 /* Set the inode dirty so it is written out later. */
4859 ntfs_inode_mark_dirty(ctx->ntfs_ino);
4860 /* Done! */
4861 ntfs_attr_put_search_ctx(ctx);
4862 return 0;
4863 put_err_out:
4864 ntfs_attr_put_search_ctx(ctx);
4865 errno = err;
4866 return -1;
4867 }
4868
4869 /**
4870 * ntfs_non_resident_attr_expand - expand a non-resident, open ntfs attribute
4871 * @na: non-resident ntfs attribute to expand
4872 * @newsize: new size (in bytes) to which to expand the attribute
4873 * @sparse: if TRUE then will create hole if possible
4874 *
4875 * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes,
4876 * by allocating new clusters.
4877 *
4878 * On success return 0 and on error return -1 with errno set to the error code.
4879 * The following error codes are defined:
4880 * ENOMEM - Not enough memory to complete operation.
4881 * ERANGE - @newsize is not valid for the attribute type of @na.
4882 * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
4883 */
ntfs_non_resident_attr_expand(ntfs_attr * na,const s64 newsize,BOOL sparse)4884 static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
4885 BOOL sparse)
4886 {
4887 VCN first_free_vcn;
4888 ntfs_volume *vol;
4889 ntfs_attr_search_ctx *ctx;
4890 runlist *rl, *rln;
4891 s64 org_alloc_size;
4892 int err;
4893
4894 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, new size %lld, "
4895 "current size %lld.\n",
4896 (unsigned long long)na->ni->mft_no, na->type,
4897 (long long)newsize, (long long)na->data_size);
4898
4899 vol = na->ni->vol;
4900
4901 /*
4902 * Check the attribute type and the corresponding maximum size
4903 * against @newsize and fail if @newsize is too big.
4904 */
4905 if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
4906 if (errno == ERANGE) {
4907 ntfs_log_trace("Eeek! Size bounds check failed. "
4908 "Aborting...\n");
4909 } else if (errno == ENOENT)
4910 errno = EIO;
4911 return -1;
4912 }
4913
4914 /* Save for future use. */
4915 org_alloc_size = na->allocated_size;
4916 /* The first cluster outside the new allocation. */
4917 first_free_vcn = (newsize + vol->cluster_size - 1) >>
4918 vol->cluster_size_bits;
4919 /*
4920 * Compare the new allocation with the old one and only allocate
4921 * clusters if there is a change.
4922 */
4923 if ((na->allocated_size >> vol->cluster_size_bits) < first_free_vcn) {
4924 /* Map required part of runlist. */
4925 if (ntfs_attr_map_runlist(na, na->allocated_size >>
4926 vol->cluster_size_bits)) {
4927 ntfs_log_error("Failed to map runlist.\n");
4928 return -1;
4929 }
4930
4931 /*
4932 * If we extend $DATA attribute on NTFS 3+ volume, we can add
4933 * sparse runs instead of real allocation of clusters.
4934 */
4935 if (na->type == AT_DATA && vol->major_ver >= 3 && sparse) {
4936 rl = ntfs_malloc(0x1000);
4937 if (!rl)
4938 return -1;
4939
4940 rl[0].vcn = (na->allocated_size >>
4941 vol->cluster_size_bits);
4942 rl[0].lcn = LCN_HOLE;
4943 rl[0].length = first_free_vcn -
4944 (na->allocated_size >> vol->cluster_size_bits);
4945 rl[1].vcn = first_free_vcn;
4946 rl[1].lcn = LCN_ENOENT;
4947 rl[1].length = 0;
4948 } else {
4949 /*
4950 * Determine first after last LCN of attribute.
4951 * We will start seek clusters from this LCN to avoid
4952 * fragmentation. If there are no valid LCNs in the
4953 * attribute let the cluster allocator choose the
4954 * starting LCN.
4955 */
4956 LCN lcn_seek_from;
4957
4958 lcn_seek_from = -1;
4959 if (na->rl->length) {
4960 /* Seek to the last run list element. */
4961 for (rl = na->rl; (rl + 1)->length; rl++)
4962 ;
4963 /*
4964 * If the last LCN is a hole or similar seek
4965 * back to last valid LCN.
4966 */
4967 while (rl->lcn < 0 && rl != na->rl)
4968 rl--;
4969 /*
4970 * Only set lcn_seek_from it the LCN is valid.
4971 */
4972 if (rl->lcn >= 0)
4973 lcn_seek_from = rl->lcn + rl->length;
4974 }
4975
4976 rl = ntfs_cluster_alloc(vol, na->allocated_size >>
4977 vol->cluster_size_bits, first_free_vcn -
4978 (na->allocated_size >>
4979 vol->cluster_size_bits), lcn_seek_from,
4980 DATA_ZONE);
4981 if (!rl) {
4982 ntfs_log_trace("Cluster allocation failed.\n");
4983 return -1;
4984 }
4985 }
4986
4987 /* Append new clusters to attribute runlist. */
4988 rln = ntfs_runlists_merge(na->rl, rl);
4989 if (!rln) {
4990 /* Failed, free just allocated clusters. */
4991 err = errno;
4992 ntfs_log_trace("Run list merge failed.\n");
4993 ntfs_cluster_free_from_rl(vol, rl);
4994 free(rl);
4995 errno = err;
4996 return -1;
4997 }
4998 na->rl = rln;
4999
5000 /* Prepare to mapping pairs update. */
5001 na->allocated_size = first_free_vcn << vol->cluster_size_bits;
5002 /* Write mapping pairs for new runlist. */
5003 if (ntfs_attr_update_mapping_pairs(na, org_alloc_size >>
5004 vol->cluster_size_bits)) {
5005 err = errno;
5006 ntfs_log_trace("Mapping pairs update failed.\n");
5007 goto rollback;
5008 }
5009 }
5010
5011 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
5012 if (!ctx) {
5013 ntfs_log_trace("Failed to get search context.\n");
5014 if (na->allocated_size == org_alloc_size) {
5015 return -1;
5016 }
5017 err = errno;
5018 goto rollback;
5019 }
5020
5021 if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
5022 0, NULL, 0, ctx)) {
5023 err = errno;
5024 ntfs_log_trace("Lookup of first attribute extent failed.\n");
5025 if (err == ENOENT)
5026 err = EIO;
5027 if (na->allocated_size != org_alloc_size) {
5028 ntfs_attr_put_search_ctx(ctx);
5029 goto rollback;
5030 } else
5031 goto put_err_out;
5032 }
5033
5034 /* Update data size. */
5035 na->data_size = newsize;
5036 ctx->attr->u.nonres.data_size = cpu_to_sle64(newsize);
5037 /* Update data size in the index. */
5038 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
5039 na->ni->data_size = na->data_size;
5040 NInoFileNameSetDirty(na->ni);
5041 }
5042 /* Set the inode dirty so it is written out later. */
5043 ntfs_inode_mark_dirty(ctx->ntfs_ino);
5044 /* Done! */
5045 ntfs_attr_put_search_ctx(ctx);
5046 return 0;
5047 rollback:
5048 /* Free allocated clusters. */
5049 if (ntfs_cluster_free(vol, na, org_alloc_size >>
5050 vol->cluster_size_bits, -1) < 0) {
5051 ntfs_log_trace("Eeek! Leaking clusters. Run chkdsk!\n");
5052 err = EIO;
5053 }
5054 /* Now, truncate the runlist itself. */
5055 if (ntfs_rl_truncate(&na->rl, org_alloc_size >>
5056 vol->cluster_size_bits)) {
5057 /*
5058 * Failed to truncate the runlist, so just throw it away, it
5059 * will be mapped afresh on next use.
5060 */
5061 free(na->rl);
5062 na->rl = NULL;
5063 ntfs_log_trace("Couldn't truncate runlist. Rollback failed.\n");
5064 } else {
5065 /* Prepare to mapping pairs update. */
5066 na->allocated_size = org_alloc_size;
5067 /* Restore mapping pairs. */
5068 if (ntfs_attr_update_mapping_pairs(na, na->allocated_size >>
5069 vol->cluster_size_bits)) {
5070 ntfs_log_trace("Failed to restore old mapping pairs. "
5071 "Rollback failed.\n");
5072 }
5073 }
5074 errno = err;
5075 return -1;
5076 put_err_out:
5077 ntfs_attr_put_search_ctx(ctx);
5078 errno = err;
5079 return -1;
5080 }
5081
5082
5083 /**
5084 * __ntfs_attr_truncate - resize an ntfs attribute
5085 * @na: open ntfs attribute to resize
5086 * @newsize: new size (in bytes) to which to resize the attribute
5087 * @sparse: if TRUE then will create hole if possible
5088 *
5089 * Change the size of an open ntfs attribute @na to @newsize bytes. If the
5090 * attribute is made bigger and the attribute is resident the newly
5091 * "allocated" space is cleared and if the attribute is non-resident the
5092 * newly allocated space is marked as not initialised and no real allocation
5093 * on disk is performed.
5094 *
5095 * On success return 0 and on error return -1 with errno set to the error code.
5096 * The following error codes are defined:
5097 * EINVAL - Invalid arguments were passed to the function.
5098 * EACCES - Attribute is encrypted.
5099 * ERANGE - @newsize is not valid for the attribute type of @na.
5100 * ENOSPC - There is no enough space on the volume to allocate
5101 * new clusters or in base mft to resize $ATTRIBUTE_LIST.
5102 * EOVERFLOW - Resident attribute can not become non resident and
5103 * already filled whole MFT record, but had not reached
5104 * @newsize bytes length.
5105 * EOPNOTSUPP - The desired resize is not implemented yet.
5106 */
__ntfs_attr_truncate(ntfs_attr * na,const s64 newsize,BOOL sparse)5107 int __ntfs_attr_truncate(ntfs_attr *na, const s64 newsize, BOOL sparse)
5108 {
5109 int ret;
5110
5111 if (!na || newsize < 0 ||
5112 (na->ni->mft_no == FILE_MFT && na->type == AT_DATA)) {
5113 ntfs_log_trace("Invalid arguments passed.\n");
5114 errno = EINVAL;
5115 return -1;
5116 }
5117
5118 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
5119 long)na->ni->mft_no, na->type);
5120
5121 if (na->data_size == newsize)
5122 return 0;
5123 /*
5124 * Encrypted attributes are not supported. We return access denied,
5125 * which is what Windows NT4 does, too.
5126 */
5127 if (NAttrEncrypted(na)) {
5128 errno = EACCES;
5129 ntfs_log_trace("Failed (encrypted).\n");
5130 return -1;
5131 }
5132 /*
5133 * TODO: Implement making handling of compressed attributes.
5134 */
5135 if (NAttrCompressed(na)) {
5136 errno = EOPNOTSUPP;
5137 ntfs_log_trace("Failed (compressed).\n");
5138 return -1;
5139 }
5140 if (NAttrNonResident(na)) {
5141 if (newsize > na->data_size)
5142 ret = ntfs_non_resident_attr_expand(na, newsize,
5143 sparse);
5144 else
5145 ret = ntfs_non_resident_attr_shrink(na, newsize);
5146 } else
5147 ret = ntfs_resident_attr_resize(na, newsize);
5148 if (!ret)
5149 ntfs_log_trace("Done!\n");
5150 else
5151 ntfs_log_trace("Failed.\n");
5152 return ret;
5153 }
5154
5155
5156 /**
5157 * Wrapper around __ntfs_attr_truncate that always tries to creates hole
5158 */
ntfs_attr_truncate(ntfs_attr * na,const s64 newsize)5159 int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
5160 {
5161 return __ntfs_attr_truncate(na, newsize, TRUE);
5162 }
5163
5164
5165 /**
5166 * ntfs_attr_readall - read the entire data from an ntfs attribute
5167 * @ni: open ntfs inode in which the ntfs attribute resides
5168 * @type: attribute type
5169 * @name: attribute name in little endian Unicode or AT_UNNAMED or NULL
5170 * @name_len: length of attribute @name in Unicode characters (if @name given)
5171 * @data_size: if non-NULL then store here the data size
5172 *
5173 * This function will read the entire content of an ntfs attribute.
5174 * If @name is AT_UNNAMED then look specifically for an unnamed attribute.
5175 * If @name is NULL then the attribute could be either named or not.
5176 * In both those cases @name_len is not used at all.
5177 *
5178 * On success a buffer is allocated with the content of the attribute
5179 * and which needs to be freed when it's not needed anymore. If the
5180 * @data_size parameter is non-NULL then the data size is set there.
5181 *
5182 * On error NULL is returned with errno set to the error code.
5183 */
ntfs_attr_readall(ntfs_inode * ni,const ATTR_TYPES type,ntfschar * name,u32 name_len,s64 * data_size)5184 void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
5185 ntfschar *name, u32 name_len, s64 *data_size)
5186 {
5187 ntfs_attr *na;
5188 void *data, *ret = NULL;
5189 s64 size;
5190
5191 na = ntfs_attr_open(ni, type, name, name_len);
5192 if (!na) {
5193 ntfs_log_perror("ntfs_attr_open failed");
5194 return NULL;
5195 }
5196 data = ntfs_malloc(na->data_size);
5197 if (!data)
5198 goto out;
5199
5200 size = ntfs_attr_pread(na, 0, na->data_size, data);
5201 if (size != na->data_size) {
5202 ntfs_log_perror("ntfs_attr_pread failed");
5203 free(data);
5204 goto out;
5205 }
5206 ret = data;
5207 if (data_size)
5208 *data_size = size;
5209 out:
5210 ntfs_attr_close(na);
5211 return ret;
5212 }
5213
5214 /**
5215 * ntfs_attr_exist - FIXME: description
5216 */
ntfs_attr_exist(ntfs_inode * ni,const ATTR_TYPES type,ntfschar * name,u32 name_len)5217 int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,
5218 u32 name_len)
5219 {
5220 ntfs_attr_search_ctx *ctx;
5221 int ret;
5222
5223 ntfs_log_trace("Entering.\n");
5224
5225 ctx = ntfs_attr_get_search_ctx(ni, NULL);
5226 if (!ctx)
5227 return 0;
5228
5229 ret = ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, 0, NULL, 0,
5230 ctx);
5231
5232 ntfs_attr_put_search_ctx(ctx);
5233 return !ret;
5234 }
5235