dnsmasq latest
[tomato.git] / release / src / router / ntfs-3g / libntfs-3g / attrib.c
blobc116d9ad752fd6a3c9ac24068ac233ea723f4060
1 /**
2 * attrib.c - Attribute handling code. Originated from the Linux-NTFS project.
4 * Copyright (c) 2000-2010 Anton Altaparmakov
5 * Copyright (c) 2002-2005 Richard Russon
6 * Copyright (c) 2002-2008 Szabolcs Szakacsits
7 * Copyright (c) 2004-2007 Yura Pakhuchiy
8 * Copyright (c) 2007-2011 Jean-Pierre Andre
9 * Copyright (c) 2010 Erik Larsson
11 * This program/include file is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as published
13 * by the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program/include file is distributed in the hope that it will be
17 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
18 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (in the main directory of the NTFS-3G
23 * distribution in the file COPYING); if not, write to the Free Software
24 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
31 #ifdef HAVE_STDIO_H
32 #include <stdio.h>
33 #endif
34 #ifdef HAVE_STRING_H
35 #include <string.h>
36 #endif
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40 #ifdef HAVE_ERRNO_H
41 #include <errno.h>
42 #endif
43 #ifdef HAVE_LIMITS_H
44 #include <limits.h>
45 #endif
47 #include "param.h"
48 #include "compat.h"
49 #include "attrib.h"
50 #include "attrlist.h"
51 #include "device.h"
52 #include "mft.h"
53 #include "debug.h"
54 #include "mst.h"
55 #include "volume.h"
56 #include "types.h"
57 #include "layout.h"
58 #include "inode.h"
59 #include "runlist.h"
60 #include "lcnalloc.h"
61 #include "dir.h"
62 #include "compress.h"
63 #include "bitmap.h"
64 #include "logging.h"
65 #include "misc.h"
66 #include "efs.h"
68 ntfschar AT_UNNAMED[] = { const_cpu_to_le16('\0') };
69 ntfschar STREAM_SDS[] = { const_cpu_to_le16('$'),
70 const_cpu_to_le16('S'),
71 const_cpu_to_le16('D'),
72 const_cpu_to_le16('S'),
73 const_cpu_to_le16('\0') };
75 ntfschar TXF_DATA[] = { const_cpu_to_le16('$'),
76 const_cpu_to_le16('T'),
77 const_cpu_to_le16('X'),
78 const_cpu_to_le16('F'),
79 const_cpu_to_le16('_'),
80 const_cpu_to_le16('D'),
81 const_cpu_to_le16('A'),
82 const_cpu_to_le16('T'),
83 const_cpu_to_le16('A'),
84 const_cpu_to_le16('\0') };
86 static int NAttrFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
88 if (na->type == AT_DATA && na->name == AT_UNNAMED)
89 return (na->ni->flags & flag);
90 return 0;
93 static void NAttrSetFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
95 if (na->type == AT_DATA && na->name == AT_UNNAMED)
96 na->ni->flags |= flag;
97 else
98 ntfs_log_trace("Denied setting flag %d for not unnamed data "
99 "attribute\n", flag);
102 static void NAttrClearFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
104 if (na->type == AT_DATA && na->name == AT_UNNAMED)
105 na->ni->flags &= ~flag;
108 #define GenNAttrIno(func_name, flag) \
109 int NAttr##func_name(ntfs_attr *na) { return NAttrFlag (na, flag); } \
110 void NAttrSet##func_name(ntfs_attr *na) { NAttrSetFlag (na, flag); } \
111 void NAttrClear##func_name(ntfs_attr *na){ NAttrClearFlag(na, flag); }
113 GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED)
114 GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED)
115 GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE)
118 * ntfs_get_attribute_value_length - Find the length of an attribute
119 * @a:
121 * Description...
123 * Returns:
125 s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a)
127 if (!a) {
128 errno = EINVAL;
129 return 0;
131 errno = 0;
132 if (a->non_resident)
133 return sle64_to_cpu(a->data_size);
135 return (s64)le32_to_cpu(a->value_length);
139 * ntfs_get_attribute_value - Get a copy of an attribute
140 * @vol:
141 * @a:
142 * @b:
144 * Description...
146 * Returns:
148 s64 ntfs_get_attribute_value(const ntfs_volume *vol,
149 const ATTR_RECORD *a, u8 *b)
151 runlist *rl;
152 s64 total, r;
153 int i;
155 /* Sanity checks. */
156 if (!vol || !a || !b) {
157 errno = EINVAL;
158 return 0;
160 /* Complex attribute? */
162 * Ignore the flags in case they are not zero for an attribute list
163 * attribute. Windows does not complain about invalid flags and chkdsk
164 * does not detect or fix them so we need to cope with it, too.
166 if (a->type != AT_ATTRIBUTE_LIST && a->flags) {
167 ntfs_log_error("Non-zero (%04x) attribute flags. Cannot handle "
168 "this yet.\n", le16_to_cpu(a->flags));
169 errno = EOPNOTSUPP;
170 return 0;
172 if (!a->non_resident) {
173 /* Attribute is resident. */
175 /* Sanity check. */
176 if (le32_to_cpu(a->value_length) + le16_to_cpu(a->value_offset)
177 > le32_to_cpu(a->length)) {
178 return 0;
181 memcpy(b, (const char*)a + le16_to_cpu(a->value_offset),
182 le32_to_cpu(a->value_length));
183 errno = 0;
184 return (s64)le32_to_cpu(a->value_length);
187 /* Attribute is not resident. */
189 /* If no data, return 0. */
190 if (!(a->data_size)) {
191 errno = 0;
192 return 0;
195 * FIXME: What about attribute lists?!? (AIA)
197 /* Decompress the mapping pairs array into a runlist. */
198 rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
199 if (!rl) {
200 errno = EINVAL;
201 return 0;
204 * FIXED: We were overflowing here in a nasty fashion when we
205 * reach the last cluster in the runlist as the buffer will
206 * only be big enough to hold data_size bytes while we are
207 * reading in allocated_size bytes which is usually larger
208 * than data_size, since the actual data is unlikely to have a
209 * size equal to a multiple of the cluster size!
210 * FIXED2: We were also overflowing here in the same fashion
211 * when the data_size was more than one run smaller than the
212 * allocated size which happens with Windows XP sometimes.
214 /* Now load all clusters in the runlist into b. */
215 for (i = 0, total = 0; rl[i].length; i++) {
216 if (total + (rl[i].length << vol->cluster_size_bits) >=
217 sle64_to_cpu(a->data_size)) {
218 unsigned char *intbuf = NULL;
220 * We have reached the last run so we were going to
221 * overflow when executing the ntfs_pread() which is
222 * BAAAAAAAD!
223 * Temporary fix:
224 * Allocate a new buffer with size:
225 * rl[i].length << vol->cluster_size_bits, do the
226 * read into our buffer, then memcpy the correct
227 * amount of data into the caller supplied buffer,
228 * free our buffer, and continue.
229 * We have reached the end of data size so we were
230 * going to overflow in the same fashion.
231 * Temporary fix: same as above.
233 intbuf = ntfs_malloc(rl[i].length << vol->cluster_size_bits);
234 if (!intbuf) {
235 free(rl);
236 return 0;
239 * FIXME: If compressed file: Only read if lcn != -1.
240 * Otherwise, we are dealing with a sparse run and we
241 * just memset the user buffer to 0 for the length of
242 * the run, which should be 16 (= compression unit
243 * size).
244 * FIXME: Really only when file is compressed, or can
245 * we have sparse runs in uncompressed files as well?
246 * - Yes we can, in sparse files! But not necessarily
247 * size of 16, just run length.
249 r = ntfs_pread(vol->dev, rl[i].lcn <<
250 vol->cluster_size_bits, rl[i].length <<
251 vol->cluster_size_bits, intbuf);
252 if (r != rl[i].length << vol->cluster_size_bits) {
253 #define ESTR "Error reading attribute value"
254 if (r == -1)
255 ntfs_log_perror(ESTR);
256 else if (r < rl[i].length <<
257 vol->cluster_size_bits) {
258 ntfs_log_debug(ESTR ": Ran out of input data.\n");
259 errno = EIO;
260 } else {
261 ntfs_log_debug(ESTR ": unknown error\n");
262 errno = EIO;
264 #undef ESTR
265 free(rl);
266 free(intbuf);
267 return 0;
269 memcpy(b + total, intbuf, sle64_to_cpu(a->data_size) -
270 total);
271 free(intbuf);
272 total = sle64_to_cpu(a->data_size);
273 break;
276 * FIXME: If compressed file: Only read if lcn != -1.
277 * Otherwise, we are dealing with a sparse run and we just
278 * memset the user buffer to 0 for the length of the run, which
279 * should be 16 (= compression unit size).
280 * FIXME: Really only when file is compressed, or can
281 * we have sparse runs in uncompressed files as well?
282 * - Yes we can, in sparse files! But not necessarily size of
283 * 16, just run length.
285 r = ntfs_pread(vol->dev, rl[i].lcn << vol->cluster_size_bits,
286 rl[i].length << vol->cluster_size_bits,
287 b + total);
288 if (r != rl[i].length << vol->cluster_size_bits) {
289 #define ESTR "Error reading attribute value"
290 if (r == -1)
291 ntfs_log_perror(ESTR);
292 else if (r < rl[i].length << vol->cluster_size_bits) {
293 ntfs_log_debug(ESTR ": Ran out of input data.\n");
294 errno = EIO;
295 } else {
296 ntfs_log_debug(ESTR ": unknown error\n");
297 errno = EIO;
299 #undef ESTR
300 free(rl);
301 return 0;
303 total += r;
305 free(rl);
306 return total;
309 /* Already cleaned up code below, but still look for FIXME:... */
312 * __ntfs_attr_init - primary initialization of an ntfs attribute structure
313 * @na: ntfs attribute to initialize
314 * @ni: ntfs inode with which to initialize the ntfs attribute
315 * @type: attribute type
316 * @name: attribute name in little endian Unicode or NULL
317 * @name_len: length of attribute @name in Unicode characters (if @name given)
319 * Initialize the ntfs attribute @na with @ni, @type, @name, and @name_len.
321 static void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni,
322 const ATTR_TYPES type, ntfschar *name, const u32 name_len)
324 na->rl = NULL;
325 na->ni = ni;
326 na->type = type;
327 na->name = name;
328 if (name)
329 na->name_len = name_len;
330 else
331 na->name_len = 0;
335 * ntfs_attr_init - initialize an ntfs_attr with data sizes and status
336 * @na:
337 * @non_resident:
338 * @compressed:
339 * @encrypted:
340 * @sparse:
341 * @allocated_size:
342 * @data_size:
343 * @initialized_size:
344 * @compressed_size:
345 * @compression_unit:
347 * Final initialization for an ntfs attribute.
349 void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
350 const ATTR_FLAGS data_flags,
351 const BOOL encrypted, const BOOL sparse,
352 const s64 allocated_size, const s64 data_size,
353 const s64 initialized_size, const s64 compressed_size,
354 const u8 compression_unit)
356 if (!NAttrInitialized(na)) {
357 na->data_flags = data_flags;
358 if (non_resident)
359 NAttrSetNonResident(na);
360 if (data_flags & ATTR_COMPRESSION_MASK)
361 NAttrSetCompressed(na);
362 if (encrypted)
363 NAttrSetEncrypted(na);
364 if (sparse)
365 NAttrSetSparse(na);
366 na->allocated_size = allocated_size;
367 na->data_size = data_size;
368 na->initialized_size = initialized_size;
369 if ((data_flags & ATTR_COMPRESSION_MASK) || sparse) {
370 ntfs_volume *vol = na->ni->vol;
372 na->compressed_size = compressed_size;
373 na->compression_block_clusters = 1 << compression_unit;
374 na->compression_block_size = 1 << (compression_unit +
375 vol->cluster_size_bits);
376 na->compression_block_size_bits = ffs(
377 na->compression_block_size) - 1;
379 NAttrSetInitialized(na);
384 * ntfs_attr_open - open an ntfs attribute for access
385 * @ni: open ntfs inode in which the ntfs attribute resides
386 * @type: attribute type
387 * @name: attribute name in little endian Unicode or AT_UNNAMED or NULL
388 * @name_len: length of attribute @name in Unicode characters (if @name given)
390 * Allocate a new ntfs attribute structure, initialize it with @ni, @type,
391 * @name, and @name_len, then return it. Return NULL on error with
392 * errno set to the error code.
394 * If @name is AT_UNNAMED look specifically for an unnamed attribute. If you
395 * do not care whether the attribute is named or not set @name to NULL. In
396 * both those cases @name_len is not used at all.
398 ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
399 ntfschar *name, u32 name_len)
401 ntfs_attr_search_ctx *ctx;
402 ntfs_attr *na = NULL;
403 ntfschar *newname = NULL;
404 ATTR_RECORD *a;
405 le16 cs;
407 ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n",
408 (unsigned long long)ni->mft_no, type);
410 if (!ni || !ni->vol || !ni->mrec) {
411 errno = EINVAL;
412 goto out;
414 na = ntfs_calloc(sizeof(ntfs_attr));
415 if (!na)
416 goto out;
417 if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) {
418 name = ntfs_ucsndup(name, name_len);
419 if (!name)
420 goto err_out;
421 newname = name;
424 ctx = ntfs_attr_get_search_ctx(ni, NULL);
425 if (!ctx)
426 goto err_out;
428 if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx))
429 goto put_err_out;
431 a = ctx->attr;
433 if (!name) {
434 if (a->name_length) {
435 name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu(
436 a->name_offset)), a->name_length);
437 if (!name)
438 goto put_err_out;
439 newname = name;
440 name_len = a->name_length;
441 } else {
442 name = AT_UNNAMED;
443 name_len = 0;
447 __ntfs_attr_init(na, ni, type, name, name_len);
450 * Wipe the flags in case they are not zero for an attribute list
451 * attribute. Windows does not complain about invalid flags and chkdsk
452 * does not detect or fix them so we need to cope with it, too.
454 if (type == AT_ATTRIBUTE_LIST)
455 a->flags = 0;
457 if ((type == AT_DATA) && !a->initialized_size) {
459 * Define/redefine the compression state if stream is
460 * empty, based on the compression mark on parent
461 * directory (for unnamed data streams) or on current
462 * inode (for named data streams). The compression mark
463 * may change any time, the compression state can only
464 * change when stream is wiped out.
466 * Also prevent compression on NTFS version < 3.0
467 * or cluster size > 4K or compression is disabled
469 a->flags &= ~ATTR_COMPRESSION_MASK;
470 if ((ni->flags & FILE_ATTR_COMPRESSED)
471 && (ni->vol->major_ver >= 3)
472 && NVolCompression(ni->vol)
473 && (ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE))
474 a->flags |= ATTR_IS_COMPRESSED;
477 cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
479 /* a file may be sparse though its unnamed data is not (cf $UsnJrnl) */
480 if (na->type == AT_DATA && na->name == AT_UNNAMED &&
481 (((a->flags & ATTR_IS_SPARSE) && !NAttrSparse(na)) ||
482 (!(a->flags & ATTR_IS_ENCRYPTED) != !NAttrEncrypted(na)))) {
483 errno = EIO;
484 ntfs_log_perror("Inode %lld has corrupt attribute flags "
485 "(0x%x <> 0x%x)",(unsigned long long)ni->mft_no,
486 a->flags, na->ni->flags);
487 goto put_err_out;
490 if (a->non_resident) {
491 if ((a->flags & ATTR_COMPRESSION_MASK)
492 && !a->compression_unit) {
493 errno = EIO;
494 ntfs_log_perror("Compressed inode %lld attr 0x%x has "
495 "no compression unit",
496 (unsigned long long)ni->mft_no, type);
497 goto put_err_out;
499 ntfs_attr_init(na, TRUE, a->flags,
500 a->flags & ATTR_IS_ENCRYPTED,
501 a->flags & ATTR_IS_SPARSE,
502 sle64_to_cpu(a->allocated_size),
503 sle64_to_cpu(a->data_size),
504 sle64_to_cpu(a->initialized_size),
505 cs ? sle64_to_cpu(a->compressed_size) : 0,
506 cs ? a->compression_unit : 0);
507 } else {
508 s64 l = le32_to_cpu(a->value_length);
509 ntfs_attr_init(na, FALSE, a->flags,
510 a->flags & ATTR_IS_ENCRYPTED,
511 a->flags & ATTR_IS_SPARSE, (l + 7) & ~7, l, l,
512 cs ? (l + 7) & ~7 : 0, 0);
514 ntfs_attr_put_search_ctx(ctx);
515 out:
516 ntfs_log_leave("\n");
517 return na;
519 put_err_out:
520 ntfs_attr_put_search_ctx(ctx);
521 err_out:
522 free(newname);
523 free(na);
524 na = NULL;
525 goto out;
529 * ntfs_attr_close - free an ntfs attribute structure
530 * @na: ntfs attribute structure to free
532 * Release all memory associated with the ntfs attribute @na and then release
533 * @na itself.
535 void ntfs_attr_close(ntfs_attr *na)
537 if (!na)
538 return;
539 if (NAttrNonResident(na) && na->rl)
540 free(na->rl);
541 /* Don't release if using an internal constant. */
542 if (na->name != AT_UNNAMED && na->name != NTFS_INDEX_I30
543 && na->name != STREAM_SDS)
544 free(na->name);
545 free(na);
549 * ntfs_attr_map_runlist - map (a part of) a runlist of an ntfs attribute
550 * @na: ntfs attribute for which to map (part of) a runlist
551 * @vcn: map runlist part containing this vcn
553 * Map the part of a runlist containing the @vcn of the ntfs attribute @na.
555 * Return 0 on success and -1 on error with errno set to the error code.
557 int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
559 LCN lcn;
560 ntfs_attr_search_ctx *ctx;
562 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n",
563 (unsigned long long)na->ni->mft_no, na->type, (long long)vcn);
565 lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
566 if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
567 return 0;
569 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
570 if (!ctx)
571 return -1;
573 /* Find the attribute in the mft record. */
574 if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
575 vcn, NULL, 0, ctx)) {
576 runlist_element *rl;
578 /* Decode the runlist. */
579 rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr,
580 na->rl);
581 if (rl) {
582 na->rl = rl;
583 ntfs_attr_put_search_ctx(ctx);
584 return 0;
588 ntfs_attr_put_search_ctx(ctx);
589 return -1;
592 #if PARTIAL_RUNLIST_UPDATING
595 * Map the runlist of an attribute from some point to the end
597 * Returns 0 if success,
598 * -1 if it failed (errno telling why)
601 static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
603 LCN lcn;
604 VCN last_vcn;
605 VCN highest_vcn;
606 VCN needed;
607 VCN existing_vcn;
608 runlist_element *rl;
609 ATTR_RECORD *a;
610 BOOL startseen;
611 ntfs_attr_search_ctx *ctx;
613 lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
614 if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
615 return 0;
617 existing_vcn = (na->rl ? na->rl->vcn : -1);
619 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
620 if (!ctx)
621 return -1;
623 /* Get the last vcn in the attribute. */
624 last_vcn = na->allocated_size >> na->ni->vol->cluster_size_bits;
626 needed = vcn;
627 highest_vcn = 0;
628 startseen = FALSE;
629 do {
630 /* Find the attribute in the mft record. */
631 if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
632 needed, NULL, 0, ctx)) {
634 a = ctx->attr;
635 /* Decode and merge the runlist. */
636 rl = ntfs_mapping_pairs_decompress(na->ni->vol, a,
637 na->rl);
638 if (rl) {
639 na->rl = rl;
640 highest_vcn = le64_to_cpu(a->highest_vcn);
641 /* corruption detection */
642 if (((highest_vcn + 1) < last_vcn)
643 && ((highest_vcn + 1) <= needed)) {
644 ntfs_log_error("Corrupt attribute list\n");
645 rl = (runlist_element*)NULL;
647 needed = highest_vcn + 1;
648 if (!a->lowest_vcn)
649 startseen = TRUE;
650 /* reaching a previously allocated part ? */
651 if ((existing_vcn >= 0)
652 && (needed >= existing_vcn)) {
653 needed = last_vcn;
656 } else
657 rl = (runlist_element*)NULL;
658 } while (rl && (needed < last_vcn));
659 ntfs_attr_put_search_ctx(ctx);
660 /* mark fully mapped if we did so */
661 if (rl && startseen)
662 NAttrSetFullyMapped(na);
663 return (rl ? 0 : -1);
666 #endif
669 * ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
670 * @na: ntfs attribute for which to map the runlist
672 * Map the whole runlist of the ntfs attribute @na. For an attribute made up
673 * of only one attribute extent this is the same as calling
674 * ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this
675 * will map the runlist fragments from each of the extents thus giving access
676 * to the entirety of the disk allocation of an attribute.
678 * Return 0 on success and -1 on error with errno set to the error code.
680 int ntfs_attr_map_whole_runlist(ntfs_attr *na)
682 VCN next_vcn, last_vcn, highest_vcn;
683 ntfs_attr_search_ctx *ctx;
684 ntfs_volume *vol = na->ni->vol;
685 ATTR_RECORD *a;
686 int ret = -1;
688 ntfs_log_enter("Entering for inode %llu, attr 0x%x.\n",
689 (unsigned long long)na->ni->mft_no, na->type);
691 /* avoid multiple full runlist mappings */
692 if (NAttrFullyMapped(na)) {
693 ret = 0;
694 goto out;
696 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
697 if (!ctx)
698 goto out;
700 /* Map all attribute extents one by one. */
701 next_vcn = last_vcn = highest_vcn = 0;
702 a = NULL;
703 while (1) {
704 runlist_element *rl;
706 int not_mapped = 0;
707 if (ntfs_rl_vcn_to_lcn(na->rl, next_vcn) == LCN_RL_NOT_MAPPED)
708 not_mapped = 1;
710 if (ntfs_attr_lookup(na->type, na->name, na->name_len,
711 CASE_SENSITIVE, next_vcn, NULL, 0, ctx))
712 break;
714 a = ctx->attr;
716 if (not_mapped) {
717 /* Decode the runlist. */
718 rl = ntfs_mapping_pairs_decompress(na->ni->vol,
719 a, na->rl);
720 if (!rl)
721 goto err_out;
722 na->rl = rl;
725 /* Are we in the first extent? */
726 if (!next_vcn) {
727 if (a->lowest_vcn) {
728 errno = EIO;
729 ntfs_log_perror("First extent of inode %llu "
730 "attribute has non-zero lowest_vcn",
731 (unsigned long long)na->ni->mft_no);
732 goto err_out;
734 /* Get the last vcn in the attribute. */
735 last_vcn = sle64_to_cpu(a->allocated_size) >>
736 vol->cluster_size_bits;
739 /* Get the lowest vcn for the next extent. */
740 highest_vcn = sle64_to_cpu(a->highest_vcn);
741 next_vcn = highest_vcn + 1;
743 /* Only one extent or error, which we catch below. */
744 if (next_vcn <= 0) {
745 errno = ENOENT;
746 break;
749 /* Avoid endless loops due to corruption. */
750 if (next_vcn < sle64_to_cpu(a->lowest_vcn)) {
751 errno = EIO;
752 ntfs_log_perror("Inode %llu has corrupt attribute list",
753 (unsigned long long)na->ni->mft_no);
754 goto err_out;
757 if (!a) {
758 ntfs_log_perror("Couldn't find attribute for runlist mapping");
759 goto err_out;
761 if (highest_vcn && highest_vcn != last_vcn - 1) {
762 errno = EIO;
763 ntfs_log_perror("Failed to load full runlist: inode: %llu "
764 "highest_vcn: 0x%llx last_vcn: 0x%llx",
765 (unsigned long long)na->ni->mft_no,
766 (long long)highest_vcn, (long long)last_vcn);
767 goto err_out;
769 if (errno == ENOENT) {
770 NAttrSetFullyMapped(na);
771 ret = 0;
773 err_out:
774 ntfs_attr_put_search_ctx(ctx);
775 out:
776 ntfs_log_leave("\n");
777 return ret;
781 * ntfs_attr_vcn_to_lcn - convert a vcn into a lcn given an ntfs attribute
782 * @na: ntfs attribute whose runlist to use for conversion
783 * @vcn: vcn to convert
785 * Convert the virtual cluster number @vcn of an attribute into a logical
786 * cluster number (lcn) of a device using the runlist @na->rl to map vcns to
787 * their corresponding lcns.
789 * If the @vcn is not mapped yet, attempt to map the attribute extent
790 * containing the @vcn and retry the vcn to lcn conversion.
792 * Since lcns must be >= 0, we use negative return values with special meaning:
794 * Return value Meaning / Description
795 * ==========================================
796 * -1 = LCN_HOLE Hole / not allocated on disk.
797 * -3 = LCN_ENOENT There is no such vcn in the attribute.
798 * -4 = LCN_EINVAL Input parameter error.
799 * -5 = LCN_EIO Corrupt fs, disk i/o error, or not enough memory.
801 LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn)
803 LCN lcn;
804 BOOL is_retry = FALSE;
806 if (!na || !NAttrNonResident(na) || vcn < 0)
807 return (LCN)LCN_EINVAL;
809 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
810 long)na->ni->mft_no, na->type);
811 retry:
812 /* Convert vcn to lcn. If that fails map the runlist and retry once. */
813 lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
814 if (lcn >= 0)
815 return lcn;
816 if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
817 is_retry = TRUE;
818 goto retry;
821 * If the attempt to map the runlist failed, or we are getting
822 * LCN_RL_NOT_MAPPED despite having mapped the attribute extent
823 * successfully, something is really badly wrong...
825 if (!is_retry || lcn == (LCN)LCN_RL_NOT_MAPPED)
826 return (LCN)LCN_EIO;
827 /* lcn contains the appropriate error code. */
828 return lcn;
832 * ntfs_attr_find_vcn - find a vcn in the runlist of an ntfs attribute
833 * @na: ntfs attribute whose runlist to search
834 * @vcn: vcn to find
836 * Find the virtual cluster number @vcn in the runlist of the ntfs attribute
837 * @na and return the the address of the runlist element containing the @vcn.
839 * Note you need to distinguish between the lcn of the returned runlist
840 * element being >= 0 and LCN_HOLE. In the later case you have to return zeroes
841 * on read and allocate clusters on write. You need to update the runlist, the
842 * attribute itself as well as write the modified mft record to disk.
844 * If there is an error return NULL with errno set to the error code. The
845 * following error codes are defined:
846 * EINVAL Input parameter error.
847 * ENOENT There is no such vcn in the runlist.
848 * ENOMEM Not enough memory.
849 * EIO I/O error or corrupt metadata.
851 runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn)
853 runlist_element *rl;
854 BOOL is_retry = FALSE;
856 if (!na || !NAttrNonResident(na) || vcn < 0) {
857 errno = EINVAL;
858 return NULL;
861 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn %llx\n",
862 (unsigned long long)na->ni->mft_no, na->type,
863 (long long)vcn);
864 retry:
865 rl = na->rl;
866 if (!rl)
867 goto map_rl;
868 if (vcn < rl[0].vcn)
869 goto map_rl;
870 while (rl->length) {
871 if (vcn < rl[1].vcn) {
872 if (rl->lcn >= (LCN)LCN_HOLE)
873 return rl;
874 break;
876 rl++;
878 switch (rl->lcn) {
879 case (LCN)LCN_RL_NOT_MAPPED:
880 goto map_rl;
881 case (LCN)LCN_ENOENT:
882 errno = ENOENT;
883 break;
884 case (LCN)LCN_EINVAL:
885 errno = EINVAL;
886 break;
887 default:
888 errno = EIO;
889 break;
891 return NULL;
892 map_rl:
893 /* The @vcn is in an unmapped region, map the runlist and retry. */
894 if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
895 is_retry = TRUE;
896 goto retry;
899 * If we already retried or the mapping attempt failed something has
900 * gone badly wrong. EINVAL and ENOENT coming from a failed mapping
901 * attempt are equivalent to errors for us as they should not happen
902 * in our code paths.
904 if (is_retry || errno == EINVAL || errno == ENOENT)
905 errno = EIO;
906 return NULL;
910 * ntfs_attr_pread_i - see description at ntfs_attr_pread()
912 static s64 ntfs_attr_pread_i(ntfs_attr *na, const s64 pos, s64 count, void *b)
914 s64 br, to_read, ofs, total, total2, max_read, max_init;
915 ntfs_volume *vol;
916 runlist_element *rl;
917 u16 efs_padding_length;
919 /* Sanity checking arguments is done in ntfs_attr_pread(). */
921 if ((na->data_flags & ATTR_COMPRESSION_MASK) && NAttrNonResident(na)) {
922 if ((na->data_flags & ATTR_COMPRESSION_MASK)
923 == ATTR_IS_COMPRESSED)
924 return ntfs_compressed_attr_pread(na, pos, count, b);
925 else {
926 /* compression mode not supported */
927 errno = EOPNOTSUPP;
928 return -1;
932 * Encrypted non-resident attributes are not supported. We return
933 * access denied, which is what Windows NT4 does, too.
934 * However, allow if mounted with efs_raw option
936 vol = na->ni->vol;
937 if (!vol->efs_raw && NAttrEncrypted(na) && NAttrNonResident(na)) {
938 errno = EACCES;
939 return -1;
942 if (!count)
943 return 0;
945 * Truncate reads beyond end of attribute,
946 * but round to next 512 byte boundary for encrypted
947 * attributes with efs_raw mount option
949 max_read = na->data_size;
950 max_init = na->initialized_size;
951 if (na->ni->vol->efs_raw
952 && (na->data_flags & ATTR_IS_ENCRYPTED)
953 && NAttrNonResident(na)) {
954 if (na->data_size != na->initialized_size) {
955 ntfs_log_error("uninitialized encrypted file not supported\n");
956 errno = EINVAL;
957 return -1;
959 max_init = max_read = ((na->data_size + 511) & ~511) + 2;
961 if (pos + count > max_read) {
962 if (pos >= max_read)
963 return 0;
964 count = max_read - pos;
966 /* If it is a resident attribute, get the value from the mft record. */
967 if (!NAttrNonResident(na)) {
968 ntfs_attr_search_ctx *ctx;
969 char *val;
971 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
972 if (!ctx)
973 return -1;
974 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
975 0, NULL, 0, ctx)) {
976 res_err_out:
977 ntfs_attr_put_search_ctx(ctx);
978 return -1;
980 val = (char*)ctx->attr + le16_to_cpu(ctx->attr->value_offset);
981 if (val < (char*)ctx->attr || val +
982 le32_to_cpu(ctx->attr->value_length) >
983 (char*)ctx->mrec + vol->mft_record_size) {
984 errno = EIO;
985 ntfs_log_perror("%s: Sanity check failed", __FUNCTION__);
986 goto res_err_out;
988 memcpy(b, val + pos, count);
989 ntfs_attr_put_search_ctx(ctx);
990 return count;
992 total = total2 = 0;
993 /* Zero out reads beyond initialized size. */
994 if (pos + count > max_init) {
995 if (pos >= max_init) {
996 memset(b, 0, count);
997 return count;
999 total2 = pos + count - max_init;
1000 count -= total2;
1001 memset((u8*)b + count, 0, total2);
1004 * for encrypted non-resident attributes with efs_raw set
1005 * the last two bytes aren't read from disk but contain
1006 * the number of padding bytes so original size can be
1007 * restored
1009 if (na->ni->vol->efs_raw &&
1010 (na->data_flags & ATTR_IS_ENCRYPTED) &&
1011 ((pos + count) > max_init-2)) {
1012 efs_padding_length = 511 - ((na->data_size - 1) & 511);
1013 if (pos+count == max_init) {
1014 if (count == 1) {
1015 *((u8*)b+count-1) = (u8)(efs_padding_length >> 8);
1016 count--;
1017 total2++;
1018 } else {
1019 *(u16*)((u8*)b+count-2) = cpu_to_le16(efs_padding_length);
1020 count -= 2;
1021 total2 +=2;
1023 } else {
1024 *((u8*)b+count-1) = (u8)(efs_padding_length & 0xff);
1025 count--;
1026 total2++;
1030 /* Find the runlist element containing the vcn. */
1031 rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
1032 if (!rl) {
1034 * If the vcn is not present it is an out of bounds read.
1035 * However, we already truncated the read to the data_size,
1036 * so getting this here is an error.
1038 if (errno == ENOENT) {
1039 errno = EIO;
1040 ntfs_log_perror("%s: Failed to find VCN #1", __FUNCTION__);
1042 return -1;
1045 * Gather the requested data into the linear destination buffer. Note,
1046 * a partial final vcn is taken care of by the @count capping of read
1047 * length.
1049 ofs = pos - (rl->vcn << vol->cluster_size_bits);
1050 for (; count; rl++, ofs = 0) {
1051 if (rl->lcn == LCN_RL_NOT_MAPPED) {
1052 rl = ntfs_attr_find_vcn(na, rl->vcn);
1053 if (!rl) {
1054 if (errno == ENOENT) {
1055 errno = EIO;
1056 ntfs_log_perror("%s: Failed to find VCN #2",
1057 __FUNCTION__);
1059 goto rl_err_out;
1061 /* Needed for case when runs merged. */
1062 ofs = pos + total - (rl->vcn << vol->cluster_size_bits);
1064 if (!rl->length) {
1065 errno = EIO;
1066 ntfs_log_perror("%s: Zero run length", __FUNCTION__);
1067 goto rl_err_out;
1069 if (rl->lcn < (LCN)0) {
1070 if (rl->lcn != (LCN)LCN_HOLE) {
1071 ntfs_log_perror("%s: Bad run (%lld)",
1072 __FUNCTION__,
1073 (long long)rl->lcn);
1074 goto rl_err_out;
1076 /* It is a hole, just zero the matching @b range. */
1077 to_read = min(count, (rl->length <<
1078 vol->cluster_size_bits) - ofs);
1079 memset(b, 0, to_read);
1080 /* Update progress counters. */
1081 total += to_read;
1082 count -= to_read;
1083 b = (u8*)b + to_read;
1084 continue;
1086 /* It is a real lcn, read it into @dst. */
1087 to_read = min(count, (rl->length << vol->cluster_size_bits) -
1088 ofs);
1089 retry:
1090 ntfs_log_trace("Reading %lld bytes from vcn %lld, lcn %lld, ofs"
1091 " %lld.\n", (long long)to_read, (long long)rl->vcn,
1092 (long long )rl->lcn, (long long)ofs);
1093 br = ntfs_pread(vol->dev, (rl->lcn << vol->cluster_size_bits) +
1094 ofs, to_read, b);
1095 /* If everything ok, update progress counters and continue. */
1096 if (br > 0) {
1097 total += br;
1098 count -= br;
1099 b = (u8*)b + br;
1101 if (br == to_read)
1102 continue;
1103 /* If the syscall was interrupted, try again. */
1104 if (br == (s64)-1 && errno == EINTR)
1105 goto retry;
1106 if (total)
1107 return total;
1108 if (!br)
1109 errno = EIO;
1110 ntfs_log_perror("%s: ntfs_pread failed", __FUNCTION__);
1111 return -1;
1113 /* Finally, return the number of bytes read. */
1114 return total + total2;
1115 rl_err_out:
1116 if (total)
1117 return total;
1118 errno = EIO;
1119 return -1;
1123 * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
1124 * @na: ntfs attribute to read from
1125 * @pos: byte position in the attribute to begin reading from
1126 * @count: number of bytes to read
1127 * @b: output data buffer
1129 * This function will read @count bytes starting at offset @pos from the ntfs
1130 * attribute @na into the data buffer @b.
1132 * On success, return the number of successfully read bytes. If this number is
1133 * lower than @count this means that the read reached end of file or that an
1134 * error was encountered during the read so that the read is partial. 0 means
1135 * end of file or nothing was read (also return 0 when @count is 0).
1137 * On error and nothing has been read, return -1 with errno set appropriately
1138 * to the return code of ntfs_pread(), or to EINVAL in case of invalid
1139 * arguments.
1141 s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
1143 s64 ret;
1145 if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
1146 errno = EINVAL;
1147 ntfs_log_perror("%s: na=%p b=%p pos=%lld count=%lld",
1148 __FUNCTION__, na, b, (long long)pos,
1149 (long long)count);
1150 return -1;
1153 ntfs_log_enter("Entering for inode %lld attr 0x%x pos %lld count "
1154 "%lld\n", (unsigned long long)na->ni->mft_no,
1155 na->type, (long long)pos, (long long)count);
1157 ret = ntfs_attr_pread_i(na, pos, count, b);
1159 ntfs_log_leave("\n");
1160 return ret;
1163 static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count)
1165 char *buf;
1166 s64 written, size, end = pos + count;
1167 s64 ofsi;
1168 const runlist_element *rli;
1169 ntfs_volume *vol;
1170 int ret = -1;
1172 ntfs_log_trace("pos %lld, count %lld\n", (long long)pos,
1173 (long long)count);
1175 if (!na || pos < 0 || count < 0) {
1176 errno = EINVAL;
1177 goto err_out;
1180 buf = ntfs_calloc(NTFS_BUF_SIZE);
1181 if (!buf)
1182 goto err_out;
1184 rli = na->rl;
1185 ofsi = 0;
1186 vol = na->ni->vol;
1187 while (pos < end) {
1188 while (rli->length && (ofsi + (rli->length <<
1189 vol->cluster_size_bits) <= pos)) {
1190 ofsi += (rli->length << vol->cluster_size_bits);
1191 rli++;
1193 size = min(end - pos, NTFS_BUF_SIZE);
1195 * If the zeroed block is fully within a hole,
1196 * we need not write anything, so advance as far
1197 * as possible within the hole.
1199 if ((rli->lcn == (LCN)LCN_HOLE)
1200 && (ofsi <= pos)
1201 && (ofsi + (rli->length << vol->cluster_size_bits)
1202 >= (pos + size))) {
1203 size = min(end - pos, ofsi - pos
1204 + (rli->length << vol->cluster_size_bits));
1205 pos += size;
1206 } else {
1207 written = ntfs_rl_pwrite(vol, rli, ofsi, pos,
1208 size, buf);
1209 if (written <= 0) {
1210 ntfs_log_perror("Failed to zero space");
1211 goto err_free;
1213 pos += written;
1217 ret = 0;
1218 err_free:
1219 free(buf);
1220 err_out:
1221 return ret;
1224 static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs,
1225 runlist_element **rl, VCN *update_from)
1227 s64 to_write;
1228 s64 need;
1229 ntfs_volume *vol = na->ni->vol;
1230 int eo, ret = -1;
1231 runlist *rlc;
1232 LCN lcn_seek_from = -1;
1233 VCN cur_vcn, from_vcn;
1235 to_write = min(count, ((*rl)->length << vol->cluster_size_bits) - *ofs);
1237 cur_vcn = (*rl)->vcn;
1238 from_vcn = (*rl)->vcn + (*ofs >> vol->cluster_size_bits);
1240 ntfs_log_trace("count: %lld, cur_vcn: %lld, from: %lld, to: %lld, ofs: "
1241 "%lld\n", (long long)count, (long long)cur_vcn,
1242 (long long)from_vcn, (long long)to_write, (long long)*ofs);
1244 /* Map the runlist to be able to update mapping pairs later. */
1245 #if PARTIAL_RUNLIST_UPDATING
1246 if ((!na->rl
1247 || !NAttrDataAppending(na))) {
1248 if (ntfs_attr_map_whole_runlist(na))
1249 goto err_out;
1250 } else {
1251 /* make sure the previous non-hole is mapped */
1252 rlc = *rl;
1253 rlc--;
1254 if (((*rl)->lcn == LCN_HOLE)
1255 && cur_vcn
1256 && (rlc->vcn < 0)) {
1257 if (ntfs_attr_map_partial_runlist(na, cur_vcn - 1))
1258 goto err_out;
1261 #else
1262 if (ntfs_attr_map_whole_runlist(na))
1263 goto err_out;
1264 #endif
1266 /* Restore @*rl, it probably get lost during runlist mapping. */
1267 *rl = ntfs_attr_find_vcn(na, cur_vcn);
1268 if (!*rl) {
1269 ntfs_log_error("Failed to find run after mapping runlist. "
1270 "Please report to %s.\n", NTFS_DEV_LIST);
1271 errno = EIO;
1272 goto err_out;
1275 /* Search backwards to find the best lcn to start seek from. */
1276 rlc = *rl;
1277 while (rlc->vcn) {
1278 rlc--;
1279 if (rlc->lcn >= 0) {
1281 * avoid fragmenting a compressed file
1282 * Windows does not do that, and that may
1283 * not be desirable for files which can
1284 * be updated
1286 if (na->data_flags & ATTR_COMPRESSION_MASK)
1287 lcn_seek_from = rlc->lcn + rlc->length;
1288 else
1289 lcn_seek_from = rlc->lcn + (from_vcn - rlc->vcn);
1290 break;
1293 if (lcn_seek_from == -1) {
1294 /* Backwards search failed, search forwards. */
1295 rlc = *rl;
1296 while (rlc->length) {
1297 rlc++;
1298 if (rlc->lcn >= 0) {
1299 lcn_seek_from = rlc->lcn - (rlc->vcn - from_vcn);
1300 if (lcn_seek_from < -1)
1301 lcn_seek_from = -1;
1302 break;
1307 need = ((*ofs + to_write - 1) >> vol->cluster_size_bits)
1308 + 1 + (*rl)->vcn - from_vcn;
1309 if ((na->data_flags & ATTR_COMPRESSION_MASK)
1310 && (need < na->compression_block_clusters)) {
1312 * for a compressed file, be sure to allocate the full
1313 * compression block, as we may need space to decompress
1314 * existing compressed data.
1315 * So allocate the space common to compression block
1316 * and existing hole.
1318 VCN alloc_vcn;
1320 if ((from_vcn & -na->compression_block_clusters) <= (*rl)->vcn)
1321 alloc_vcn = (*rl)->vcn;
1322 else
1323 alloc_vcn = from_vcn & -na->compression_block_clusters;
1324 need = (alloc_vcn | (na->compression_block_clusters - 1))
1325 + 1 - alloc_vcn;
1326 if (need > (*rl)->length) {
1327 ntfs_log_error("Cannot allocate %lld clusters"
1328 " within a hole of %lld\n",
1329 (long long)need,
1330 (long long)(*rl)->length);
1331 errno = EIO;
1332 goto err_out;
1334 rlc = ntfs_cluster_alloc(vol, alloc_vcn, need,
1335 lcn_seek_from, DATA_ZONE);
1336 } else
1337 rlc = ntfs_cluster_alloc(vol, from_vcn, need,
1338 lcn_seek_from, DATA_ZONE);
1339 if (!rlc)
1340 goto err_out;
1341 if (na->data_flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE))
1342 na->compressed_size += need << vol->cluster_size_bits;
1344 *rl = ntfs_runlists_merge(na->rl, rlc);
1346 * For a compressed attribute, we must be sure there are two
1347 * available entries, so reserve them before it gets too late.
1349 if (*rl && (na->data_flags & ATTR_COMPRESSION_MASK)) {
1350 runlist_element *oldrl = na->rl;
1351 na->rl = *rl;
1352 *rl = ntfs_rl_extend(na,*rl,2);
1353 if (!*rl) na->rl = oldrl; /* restore to original if failed */
1355 if (!*rl) {
1356 eo = errno;
1357 ntfs_log_perror("Failed to merge runlists");
1358 if (ntfs_cluster_free_from_rl(vol, rlc)) {
1359 ntfs_log_perror("Failed to free hot clusters. "
1360 "Please run chkdsk /f");
1362 errno = eo;
1363 goto err_out;
1365 na->unused_runs = 2;
1366 na->rl = *rl;
1367 if ((*update_from == -1) || (from_vcn < *update_from))
1368 *update_from = from_vcn;
1369 *rl = ntfs_attr_find_vcn(na, cur_vcn);
1370 if (!*rl) {
1372 * It's definitely a BUG, if we failed to find @cur_vcn, because
1373 * we missed it during instantiating of the hole.
1375 ntfs_log_error("Failed to find run after hole instantiation. "
1376 "Please report to %s.\n", NTFS_DEV_LIST);
1377 errno = EIO;
1378 goto err_out;
1380 /* If leaved part of the hole go to the next run. */
1381 if ((*rl)->lcn < 0)
1382 (*rl)++;
1383 /* Now LCN shoudn't be less than 0. */
1384 if ((*rl)->lcn < 0) {
1385 ntfs_log_error("BUG! LCN is lesser than 0. "
1386 "Please report to the %s.\n", NTFS_DEV_LIST);
1387 errno = EIO;
1388 goto err_out;
1390 if (*ofs) {
1391 /* Clear non-sparse region from @cur_vcn to @*ofs. */
1392 if (ntfs_attr_fill_zero(na, cur_vcn << vol->cluster_size_bits,
1393 *ofs))
1394 goto err_out;
1396 if ((*rl)->vcn < cur_vcn) {
1398 * Clusters that replaced hole are merged with
1399 * previous run, so we need to update offset.
1401 *ofs += (cur_vcn - (*rl)->vcn) << vol->cluster_size_bits;
1403 if ((*rl)->vcn > cur_vcn) {
1405 * We left part of the hole, so we need to update offset
1407 *ofs -= ((*rl)->vcn - cur_vcn) << vol->cluster_size_bits;
1410 ret = 0;
1411 err_out:
1412 return ret;
1415 static int stuff_hole(ntfs_attr *na, const s64 pos);
1418 * Split an existing hole for overwriting with data
1419 * The hole may have to be split into two or three parts, so
1420 * that the overwritten part fits within a single compression block
1422 * No cluster allocation is needed, this will be done later in
1423 * standard hole filling, hence no need to reserve runs for
1424 * future needs.
1426 * Returns the number of clusters with existing compressed data
1427 * in the compression block to be written to
1428 * (or the full block, if it was a full hole)
1429 * -1 if there were an error
1432 static int split_compressed_hole(ntfs_attr *na, runlist_element **prl,
1433 s64 pos, s64 count, VCN *update_from)
1435 int compressed_part;
1436 int cluster_size_bits = na->ni->vol->cluster_size_bits;
1437 runlist_element *rl = *prl;
1439 compressed_part
1440 = na->compression_block_clusters;
1441 /* reserve entries in runlist if we have to split */
1442 if (rl->length > na->compression_block_clusters) {
1443 *prl = ntfs_rl_extend(na,*prl,2);
1444 if (!*prl) {
1445 compressed_part = -1;
1446 } else {
1447 rl = *prl;
1448 na->unused_runs = 2;
1451 if (*prl && (rl->length > na->compression_block_clusters)) {
1453 * Locate the update part relative to beginning of
1454 * current run
1456 int beginwrite = (pos >> cluster_size_bits) - rl->vcn;
1457 s32 endblock = (((pos + count - 1) >> cluster_size_bits)
1458 | (na->compression_block_clusters - 1)) + 1 - rl->vcn;
1460 compressed_part = na->compression_block_clusters
1461 - (rl->length & (na->compression_block_clusters - 1));
1462 if ((beginwrite + compressed_part) >= na->compression_block_clusters)
1463 compressed_part = na->compression_block_clusters;
1465 * if the run ends beyond end of needed block
1466 * we have to split the run
1468 if (endblock < rl[0].length) {
1469 runlist_element *xrl;
1470 int n;
1473 * we have to split into three parts if the run
1474 * does not end within the first compression block.
1475 * This means the hole begins before the
1476 * compression block.
1478 if (endblock > na->compression_block_clusters) {
1479 if (na->unused_runs < 2) {
1480 ntfs_log_error("No free run, case 1\n");
1482 na->unused_runs -= 2;
1483 xrl = rl;
1484 n = 0;
1485 while (xrl->length) {
1486 xrl++;
1487 n++;
1489 do {
1490 xrl[2] = *xrl;
1491 xrl--;
1492 } while (xrl != rl);
1493 rl[1].length = na->compression_block_clusters;
1494 rl[2].length = rl[0].length - endblock;
1495 rl[0].length = endblock
1496 - na->compression_block_clusters;
1497 rl[1].lcn = LCN_HOLE;
1498 rl[2].lcn = LCN_HOLE;
1499 rl[1].vcn = rl[0].vcn + rl[0].length;
1500 rl[2].vcn = rl[1].vcn
1501 + na->compression_block_clusters;
1502 rl = ++(*prl);
1503 } else {
1505 * split into two parts and use the
1506 * first one
1508 if (!na->unused_runs) {
1509 ntfs_log_error("No free run, case 2\n");
1511 na->unused_runs--;
1512 xrl = rl;
1513 n = 0;
1514 while (xrl->length) {
1515 xrl++;
1516 n++;
1518 do {
1519 xrl[1] = *xrl;
1520 xrl--;
1521 } while (xrl != rl);
1522 if (beginwrite < endblock) {
1523 /* we will write into the first part of hole */
1524 rl[1].length = rl[0].length - endblock;
1525 rl[0].length = endblock;
1526 rl[1].vcn = rl[0].vcn + rl[0].length;
1527 rl[1].lcn = LCN_HOLE;
1528 } else {
1529 /* we will write into the second part of hole */
1530 // impossible ?
1531 rl[1].length = rl[0].length - endblock;
1532 rl[0].length = endblock;
1533 rl[1].vcn = rl[0].vcn + rl[0].length;
1534 rl[1].lcn = LCN_HOLE;
1535 rl = ++(*prl);
1538 } else {
1539 if (rl[1].length) {
1540 runlist_element *xrl;
1541 int n;
1544 * split into two parts and use the
1545 * last one
1547 if (!na->unused_runs) {
1548 ntfs_log_error("No free run, case 4\n");
1550 na->unused_runs--;
1551 xrl = rl;
1552 n = 0;
1553 while (xrl->length) {
1554 xrl++;
1555 n++;
1557 do {
1558 xrl[1] = *xrl;
1559 xrl--;
1560 } while (xrl != rl);
1561 } else {
1562 rl[2].lcn = rl[1].lcn;
1563 rl[2].vcn = rl[1].vcn;
1564 rl[2].length = rl[1].length;
1566 rl[1].vcn -= na->compression_block_clusters;
1567 rl[1].lcn = LCN_HOLE;
1568 rl[1].length = na->compression_block_clusters;
1569 rl[0].length -= na->compression_block_clusters;
1570 if (pos >= (rl[1].vcn << cluster_size_bits)) {
1571 rl = ++(*prl);
1574 if ((*update_from == -1) || ((*prl)->vcn < *update_from))
1575 *update_from = (*prl)->vcn;
1577 return (compressed_part);
1581 * Borrow space from adjacent hole for appending data
1582 * The hole may have to be split so that the end of hole is not
1583 * affected by cluster allocation and overwriting
1584 * Cluster allocation is needed for the overwritten compression block
1586 * Must always leave two unused entries in the runlist
1588 * Returns the number of clusters with existing compressed data
1589 * in the compression block to be written to
1590 * -1 if there were an error
1593 static int borrow_from_hole(ntfs_attr *na, runlist_element **prl,
1594 s64 pos, s64 count, VCN *update_from, BOOL wasnonresident)
1596 int compressed_part = 0;
1597 int cluster_size_bits = na->ni->vol->cluster_size_bits;
1598 runlist_element *rl = *prl;
1599 s32 endblock;
1600 long long allocated;
1601 runlist_element *zrl;
1602 int irl;
1603 BOOL undecided;
1604 BOOL nothole;
1606 /* check whether the compression block is fully allocated */
1607 endblock = (((pos + count - 1) >> cluster_size_bits) | (na->compression_block_clusters - 1)) + 1 - rl->vcn;
1608 allocated = 0;
1609 zrl = rl;
1610 irl = 0;
1611 while (zrl->length && (zrl->lcn >= 0) && (allocated < endblock)) {
1612 allocated += zrl->length;
1613 zrl++;
1614 irl++;
1617 undecided = (allocated < endblock) && (zrl->lcn == LCN_RL_NOT_MAPPED);
1618 nothole = (allocated >= endblock) || (zrl->lcn != LCN_HOLE);
1620 if (undecided || nothole) {
1621 runlist_element *orl = na->rl;
1622 s64 olcn = (*prl)->lcn;
1623 #if PARTIAL_RUNLIST_UPDATING
1624 VCN prevblock;
1625 #endif
1627 * Map the runlist, unless it has not been created.
1628 * If appending data, a partial mapping from the
1629 * end of previous block will do.
1631 irl = *prl - na->rl;
1632 #if PARTIAL_RUNLIST_UPDATING
1633 prevblock = pos >> cluster_size_bits;
1634 if (prevblock)
1635 prevblock--;
1636 if (!NAttrBeingNonResident(na)
1637 && (NAttrDataAppending(na)
1638 ? ntfs_attr_map_partial_runlist(na,prevblock)
1639 : ntfs_attr_map_whole_runlist(na))) {
1640 #else
1641 if (!NAttrBeingNonResident(na)
1642 && ntfs_attr_map_whole_runlist(na)) {
1643 #endif
1644 rl = (runlist_element*)NULL;
1645 } else {
1647 * Mapping the runlist may cause its relocation,
1648 * and relocation may be at the same place with
1649 * relocated contents.
1650 * Have to find the current run again when this
1651 * happens.
1653 if ((na->rl != orl) || ((*prl)->lcn != olcn)) {
1654 zrl = &na->rl[irl];
1655 while (zrl->length && (zrl->lcn != olcn))
1656 zrl++;
1657 *prl = zrl;
1659 if (!(*prl)->length) {
1660 ntfs_log_error("Mapped run not found,"
1661 " inode %lld lcn 0x%llx\n",
1662 (long long)na->ni->mft_no,
1663 (long long)olcn);
1664 rl = (runlist_element*)NULL;
1665 } else {
1666 rl = ntfs_rl_extend(na,*prl,2);
1667 na->unused_runs = 2;
1670 *prl = rl;
1671 if (rl && undecided) {
1672 allocated = 0;
1673 zrl = rl;
1674 irl = 0;
1675 while (zrl->length && (zrl->lcn >= 0)
1676 && (allocated < endblock)) {
1677 allocated += zrl->length;
1678 zrl++;
1679 irl++;
1684 * compression block not fully allocated and followed
1685 * by a hole : we must allocate in the hole.
1687 if (rl && (allocated < endblock) && (zrl->lcn == LCN_HOLE)) {
1688 s64 xofs;
1691 * split the hole if not fully needed
1693 if ((allocated + zrl->length) > endblock) {
1694 runlist_element *xrl;
1696 *prl = ntfs_rl_extend(na,*prl,1);
1697 if (*prl) {
1698 /* beware : rl was reallocated */
1699 rl = *prl;
1700 zrl = &rl[irl];
1701 na->unused_runs = 0;
1702 xrl = zrl;
1703 while (xrl->length) xrl++;
1704 do {
1705 xrl[1] = *xrl;
1706 } while (xrl-- != zrl);
1707 zrl->length = endblock - allocated;
1708 zrl[1].length -= zrl->length;
1709 zrl[1].vcn = zrl->vcn + zrl->length;
1712 if (*prl) {
1713 if (wasnonresident)
1714 compressed_part = na->compression_block_clusters
1715 - zrl->length;
1716 xofs = 0;
1717 if (ntfs_attr_fill_hole(na,
1718 zrl->length << cluster_size_bits,
1719 &xofs, &zrl, update_from))
1720 compressed_part = -1;
1721 else {
1722 /* go back to initial cluster, now reallocated */
1723 while (zrl->vcn > (pos >> cluster_size_bits))
1724 zrl--;
1725 *prl = zrl;
1729 if (!*prl) {
1730 ntfs_log_error("No elements to borrow from a hole\n");
1731 compressed_part = -1;
1732 } else
1733 if ((*update_from == -1) || ((*prl)->vcn < *update_from))
1734 *update_from = (*prl)->vcn;
1735 return (compressed_part);
1738 static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
1739 hole_type holes);
1742 * ntfs_attr_pwrite - positioned write to an ntfs attribute
1743 * @na: ntfs attribute to write to
1744 * @pos: position in the attribute to write to
1745 * @count: number of bytes to write
1746 * @b: data buffer to write to disk
1748 * This function will write @count bytes from data buffer @b to ntfs attribute
1749 * @na at position @pos.
1751 * On success, return the number of successfully written bytes. If this number
1752 * is lower than @count this means that an error was encountered during the
1753 * write so that the write is partial. 0 means nothing was written (also return
1754 * 0 when @count is 0).
1756 * On error and nothing has been written, return -1 with errno set
1757 * appropriately to the return code of ntfs_pwrite(), or to EINVAL in case of
1758 * invalid arguments.
1760 s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
1762 s64 written, to_write, ofs, old_initialized_size, old_data_size;
1763 s64 total = 0;
1764 VCN update_from = -1;
1765 ntfs_volume *vol;
1766 s64 fullcount;
1767 ntfs_attr_search_ctx *ctx = NULL;
1768 runlist_element *rl;
1769 s64 hole_end;
1770 int eo;
1771 int compressed_part;
1772 struct {
1773 unsigned int undo_initialized_size : 1;
1774 unsigned int undo_data_size : 1;
1775 } need_to = { 0, 0 };
1776 BOOL wasnonresident = FALSE;
1777 BOOL compressed;
1778 BOOL updatemap;
1780 ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count "
1781 "0x%llx.\n", (long long)na->ni->mft_no, na->type,
1782 (long long)pos, (long long)count);
1784 if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
1785 errno = EINVAL;
1786 ntfs_log_perror("%s", __FUNCTION__);
1787 goto errno_set;
1789 vol = na->ni->vol;
1790 compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
1791 != const_cpu_to_le16(0);
1792 na->unused_runs = 0; /* prepare overflow checks */
1794 * Encrypted attributes are only supported in raw mode. We return
1795 * access denied, which is what Windows NT4 does, too.
1796 * Moreover a file cannot be both encrypted and compressed.
1798 if ((na->data_flags & ATTR_IS_ENCRYPTED)
1799 && (compressed || !vol->efs_raw)) {
1800 errno = EACCES;
1801 goto errno_set;
1804 * Fill the gap, when writing beyond the end of a compressed
1805 * file. This will make recursive calls
1807 if (compressed
1808 && (na->type == AT_DATA)
1809 && (pos > na->initialized_size)
1810 && stuff_hole(na,pos))
1811 goto errno_set;
1812 /* If this is a compressed attribute it needs special treatment. */
1813 wasnonresident = NAttrNonResident(na) != 0;
1815 * Compression is restricted to data streams and
1816 * only ATTR_IS_COMPRESSED compression mode is supported.
1818 if (compressed
1819 && ((na->type != AT_DATA)
1820 || ((na->data_flags & ATTR_COMPRESSION_MASK)
1821 != ATTR_IS_COMPRESSED))) {
1822 errno = EOPNOTSUPP;
1823 goto errno_set;
1826 if (!count)
1827 goto out;
1828 /* for a compressed file, get prepared to reserve a full block */
1829 fullcount = count;
1830 /* If the write reaches beyond the end, extend the attribute. */
1831 old_data_size = na->data_size;
1832 /* identify whether this is appending to a non resident data attribute */
1833 if ((na->type == AT_DATA) && (pos >= old_data_size)
1834 && NAttrNonResident(na))
1835 NAttrSetDataAppending(na);
1836 if (pos + count > na->data_size) {
1837 #if PARTIAL_RUNLIST_UPDATING
1839 * When appending data, the attribute is first extended
1840 * before being filled with data. This may cause the
1841 * attribute to be made temporarily sparse, which
1842 * implies reformating the inode and reorganizing the
1843 * full runlist. To avoid unnecessary reorganization,
1844 * we avoid sparse testing until the data is filled in.
1846 if (ntfs_attr_truncate_i(na, pos + count,
1847 (NAttrDataAppending(na) ?
1848 HOLES_DELAY : HOLES_OK))) {
1849 ntfs_log_perror("Failed to enlarge attribute");
1850 goto errno_set;
1853 * If we avoided updating the runlist, we must be sure
1854 * to cancel the enlargement and put back the runlist to
1855 * a clean state if we get into some error.
1857 if (NAttrDataAppending(na))
1858 need_to.undo_data_size = 1;
1859 #else
1860 if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) {
1861 ntfs_log_perror("Failed to enlarge attribute");
1862 goto errno_set;
1864 #endif
1865 /* resizing may change the compression mode */
1866 compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
1867 != const_cpu_to_le16(0);
1868 need_to.undo_data_size = 1;
1871 * For compressed data, a single full block was allocated
1872 * to deal with compression, possibly in a previous call.
1873 * We are not able to process several blocks because
1874 * some clusters are freed after compression and
1875 * new allocations have to be done before proceeding,
1876 * so truncate the requested count if needed (big buffers).
1878 if (compressed) {
1879 fullcount = (pos | (na->compression_block_size - 1)) + 1 - pos;
1880 if (count > fullcount)
1881 count = fullcount;
1883 old_initialized_size = na->initialized_size;
1884 /* If it is a resident attribute, write the data to the mft record. */
1885 if (!NAttrNonResident(na)) {
1886 char *val;
1888 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
1889 if (!ctx)
1890 goto err_out;
1891 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
1892 0, NULL, 0, ctx)) {
1893 ntfs_log_perror("%s: lookup failed", __FUNCTION__);
1894 goto err_out;
1896 val = (char*)ctx->attr + le16_to_cpu(ctx->attr->value_offset);
1897 if (val < (char*)ctx->attr || val +
1898 le32_to_cpu(ctx->attr->value_length) >
1899 (char*)ctx->mrec + vol->mft_record_size) {
1900 errno = EIO;
1901 ntfs_log_perror("%s: Sanity check failed", __FUNCTION__);
1902 goto err_out;
1904 memcpy(val + pos, b, count);
1905 if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
1906 ctx->mrec)) {
1908 * NOTE: We are in a bad state at this moment. We have
1909 * dirtied the mft record but we failed to commit it to
1910 * disk. Since we have read the mft record ok before,
1911 * it is unlikely to fail writing it, so is ok to just
1912 * return error here... (AIA)
1914 ntfs_log_perror("%s: failed to write mft record", __FUNCTION__);
1915 goto err_out;
1917 ntfs_attr_put_search_ctx(ctx);
1918 total = count;
1919 goto out;
1922 /* Handle writes beyond initialized_size. */
1924 if (pos + count > na->initialized_size) {
1925 #if PARTIAL_RUNLIST_UPDATING
1927 * When appending, we only need to map the end of the runlist,
1928 * starting at the last previously allocated run, so that
1929 * we are able a new one to it.
1930 * However, for compressed file, we need the full compression
1931 * block, which may be split in several extents.
1933 if (NAttrDataAppending(na)) {
1934 VCN block_begin = pos >> vol->cluster_size_bits;
1936 if (compressed)
1937 block_begin &= -na->compression_block_clusters;
1938 if (block_begin)
1939 block_begin--;
1940 if (ntfs_attr_map_partial_runlist(na, block_begin))
1941 goto err_out;
1942 if ((update_from == -1) || (block_begin < update_from))
1943 update_from = block_begin;
1944 } else
1945 #endif
1946 if (ntfs_attr_map_whole_runlist(na))
1947 goto err_out;
1949 * For a compressed attribute, we must be sure there is an
1950 * available entry, and, when reopening a compressed file,
1951 * we may need to split a hole. So reserve the entries
1952 * before it gets too late.
1954 if (compressed) {
1955 na->rl = ntfs_rl_extend(na,na->rl,2);
1956 if (!na->rl)
1957 goto err_out;
1958 na->unused_runs = 2;
1960 /* Set initialized_size to @pos + @count. */
1961 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
1962 if (!ctx)
1963 goto err_out;
1964 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
1965 0, NULL, 0, ctx))
1966 goto err_out;
1968 /* If write starts beyond initialized_size, zero the gap. */
1969 if (pos > na->initialized_size)
1970 if (ntfs_attr_fill_zero(na, na->initialized_size,
1971 pos - na->initialized_size))
1972 goto err_out;
1974 ctx->attr->initialized_size = cpu_to_sle64(pos + count);
1975 /* fix data_size for compressed files */
1976 if (compressed) {
1977 na->data_size = pos + count;
1978 ctx->attr->data_size = ctx->attr->initialized_size;
1980 if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
1981 ctx->mrec)) {
1983 * Undo the change in the in-memory copy and send it
1984 * back for writing.
1986 ctx->attr->initialized_size =
1987 cpu_to_sle64(old_initialized_size);
1988 ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
1989 ctx->mrec);
1990 goto err_out;
1992 na->initialized_size = pos + count;
1993 #if CACHE_NIDATA_SIZE
1994 if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
1995 ? na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30
1996 : na->type == AT_DATA && na->name == AT_UNNAMED) {
1997 na->ni->data_size = na->data_size;
1998 if ((compressed || NAttrSparse(na))
1999 && NAttrNonResident(na))
2000 na->ni->allocated_size = na->compressed_size;
2001 else
2002 na->ni->allocated_size = na->allocated_size;
2003 set_nino_flag(na->ni,KnownSize);
2005 #endif
2006 ntfs_attr_put_search_ctx(ctx);
2007 ctx = NULL;
2009 * NOTE: At this point the initialized_size in the mft record
2010 * has been updated BUT there is random data on disk thus if
2011 * we decide to abort, we MUST change the initialized_size
2012 * again.
2014 need_to.undo_initialized_size = 1;
2016 /* Find the runlist element containing the vcn. */
2017 rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
2018 if (!rl) {
2020 * If the vcn is not present it is an out of bounds write.
2021 * However, we already extended the size of the attribute,
2022 * so getting this here must be an error of some kind.
2024 if (errno == ENOENT) {
2025 errno = EIO;
2026 ntfs_log_perror("%s: Failed to find VCN #3", __FUNCTION__);
2028 goto err_out;
2031 * Determine if there is compressed data in the current
2032 * compression block (when appending to an existing file).
2033 * If so, decompression will be needed, and the full block
2034 * must be allocated to be identified as uncompressed.
2035 * This comes in two variants, depending on whether
2036 * compression has saved at least one cluster.
2037 * The compressed size can never be over full size by
2038 * more than 485 (maximum for 15 compression blocks
2039 * compressed to 4098 and the last 3640 bytes compressed
2040 * to 3640 + 3640/8 = 4095, with 15*2 + 4095 - 3640 = 485)
2041 * This is less than the smallest cluster, so the hole is
2042 * is never beyond the cluster next to the position of
2043 * the first uncompressed byte to write.
2045 compressed_part = 0;
2046 if (compressed) {
2047 if ((rl->lcn == (LCN)LCN_HOLE)
2048 && wasnonresident) {
2049 if (rl->length < na->compression_block_clusters)
2051 * the needed block is in a hole smaller
2052 * than the compression block : we can use
2053 * it fully
2055 compressed_part
2056 = na->compression_block_clusters
2057 - rl->length;
2058 else {
2060 * the needed block is in a hole bigger
2061 * than the compression block : we must
2062 * split the hole and use it partially
2064 compressed_part = split_compressed_hole(na,
2065 &rl, pos, count, &update_from);
2067 } else {
2068 if (rl->lcn >= 0) {
2070 * the needed block contains data, make
2071 * sure the full compression block is
2072 * allocated. Borrow from hole if needed
2074 compressed_part = borrow_from_hole(na,
2075 &rl, pos, count, &update_from,
2076 wasnonresident);
2080 if (compressed_part < 0)
2081 goto err_out;
2083 /* just making non-resident, so not yet compressed */
2084 if (NAttrBeingNonResident(na)
2085 && (compressed_part < na->compression_block_clusters))
2086 compressed_part = 0;
2088 ofs = pos - (rl->vcn << vol->cluster_size_bits);
2090 * Scatter the data from the linear data buffer to the volume. Note, a
2091 * partial final vcn is taken care of by the @count capping of write
2092 * length.
2094 for (hole_end = 0; count; rl++, ofs = 0) {
2095 if (rl->lcn == LCN_RL_NOT_MAPPED) {
2096 rl = ntfs_attr_find_vcn(na, rl->vcn);
2097 if (!rl) {
2098 if (errno == ENOENT) {
2099 errno = EIO;
2100 ntfs_log_perror("%s: Failed to find VCN"
2101 " #4", __FUNCTION__);
2103 goto rl_err_out;
2105 /* Needed for case when runs merged. */
2106 ofs = pos + total - (rl->vcn << vol->cluster_size_bits);
2108 if (!rl->length) {
2109 errno = EIO;
2110 ntfs_log_perror("%s: Zero run length", __FUNCTION__);
2111 goto rl_err_out;
2113 if (rl->lcn < (LCN)0) {
2114 hole_end = rl->vcn + rl->length;
2116 if (rl->lcn != (LCN)LCN_HOLE) {
2117 errno = EIO;
2118 ntfs_log_perror("%s: Unexpected LCN (%lld)",
2119 __FUNCTION__,
2120 (long long)rl->lcn);
2121 goto rl_err_out;
2123 if (ntfs_attr_fill_hole(na, fullcount, &ofs, &rl,
2124 &update_from))
2125 goto err_out;
2127 if (compressed) {
2128 while (rl->length
2129 && (ofs >= (rl->length << vol->cluster_size_bits))) {
2130 ofs -= rl->length << vol->cluster_size_bits;
2131 rl++;
2135 /* It is a real lcn, write it to the volume. */
2136 to_write = min(count, (rl->length << vol->cluster_size_bits) - ofs);
2137 retry:
2138 ntfs_log_trace("Writing %lld bytes to vcn %lld, lcn %lld, ofs "
2139 "%lld.\n", (long long)to_write, (long long)rl->vcn,
2140 (long long)rl->lcn, (long long)ofs);
2141 if (!NVolReadOnly(vol)) {
2143 s64 wpos = (rl->lcn << vol->cluster_size_bits) + ofs;
2144 s64 wend = (rl->vcn << vol->cluster_size_bits) + ofs + to_write;
2145 u32 bsize = vol->cluster_size;
2146 /* Byte size needed to zero fill a cluster */
2147 s64 rounding = ((wend + bsize - 1) & ~(s64)(bsize - 1)) - wend;
2149 * Zero fill to cluster boundary if we're writing at the
2150 * end of the attribute or into an ex-sparse cluster.
2151 * This will cause the kernel not to seek and read disk
2152 * blocks during write(2) to fill the end of the buffer
2153 * which increases write speed by 2-10 fold typically.
2155 * This is done even for compressed files, because
2156 * data is generally first written uncompressed.
2158 if (rounding && ((wend == na->initialized_size) ||
2159 (wend < (hole_end << vol->cluster_size_bits)))){
2161 char *cb;
2163 rounding += to_write;
2165 cb = ntfs_malloc(rounding);
2166 if (!cb)
2167 goto err_out;
2169 memcpy(cb, b, to_write);
2170 memset(cb + to_write, 0, rounding - to_write);
2172 if (compressed) {
2173 written = ntfs_compressed_pwrite(na,
2174 rl, wpos, ofs, to_write,
2175 rounding, cb, compressed_part,
2176 &update_from);
2177 } else {
2178 written = ntfs_pwrite(vol->dev, wpos,
2179 rounding, cb);
2180 if (written == rounding)
2181 written = to_write;
2184 free(cb);
2185 } else {
2186 if (compressed) {
2187 written = ntfs_compressed_pwrite(na,
2188 rl, wpos, ofs, to_write,
2189 to_write, b, compressed_part,
2190 &update_from);
2191 } else
2192 written = ntfs_pwrite(vol->dev, wpos,
2193 to_write, b);
2195 } else
2196 written = to_write;
2197 /* If everything ok, update progress counters and continue. */
2198 if (written > 0) {
2199 total += written;
2200 count -= written;
2201 fullcount -= written;
2202 b = (const u8*)b + written;
2204 if (written != to_write) {
2205 /* Partial write cannot be dealt with, stop there */
2206 /* If the syscall was interrupted, try again. */
2207 if (written == (s64)-1 && errno == EINTR)
2208 goto retry;
2209 if (!written)
2210 errno = EIO;
2211 goto rl_err_out;
2213 compressed_part = 0;
2215 done:
2216 if (ctx)
2217 ntfs_attr_put_search_ctx(ctx);
2219 * Update mapping pairs if needed.
2220 * For a compressed file, we try to make a partial update
2221 * of the mapping list. This makes a difference only if
2222 * inode extents were needed.
2224 #if PARTIAL_RUNLIST_UPDATING
2225 updatemap = NAttrFullyMapped(na) || NAttrDataAppending(na);
2226 #else
2227 updatemap = (compressed
2228 ? NAttrFullyMapped(na) != 0 : update_from != -1);
2229 #endif
2230 if (updatemap) {
2231 if (ntfs_attr_update_mapping_pairs(na,
2232 (update_from < 0 ? 0 : update_from))) {
2234 * FIXME: trying to recover by goto rl_err_out;
2235 * could cause driver hang by infinite looping.
2237 total = -1;
2238 goto out;
2240 if (!wasnonresident)
2241 NAttrClearBeingNonResident(na);
2242 NAttrClearDataAppending(na);
2244 out:
2245 ntfs_log_leave("\n");
2246 return total;
2247 rl_err_out:
2248 eo = errno;
2249 if (total) {
2250 if (need_to.undo_initialized_size) {
2251 if (pos + total > na->initialized_size)
2252 goto done;
2254 * TODO: Need to try to change initialized_size. If it
2255 * succeeds goto done, otherwise goto err_out. (AIA)
2257 goto err_out;
2259 goto done;
2261 errno = eo;
2262 err_out:
2263 eo = errno;
2264 if (need_to.undo_initialized_size) {
2265 int err;
2267 err = 0;
2268 if (!ctx) {
2269 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
2270 if (!ctx)
2271 err = 1;
2272 } else
2273 ntfs_attr_reinit_search_ctx(ctx);
2274 if (!err) {
2275 err = ntfs_attr_lookup(na->type, na->name,
2276 na->name_len, 0, 0, NULL, 0, ctx);
2277 if (!err) {
2278 na->initialized_size = old_initialized_size;
2279 ctx->attr->initialized_size = cpu_to_sle64(
2280 old_initialized_size);
2281 err = ntfs_mft_record_write(vol,
2282 ctx->ntfs_ino->mft_no,
2283 ctx->mrec);
2286 if (err) {
2288 * FIXME: At this stage could try to recover by filling
2289 * old_initialized_size -> new_initialized_size with
2290 * data or at least zeroes. (AIA)
2292 ntfs_log_error("Eeek! Failed to recover from error. "
2293 "Leaving metadata in inconsistent "
2294 "state! Run chkdsk!\n");
2297 if (ctx)
2298 ntfs_attr_put_search_ctx(ctx);
2299 /* Update mapping pairs if needed. */
2300 updatemap = (compressed
2301 ? NAttrFullyMapped(na) != 0 : update_from != -1);
2302 if (updatemap)
2303 ntfs_attr_update_mapping_pairs(na, 0);
2304 /* Restore original data_size if needed. */
2305 if (need_to.undo_data_size
2306 && ntfs_attr_truncate_i(na, old_data_size, HOLES_OK))
2307 ntfs_log_perror("Failed to restore data_size");
2308 errno = eo;
2309 errno_set:
2310 total = -1;
2311 goto out;
2314 int ntfs_attr_pclose(ntfs_attr *na)
2316 s64 ofs;
2317 int failed;
2318 BOOL ok = TRUE;
2319 VCN update_from = -1;
2320 ntfs_volume *vol;
2321 ntfs_attr_search_ctx *ctx = NULL;
2322 runlist_element *rl;
2323 int eo;
2324 int compressed_part;
2325 BOOL compressed;
2327 ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x.\n",
2328 na->ni->mft_no, na->type);
2330 if (!na || !na->ni || !na->ni->vol) {
2331 errno = EINVAL;
2332 ntfs_log_perror("%s", __FUNCTION__);
2333 goto errno_set;
2335 vol = na->ni->vol;
2336 na->unused_runs = 0;
2337 compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
2338 != const_cpu_to_le16(0);
2340 * Encrypted non-resident attributes are not supported. We return
2341 * access denied, which is what Windows NT4 does, too.
2343 if (NAttrEncrypted(na) && NAttrNonResident(na)) {
2344 errno = EACCES;
2345 goto errno_set;
2347 /* If this is not a compressed attribute get out */
2348 /* same if it is resident */
2349 if (!compressed || !NAttrNonResident(na))
2350 goto out;
2352 /* safety check : no recursion on close */
2353 if (NAttrComprClosing(na)) {
2354 errno = EIO;
2355 ntfs_log_error("Bad ntfs_attr_pclose"
2356 " recursion on inode %lld\n",
2357 (long long)na->ni->mft_no);
2358 goto out;
2360 NAttrSetComprClosing(na);
2362 * For a compressed attribute, we must be sure there are two
2363 * available entries, so reserve them before it gets too late.
2365 if (ntfs_attr_map_whole_runlist(na))
2366 goto err_out;
2367 na->rl = ntfs_rl_extend(na,na->rl,2);
2368 if (!na->rl)
2369 goto err_out;
2370 na->unused_runs = 2;
2371 /* Find the runlist element containing the terminal vcn. */
2372 rl = ntfs_attr_find_vcn(na, (na->initialized_size - 1) >> vol->cluster_size_bits);
2373 if (!rl) {
2375 * If the vcn is not present it is an out of bounds write.
2376 * However, we have already written the last byte uncompressed,
2377 * so getting this here must be an error of some kind.
2379 if (errno == ENOENT) {
2380 errno = EIO;
2381 ntfs_log_perror("%s: Failed to find VCN #5", __FUNCTION__);
2383 goto err_out;
2386 * Scatter the data from the linear data buffer to the volume. Note, a
2387 * partial final vcn is taken care of by the @count capping of write
2388 * length.
2390 compressed_part = 0;
2391 if (rl->lcn >= 0) {
2392 runlist_element *xrl;
2394 xrl = rl;
2395 do {
2396 xrl++;
2397 } while (xrl->lcn >= 0);
2398 compressed_part = (-xrl->length)
2399 & (na->compression_block_clusters - 1);
2400 } else
2401 if (rl->lcn == (LCN)LCN_HOLE) {
2402 if (rl->length < na->compression_block_clusters)
2403 compressed_part
2404 = na->compression_block_clusters
2405 - rl->length;
2406 else
2407 compressed_part
2408 = na->compression_block_clusters;
2410 /* done, if the last block set was compressed */
2411 if (compressed_part)
2412 goto out;
2414 ofs = na->initialized_size - (rl->vcn << vol->cluster_size_bits);
2416 if (rl->lcn == LCN_RL_NOT_MAPPED) {
2417 rl = ntfs_attr_find_vcn(na, rl->vcn);
2418 if (!rl) {
2419 if (errno == ENOENT) {
2420 errno = EIO;
2421 ntfs_log_perror("%s: Failed to find VCN"
2422 " #6", __FUNCTION__);
2424 goto rl_err_out;
2426 /* Needed for case when runs merged. */
2427 ofs = na->initialized_size - (rl->vcn << vol->cluster_size_bits);
2429 if (!rl->length) {
2430 errno = EIO;
2431 ntfs_log_perror("%s: Zero run length", __FUNCTION__);
2432 goto rl_err_out;
2434 if (rl->lcn < (LCN)0) {
2435 if (rl->lcn != (LCN)LCN_HOLE) {
2436 errno = EIO;
2437 ntfs_log_perror("%s: Unexpected LCN (%lld)",
2438 __FUNCTION__,
2439 (long long)rl->lcn);
2440 goto rl_err_out;
2443 if (ntfs_attr_fill_hole(na, (s64)0, &ofs, &rl, &update_from))
2444 goto err_out;
2446 while (rl->length
2447 && (ofs >= (rl->length << vol->cluster_size_bits))) {
2448 ofs -= rl->length << vol->cluster_size_bits;
2449 rl++;
2452 retry:
2453 failed = 0;
2454 if (update_from < 0) update_from = 0;
2455 if (!NVolReadOnly(vol)) {
2456 failed = ntfs_compressed_close(na, rl, ofs, &update_from);
2457 #if CACHE_NIDATA_SIZE
2458 if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
2459 ? na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30
2460 : na->type == AT_DATA && na->name == AT_UNNAMED) {
2461 na->ni->data_size = na->data_size;
2462 na->ni->allocated_size = na->compressed_size;
2463 set_nino_flag(na->ni,KnownSize);
2465 #endif
2467 if (failed) {
2468 /* If the syscall was interrupted, try again. */
2469 if (errno == EINTR)
2470 goto retry;
2471 else
2472 goto rl_err_out;
2474 if (ctx)
2475 ntfs_attr_put_search_ctx(ctx);
2476 /* Update mapping pairs if needed. */
2477 if (NAttrFullyMapped(na))
2478 if (ntfs_attr_update_mapping_pairs(na, update_from)) {
2480 * FIXME: trying to recover by goto rl_err_out;
2481 * could cause driver hang by infinite looping.
2483 ok = FALSE;
2484 goto out;
2486 out:
2487 NAttrClearComprClosing(na);
2488 ntfs_log_leave("\n");
2489 return (!ok);
2490 rl_err_out:
2492 * need not restore old sizes, only compressed_size
2493 * can have changed. It has been set according to
2494 * the current runlist while updating the mapping pairs,
2495 * and must be kept consistent with the runlists.
2497 err_out:
2498 eo = errno;
2499 if (ctx)
2500 ntfs_attr_put_search_ctx(ctx);
2501 /* Update mapping pairs if needed. */
2502 if (NAttrFullyMapped(na))
2503 ntfs_attr_update_mapping_pairs(na, 0);
2504 errno = eo;
2505 errno_set:
2506 ok = FALSE;
2507 goto out;
2511 * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read
2512 * @na: multi sector transfer protected ntfs attribute to read from
2513 * @pos: byte position in the attribute to begin reading from
2514 * @bk_cnt: number of mst protected blocks to read
2515 * @bk_size: size of each mst protected block in bytes
2516 * @dst: output data buffer
2518 * This function will read @bk_cnt blocks of size @bk_size bytes each starting
2519 * at offset @pos from the ntfs attribute @na into the data buffer @b.
2521 * On success, the multi sector transfer fixups are applied and the number of
2522 * read blocks is returned. If this number is lower than @bk_cnt this means
2523 * that the read has either reached end of attribute or that an error was
2524 * encountered during the read so that the read is partial. 0 means end of
2525 * attribute or nothing to read (also return 0 when @bk_cnt or @bk_size are 0).
2527 * On error and nothing has been read, return -1 with errno set appropriately
2528 * to the return code of ntfs_attr_pread() or to EINVAL in case of invalid
2529 * arguments.
2531 * NOTE: If an incomplete multi sector transfer is detected the magic is
2532 * changed to BAAD but no error is returned, i.e. it is possible that any of
2533 * the returned blocks have multi sector transfer errors. This should be
2534 * detected by the caller by checking each block with is_baad_recordp(&block).
2535 * The reasoning is that we want to fixup as many blocks as possible and we
2536 * want to return even bad ones to the caller so, e.g. in case of ntfsck, the
2537 * errors can be repaired.
2539 s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
2540 const u32 bk_size, void *dst)
2542 s64 br;
2543 u8 *end;
2544 BOOL warn;
2546 ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 0x%llx.\n",
2547 (unsigned long long)na->ni->mft_no, na->type,
2548 (long long)pos);
2549 if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
2550 errno = EINVAL;
2551 ntfs_log_perror("%s", __FUNCTION__);
2552 return -1;
2554 br = ntfs_attr_pread(na, pos, bk_cnt * bk_size, dst);
2555 if (br <= 0)
2556 return br;
2557 br /= bk_size;
2558 /* log errors unless silenced */
2559 warn = !na->ni || !na->ni->vol || !NVolNoFixupWarn(na->ni->vol);
2560 for (end = (u8*)dst + br * bk_size; (u8*)dst < end; dst = (u8*)dst +
2561 bk_size)
2562 ntfs_mst_post_read_fixup_warn((NTFS_RECORD*)dst, bk_size, warn);
2563 /* Finally, return the number of blocks read. */
2564 return br;
2568 * ntfs_attr_mst_pwrite - multi sector transfer protected ntfs attribute write
2569 * @na: multi sector transfer protected ntfs attribute to write to
2570 * @pos: position in the attribute to write to
2571 * @bk_cnt: number of mst protected blocks to write
2572 * @bk_size: size of each mst protected block in bytes
2573 * @src: data buffer to write to disk
2575 * This function will write @bk_cnt blocks of size @bk_size bytes each from
2576 * data buffer @b to multi sector transfer (mst) protected ntfs attribute @na
2577 * at position @pos.
2579 * On success, return the number of successfully written blocks. If this number
2580 * is lower than @bk_cnt this means that an error was encountered during the
2581 * write so that the write is partial. 0 means nothing was written (also
2582 * return 0 when @bk_cnt or @bk_size are 0).
2584 * On error and nothing has been written, return -1 with errno set
2585 * appropriately to the return code of ntfs_attr_pwrite(), or to EINVAL in case
2586 * of invalid arguments.
2588 * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
2589 * deprotect algorithm (no checking). This saves us from making a copy before
2590 * the write and at the same time causes the usn to be incremented in the
2591 * buffer. This conceptually fits in better with the idea that cached data is
2592 * always deprotected and protection is performed when the data is actually
2593 * going to hit the disk and the cache is immediately deprotected again
2594 * simulating an mst read on the written data. This way cache coherency is
2595 * achieved.
2597 s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, s64 bk_cnt,
2598 const u32 bk_size, void *src)
2600 s64 written, i;
2602 ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 0x%llx.\n",
2603 (unsigned long long)na->ni->mft_no, na->type,
2604 (long long)pos);
2605 if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
2606 errno = EINVAL;
2607 return -1;
2609 if (!bk_cnt)
2610 return 0;
2611 /* Prepare data for writing. */
2612 for (i = 0; i < bk_cnt; ++i) {
2613 int err;
2615 err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
2616 ((u8*)src + i * bk_size), bk_size);
2617 if (err < 0) {
2618 /* Abort write at this position. */
2619 ntfs_log_perror("%s #1", __FUNCTION__);
2620 if (!i)
2621 return err;
2622 bk_cnt = i;
2623 break;
2626 /* Write the prepared data. */
2627 written = ntfs_attr_pwrite(na, pos, bk_cnt * bk_size, src);
2628 if (written <= 0) {
2629 ntfs_log_perror("%s: written=%lld", __FUNCTION__,
2630 (long long)written);
2632 /* Quickly deprotect the data again. */
2633 for (i = 0; i < bk_cnt; ++i)
2634 ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)src + i *
2635 bk_size));
2636 if (written <= 0)
2637 return written;
2638 /* Finally, return the number of complete blocks written. */
2639 return written / bk_size;
2643 * ntfs_attr_find - find (next) attribute in mft record
2644 * @type: attribute type to find
2645 * @name: attribute name to find (optional, i.e. NULL means don't care)
2646 * @name_len: attribute name length (only needed if @name present)
2647 * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
2648 * @val: attribute value to find (optional, resident attributes only)
2649 * @val_len: attribute value length
2650 * @ctx: search context with mft record and attribute to search from
2652 * You shouldn't need to call this function directly. Use lookup_attr() instead.
2654 * ntfs_attr_find() takes a search context @ctx as parameter and searches the
2655 * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
2656 * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
2657 * returns 0 and @ctx->attr will point to the found attribute.
2659 * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
2660 * @ctx->attr will point to the attribute before which the attribute being
2661 * searched for would need to be inserted if such an action were to be desired.
2663 * On actual error, ntfs_attr_find() returns -1 with errno set to the error
2664 * code but not to ENOENT. In this case @ctx->attr is undefined and in
2665 * particular do not rely on it not changing.
2667 * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
2668 * is FALSE, the search begins after @ctx->attr.
2670 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
2671 * enumerate all attributes by setting @type to AT_UNUSED and then calling
2672 * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
2673 * indicate that there are no more entries. During the enumeration, each
2674 * successful call of ntfs_attr_find() will return the next attribute in the
2675 * mft record @ctx->mrec.
2677 * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
2678 * AT_END is not a valid attribute, its length is zero for example, thus it is
2679 * safer to return error instead of success in this case. This also allows us
2680 * to interoperate cleanly with ntfs_external_attr_find().
2682 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
2683 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
2684 * match both named and unnamed attributes.
2686 * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
2687 * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
2688 * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
2689 * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
2690 * sensitive. When @name is present, @name_len is the @name length in Unicode
2691 * characters.
2693 * If @name is not present (NULL), we assume that the unnamed attribute is
2694 * being searched for.
2696 * Finally, the resident attribute value @val is looked for, if present.
2697 * If @val is not present (NULL), @val_len is ignored.
2699 * ntfs_attr_find() only searches the specified mft record and it ignores the
2700 * presence of an attribute list attribute (unless it is the one being searched
2701 * for, obviously). If you need to take attribute lists into consideration, use
2702 * ntfs_attr_lookup() instead (see below). This also means that you cannot use
2703 * ntfs_attr_find() to search for extent records of non-resident attributes, as
2704 * extents with lowest_vcn != 0 are usually described by the attribute list
2705 * attribute only. - Note that it is possible that the first extent is only in
2706 * the attribute list while the last extent is in the base mft record, so don't
2707 * rely on being able to find the first extent in the base mft record.
2709 * Warning: Never use @val when looking for attribute types which can be
2710 * non-resident as this most likely will result in a crash!
2712 static int ntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
2713 const u32 name_len, const IGNORE_CASE_BOOL ic,
2714 const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
2716 ATTR_RECORD *a;
2717 ntfs_volume *vol;
2718 ntfschar *upcase;
2719 u32 upcase_len;
2721 ntfs_log_trace("attribute type 0x%x.\n", type);
2723 if (ctx->ntfs_ino) {
2724 vol = ctx->ntfs_ino->vol;
2725 upcase = vol->upcase;
2726 upcase_len = vol->upcase_len;
2727 } else {
2728 if (name && name != AT_UNNAMED) {
2729 errno = EINVAL;
2730 ntfs_log_perror("%s", __FUNCTION__);
2731 return -1;
2733 vol = NULL;
2734 upcase = NULL;
2735 upcase_len = 0;
2738 * Iterate over attributes in mft record starting at @ctx->attr, or the
2739 * attribute following that, if @ctx->is_first is TRUE.
2741 if (ctx->is_first) {
2742 a = ctx->attr;
2743 ctx->is_first = FALSE;
2744 } else
2745 a = (ATTR_RECORD*)((char*)ctx->attr +
2746 le32_to_cpu(ctx->attr->length));
2747 for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
2748 if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
2749 le32_to_cpu(ctx->mrec->bytes_allocated))
2750 break;
2751 ctx->attr = a;
2752 if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
2753 le32_to_cpu(type))) ||
2754 (a->type == AT_END)) {
2755 errno = ENOENT;
2756 return -1;
2758 if (!a->length)
2759 break;
2760 /* If this is an enumeration return this attribute. */
2761 if (type == AT_UNUSED)
2762 return 0;
2763 if (a->type != type)
2764 continue;
2766 * If @name is AT_UNNAMED we want an unnamed attribute.
2767 * If @name is present, compare the two names.
2768 * Otherwise, match any attribute.
2770 if (name == AT_UNNAMED) {
2771 /* The search failed if the found attribute is named. */
2772 if (a->name_length) {
2773 errno = ENOENT;
2774 return -1;
2776 } else {
2777 register int rc;
2778 if (name && ((rc = ntfs_names_full_collate(name,
2779 name_len, (ntfschar*)((char*)a +
2780 le16_to_cpu(a->name_offset)),
2781 a->name_length, ic,
2782 upcase, upcase_len)))) {
2784 * If @name collates before a->name,
2785 * there is no matching attribute.
2787 if (rc < 0) {
2788 errno = ENOENT;
2789 return -1;
2791 /* If the strings are not equal, continue search. */
2792 continue;
2796 * The names match or @name not present and attribute is
2797 * unnamed. If no @val specified, we have found the attribute
2798 * and are done.
2800 if (!val)
2801 return 0;
2802 /* @val is present; compare values. */
2803 else {
2804 register int rc;
2806 rc = memcmp(val, (char*)a +le16_to_cpu(a->value_offset),
2807 min(val_len,
2808 le32_to_cpu(a->value_length)));
2810 * If @val collates before the current attribute's
2811 * value, there is no matching attribute.
2813 if (!rc) {
2814 register u32 avl;
2815 avl = le32_to_cpu(a->value_length);
2816 if (val_len == avl)
2817 return 0;
2818 if (val_len < avl) {
2819 errno = ENOENT;
2820 return -1;
2822 } else if (rc < 0) {
2823 errno = ENOENT;
2824 return -1;
2828 errno = EIO;
2829 ntfs_log_perror("%s: Corrupt inode (%lld)", __FUNCTION__,
2830 ctx->ntfs_ino ? (long long)ctx->ntfs_ino->mft_no : -1);
2831 return -1;
2834 void ntfs_attr_name_free(char **name)
2836 if (*name) {
2837 free(*name);
2838 *name = NULL;
2842 char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len)
2844 char *name = NULL;
2845 int name_len;
2847 name_len = ntfs_ucstombs(uname, uname_len, &name, 0);
2848 if (name_len < 0) {
2849 ntfs_log_perror("ntfs_ucstombs");
2850 return NULL;
2852 } else if (name_len > 0)
2853 return name;
2855 ntfs_attr_name_free(&name);
2856 return NULL;
2860 * ntfs_external_attr_find - find an attribute in the attribute list of an inode
2861 * @type: attribute type to find
2862 * @name: attribute name to find (optional, i.e. NULL means don't care)
2863 * @name_len: attribute name length (only needed if @name present)
2864 * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
2865 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
2866 * @val: attribute value to find (optional, resident attributes only)
2867 * @val_len: attribute value length
2868 * @ctx: search context with mft record and attribute to search from
2870 * You shouldn't need to call this function directly. Use ntfs_attr_lookup()
2871 * instead.
2873 * Find an attribute by searching the attribute list for the corresponding
2874 * attribute list entry. Having found the entry, map the mft record for read
2875 * if the attribute is in a different mft record/inode, find the attribute in
2876 * there and return it.
2878 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
2879 * enumerate all attributes by setting @type to AT_UNUSED and then calling
2880 * ntfs_external_attr_find() repeatedly until it returns -1 with errno set to
2881 * ENOENT to indicate that there are no more entries. During the enumeration,
2882 * each successful call of ntfs_external_attr_find() will return the next
2883 * attribute described by the attribute list of the base mft record described
2884 * by the search context @ctx.
2886 * If @type is AT_END, seek to the end of the base mft record ignoring the
2887 * attribute list completely and return -1 with errno set to ENOENT. AT_END is
2888 * not a valid attribute, its length is zero for example, thus it is safer to
2889 * return error instead of success in this case.
2891 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
2892 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
2893 * match both named and unnamed attributes.
2895 * On first search @ctx->ntfs_ino must be the inode of the base mft record and
2896 * @ctx must have been obtained from a call to ntfs_attr_get_search_ctx().
2897 * On subsequent calls, @ctx->ntfs_ino can be any extent inode, too
2898 * (@ctx->base_ntfs_ino is then the base inode).
2900 * After finishing with the attribute/mft record you need to call
2901 * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
2902 * mapped extent inodes, etc).
2904 * Return 0 if the search was successful and -1 if not, with errno set to the
2905 * error code.
2907 * On success, @ctx->attr is the found attribute, it is in mft record
2908 * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
2909 * attribute with @ctx->base_* being the base mft record to which @ctx->attr
2910 * belongs.
2912 * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
2913 * attribute which collates just after the attribute being searched for in the
2914 * base ntfs inode, i.e. if one wants to add the attribute to the mft record
2915 * this is the correct place to insert it into, and if there is not enough
2916 * space, the attribute should be placed in an extent mft record.
2917 * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
2918 * at which the new attribute's attribute list entry should be inserted. The
2919 * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
2920 * The only exception to this is when @type is AT_END, in which case
2921 * @ctx->al_entry is set to NULL also (see above).
2923 * The following error codes are defined:
2924 * ENOENT Attribute not found, not an error as such.
2925 * EINVAL Invalid arguments.
2926 * EIO I/O error or corrupt data structures found.
2927 * ENOMEM Not enough memory to allocate necessary buffers.
2929 static int ntfs_external_attr_find(ATTR_TYPES type, const ntfschar *name,
2930 const u32 name_len, const IGNORE_CASE_BOOL ic,
2931 const VCN lowest_vcn, const u8 *val, const u32 val_len,
2932 ntfs_attr_search_ctx *ctx)
2934 ntfs_inode *base_ni, *ni;
2935 ntfs_volume *vol;
2936 ATTR_LIST_ENTRY *al_entry, *next_al_entry;
2937 u8 *al_start, *al_end;
2938 ATTR_RECORD *a;
2939 ntfschar *al_name;
2940 u32 al_name_len;
2941 BOOL is_first_search = FALSE;
2943 ni = ctx->ntfs_ino;
2944 base_ni = ctx->base_ntfs_ino;
2945 ntfs_log_trace("Entering for inode %lld, attribute type 0x%x.\n",
2946 (unsigned long long)ni->mft_no, type);
2947 if (!base_ni) {
2948 /* First call happens with the base mft record. */
2949 base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino;
2950 ctx->base_mrec = ctx->mrec;
2952 if (ni == base_ni)
2953 ctx->base_attr = ctx->attr;
2954 if (type == AT_END)
2955 goto not_found;
2956 vol = base_ni->vol;
2957 al_start = base_ni->attr_list;
2958 al_end = al_start + base_ni->attr_list_size;
2959 if (!ctx->al_entry) {
2960 ctx->al_entry = (ATTR_LIST_ENTRY*)al_start;
2961 is_first_search = TRUE;
2964 * Iterate over entries in attribute list starting at @ctx->al_entry,
2965 * or the entry following that, if @ctx->is_first is TRUE.
2967 if (ctx->is_first) {
2968 al_entry = ctx->al_entry;
2969 ctx->is_first = FALSE;
2971 * If an enumeration and the first attribute is higher than
2972 * the attribute list itself, need to return the attribute list
2973 * attribute.
2975 if ((type == AT_UNUSED) && is_first_search &&
2976 le32_to_cpu(al_entry->type) >
2977 le32_to_cpu(AT_ATTRIBUTE_LIST))
2978 goto find_attr_list_attr;
2979 } else {
2980 al_entry = (ATTR_LIST_ENTRY*)((char*)ctx->al_entry +
2981 le16_to_cpu(ctx->al_entry->length));
2983 * If this is an enumeration and the attribute list attribute
2984 * is the next one in the enumeration sequence, just return the
2985 * attribute list attribute from the base mft record as it is
2986 * not listed in the attribute list itself.
2988 if ((type == AT_UNUSED) && le32_to_cpu(ctx->al_entry->type) <
2989 le32_to_cpu(AT_ATTRIBUTE_LIST) &&
2990 le32_to_cpu(al_entry->type) >
2991 le32_to_cpu(AT_ATTRIBUTE_LIST)) {
2992 int rc;
2993 find_attr_list_attr:
2995 /* Check for bogus calls. */
2996 if (name || name_len || val || val_len || lowest_vcn) {
2997 errno = EINVAL;
2998 ntfs_log_perror("%s", __FUNCTION__);
2999 return -1;
3002 /* We want the base record. */
3003 ctx->ntfs_ino = base_ni;
3004 ctx->mrec = ctx->base_mrec;
3005 ctx->is_first = TRUE;
3006 /* Sanity checks are performed elsewhere. */
3007 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
3008 le16_to_cpu(ctx->mrec->attrs_offset));
3010 /* Find the attribute list attribute. */
3011 rc = ntfs_attr_find(AT_ATTRIBUTE_LIST, NULL, 0,
3012 IGNORE_CASE, NULL, 0, ctx);
3015 * Setup the search context so the correct
3016 * attribute is returned next time round.
3018 ctx->al_entry = al_entry;
3019 ctx->is_first = TRUE;
3021 /* Got it. Done. */
3022 if (!rc)
3023 return 0;
3025 /* Error! If other than not found return it. */
3026 if (errno != ENOENT)
3027 return rc;
3029 /* Not found?!? Absurd! */
3030 errno = EIO;
3031 ntfs_log_error("Attribute list wasn't found");
3032 return -1;
3035 for (;; al_entry = next_al_entry) {
3036 /* Out of bounds check. */
3037 if ((u8*)al_entry < base_ni->attr_list ||
3038 (u8*)al_entry > al_end)
3039 break; /* Inode is corrupt. */
3040 ctx->al_entry = al_entry;
3041 /* Catch the end of the attribute list. */
3042 if ((u8*)al_entry == al_end)
3043 goto not_found;
3044 if (!al_entry->length)
3045 break;
3046 if ((u8*)al_entry + 6 > al_end || (u8*)al_entry +
3047 le16_to_cpu(al_entry->length) > al_end)
3048 break;
3049 next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
3050 le16_to_cpu(al_entry->length));
3051 if (type != AT_UNUSED) {
3052 if (le32_to_cpu(al_entry->type) > le32_to_cpu(type))
3053 goto not_found;
3054 if (type != al_entry->type)
3055 continue;
3057 al_name_len = al_entry->name_length;
3058 al_name = (ntfschar*)((u8*)al_entry + al_entry->name_offset);
3060 * If !@type we want the attribute represented by this
3061 * attribute list entry.
3063 if (type == AT_UNUSED)
3064 goto is_enumeration;
3066 * If @name is AT_UNNAMED we want an unnamed attribute.
3067 * If @name is present, compare the two names.
3068 * Otherwise, match any attribute.
3070 if (name == AT_UNNAMED) {
3071 if (al_name_len)
3072 goto not_found;
3073 } else {
3074 int rc;
3076 if (name && ((rc = ntfs_names_full_collate(name,
3077 name_len, al_name, al_name_len, ic,
3078 vol->upcase, vol->upcase_len)))) {
3081 * If @name collates before al_name,
3082 * there is no matching attribute.
3084 if (rc < 0)
3085 goto not_found;
3086 /* If the strings are not equal, continue search. */
3087 continue;
3091 * The names match or @name not present and attribute is
3092 * unnamed. Now check @lowest_vcn. Continue search if the
3093 * next attribute list entry still fits @lowest_vcn. Otherwise
3094 * we have reached the right one or the search has failed.
3096 if (lowest_vcn && (u8*)next_al_entry >= al_start &&
3097 (u8*)next_al_entry + 6 < al_end &&
3098 (u8*)next_al_entry + le16_to_cpu(
3099 next_al_entry->length) <= al_end &&
3100 sle64_to_cpu(next_al_entry->lowest_vcn) <=
3101 lowest_vcn &&
3102 next_al_entry->type == al_entry->type &&
3103 next_al_entry->name_length == al_name_len &&
3104 ntfs_names_are_equal((ntfschar*)((char*)
3105 next_al_entry +
3106 next_al_entry->name_offset),
3107 next_al_entry->name_length,
3108 al_name, al_name_len, CASE_SENSITIVE,
3109 vol->upcase, vol->upcase_len))
3110 continue;
3111 is_enumeration:
3112 if (MREF_LE(al_entry->mft_reference) == ni->mft_no) {
3113 if (MSEQNO_LE(al_entry->mft_reference) !=
3114 le16_to_cpu(
3115 ni->mrec->sequence_number)) {
3116 ntfs_log_error("Found stale mft reference in "
3117 "attribute list!\n");
3118 break;
3120 } else { /* Mft references do not match. */
3121 /* Do we want the base record back? */
3122 if (MREF_LE(al_entry->mft_reference) ==
3123 base_ni->mft_no) {
3124 ni = ctx->ntfs_ino = base_ni;
3125 ctx->mrec = ctx->base_mrec;
3126 } else {
3127 /* We want an extent record. */
3128 ni = ntfs_extent_inode_open(base_ni,
3129 al_entry->mft_reference);
3130 if (!ni)
3131 break;
3132 ctx->ntfs_ino = ni;
3133 ctx->mrec = ni->mrec;
3136 a = ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec +
3137 le16_to_cpu(ctx->mrec->attrs_offset));
3139 * ctx->ntfs_ino, ctx->mrec, and ctx->attr now point to the
3140 * mft record containing the attribute represented by the
3141 * current al_entry.
3143 * We could call into ntfs_attr_find() to find the right
3144 * attribute in this mft record but this would be less
3145 * efficient and not quite accurate as ntfs_attr_find() ignores
3146 * the attribute instance numbers for example which become
3147 * important when one plays with attribute lists. Also, because
3148 * a proper match has been found in the attribute list entry
3149 * above, the comparison can now be optimized. So it is worth
3150 * re-implementing a simplified ntfs_attr_find() here.
3152 * Use a manual loop so we can still use break and continue
3153 * with the same meanings as above.
3155 do_next_attr_loop:
3156 if ((char*)a < (char*)ctx->mrec || (char*)a > (char*)ctx->mrec +
3157 le32_to_cpu(ctx->mrec->bytes_allocated))
3158 break;
3159 if (a->type == AT_END)
3160 continue;
3161 if (!a->length)
3162 break;
3163 if (al_entry->instance != a->instance)
3164 goto do_next_attr;
3166 * If the type and/or the name are/is mismatched between the
3167 * attribute list entry and the attribute record, there is
3168 * corruption so we break and return error EIO.
3170 if (al_entry->type != a->type)
3171 break;
3172 if (!ntfs_names_are_equal((ntfschar*)((char*)a +
3173 le16_to_cpu(a->name_offset)),
3174 a->name_length, al_name,
3175 al_name_len, CASE_SENSITIVE,
3176 vol->upcase, vol->upcase_len))
3177 break;
3178 ctx->attr = a;
3180 * If no @val specified or @val specified and it matches, we
3181 * have found it! Also, if !@type, it is an enumeration, so we
3182 * want the current attribute.
3184 if ((type == AT_UNUSED) || !val || (!a->non_resident &&
3185 le32_to_cpu(a->value_length) == val_len &&
3186 !memcmp((char*)a + le16_to_cpu(a->value_offset),
3187 val, val_len))) {
3188 return 0;
3190 do_next_attr:
3191 /* Proceed to the next attribute in the current mft record. */
3192 a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
3193 goto do_next_attr_loop;
3195 if (ni != base_ni) {
3196 ctx->ntfs_ino = base_ni;
3197 ctx->mrec = ctx->base_mrec;
3198 ctx->attr = ctx->base_attr;
3200 errno = EIO;
3201 ntfs_log_perror("Inode is corrupt (%lld)", (long long)base_ni->mft_no);
3202 return -1;
3203 not_found:
3205 * If we were looking for AT_END or we were enumerating and reached the
3206 * end, we reset the search context @ctx and use ntfs_attr_find() to
3207 * seek to the end of the base mft record.
3209 if (type == AT_UNUSED || type == AT_END) {
3210 ntfs_attr_reinit_search_ctx(ctx);
3211 return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len,
3212 ctx);
3215 * The attribute wasn't found. Before we return, we want to ensure
3216 * @ctx->mrec and @ctx->attr indicate the position at which the
3217 * attribute should be inserted in the base mft record. Since we also
3218 * want to preserve @ctx->al_entry we cannot reinitialize the search
3219 * context using ntfs_attr_reinit_search_ctx() as this would set
3220 * @ctx->al_entry to NULL. Thus we do the necessary bits manually (see
3221 * ntfs_attr_init_search_ctx() below). Note, we _only_ preserve
3222 * @ctx->al_entry as the remaining fields (base_*) are identical to
3223 * their non base_ counterparts and we cannot set @ctx->base_attr
3224 * correctly yet as we do not know what @ctx->attr will be set to by
3225 * the call to ntfs_attr_find() below.
3227 ctx->mrec = ctx->base_mrec;
3228 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
3229 le16_to_cpu(ctx->mrec->attrs_offset));
3230 ctx->is_first = TRUE;
3231 ctx->ntfs_ino = ctx->base_ntfs_ino;
3232 ctx->base_ntfs_ino = NULL;
3233 ctx->base_mrec = NULL;
3234 ctx->base_attr = NULL;
3236 * In case there are multiple matches in the base mft record, need to
3237 * keep enumerating until we get an attribute not found response (or
3238 * another error), otherwise we would keep returning the same attribute
3239 * over and over again and all programs using us for enumeration would
3240 * lock up in a tight loop.
3243 int ret;
3245 do {
3246 ret = ntfs_attr_find(type, name, name_len, ic, val,
3247 val_len, ctx);
3248 } while (!ret);
3249 return ret;
3254 * ntfs_attr_lookup - find an attribute in an ntfs inode
3255 * @type: attribute type to find
3256 * @name: attribute name to find (optional, i.e. NULL means don't care)
3257 * @name_len: attribute name length (only needed if @name present)
3258 * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
3259 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
3260 * @val: attribute value to find (optional, resident attributes only)
3261 * @val_len: attribute value length
3262 * @ctx: search context with mft record and attribute to search from
3264 * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
3265 * be the base mft record and @ctx must have been obtained from a call to
3266 * ntfs_attr_get_search_ctx().
3268 * This function transparently handles attribute lists and @ctx is used to
3269 * continue searches where they were left off at.
3271 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
3272 * enumerate all attributes by setting @type to AT_UNUSED and then calling
3273 * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
3274 * to indicate that there are no more entries. During the enumeration, each
3275 * successful call of ntfs_attr_lookup() will return the next attribute, with
3276 * the current attribute being described by the search context @ctx.
3278 * If @type is AT_END, seek to the end of the base mft record ignoring the
3279 * attribute list completely and return -1 with errno set to ENOENT. AT_END is
3280 * not a valid attribute, its length is zero for example, thus it is safer to
3281 * return error instead of success in this case. It should never be needed to
3282 * do this, but we implement the functionality because it allows for simpler
3283 * code inside ntfs_external_attr_find().
3285 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
3286 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
3287 * match both named and unnamed attributes.
3289 * After finishing with the attribute/mft record you need to call
3290 * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
3291 * mapped extent inodes, etc).
3293 * Return 0 if the search was successful and -1 if not, with errno set to the
3294 * error code.
3296 * On success, @ctx->attr is the found attribute, it is in mft record
3297 * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
3298 * attribute with @ctx->base_* being the base mft record to which @ctx->attr
3299 * belongs. If no attribute list attribute is present @ctx->al_entry and
3300 * @ctx->base_* are NULL.
3302 * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
3303 * attribute which collates just after the attribute being searched for in the
3304 * base ntfs inode, i.e. if one wants to add the attribute to the mft record
3305 * this is the correct place to insert it into, and if there is not enough
3306 * space, the attribute should be placed in an extent mft record.
3307 * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
3308 * at which the new attribute's attribute list entry should be inserted. The
3309 * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
3310 * The only exception to this is when @type is AT_END, in which case
3311 * @ctx->al_entry is set to NULL also (see above).
3314 * The following error codes are defined:
3315 * ENOENT Attribute not found, not an error as such.
3316 * EINVAL Invalid arguments.
3317 * EIO I/O error or corrupt data structures found.
3318 * ENOMEM Not enough memory to allocate necessary buffers.
3320 int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
3321 const u32 name_len, const IGNORE_CASE_BOOL ic,
3322 const VCN lowest_vcn, const u8 *val, const u32 val_len,
3323 ntfs_attr_search_ctx *ctx)
3325 ntfs_volume *vol;
3326 ntfs_inode *base_ni;
3327 int ret = -1;
3329 ntfs_log_enter("Entering for attribute type 0x%x\n", type);
3331 if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED &&
3332 (!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) ||
3333 !vol->upcase || !vol->upcase_len))) {
3334 errno = EINVAL;
3335 ntfs_log_perror("%s", __FUNCTION__);
3336 goto out;
3339 if (ctx->base_ntfs_ino)
3340 base_ni = ctx->base_ntfs_ino;
3341 else
3342 base_ni = ctx->ntfs_ino;
3343 if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
3344 ret = ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx);
3345 else
3346 ret = ntfs_external_attr_find(type, name, name_len, ic,
3347 lowest_vcn, val, val_len, ctx);
3348 out:
3349 ntfs_log_leave("\n");
3350 return ret;
3354 * ntfs_attr_position - find given or next attribute type in an ntfs inode
3355 * @type: attribute type to start lookup
3356 * @ctx: search context with mft record and attribute to search from
3358 * Find an attribute type in an ntfs inode or the next attribute which is not
3359 * the AT_END attribute. Please see more details at ntfs_attr_lookup.
3361 * Return 0 if the search was successful and -1 if not, with errno set to the
3362 * error code.
3364 * The following error codes are defined:
3365 * EINVAL Invalid arguments.
3366 * EIO I/O error or corrupt data structures found.
3367 * ENOMEM Not enough memory to allocate necessary buffers.
3368 * ENOSPC No attribute was found after 'type', only AT_END.
3370 int ntfs_attr_position(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx)
3372 if (ntfs_attr_lookup(type, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
3373 if (errno != ENOENT)
3374 return -1;
3375 if (ctx->attr->type == AT_END) {
3376 errno = ENOSPC;
3377 return -1;
3380 return 0;
3384 * ntfs_attr_init_search_ctx - initialize an attribute search context
3385 * @ctx: attribute search context to initialize
3386 * @ni: ntfs inode with which to initialize the search context
3387 * @mrec: mft record with which to initialize the search context
3389 * Initialize the attribute search context @ctx with @ni and @mrec.
3391 static void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
3392 ntfs_inode *ni, MFT_RECORD *mrec)
3394 if (!mrec)
3395 mrec = ni->mrec;
3396 ctx->mrec = mrec;
3397 /* Sanity checks are performed elsewhere. */
3398 ctx->attr = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset));
3399 ctx->is_first = TRUE;
3400 ctx->ntfs_ino = ni;
3401 ctx->al_entry = NULL;
3402 ctx->base_ntfs_ino = NULL;
3403 ctx->base_mrec = NULL;
3404 ctx->base_attr = NULL;
3408 * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
3409 * @ctx: attribute search context to reinitialize
3411 * Reinitialize the attribute search context @ctx.
3413 * This is used when a search for a new attribute is being started to reset
3414 * the search context to the beginning.
3416 void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
3418 if (!ctx->base_ntfs_ino) {
3419 /* No attribute list. */
3420 ctx->is_first = TRUE;
3421 /* Sanity checks are performed elsewhere. */
3422 ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
3423 le16_to_cpu(ctx->mrec->attrs_offset));
3425 * This needs resetting due to ntfs_external_attr_find() which
3426 * can leave it set despite having zeroed ctx->base_ntfs_ino.
3428 ctx->al_entry = NULL;
3429 return;
3430 } /* Attribute list. */
3431 ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
3432 return;
3436 * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
3437 * @ni: ntfs inode with which to initialize the search context
3438 * @mrec: mft record with which to initialize the search context
3440 * Allocate a new attribute search context, initialize it with @ni and @mrec,
3441 * and return it. Return NULL on error with errno set.
3443 * @mrec can be NULL, in which case the mft record is taken from @ni.
3445 * Note: For low level utilities which know what they are doing we allow @ni to
3446 * be NULL and @mrec to be set. Do NOT do this unless you understand the
3447 * implications!!! For example it is no longer safe to call ntfs_attr_lookup().
3449 ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
3451 ntfs_attr_search_ctx *ctx;
3453 if (!ni && !mrec) {
3454 errno = EINVAL;
3455 ntfs_log_perror("NULL arguments");
3456 return NULL;
3458 ctx = ntfs_malloc(sizeof(ntfs_attr_search_ctx));
3459 if (ctx)
3460 ntfs_attr_init_search_ctx(ctx, ni, mrec);
3461 return ctx;
3465 * ntfs_attr_put_search_ctx - release an attribute search context
3466 * @ctx: attribute search context to free
3468 * Release the attribute search context @ctx.
3470 void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
3472 // NOTE: save errno if it could change and function stays void!
3473 free(ctx);
3477 * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file
3478 * @vol: ntfs volume to which the attribute belongs
3479 * @type: attribute type which to find
3481 * Search for the attribute definition record corresponding to the attribute
3482 * @type in the $AttrDef system file.
3484 * Return the attribute type definition record if found and NULL if not found
3485 * or an error occurred. On error the error code is stored in errno. The
3486 * following error codes are defined:
3487 * ENOENT - The attribute @type is not specified in $AttrDef.
3488 * EINVAL - Invalid parameters (e.g. @vol is not valid).
3490 ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
3491 const ATTR_TYPES type)
3493 ATTR_DEF *ad;
3495 if (!vol || !vol->attrdef || !type) {
3496 errno = EINVAL;
3497 ntfs_log_perror("%s: type=%d", __FUNCTION__, type);
3498 return NULL;
3500 for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef <
3501 vol->attrdef_len && ad->type; ++ad) {
3502 /* We haven't found it yet, carry on searching. */
3503 if (le32_to_cpu(ad->type) < le32_to_cpu(type))
3504 continue;
3505 /* We found the attribute; return it. */
3506 if (ad->type == type)
3507 return ad;
3508 /* We have gone too far already. No point in continuing. */
3509 break;
3511 errno = ENOENT;
3512 ntfs_log_perror("%s: type=%d", __FUNCTION__, type);
3513 return NULL;
3517 * ntfs_attr_size_bounds_check - check a size of an attribute type for validity
3518 * @vol: ntfs volume to which the attribute belongs
3519 * @type: attribute type which to check
3520 * @size: size which to check
3522 * Check whether the @size in bytes is valid for an attribute of @type on the
3523 * ntfs volume @vol. This information is obtained from $AttrDef system file.
3525 * Return 0 if valid and -1 if not valid or an error occurred. On error the
3526 * error code is stored in errno. The following error codes are defined:
3527 * ERANGE - @size is not valid for the attribute @type.
3528 * ENOENT - The attribute @type is not specified in $AttrDef.
3529 * EINVAL - Invalid parameters (e.g. @size is < 0 or @vol is not valid).
3531 int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
3532 const s64 size)
3534 ATTR_DEF *ad;
3535 s64 min_size, max_size;
3537 if (size < 0) {
3538 errno = EINVAL;
3539 ntfs_log_perror("%s: size=%lld", __FUNCTION__,
3540 (long long)size);
3541 return -1;
3545 * $ATTRIBUTE_LIST shouldn't be greater than 0x40000, otherwise
3546 * Windows would crash. This is not listed in the AttrDef.
3548 if (type == AT_ATTRIBUTE_LIST && size > 0x40000) {
3549 errno = ERANGE;
3550 ntfs_log_perror("Too large attrlist (%lld)", (long long)size);
3551 return -1;
3554 ad = ntfs_attr_find_in_attrdef(vol, type);
3555 if (!ad)
3556 return -1;
3558 min_size = sle64_to_cpu(ad->min_size);
3559 max_size = sle64_to_cpu(ad->max_size);
3561 /* The $AttrDef generated by Windows specifies 2 as min_size for the
3562 * volume name attribute, but in reality Windows sets it to 0 when
3563 * clearing the volume name. If we want to be able to clear the volume
3564 * name we must also accept 0 as min_size, despite the $AttrDef
3565 * definition. */
3566 if(type == AT_VOLUME_NAME)
3567 min_size = 0;
3569 if ((min_size && (size < min_size)) ||
3570 ((max_size > 0) && (size > max_size))) {
3571 errno = ERANGE;
3572 ntfs_log_perror("Attr type %d size check failed (min,size,max="
3573 "%lld,%lld,%lld)", type, (long long)min_size,
3574 (long long)size, (long long)max_size);
3575 return -1;
3577 return 0;
3581 * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident
3582 * @vol: ntfs volume to which the attribute belongs
3583 * @type: attribute type to check
3584 * @name: attribute name to check
3585 * @name_len: attribute name length
3587 * Check whether the attribute of @type and @name with name length @name_len on
3588 * the ntfs volume @vol is allowed to be non-resident. This information is
3589 * obtained from $AttrDef system file and is augmented by rules imposed by
3590 * Microsoft (e.g. see http://support.microsoft.com/kb/974729/).
3592 * Return 0 if the attribute is allowed to be non-resident and -1 if not or an
3593 * error occurred. On error the error code is stored in errno. The following
3594 * error codes are defined:
3595 * EPERM - The attribute is not allowed to be non-resident.
3596 * ENOENT - The attribute @type is not specified in $AttrDef.
3597 * EINVAL - Invalid parameters (e.g. @vol is not valid).
3599 static int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type,
3600 const ntfschar *name, int name_len)
3602 ATTR_DEF *ad;
3603 BOOL allowed;
3606 * Microsoft has decreed that $LOGGED_UTILITY_STREAM attributes with a
3607 * name of $TXF_DATA must be resident despite the entry for
3608 * $LOGGED_UTILITY_STREAM in $AttrDef allowing them to be non-resident.
3609 * Failure to obey this on the root directory mft record of a volume
3610 * causes Windows Vista and later to see the volume as a RAW volume and
3611 * thus cannot mount it at all.
3613 if ((type == AT_LOGGED_UTILITY_STREAM)
3614 && name
3615 && ntfs_names_are_equal(TXF_DATA, 9, name, name_len,
3616 CASE_SENSITIVE, vol->upcase, vol->upcase_len))
3617 allowed = FALSE;
3618 else {
3619 /* Find the attribute definition record in $AttrDef. */
3620 ad = ntfs_attr_find_in_attrdef(vol, type);
3621 if (!ad)
3622 return -1;
3623 /* Check the flags and return the result. */
3624 allowed = !(ad->flags & ATTR_DEF_RESIDENT);
3626 if (!allowed) {
3627 errno = EPERM;
3628 ntfs_log_trace("Attribute can't be non-resident\n");
3629 return -1;
3631 return 0;
3635 * ntfs_attr_can_be_resident - check if an attribute can be resident
3636 * @vol: ntfs volume to which the attribute belongs
3637 * @type: attribute type which to check
3639 * Check whether the attribute of @type on the ntfs volume @vol is allowed to
3640 * be resident. This information is derived from our ntfs knowledge and may
3641 * not be completely accurate, especially when user defined attributes are
3642 * present. Basically we allow everything to be resident except for index
3643 * allocation and extended attribute attributes.
3645 * Return 0 if the attribute is allowed to be resident and -1 if not or an
3646 * error occurred. On error the error code is stored in errno. The following
3647 * error codes are defined:
3648 * EPERM - The attribute is not allowed to be resident.
3649 * EINVAL - Invalid parameters (e.g. @vol is not valid).
3651 * Warning: In the system file $MFT the attribute $Bitmap must be non-resident
3652 * otherwise windows will not boot (blue screen of death)! We cannot
3653 * check for this here as we don't know which inode's $Bitmap is being
3654 * asked about so the caller needs to special case this.
3656 int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPES type)
3658 if (!vol || !vol->attrdef || !type) {
3659 errno = EINVAL;
3660 return -1;
3662 if (type != AT_INDEX_ALLOCATION)
3663 return 0;
3665 ntfs_log_trace("Attribute can't be resident\n");
3666 errno = EPERM;
3667 return -1;
3671 * ntfs_make_room_for_attr - make room for an attribute inside an mft record
3672 * @m: mft record
3673 * @pos: position at which to make space
3674 * @size: byte size to make available at this position
3676 * @pos points to the attribute in front of which we want to make space.
3678 * Return 0 on success or -1 on error. On error the error code is stored in
3679 * errno. Possible error codes are:
3680 * ENOSPC - There is not enough space available to complete operation. The
3681 * caller has to make space before calling this.
3682 * EINVAL - Input parameters were faulty.
3684 int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size)
3686 u32 biu;
3688 ntfs_log_trace("Entering for pos 0x%d, size %u.\n",
3689 (int)(pos - (u8*)m), (unsigned) size);
3691 /* Make size 8-byte alignment. */
3692 size = (size + 7) & ~7;
3694 /* Rigorous consistency checks. */
3695 if (!m || !pos || pos < (u8*)m) {
3696 errno = EINVAL;
3697 ntfs_log_perror("%s: pos=%p m=%p", __FUNCTION__, pos, m);
3698 return -1;
3700 /* The -8 is for the attribute terminator. */
3701 if (pos - (u8*)m > (int)le32_to_cpu(m->bytes_in_use) - 8) {
3702 errno = EINVAL;
3703 return -1;
3705 /* Nothing to do. */
3706 if (!size)
3707 return 0;
3709 biu = le32_to_cpu(m->bytes_in_use);
3710 /* Do we have enough space? */
3711 if (biu + size > le32_to_cpu(m->bytes_allocated) ||
3712 pos + size > (u8*)m + le32_to_cpu(m->bytes_allocated)) {
3713 errno = ENOSPC;
3714 ntfs_log_trace("No enough space in the MFT record\n");
3715 return -1;
3717 /* Move everything after pos to pos + size. */
3718 memmove(pos + size, pos, biu - (pos - (u8*)m));
3719 /* Update mft record. */
3720 m->bytes_in_use = cpu_to_le32(biu + size);
3721 return 0;
3725 * ntfs_resident_attr_record_add - add resident attribute to inode
3726 * @ni: opened ntfs inode to which MFT record add attribute
3727 * @type: type of the new attribute
3728 * @name: name of the new attribute
3729 * @name_len: name length of the new attribute
3730 * @val: value of the new attribute
3731 * @size: size of new attribute (length of @val, if @val != NULL)
3732 * @flags: flags of the new attribute
3734 * Return offset to attribute from the beginning of the mft record on success
3735 * and -1 on error. On error the error code is stored in errno.
3736 * Possible error codes are:
3737 * EINVAL - Invalid arguments passed to function.
3738 * EEXIST - Attribute of such type and with same name already exists.
3739 * EIO - I/O error occurred or damaged filesystem.
3741 int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
3742 const ntfschar *name, u8 name_len, const u8 *val,
3743 u32 size, ATTR_FLAGS data_flags)
3745 ntfs_attr_search_ctx *ctx;
3746 u32 length;
3747 ATTR_RECORD *a;
3748 MFT_RECORD *m;
3749 int err, offset;
3750 ntfs_inode *base_ni;
3752 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, flags 0x%x.\n",
3753 (long long) ni->mft_no, (unsigned) type, (unsigned) data_flags);
3755 if (!ni || (!name && name_len)) {
3756 errno = EINVAL;
3757 return -1;
3760 if (ntfs_attr_can_be_resident(ni->vol, type)) {
3761 if (errno == EPERM)
3762 ntfs_log_trace("Attribute can't be resident.\n");
3763 else
3764 ntfs_log_trace("ntfs_attr_can_be_resident failed.\n");
3765 return -1;
3768 /* Locate place where record should be. */
3769 ctx = ntfs_attr_get_search_ctx(ni, NULL);
3770 if (!ctx)
3771 return -1;
3773 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
3774 * attribute in @ni->mrec, not any extent inode in case if @ni is base
3775 * file record.
3777 if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, val, size,
3778 ctx)) {
3779 err = EEXIST;
3780 ntfs_log_trace("Attribute already present.\n");
3781 goto put_err_out;
3783 if (errno != ENOENT) {
3784 err = EIO;
3785 goto put_err_out;
3787 a = ctx->attr;
3788 m = ctx->mrec;
3790 /* Make room for attribute. */
3791 length = offsetof(ATTR_RECORD, resident_end) +
3792 ((name_len * sizeof(ntfschar) + 7) & ~7) +
3793 ((size + 7) & ~7);
3794 if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) {
3795 err = errno;
3796 ntfs_log_trace("Failed to make room for attribute.\n");
3797 goto put_err_out;
3800 /* Setup record fields. */
3801 offset = ((u8*)a - (u8*)m);
3802 a->type = type;
3803 a->length = cpu_to_le32(length);
3804 a->non_resident = 0;
3805 a->name_length = name_len;
3806 a->name_offset = (name_len
3807 ? cpu_to_le16(offsetof(ATTR_RECORD, resident_end))
3808 : const_cpu_to_le16(0));
3809 a->flags = data_flags;
3810 a->instance = m->next_attr_instance;
3811 a->value_length = cpu_to_le32(size);
3812 a->value_offset = cpu_to_le16(length - ((size + 7) & ~7));
3813 if (val)
3814 memcpy((u8*)a + le16_to_cpu(a->value_offset), val, size);
3815 else
3816 memset((u8*)a + le16_to_cpu(a->value_offset), 0, size);
3817 if (type == AT_FILE_NAME)
3818 a->resident_flags = RESIDENT_ATTR_IS_INDEXED;
3819 else
3820 a->resident_flags = 0;
3821 if (name_len)
3822 memcpy((u8*)a + le16_to_cpu(a->name_offset),
3823 name, sizeof(ntfschar) * name_len);
3824 m->next_attr_instance =
3825 cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
3826 if (ni->nr_extents == -1)
3827 base_ni = ni->base_ni;
3828 else
3829 base_ni = ni;
3830 if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
3831 if (ntfs_attrlist_entry_add(ni, a)) {
3832 err = errno;
3833 ntfs_attr_record_resize(m, a, 0);
3834 ntfs_log_trace("Failed add attribute entry to "
3835 "ATTRIBUTE_LIST.\n");
3836 goto put_err_out;
3839 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
3840 ? type == AT_INDEX_ROOT && name == NTFS_INDEX_I30
3841 : type == AT_DATA && name == AT_UNNAMED) {
3842 ni->data_size = size;
3843 ni->allocated_size = (size + 7) & ~7;
3844 set_nino_flag(ni,KnownSize);
3846 ntfs_inode_mark_dirty(ni);
3847 ntfs_attr_put_search_ctx(ctx);
3848 return offset;
3849 put_err_out:
3850 ntfs_attr_put_search_ctx(ctx);
3851 errno = err;
3852 return -1;
3856 * ntfs_non_resident_attr_record_add - add extent of non-resident attribute
3857 * @ni: opened ntfs inode to which MFT record add attribute
3858 * @type: type of the new attribute extent
3859 * @name: name of the new attribute extent
3860 * @name_len: name length of the new attribute extent
3861 * @lowest_vcn: lowest vcn of the new attribute extent
3862 * @dataruns_size: dataruns size of the new attribute extent
3863 * @flags: flags of the new attribute extent
3865 * Return offset to attribute from the beginning of the mft record on success
3866 * and -1 on error. On error the error code is stored in errno.
3867 * Possible error codes are:
3868 * EINVAL - Invalid arguments passed to function.
3869 * EEXIST - Attribute of such type, with same lowest vcn and with same
3870 * name already exists.
3871 * EIO - I/O error occurred or damaged filesystem.
3873 int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
3874 const ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
3875 ATTR_FLAGS flags)
3877 ntfs_attr_search_ctx *ctx;
3878 u32 length;
3879 ATTR_RECORD *a;
3880 MFT_RECORD *m;
3881 ntfs_inode *base_ni;
3882 int err, offset;
3884 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld, "
3885 "dataruns_size %d, flags 0x%x.\n",
3886 (long long) ni->mft_no, (unsigned) type,
3887 (long long) lowest_vcn, dataruns_size, (unsigned) flags);
3889 if (!ni || dataruns_size <= 0 || (!name && name_len)) {
3890 errno = EINVAL;
3891 return -1;
3894 if (ntfs_attr_can_be_non_resident(ni->vol, type, name, name_len)) {
3895 if (errno == EPERM)
3896 ntfs_log_perror("Attribute can't be non resident");
3897 else
3898 ntfs_log_perror("ntfs_attr_can_be_non_resident failed");
3899 return -1;
3902 /* Locate place where record should be. */
3903 ctx = ntfs_attr_get_search_ctx(ni, NULL);
3904 if (!ctx)
3905 return -1;
3907 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
3908 * attribute in @ni->mrec, not any extent inode in case if @ni is base
3909 * file record.
3911 if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, NULL, 0,
3912 ctx)) {
3913 err = EEXIST;
3914 ntfs_log_perror("Attribute 0x%x already present", type);
3915 goto put_err_out;
3917 if (errno != ENOENT) {
3918 ntfs_log_perror("ntfs_attr_find failed");
3919 err = EIO;
3920 goto put_err_out;
3922 a = ctx->attr;
3923 m = ctx->mrec;
3925 /* Make room for attribute. */
3926 dataruns_size = (dataruns_size + 7) & ~7;
3927 length = offsetof(ATTR_RECORD, compressed_size) + ((sizeof(ntfschar) *
3928 name_len + 7) & ~7) + dataruns_size +
3929 ((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ?
3930 sizeof(a->compressed_size) : 0);
3931 if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) {
3932 err = errno;
3933 ntfs_log_perror("Failed to make room for attribute");
3934 goto put_err_out;
3937 /* Setup record fields. */
3938 a->type = type;
3939 a->length = cpu_to_le32(length);
3940 a->non_resident = 1;
3941 a->name_length = name_len;
3942 a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, compressed_size) +
3943 ((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ?
3944 sizeof(a->compressed_size) : 0));
3945 a->flags = flags;
3946 a->instance = m->next_attr_instance;
3947 a->lowest_vcn = cpu_to_sle64(lowest_vcn);
3948 a->mapping_pairs_offset = cpu_to_le16(length - dataruns_size);
3949 a->compression_unit = (flags & ATTR_IS_COMPRESSED)
3950 ? STANDARD_COMPRESSION_UNIT : 0;
3951 /* If @lowest_vcn == 0, than setup empty attribute. */
3952 if (!lowest_vcn) {
3953 a->highest_vcn = cpu_to_sle64(-1);
3954 a->allocated_size = 0;
3955 a->data_size = 0;
3956 a->initialized_size = 0;
3957 /* Set empty mapping pairs. */
3958 *((u8*)a + le16_to_cpu(a->mapping_pairs_offset)) = 0;
3960 if (name_len)
3961 memcpy((u8*)a + le16_to_cpu(a->name_offset),
3962 name, sizeof(ntfschar) * name_len);
3963 m->next_attr_instance =
3964 cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
3965 if (ni->nr_extents == -1)
3966 base_ni = ni->base_ni;
3967 else
3968 base_ni = ni;
3969 if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
3970 if (ntfs_attrlist_entry_add(ni, a)) {
3971 err = errno;
3972 ntfs_log_perror("Failed add attr entry to attrlist");
3973 ntfs_attr_record_resize(m, a, 0);
3974 goto put_err_out;
3977 ntfs_inode_mark_dirty(ni);
3979 * Locate offset from start of the MFT record where new attribute is
3980 * placed. We need relookup it, because record maybe moved during
3981 * update of attribute list.
3983 ntfs_attr_reinit_search_ctx(ctx);
3984 if (ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE,
3985 lowest_vcn, NULL, 0, ctx)) {
3986 ntfs_log_perror("%s: attribute lookup failed", __FUNCTION__);
3987 ntfs_attr_put_search_ctx(ctx);
3988 return -1;
3991 offset = (u8*)ctx->attr - (u8*)ctx->mrec;
3992 ntfs_attr_put_search_ctx(ctx);
3993 return offset;
3994 put_err_out:
3995 ntfs_attr_put_search_ctx(ctx);
3996 errno = err;
3997 return -1;
4001 * ntfs_attr_record_rm - remove attribute extent
4002 * @ctx: search context describing the attribute which should be removed
4004 * If this function succeed, user should reinit search context if he/she wants
4005 * use it anymore.
4007 * Return 0 on success and -1 on error. On error the error code is stored in
4008 * errno. Possible error codes are:
4009 * EINVAL - Invalid arguments passed to function.
4010 * EIO - I/O error occurred or damaged filesystem.
4012 int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx)
4014 ntfs_inode *base_ni, *ni;
4015 ATTR_TYPES type;
4017 if (!ctx || !ctx->ntfs_ino || !ctx->mrec || !ctx->attr) {
4018 errno = EINVAL;
4019 return -1;
4022 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
4023 (long long) ctx->ntfs_ino->mft_no,
4024 (unsigned) le32_to_cpu(ctx->attr->type));
4025 type = ctx->attr->type;
4026 ni = ctx->ntfs_ino;
4027 if (ctx->base_ntfs_ino)
4028 base_ni = ctx->base_ntfs_ino;
4029 else
4030 base_ni = ctx->ntfs_ino;
4032 /* Remove attribute itself. */
4033 if (ntfs_attr_record_resize(ctx->mrec, ctx->attr, 0)) {
4034 ntfs_log_trace("Couldn't remove attribute record. Bug or damaged MFT "
4035 "record.\n");
4036 if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST)
4037 if (ntfs_attrlist_entry_add(ni, ctx->attr))
4038 ntfs_log_trace("Rollback failed. Leaving inconstant "
4039 "metadata.\n");
4040 errno = EIO;
4041 return -1;
4043 ntfs_inode_mark_dirty(ni);
4046 * Remove record from $ATTRIBUTE_LIST if present and we don't want
4047 * delete $ATTRIBUTE_LIST itself.
4049 if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) {
4050 if (ntfs_attrlist_entry_rm(ctx)) {
4051 ntfs_log_trace("Couldn't delete record from "
4052 "$ATTRIBUTE_LIST.\n");
4053 return -1;
4057 /* Post $ATTRIBUTE_LIST delete setup. */
4058 if (type == AT_ATTRIBUTE_LIST) {
4059 if (NInoAttrList(base_ni) && base_ni->attr_list)
4060 free(base_ni->attr_list);
4061 base_ni->attr_list = NULL;
4062 NInoClearAttrList(base_ni);
4063 NInoAttrListClearDirty(base_ni);
4066 /* Free MFT record, if it doesn't contain attributes. */
4067 if (le32_to_cpu(ctx->mrec->bytes_in_use) -
4068 le16_to_cpu(ctx->mrec->attrs_offset) == 8) {
4069 if (ntfs_mft_record_free(ni->vol, ni)) {
4070 // FIXME: We need rollback here.
4071 ntfs_log_trace("Couldn't free MFT record.\n");
4072 errno = EIO;
4073 return -1;
4075 /* Remove done if we freed base inode. */
4076 if (ni == base_ni)
4077 return 0;
4080 if (type == AT_ATTRIBUTE_LIST || !NInoAttrList(base_ni))
4081 return 0;
4083 /* Remove attribute list if we don't need it any more. */
4084 if (!ntfs_attrlist_need(base_ni)) {
4085 ntfs_attr_reinit_search_ctx(ctx);
4086 if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, CASE_SENSITIVE,
4087 0, NULL, 0, ctx)) {
4089 * FIXME: Should we succeed here? Definitely something
4090 * goes wrong because NInoAttrList(base_ni) returned
4091 * that we have got attribute list.
4093 ntfs_log_trace("Couldn't find attribute list. Succeed "
4094 "anyway.\n");
4095 return 0;
4097 /* Deallocate clusters. */
4098 if (ctx->attr->non_resident) {
4099 runlist *al_rl;
4101 al_rl = ntfs_mapping_pairs_decompress(base_ni->vol,
4102 ctx->attr, NULL);
4103 if (!al_rl) {
4104 ntfs_log_trace("Couldn't decompress attribute list "
4105 "runlist. Succeed anyway.\n");
4106 return 0;
4108 if (ntfs_cluster_free_from_rl(base_ni->vol, al_rl)) {
4109 ntfs_log_trace("Leaking clusters! Run chkdsk. "
4110 "Couldn't free clusters from "
4111 "attribute list runlist.\n");
4113 free(al_rl);
4115 /* Remove attribute record itself. */
4116 if (ntfs_attr_record_rm(ctx)) {
4118 * FIXME: Should we succeed here? BTW, chkdsk doesn't
4119 * complain if it find MFT record with attribute list,
4120 * but without extents.
4122 ntfs_log_trace("Couldn't remove attribute list. Succeed "
4123 "anyway.\n");
4124 return 0;
4127 return 0;
4131 * ntfs_attr_add - add attribute to inode
4132 * @ni: opened ntfs inode to which add attribute
4133 * @type: type of the new attribute
4134 * @name: name in unicode of the new attribute
4135 * @name_len: name length in unicode characters of the new attribute
4136 * @val: value of new attribute
4137 * @size: size of the new attribute / length of @val (if specified)
4139 * @val should always be specified for always resident attributes (eg. FILE_NAME
4140 * attribute), for attributes that can become non-resident @val can be NULL
4141 * (eg. DATA attribute). @size can be specified even if @val is NULL, in this
4142 * case data size will be equal to @size and initialized size will be equal
4143 * to 0.
4145 * If inode haven't got enough space to add attribute, add attribute to one of
4146 * it extents, if no extents present or no one of them have enough space, than
4147 * allocate new extent and add attribute to it.
4149 * If on one of this steps attribute list is needed but not present, than it is
4150 * added transparently to caller. So, this function should not be called with
4151 * @type == AT_ATTRIBUTE_LIST, if you really need to add attribute list call
4152 * ntfs_inode_add_attrlist instead.
4154 * On success return 0. On error return -1 with errno set to the error code.
4156 int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
4157 ntfschar *name, u8 name_len, const u8 *val, s64 size)
4159 u32 attr_rec_size;
4160 int err, i, offset;
4161 BOOL is_resident;
4162 BOOL can_be_non_resident = FALSE;
4163 ntfs_inode *attr_ni;
4164 ntfs_attr *na;
4165 ATTR_FLAGS data_flags;
4167 if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) {
4168 errno = EINVAL;
4169 ntfs_log_perror("%s: ni=%p size=%lld", __FUNCTION__, ni,
4170 (long long)size);
4171 return -1;
4174 ntfs_log_trace("Entering for inode %lld, attr %x, size %lld.\n",
4175 (long long)ni->mft_no, type, (long long)size);
4177 if (ni->nr_extents == -1)
4178 ni = ni->base_ni;
4180 /* Check the attribute type and the size. */
4181 if (ntfs_attr_size_bounds_check(ni->vol, type, size)) {
4182 if (errno == ENOENT)
4183 errno = EIO;
4184 return -1;
4187 /* Sanity checks for always resident attributes. */
4188 if (ntfs_attr_can_be_non_resident(ni->vol, type, name, name_len)) {
4189 if (errno != EPERM) {
4190 err = errno;
4191 ntfs_log_perror("ntfs_attr_can_be_non_resident failed");
4192 goto err_out;
4194 /* @val is mandatory. */
4195 if (!val) {
4196 errno = EINVAL;
4197 ntfs_log_perror("val is mandatory for always resident "
4198 "attributes");
4199 return -1;
4201 if (size > ni->vol->mft_record_size) {
4202 errno = ERANGE;
4203 ntfs_log_perror("Attribute is too big");
4204 return -1;
4206 } else
4207 can_be_non_resident = TRUE;
4210 * Determine resident or not will be new attribute. We add 8 to size in
4211 * non resident case for mapping pairs.
4213 if (!ntfs_attr_can_be_resident(ni->vol, type)) {
4214 is_resident = TRUE;
4215 } else {
4216 if (errno != EPERM) {
4217 err = errno;
4218 ntfs_log_perror("ntfs_attr_can_be_resident failed");
4219 goto err_out;
4221 is_resident = FALSE;
4223 /* Calculate attribute record size. */
4224 if (is_resident)
4225 attr_rec_size = offsetof(ATTR_RECORD, resident_end) +
4226 ((name_len * sizeof(ntfschar) + 7) & ~7) +
4227 ((size + 7) & ~7);
4228 else
4229 attr_rec_size = offsetof(ATTR_RECORD, non_resident_end) +
4230 ((name_len * sizeof(ntfschar) + 7) & ~7) + 8;
4233 * If we have enough free space for the new attribute in the base MFT
4234 * record, then add attribute to it.
4236 if (le32_to_cpu(ni->mrec->bytes_allocated) -
4237 le32_to_cpu(ni->mrec->bytes_in_use) >= attr_rec_size) {
4238 attr_ni = ni;
4239 goto add_attr_record;
4242 /* Try to add to extent inodes. */
4243 if (ntfs_inode_attach_all_extents(ni)) {
4244 err = errno;
4245 ntfs_log_perror("Failed to attach all extents to inode");
4246 goto err_out;
4248 for (i = 0; i < ni->nr_extents; i++) {
4249 attr_ni = ni->extent_nis[i];
4250 if (le32_to_cpu(attr_ni->mrec->bytes_allocated) -
4251 le32_to_cpu(attr_ni->mrec->bytes_in_use) >=
4252 attr_rec_size)
4253 goto add_attr_record;
4256 /* There is no extent that contain enough space for new attribute. */
4257 if (!NInoAttrList(ni)) {
4258 /* Add attribute list not present, add it and retry. */
4259 if (ntfs_inode_add_attrlist(ni)) {
4260 err = errno;
4261 ntfs_log_perror("Failed to add attribute list");
4262 goto err_out;
4264 return ntfs_attr_add(ni, type, name, name_len, val, size);
4266 /* Allocate new extent. */
4267 attr_ni = ntfs_mft_record_alloc(ni->vol, ni);
4268 if (!attr_ni) {
4269 err = errno;
4270 ntfs_log_perror("Failed to allocate extent record");
4271 goto err_out;
4274 add_attr_record:
4275 if ((ni->flags & FILE_ATTR_COMPRESSED)
4276 && (ni->vol->major_ver >= 3)
4277 && NVolCompression(ni->vol)
4278 && (ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
4279 && ((type == AT_DATA)
4280 || ((type == AT_INDEX_ROOT) && (name == NTFS_INDEX_I30))))
4281 data_flags = ATTR_IS_COMPRESSED;
4282 else
4283 data_flags = const_cpu_to_le16(0);
4284 if (is_resident) {
4285 /* Add resident attribute. */
4286 offset = ntfs_resident_attr_record_add(attr_ni, type, name,
4287 name_len, val, size, data_flags);
4288 if (offset < 0) {
4289 if (errno == ENOSPC && can_be_non_resident)
4290 goto add_non_resident;
4291 err = errno;
4292 ntfs_log_perror("Failed to add resident attribute");
4293 goto free_err_out;
4295 return 0;
4298 add_non_resident:
4299 /* Add non resident attribute. */
4300 offset = ntfs_non_resident_attr_record_add(attr_ni, type, name,
4301 name_len, 0, 8, data_flags);
4302 if (offset < 0) {
4303 err = errno;
4304 ntfs_log_perror("Failed to add non resident attribute");
4305 goto free_err_out;
4308 /* If @size == 0, we are done. */
4309 if (!size)
4310 return 0;
4312 /* Open new attribute and resize it. */
4313 na = ntfs_attr_open(ni, type, name, name_len);
4314 if (!na) {
4315 err = errno;
4316 ntfs_log_perror("Failed to open just added attribute");
4317 goto rm_attr_err_out;
4319 /* Resize and set attribute value. */
4320 if (ntfs_attr_truncate_i(na, size, HOLES_OK) ||
4321 (val && (ntfs_attr_pwrite(na, 0, size, val) != size))) {
4322 err = errno;
4323 ntfs_log_perror("Failed to initialize just added attribute");
4324 if (ntfs_attr_rm(na))
4325 ntfs_log_perror("Failed to remove just added attribute");
4326 ntfs_attr_close(na);
4327 goto err_out;
4329 ntfs_attr_close(na);
4330 return 0;
4332 rm_attr_err_out:
4333 /* Remove just added attribute. */
4334 if (ntfs_attr_record_resize(attr_ni->mrec,
4335 (ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0))
4336 ntfs_log_perror("Failed to remove just added attribute #2");
4337 free_err_out:
4338 /* Free MFT record, if it doesn't contain attributes. */
4339 if (le32_to_cpu(attr_ni->mrec->bytes_in_use) -
4340 le16_to_cpu(attr_ni->mrec->attrs_offset) == 8)
4341 if (ntfs_mft_record_free(attr_ni->vol, attr_ni))
4342 ntfs_log_perror("Failed to free MFT record");
4343 err_out:
4344 errno = err;
4345 return -1;
4349 * Change an attribute flag
4352 int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, const ntfschar *name,
4353 u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask)
4355 ntfs_attr_search_ctx *ctx;
4356 int res;
4358 res = -1;
4359 /* Search for designated attribute */
4360 ctx = ntfs_attr_get_search_ctx(ni, NULL);
4361 if (ctx) {
4362 if (!ntfs_attr_lookup(type, name, name_len,
4363 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
4364 /* do the requested change (all small endian le16) */
4365 ctx->attr->flags = (ctx->attr->flags & ~mask)
4366 | (flags & mask);
4367 NInoSetDirty(ni);
4368 res = 0;
4370 ntfs_attr_put_search_ctx(ctx);
4372 return (res);
4377 * ntfs_attr_rm - remove attribute from ntfs inode
4378 * @na: opened ntfs attribute to delete
4380 * Remove attribute and all it's extents from ntfs inode. If attribute was non
4381 * resident also free all clusters allocated by attribute.
4383 * Return 0 on success or -1 on error with errno set to the error code.
4385 int ntfs_attr_rm(ntfs_attr *na)
4387 ntfs_attr_search_ctx *ctx;
4388 int ret = 0;
4390 if (!na) {
4391 ntfs_log_trace("Invalid arguments passed.\n");
4392 errno = EINVAL;
4393 return -1;
4396 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
4397 (long long) na->ni->mft_no, na->type);
4399 /* Free cluster allocation. */
4400 if (NAttrNonResident(na)) {
4401 if (ntfs_attr_map_whole_runlist(na))
4402 return -1;
4403 if (ntfs_cluster_free(na->ni->vol, na, 0, -1) < 0) {
4404 ntfs_log_trace("Failed to free cluster allocation. Leaving "
4405 "inconstant metadata.\n");
4406 ret = -1;
4410 /* Search for attribute extents and remove them all. */
4411 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
4412 if (!ctx)
4413 return -1;
4414 while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
4415 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
4416 if (ntfs_attr_record_rm(ctx)) {
4417 ntfs_log_trace("Failed to remove attribute extent. Leaving "
4418 "inconstant metadata.\n");
4419 ret = -1;
4421 ntfs_attr_reinit_search_ctx(ctx);
4423 ntfs_attr_put_search_ctx(ctx);
4424 if (errno != ENOENT) {
4425 ntfs_log_trace("Attribute lookup failed. Probably leaving inconstant "
4426 "metadata.\n");
4427 ret = -1;
4430 return ret;
4434 * ntfs_attr_record_resize - resize an attribute record
4435 * @m: mft record containing attribute record
4436 * @a: attribute record to resize
4437 * @new_size: new size in bytes to which to resize the attribute record @a
4439 * Resize the attribute record @a, i.e. the resident part of the attribute, in
4440 * the mft record @m to @new_size bytes.
4442 * Return 0 on success and -1 on error with errno set to the error code.
4443 * The following error codes are defined:
4444 * ENOSPC - Not enough space in the mft record @m to perform the resize.
4445 * Note that on error no modifications have been performed whatsoever.
4447 * Warning: If you make a record smaller without having copied all the data you
4448 * are interested in the data may be overwritten!
4450 int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
4452 u32 old_size, alloc_size, attr_size;
4454 old_size = le32_to_cpu(m->bytes_in_use);
4455 alloc_size = le32_to_cpu(m->bytes_allocated);
4456 attr_size = le32_to_cpu(a->length);
4458 ntfs_log_trace("Sizes: old=%u alloc=%u attr=%u new=%u\n",
4459 (unsigned)old_size, (unsigned)alloc_size,
4460 (unsigned)attr_size, (unsigned)new_size);
4462 /* Align to 8 bytes, just in case the caller hasn't. */
4463 new_size = (new_size + 7) & ~7;
4465 /* If the actual attribute length has changed, move things around. */
4466 if (new_size != attr_size) {
4468 u32 new_muse = old_size - attr_size + new_size;
4470 /* Not enough space in this mft record. */
4471 if (new_muse > alloc_size) {
4472 errno = ENOSPC;
4473 ntfs_log_trace("Not enough space in the MFT record "
4474 "(%u > %u)\n", new_muse, alloc_size);
4475 return -1;
4478 if (a->type == AT_INDEX_ROOT && new_size > attr_size &&
4479 new_muse + 120 > alloc_size && old_size + 120 <= alloc_size) {
4480 errno = ENOSPC;
4481 ntfs_log_trace("Too big INDEX_ROOT (%u > %u)\n",
4482 new_muse, alloc_size);
4483 return STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT;
4486 /* Move attributes following @a to their new location. */
4487 memmove((u8 *)a + new_size, (u8 *)a + attr_size,
4488 old_size - ((u8 *)a - (u8 *)m) - attr_size);
4490 /* Adjust @m to reflect the change in used space. */
4491 m->bytes_in_use = cpu_to_le32(new_muse);
4493 /* Adjust @a to reflect the new size. */
4494 if (new_size >= offsetof(ATTR_REC, length) + sizeof(a->length))
4495 a->length = cpu_to_le32(new_size);
4497 return 0;
4501 * ntfs_resident_attr_value_resize - resize the value of a resident attribute
4502 * @m: mft record containing attribute record
4503 * @a: attribute record whose value to resize
4504 * @new_size: new size in bytes to which to resize the attribute value of @a
4506 * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
4507 * If the value is made bigger, the newly "allocated" space is cleared.
4509 * Return 0 on success and -1 on error with errno set to the error code.
4510 * The following error codes are defined:
4511 * ENOSPC - Not enough space in the mft record @m to perform the resize.
4512 * Note that on error no modifications have been performed whatsoever.
4514 int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
4515 const u32 new_size)
4517 int ret;
4519 ntfs_log_trace("Entering for new size %u.\n", (unsigned)new_size);
4521 /* Resize the resident part of the attribute record. */
4522 if ((ret = ntfs_attr_record_resize(m, a, (le16_to_cpu(a->value_offset) +
4523 new_size + 7) & ~7)) < 0)
4524 return ret;
4526 * If we made the attribute value bigger, clear the area between the
4527 * old size and @new_size.
4529 if (new_size > le32_to_cpu(a->value_length))
4530 memset((u8*)a + le16_to_cpu(a->value_offset) +
4531 le32_to_cpu(a->value_length), 0, new_size -
4532 le32_to_cpu(a->value_length));
4533 /* Finally update the length of the attribute value. */
4534 a->value_length = cpu_to_le32(new_size);
4535 return 0;
4539 * ntfs_attr_record_move_to - move attribute record to target inode
4540 * @ctx: attribute search context describing the attribute record
4541 * @ni: opened ntfs inode to which move attribute record
4543 * If this function succeed, user should reinit search context if he/she wants
4544 * use it anymore.
4546 * Return 0 on success and -1 on error with errno set to the error code.
4548 int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni)
4550 ntfs_attr_search_ctx *nctx;
4551 ATTR_RECORD *a;
4552 int err;
4554 if (!ctx || !ctx->attr || !ctx->ntfs_ino || !ni) {
4555 ntfs_log_trace("Invalid arguments passed.\n");
4556 errno = EINVAL;
4557 return -1;
4560 ntfs_log_trace("Entering for ctx->attr->type 0x%x, ctx->ntfs_ino->mft_no "
4561 "0x%llx, ni->mft_no 0x%llx.\n",
4562 (unsigned) le32_to_cpu(ctx->attr->type),
4563 (long long) ctx->ntfs_ino->mft_no,
4564 (long long) ni->mft_no);
4566 if (ctx->ntfs_ino == ni)
4567 return 0;
4569 if (!ctx->al_entry) {
4570 ntfs_log_trace("Inode should contain attribute list to use this "
4571 "function.\n");
4572 errno = EINVAL;
4573 return -1;
4576 /* Find place in MFT record where attribute will be moved. */
4577 a = ctx->attr;
4578 nctx = ntfs_attr_get_search_ctx(ni, NULL);
4579 if (!nctx)
4580 return -1;
4583 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
4584 * attribute in @ni->mrec, not any extent inode in case if @ni is base
4585 * file record.
4587 if (!ntfs_attr_find(a->type, (ntfschar*)((u8*)a + le16_to_cpu(
4588 a->name_offset)), a->name_length, CASE_SENSITIVE, NULL,
4589 0, nctx)) {
4590 ntfs_log_trace("Attribute of such type, with same name already "
4591 "present in this MFT record.\n");
4592 err = EEXIST;
4593 goto put_err_out;
4595 if (errno != ENOENT) {
4596 err = errno;
4597 ntfs_log_debug("Attribute lookup failed.\n");
4598 goto put_err_out;
4601 /* Make space and move attribute. */
4602 if (ntfs_make_room_for_attr(ni->mrec, (u8*) nctx->attr,
4603 le32_to_cpu(a->length))) {
4604 err = errno;
4605 ntfs_log_trace("Couldn't make space for attribute.\n");
4606 goto put_err_out;
4608 memcpy(nctx->attr, a, le32_to_cpu(a->length));
4609 nctx->attr->instance = nctx->mrec->next_attr_instance;
4610 nctx->mrec->next_attr_instance = cpu_to_le16(
4611 (le16_to_cpu(nctx->mrec->next_attr_instance) + 1) & 0xffff);
4612 ntfs_attr_record_resize(ctx->mrec, a, 0);
4613 ntfs_inode_mark_dirty(ctx->ntfs_ino);
4614 ntfs_inode_mark_dirty(ni);
4616 /* Update attribute list. */
4617 ctx->al_entry->mft_reference =
4618 MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number));
4619 ctx->al_entry->instance = nctx->attr->instance;
4620 ntfs_attrlist_mark_dirty(ni);
4622 ntfs_attr_put_search_ctx(nctx);
4623 return 0;
4624 put_err_out:
4625 ntfs_attr_put_search_ctx(nctx);
4626 errno = err;
4627 return -1;
4631 * ntfs_attr_record_move_away - move away attribute record from it's mft record
4632 * @ctx: attribute search context describing the attribute record
4633 * @extra: minimum amount of free space in the new holder of record
4635 * New attribute record holder must have free @extra bytes after moving
4636 * attribute record to it.
4638 * If this function succeed, user should reinit search context if he/she wants
4639 * use it anymore.
4641 * Return 0 on success and -1 on error with errno set to the error code.
4643 int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra)
4645 ntfs_inode *base_ni, *ni;
4646 MFT_RECORD *m;
4647 int i;
4649 if (!ctx || !ctx->attr || !ctx->ntfs_ino || extra < 0) {
4650 errno = EINVAL;
4651 ntfs_log_perror("%s: ctx=%p ctx->attr=%p extra=%d", __FUNCTION__,
4652 ctx, ctx ? ctx->attr : NULL, extra);
4653 return -1;
4656 ntfs_log_trace("Entering for attr 0x%x, inode %llu\n",
4657 (unsigned) le32_to_cpu(ctx->attr->type),
4658 (unsigned long long)ctx->ntfs_ino->mft_no);
4660 if (ctx->ntfs_ino->nr_extents == -1)
4661 base_ni = ctx->base_ntfs_ino;
4662 else
4663 base_ni = ctx->ntfs_ino;
4665 if (!NInoAttrList(base_ni)) {
4666 errno = EINVAL;
4667 ntfs_log_perror("Inode %llu has no attrlist",
4668 (unsigned long long)base_ni->mft_no);
4669 return -1;
4672 if (ntfs_inode_attach_all_extents(ctx->ntfs_ino)) {
4673 ntfs_log_perror("Couldn't attach extents, inode=%llu",
4674 (unsigned long long)base_ni->mft_no);
4675 return -1;
4678 /* Walk through all extents and try to move attribute to them. */
4679 for (i = 0; i < base_ni->nr_extents; i++) {
4680 ni = base_ni->extent_nis[i];
4681 m = ni->mrec;
4683 if (ctx->ntfs_ino->mft_no == ni->mft_no)
4684 continue;
4686 if (le32_to_cpu(m->bytes_allocated) -
4687 le32_to_cpu(m->bytes_in_use) <
4688 le32_to_cpu(ctx->attr->length) + extra)
4689 continue;
4692 * ntfs_attr_record_move_to can fail if extent with other lowest
4693 * VCN already present in inode we trying move record to. So,
4694 * do not return error.
4696 if (!ntfs_attr_record_move_to(ctx, ni))
4697 return 0;
4701 * Failed to move attribute to one of the current extents, so allocate
4702 * new extent and move attribute to it.
4704 ni = ntfs_mft_record_alloc(base_ni->vol, base_ni);
4705 if (!ni) {
4706 ntfs_log_perror("Couldn't allocate MFT record");
4707 return -1;
4709 if (ntfs_attr_record_move_to(ctx, ni)) {
4710 ntfs_log_perror("Couldn't move attribute to MFT record");
4711 return -1;
4713 return 0;
4717 * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
4718 * @na: open ntfs attribute to make non-resident
4719 * @ctx: ntfs search context describing the attribute
4721 * Convert a resident ntfs attribute to a non-resident one.
4723 * Return 0 on success and -1 on error with errno set to the error code. The
4724 * following error codes are defined:
4725 * EPERM - The attribute is not allowed to be non-resident.
4726 * TODO: others...
4728 * NOTE to self: No changes in the attribute list are required to move from
4729 * a resident to a non-resident attribute.
4731 * Warning: We do not set the inode dirty and we do not write out anything!
4732 * We expect the caller to do this as this is a fairly low level
4733 * function and it is likely there will be further changes made.
4735 int ntfs_attr_make_non_resident(ntfs_attr *na,
4736 ntfs_attr_search_ctx *ctx)
4738 s64 new_allocated_size, bw;
4739 ntfs_volume *vol = na->ni->vol;
4740 ATTR_REC *a = ctx->attr;
4741 runlist *rl;
4742 int mp_size, mp_ofs, name_ofs, arec_size, err;
4744 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
4745 long)na->ni->mft_no, na->type);
4747 /* Some preliminary sanity checking. */
4748 if (NAttrNonResident(na)) {
4749 ntfs_log_trace("Eeek! Trying to make non-resident attribute "
4750 "non-resident. Aborting...\n");
4751 errno = EINVAL;
4752 return -1;
4755 /* Check that the attribute is allowed to be non-resident. */
4756 if (ntfs_attr_can_be_non_resident(vol, na->type, na->name, na->name_len))
4757 return -1;
4759 new_allocated_size = (le32_to_cpu(a->value_length) + vol->cluster_size
4760 - 1) & ~(vol->cluster_size - 1);
4762 if (new_allocated_size > 0) {
4763 if ((a->flags & ATTR_COMPRESSION_MASK)
4764 == ATTR_IS_COMPRESSED) {
4765 /* must allocate full compression blocks */
4766 new_allocated_size = ((new_allocated_size - 1)
4767 | ((1L << (STANDARD_COMPRESSION_UNIT
4768 + vol->cluster_size_bits)) - 1)) + 1;
4770 /* Start by allocating clusters to hold the attribute value. */
4771 rl = ntfs_cluster_alloc(vol, 0, new_allocated_size >>
4772 vol->cluster_size_bits, -1, DATA_ZONE);
4773 if (!rl)
4774 return -1;
4775 } else
4776 rl = NULL;
4778 * Setup the in-memory attribute structure to be non-resident so that
4779 * we can use ntfs_attr_pwrite().
4781 NAttrSetNonResident(na);
4782 NAttrSetBeingNonResident(na);
4783 na->rl = rl;
4784 na->allocated_size = new_allocated_size;
4785 na->data_size = na->initialized_size = le32_to_cpu(a->value_length);
4787 * FIXME: For now just clear all of these as we don't support them when
4788 * writing.
4790 NAttrClearSparse(na);
4791 NAttrClearEncrypted(na);
4792 if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) {
4793 /* set compression writing parameters */
4794 na->compression_block_size
4795 = 1 << (STANDARD_COMPRESSION_UNIT + vol->cluster_size_bits);
4796 na->compression_block_clusters = 1 << STANDARD_COMPRESSION_UNIT;
4799 if (rl) {
4800 /* Now copy the attribute value to the allocated cluster(s). */
4801 bw = ntfs_attr_pwrite(na, 0, le32_to_cpu(a->value_length),
4802 (u8*)a + le16_to_cpu(a->value_offset));
4803 if (bw != le32_to_cpu(a->value_length)) {
4804 err = errno;
4805 ntfs_log_debug("Eeek! Failed to write out attribute value "
4806 "(bw = %lli, errno = %i). "
4807 "Aborting...\n", (long long)bw, err);
4808 if (bw >= 0)
4809 err = EIO;
4810 goto cluster_free_err_out;
4813 /* Determine the size of the mapping pairs array. */
4814 mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, INT_MAX);
4815 if (mp_size < 0) {
4816 err = errno;
4817 ntfs_log_debug("Eeek! Failed to get size for mapping pairs array. "
4818 "Aborting...\n");
4819 goto cluster_free_err_out;
4821 /* Calculate new offsets for the name and the mapping pairs array. */
4822 if (na->ni->flags & FILE_ATTR_COMPRESSED)
4823 name_ofs = (sizeof(ATTR_REC) + 7) & ~7;
4824 else
4825 name_ofs = (sizeof(ATTR_REC) - sizeof(a->compressed_size) + 7) & ~7;
4826 mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
4828 * Determine the size of the resident part of the non-resident
4829 * attribute record. (Not compressed thus no compressed_size element
4830 * present.)
4832 arec_size = (mp_ofs + mp_size + 7) & ~7;
4834 /* Resize the resident part of the attribute record. */
4835 if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
4836 err = errno;
4837 goto cluster_free_err_out;
4841 * Convert the resident part of the attribute record to describe a
4842 * non-resident attribute.
4844 a->non_resident = 1;
4846 /* Move the attribute name if it exists and update the offset. */
4847 if (a->name_length)
4848 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
4849 a->name_length * sizeof(ntfschar));
4850 a->name_offset = cpu_to_le16(name_ofs);
4852 /* Setup the fields specific to non-resident attributes. */
4853 a->lowest_vcn = cpu_to_sle64(0);
4854 a->highest_vcn = cpu_to_sle64((new_allocated_size - 1) >>
4855 vol->cluster_size_bits);
4857 a->mapping_pairs_offset = cpu_to_le16(mp_ofs);
4860 * Update the flags to match the in-memory ones.
4861 * However cannot change the compression state if we had
4862 * a fuse_file_info open with a mark for release.
4863 * The decisions about compression can only be made when
4864 * creating/recreating the stream, not when making non resident.
4866 a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED);
4867 if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) {
4868 /* support only ATTR_IS_COMPRESSED compression mode */
4869 a->compression_unit = STANDARD_COMPRESSION_UNIT;
4870 a->compressed_size = const_cpu_to_le64(0);
4871 } else {
4872 a->compression_unit = 0;
4873 a->flags &= ~ATTR_COMPRESSION_MASK;
4874 na->data_flags = a->flags;
4877 memset(&a->reserved1, 0, sizeof(a->reserved1));
4879 a->allocated_size = cpu_to_sle64(new_allocated_size);
4880 a->data_size = a->initialized_size = cpu_to_sle64(na->data_size);
4882 /* Generate the mapping pairs array in the attribute record. */
4883 if (ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, arec_size - mp_ofs,
4884 rl, 0, NULL) < 0) {
4885 // FIXME: Eeek! We need rollback! (AIA)
4886 ntfs_log_trace("Eeek! Failed to build mapping pairs. Leaving "
4887 "corrupt attribute record on disk. In memory "
4888 "runlist is still intact! Error code is %i. "
4889 "FIXME: Need to rollback instead!\n", errno);
4890 return -1;
4893 /* Done! */
4894 return 0;
4896 cluster_free_err_out:
4897 if (rl && ntfs_cluster_free(vol, na, 0, -1) < 0)
4898 ntfs_log_trace("Eeek! Failed to release allocated clusters in error "
4899 "code path. Leaving inconsistent metadata...\n");
4900 NAttrClearNonResident(na);
4901 NAttrClearFullyMapped(na);
4902 na->allocated_size = na->data_size;
4903 na->rl = NULL;
4904 free(rl);
4905 errno = err;
4906 return -1;
4910 static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize);
4913 * ntfs_resident_attr_resize - resize a resident, open ntfs attribute
4914 * @na: resident ntfs attribute to resize
4915 * @newsize: new size (in bytes) to which to resize the attribute
4917 * Change the size of a resident, open ntfs attribute @na to @newsize bytes.
4918 * Can also be used to force an attribute non-resident. In this case, the
4919 * size cannot be changed.
4921 * On success return 0
4922 * On error return values are:
4923 * STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT
4924 * STATUS_ERROR - otherwise
4925 * The following error codes are defined:
4926 * ENOMEM - Not enough memory to complete operation.
4927 * ERANGE - @newsize is not valid for the attribute type of @na.
4928 * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
4930 static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
4931 BOOL force_non_resident)
4933 ntfs_attr_search_ctx *ctx;
4934 ntfs_volume *vol;
4935 ntfs_inode *ni;
4936 int err, ret = STATUS_ERROR;
4938 ntfs_log_trace("Inode 0x%llx attr 0x%x new size %lld\n",
4939 (unsigned long long)na->ni->mft_no, na->type,
4940 (long long)newsize);
4942 /* Get the attribute record that needs modification. */
4943 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
4944 if (!ctx)
4945 return -1;
4946 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, 0, NULL, 0,
4947 ctx)) {
4948 err = errno;
4949 ntfs_log_perror("ntfs_attr_lookup failed");
4950 goto put_err_out;
4952 vol = na->ni->vol;
4954 * Check the attribute type and the corresponding minimum and maximum
4955 * sizes against @newsize and fail if @newsize is out of bounds.
4957 if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
4958 err = errno;
4959 if (err == ENOENT)
4960 err = EIO;
4961 ntfs_log_perror("%s: bounds check failed", __FUNCTION__);
4962 goto put_err_out;
4965 * If @newsize is bigger than the mft record we need to make the
4966 * attribute non-resident if the attribute type supports it. If it is
4967 * smaller we can go ahead and attempt the resize.
4969 if ((newsize < vol->mft_record_size) && !force_non_resident) {
4970 /* Perform the resize of the attribute record. */
4971 if (!(ret = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
4972 newsize))) {
4973 /* Update attribute size everywhere. */
4974 na->data_size = na->initialized_size = newsize;
4975 na->allocated_size = (newsize + 7) & ~7;
4976 if ((na->data_flags & ATTR_COMPRESSION_MASK)
4977 || NAttrSparse(na))
4978 na->compressed_size = na->allocated_size;
4979 if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
4980 ? na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30
4981 : na->type == AT_DATA && na->name == AT_UNNAMED) {
4982 na->ni->data_size = na->data_size;
4983 if (((na->data_flags & ATTR_COMPRESSION_MASK)
4984 || NAttrSparse(na))
4985 && NAttrNonResident(na))
4986 na->ni->allocated_size
4987 = na->compressed_size;
4988 else
4989 na->ni->allocated_size
4990 = na->allocated_size;
4991 set_nino_flag(na->ni,KnownSize);
4992 if (na->type == AT_DATA)
4993 NInoFileNameSetDirty(na->ni);
4995 goto resize_done;
4997 /* Prefer AT_INDEX_ALLOCATION instead of AT_ATTRIBUTE_LIST */
4998 if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) {
4999 err = errno;
5000 goto put_err_out;
5003 /* There is not enough space in the mft record to perform the resize. */
5005 /* Make the attribute non-resident if possible. */
5006 if (!ntfs_attr_make_non_resident(na, ctx)) {
5007 ntfs_inode_mark_dirty(ctx->ntfs_ino);
5008 ntfs_attr_put_search_ctx(ctx);
5010 * do not truncate when forcing non-resident, this
5011 * could cause the attribute to be made resident again,
5012 * so size changes are not allowed.
5014 if (force_non_resident) {
5015 ret = 0;
5016 if (newsize != na->data_size) {
5017 ntfs_log_error("Cannot change size when"
5018 " forcing non-resident\n");
5019 errno = EIO;
5020 ret = STATUS_ERROR;
5022 return (ret);
5024 /* Resize non-resident attribute */
5025 return ntfs_attr_truncate_i(na, newsize, HOLES_OK);
5026 } else if (errno != ENOSPC && errno != EPERM) {
5027 err = errno;
5028 ntfs_log_perror("Failed to make attribute non-resident");
5029 goto put_err_out;
5032 /* Try to make other attributes non-resident and retry each time. */
5033 ntfs_attr_init_search_ctx(ctx, NULL, na->ni->mrec);
5034 while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
5035 ntfs_attr *tna;
5036 ATTR_RECORD *a;
5038 a = ctx->attr;
5039 if (a->non_resident)
5040 continue;
5043 * Check out whether convert is reasonable. Assume that mapping
5044 * pairs will take 8 bytes.
5046 if (le32_to_cpu(a->length) <= offsetof(ATTR_RECORD,
5047 compressed_size) + ((a->name_length *
5048 sizeof(ntfschar) + 7) & ~7) + 8)
5049 continue;
5051 tna = ntfs_attr_open(na->ni, a->type, (ntfschar*)((u8*)a +
5052 le16_to_cpu(a->name_offset)), a->name_length);
5053 if (!tna) {
5054 err = errno;
5055 ntfs_log_perror("Couldn't open attribute");
5056 goto put_err_out;
5058 if (ntfs_attr_make_non_resident(tna, ctx)) {
5059 ntfs_attr_close(tna);
5060 continue;
5062 if ((tna->type == AT_DATA) && !tna->name_len) {
5064 * If we had to make the unnamed data attribute
5065 * non-resident, propagate its new allocated size
5066 * to all name attributes and directory indexes
5068 tna->ni->allocated_size = tna->allocated_size;
5069 NInoFileNameSetDirty(tna->ni);
5071 if (((tna->data_flags & ATTR_COMPRESSION_MASK)
5072 == ATTR_IS_COMPRESSED)
5073 && ntfs_attr_pclose(tna)) {
5074 err = errno;
5075 ntfs_attr_close(tna);
5076 goto put_err_out;
5078 ntfs_inode_mark_dirty(tna->ni);
5079 ntfs_attr_close(tna);
5080 ntfs_attr_put_search_ctx(ctx);
5081 return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
5083 /* Check whether error occurred. */
5084 if (errno != ENOENT) {
5085 err = errno;
5086 ntfs_log_perror("%s: Attribute lookup failed 1", __FUNCTION__);
5087 goto put_err_out;
5091 * The standard information and attribute list attributes can't be
5092 * moved out from the base MFT record, so try to move out others.
5094 if (na->type==AT_STANDARD_INFORMATION || na->type==AT_ATTRIBUTE_LIST) {
5095 ntfs_attr_put_search_ctx(ctx);
5096 if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD,
5097 non_resident_end) + 8)) {
5098 ntfs_log_perror("Could not free space in MFT record");
5099 return -1;
5101 return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
5105 * Move the attribute to a new mft record, creating an attribute list
5106 * attribute or modifying it if it is already present.
5109 /* Point search context back to attribute which we need resize. */
5110 ntfs_attr_init_search_ctx(ctx, na->ni, NULL);
5111 if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
5112 0, NULL, 0, ctx)) {
5113 ntfs_log_perror("%s: Attribute lookup failed 2", __FUNCTION__);
5114 err = errno;
5115 goto put_err_out;
5119 * Check whether attribute is already single in this MFT record.
5120 * 8 added for the attribute terminator.
5122 if (le32_to_cpu(ctx->mrec->bytes_in_use) ==
5123 le16_to_cpu(ctx->mrec->attrs_offset) +
5124 le32_to_cpu(ctx->attr->length) + 8) {
5125 err = ENOSPC;
5126 ntfs_log_trace("MFT record is filled with one attribute\n");
5127 ret = STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT;
5128 goto put_err_out;
5131 /* Add attribute list if not present. */
5132 if (na->ni->nr_extents == -1)
5133 ni = na->ni->base_ni;
5134 else
5135 ni = na->ni;
5136 if (!NInoAttrList(ni)) {
5137 ntfs_attr_put_search_ctx(ctx);
5138 if (ntfs_inode_add_attrlist(ni))
5139 return -1;
5140 return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
5142 /* Allocate new mft record. */
5143 ni = ntfs_mft_record_alloc(vol, ni);
5144 if (!ni) {
5145 err = errno;
5146 ntfs_log_perror("Couldn't allocate new MFT record");
5147 goto put_err_out;
5149 /* Move attribute to it. */
5150 if (ntfs_attr_record_move_to(ctx, ni)) {
5151 err = errno;
5152 ntfs_log_perror("Couldn't move attribute to new MFT record");
5153 goto put_err_out;
5155 /* Update ntfs attribute. */
5156 if (na->ni->nr_extents == -1)
5157 na->ni = ni;
5159 ntfs_attr_put_search_ctx(ctx);
5160 /* Try to perform resize once again. */
5161 return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
5163 resize_done:
5165 * Set the inode (and its base inode if it exists) dirty so it is
5166 * written out later.
5168 ntfs_inode_mark_dirty(ctx->ntfs_ino);
5169 ntfs_attr_put_search_ctx(ctx);
5170 return 0;
5171 put_err_out:
5172 ntfs_attr_put_search_ctx(ctx);
5173 errno = err;
5174 return ret;
5177 static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
5179 int ret;
5181 ntfs_log_enter("Entering\n");
5182 ret = ntfs_resident_attr_resize_i(na, newsize, FALSE);
5183 ntfs_log_leave("\n");
5184 return ret;
5188 * Force an attribute to be made non-resident without
5189 * changing its size.
5191 * This is particularly needed when the attribute has no data,
5192 * as the non-resident variant requires more space in the MFT
5193 * record, and may imply expelling some other attribute.
5195 * As a consequence the existing ntfs_attr_search_ctx's have to
5196 * be closed or reinitialized.
5198 * returns 0 if successful,
5199 * < 0 if failed, with errno telling why
5202 int ntfs_attr_force_non_resident(ntfs_attr *na)
5204 int res;
5206 res = ntfs_resident_attr_resize_i(na, na->data_size, TRUE);
5207 if (!res && !NAttrNonResident(na)) {
5208 res = -1;
5209 errno = EIO;
5210 ntfs_log_error("Failed to force non-resident\n");
5212 return (res);
5216 * ntfs_attr_make_resident - convert a non-resident to a resident attribute
5217 * @na: open ntfs attribute to make resident
5218 * @ctx: ntfs search context describing the attribute
5220 * Convert a non-resident ntfs attribute to a resident one.
5222 * Return 0 on success and -1 on error with errno set to the error code. The
5223 * following error codes are defined:
5224 * EINVAL - Invalid arguments passed.
5225 * EPERM - The attribute is not allowed to be resident.
5226 * EIO - I/O error, damaged inode or bug.
5227 * ENOSPC - There is no enough space to perform conversion.
5228 * EOPNOTSUPP - Requested conversion is not supported yet.
5230 * Warning: We do not set the inode dirty and we do not write out anything!
5231 * We expect the caller to do this as this is a fairly low level
5232 * function and it is likely there will be further changes made.
5234 static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
5236 ntfs_volume *vol = na->ni->vol;
5237 ATTR_REC *a = ctx->attr;
5238 int name_ofs, val_ofs, err = EIO;
5239 s64 arec_size, bytes_read;
5241 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
5242 long)na->ni->mft_no, na->type);
5244 /* Should be called for the first extent of the attribute. */
5245 if (sle64_to_cpu(a->lowest_vcn)) {
5246 ntfs_log_trace("Eeek! Should be called for the first extent of the "
5247 "attribute. Aborting...\n");
5248 errno = EINVAL;
5249 return -1;
5252 /* Some preliminary sanity checking. */
5253 if (!NAttrNonResident(na)) {
5254 ntfs_log_trace("Eeek! Trying to make resident attribute resident. "
5255 "Aborting...\n");
5256 errno = EINVAL;
5257 return -1;
5260 /* Make sure this is not $MFT/$BITMAP or Windows will not boot! */
5261 if (na->type == AT_BITMAP && na->ni->mft_no == FILE_MFT) {
5262 errno = EPERM;
5263 return -1;
5266 /* Check that the attribute is allowed to be resident. */
5267 if (ntfs_attr_can_be_resident(vol, na->type))
5268 return -1;
5270 if (na->data_flags & ATTR_IS_ENCRYPTED) {
5271 ntfs_log_trace("Making encrypted streams resident is not "
5272 "implemented yet.\n");
5273 errno = EOPNOTSUPP;
5274 return -1;
5277 /* Work out offsets into and size of the resident attribute. */
5278 name_ofs = 24; /* = sizeof(resident_ATTR_REC); */
5279 val_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
5280 arec_size = (val_ofs + na->data_size + 7) & ~7;
5282 /* Sanity check the size before we start modifying the attribute. */
5283 if (le32_to_cpu(ctx->mrec->bytes_in_use) - le32_to_cpu(a->length) +
5284 arec_size > le32_to_cpu(ctx->mrec->bytes_allocated)) {
5285 errno = ENOSPC;
5286 ntfs_log_trace("Not enough space to make attribute resident\n");
5287 return -1;
5290 /* Read and cache the whole runlist if not already done. */
5291 if (ntfs_attr_map_whole_runlist(na))
5292 return -1;
5294 /* Move the attribute name if it exists and update the offset. */
5295 if (a->name_length) {
5296 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
5297 a->name_length * sizeof(ntfschar));
5299 a->name_offset = cpu_to_le16(name_ofs);
5301 /* Resize the resident part of the attribute record. */
5302 if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
5304 * Bug, because ntfs_attr_record_resize should not fail (we
5305 * already checked that attribute fits MFT record).
5307 ntfs_log_error("BUG! Failed to resize attribute record. "
5308 "Please report to the %s. Aborting...\n",
5309 NTFS_DEV_LIST);
5310 errno = EIO;
5311 return -1;
5314 /* Convert the attribute record to describe a resident attribute. */
5315 a->non_resident = 0;
5316 a->flags = 0;
5317 a->value_length = cpu_to_le32(na->data_size);
5318 a->value_offset = cpu_to_le16(val_ofs);
5320 * If a data stream was wiped out, adjust the compression mode
5321 * to current state of compression flag
5323 if (!na->data_size
5324 && (na->type == AT_DATA)
5325 && (na->ni->vol->major_ver >= 3)
5326 && NVolCompression(na->ni->vol)
5327 && (na->ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
5328 && (na->ni->flags & FILE_ATTR_COMPRESSED)) {
5329 a->flags |= ATTR_IS_COMPRESSED;
5330 na->data_flags = a->flags;
5333 * File names cannot be non-resident so we would never see this here
5334 * but at least it serves as a reminder that there may be attributes
5335 * for which we do need to set this flag. (AIA)
5337 if (a->type == AT_FILE_NAME)
5338 a->resident_flags = RESIDENT_ATTR_IS_INDEXED;
5339 else
5340 a->resident_flags = 0;
5341 a->reservedR = 0;
5343 /* Sanity fixup... Shouldn't really happen. (AIA) */
5344 if (na->initialized_size > na->data_size)
5345 na->initialized_size = na->data_size;
5347 /* Copy data from run list to resident attribute value. */
5348 bytes_read = ntfs_rl_pread(vol, na->rl, 0, na->initialized_size,
5349 (u8*)a + val_ofs);
5350 if (bytes_read != na->initialized_size) {
5351 if (bytes_read < 0)
5352 err = errno;
5353 ntfs_log_trace("Eeek! Failed to read attribute data. Leaving "
5354 "inconstant metadata. Run chkdsk. "
5355 "Aborting...\n");
5356 errno = err;
5357 return -1;
5360 /* Clear memory in gap between initialized_size and data_size. */
5361 if (na->initialized_size < na->data_size)
5362 memset((u8*)a + val_ofs + na->initialized_size, 0,
5363 na->data_size - na->initialized_size);
5366 * Deallocate clusters from the runlist.
5368 * NOTE: We can use ntfs_cluster_free() because we have already mapped
5369 * the whole run list and thus it doesn't matter that the attribute
5370 * record is in a transiently corrupted state at this moment in time.
5372 if (ntfs_cluster_free(vol, na, 0, -1) < 0) {
5373 ntfs_log_perror("Eeek! Failed to release allocated clusters");
5374 ntfs_log_trace("Ignoring error and leaving behind wasted "
5375 "clusters.\n");
5378 /* Throw away the now unused runlist. */
5379 free(na->rl);
5380 na->rl = NULL;
5382 /* Update in-memory struct ntfs_attr. */
5383 NAttrClearNonResident(na);
5384 NAttrClearFullyMapped(na);
5385 NAttrClearSparse(na);
5386 NAttrClearEncrypted(na);
5387 na->initialized_size = na->data_size;
5388 na->allocated_size = na->compressed_size = (na->data_size + 7) & ~7;
5389 na->compression_block_size = 0;
5390 na->compression_block_size_bits = na->compression_block_clusters = 0;
5391 return 0;
5395 * If we are in the first extent, then set/clean sparse bit,
5396 * update allocated and compressed size.
5398 static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
5399 hole_type holes, ntfs_attr_search_ctx *ctx)
5401 int sparse, ret = 0;
5403 ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x\n",
5404 (unsigned long long)na->ni->mft_no, na->type);
5406 if (a->lowest_vcn)
5407 goto out;
5409 a->allocated_size = cpu_to_sle64(na->allocated_size);
5411 /* Update sparse bit, unless this is an intermediate state */
5412 if (holes == HOLES_DELAY)
5413 sparse = (a->flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0);
5414 else {
5415 sparse = ntfs_rl_sparse(na->rl);
5416 if (sparse == -1) {
5417 errno = EIO;
5418 goto error;
5422 /* Check whether attribute becomes sparse, unless check is delayed. */
5423 if ((holes != HOLES_DELAY)
5424 && sparse
5425 && !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) {
5427 * Move attribute to another mft record, if attribute is too
5428 * small to add compressed_size field to it and we have no
5429 * free space in the current mft record.
5431 if ((le32_to_cpu(a->length) -
5432 le16_to_cpu(a->mapping_pairs_offset) == 8)
5433 && !(le32_to_cpu(m->bytes_allocated) -
5434 le32_to_cpu(m->bytes_in_use))) {
5436 if (!NInoAttrList(na->ni)) {
5437 ntfs_attr_put_search_ctx(ctx);
5438 if (ntfs_inode_add_attrlist(na->ni))
5439 goto leave;
5440 goto retry;
5442 if (ntfs_attr_record_move_away(ctx, 8)) {
5443 ntfs_log_perror("Failed to move attribute");
5444 goto error;
5446 ntfs_attr_put_search_ctx(ctx);
5447 goto retry;
5449 if (!(le32_to_cpu(a->length) - le16_to_cpu(
5450 a->mapping_pairs_offset))) {
5451 errno = EIO;
5452 ntfs_log_perror("Mapping pairs space is 0");
5453 goto error;
5456 NAttrSetSparse(na);
5457 a->flags |= ATTR_IS_SPARSE;
5458 na->data_flags = a->flags;
5459 a->compression_unit = STANDARD_COMPRESSION_UNIT; /* Windows
5460 set it so, even if attribute is not actually compressed. */
5462 memmove((u8*)a + le16_to_cpu(a->name_offset) + 8,
5463 (u8*)a + le16_to_cpu(a->name_offset),
5464 a->name_length * sizeof(ntfschar));
5466 a->name_offset = cpu_to_le16(le16_to_cpu(a->name_offset) + 8);
5468 a->mapping_pairs_offset =
5469 cpu_to_le16(le16_to_cpu(a->mapping_pairs_offset) + 8);
5472 /* Attribute no longer sparse. */
5473 if (!sparse && (a->flags & ATTR_IS_SPARSE) &&
5474 !(a->flags & ATTR_IS_COMPRESSED)) {
5476 NAttrClearSparse(na);
5477 a->flags &= ~ATTR_IS_SPARSE;
5478 na->data_flags = a->flags;
5479 a->compression_unit = 0;
5481 memmove((u8*)a + le16_to_cpu(a->name_offset) - 8,
5482 (u8*)a + le16_to_cpu(a->name_offset),
5483 a->name_length * sizeof(ntfschar));
5485 if (le16_to_cpu(a->name_offset) >= 8)
5486 a->name_offset = cpu_to_le16(le16_to_cpu(a->name_offset) - 8);
5488 a->mapping_pairs_offset =
5489 cpu_to_le16(le16_to_cpu(a->mapping_pairs_offset) - 8);
5492 /* Update compressed size if required. */
5493 if (NAttrFullyMapped(na)
5494 && (sparse || (na->data_flags & ATTR_COMPRESSION_MASK))) {
5495 s64 new_compr_size;
5497 new_compr_size = ntfs_rl_get_compressed_size(na->ni->vol, na->rl);
5498 if (new_compr_size == -1)
5499 goto error;
5501 na->compressed_size = new_compr_size;
5502 a->compressed_size = cpu_to_sle64(new_compr_size);
5505 * Set FILE_NAME dirty flag, to update sparse bit and
5506 * allocated size in the index.
5508 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
5509 if (sparse || (na->data_flags & ATTR_COMPRESSION_MASK))
5510 na->ni->allocated_size = na->compressed_size;
5511 else
5512 na->ni->allocated_size = na->allocated_size;
5513 NInoFileNameSetDirty(na->ni);
5515 out:
5516 return ret;
5517 leave: ret = -1; goto out; /* return -1 */
5518 retry: ret = -2; goto out;
5519 error: ret = -3; goto out;
5522 #define NTFS_VCN_DELETE_MARK -2
5524 * ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs
5526 static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn,
5527 hole_type holes)
5529 ntfs_attr_search_ctx *ctx;
5530 ntfs_inode *ni, *base_ni;
5531 MFT_RECORD *m;
5532 ATTR_RECORD *a;
5533 VCN stop_vcn;
5534 const runlist_element *stop_rl;
5535 int err, mp_size, cur_max_mp_size, exp_max_mp_size, ret = -1;
5536 BOOL finished_build;
5537 BOOL first_updated = FALSE;
5539 retry:
5540 if (!na || !na->rl) {
5541 errno = EINVAL;
5542 ntfs_log_perror("%s: na=%p", __FUNCTION__, na);
5543 return -1;
5546 ntfs_log_trace("Entering for inode %llu, attr 0x%x\n",
5547 (unsigned long long)na->ni->mft_no, na->type);
5549 if (!NAttrNonResident(na)) {
5550 errno = EINVAL;
5551 ntfs_log_perror("%s: resident attribute", __FUNCTION__);
5552 return -1;
5555 #if PARTIAL_RUNLIST_UPDATING
5557 * For a file just been made sparse, we will have
5558 * to reformat the first extent, so be sure the
5559 * runlist is fully mapped and fully processed.
5560 * Same if the file was sparse and is not any more.
5561 * Note : not needed if the full runlist is to be processed
5563 if ((holes != HOLES_DELAY)
5564 && (!NAttrFullyMapped(na) || from_vcn)
5565 && !(na->data_flags & ATTR_IS_COMPRESSED)) {
5566 BOOL changed;
5568 if (!(na->data_flags & ATTR_IS_SPARSE)) {
5569 int sparse;
5570 runlist_element *xrl;
5573 * If attribute was not sparse, we only
5574 * have to check whether there is a hole
5575 * in the updated region.
5577 xrl = na->rl;
5578 if (xrl->lcn == LCN_RL_NOT_MAPPED)
5579 xrl++;
5580 sparse = ntfs_rl_sparse(xrl);
5581 if (sparse < 0) {
5582 ntfs_log_error("Could not check whether sparse\n");
5583 errno = EIO;
5584 return (-1);
5586 changed = sparse > 0;
5587 } else {
5589 * If attribute was sparse, the compressed
5590 * size has been maintained, and it gives
5591 * and easy way to check whether the
5592 * attribute is still sparse.
5594 changed = (((na->data_size - 1)
5595 | (na->ni->vol->cluster_size - 1)) + 1)
5596 == na->compressed_size;
5598 if (changed) {
5599 if (ntfs_attr_map_whole_runlist(na)) {
5600 ntfs_log_error("Could not map whole for sparse change\n");
5601 errno = EIO;
5602 return (-1);
5604 from_vcn = 0;
5607 #endif
5608 if (na->ni->nr_extents == -1)
5609 base_ni = na->ni->base_ni;
5610 else
5611 base_ni = na->ni;
5613 ctx = ntfs_attr_get_search_ctx(base_ni, NULL);
5614 if (!ctx)
5615 return -1;
5617 /* Fill attribute records with new mapping pairs. */
5618 stop_vcn = 0;
5619 stop_rl = na->rl;
5620 finished_build = FALSE;
5621 while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
5622 CASE_SENSITIVE, from_vcn, NULL, 0, ctx)) {
5623 a = ctx->attr;
5624 m = ctx->mrec;
5625 if (!a->lowest_vcn)
5626 first_updated = TRUE;
5628 * If runlist is updating not from the beginning, then set
5629 * @stop_vcn properly, i.e. to the lowest vcn of record that
5630 * contain @from_vcn. Also we do not need @from_vcn anymore,
5631 * set it to 0 to make ntfs_attr_lookup enumerate attributes.
5633 if (from_vcn) {
5634 LCN first_lcn;
5636 stop_vcn = sle64_to_cpu(a->lowest_vcn);
5637 from_vcn = 0;
5639 * Check whether the first run we need to update is
5640 * the last run in runlist, if so, then deallocate
5641 * all attrubute extents starting this one.
5643 first_lcn = ntfs_rl_vcn_to_lcn(na->rl, stop_vcn);
5644 if (first_lcn == LCN_EINVAL) {
5645 errno = EIO;
5646 ntfs_log_perror("Bad runlist");
5647 goto put_err_out;
5649 if (first_lcn == LCN_ENOENT ||
5650 first_lcn == LCN_RL_NOT_MAPPED)
5651 finished_build = TRUE;
5655 * Check whether we finished mapping pairs build, if so mark
5656 * extent as need to delete (by setting highest vcn to
5657 * NTFS_VCN_DELETE_MARK (-2), we shall check it later and
5658 * delete extent) and continue search.
5660 if (finished_build) {
5661 ntfs_log_trace("Mark attr 0x%x for delete in inode "
5662 "%lld.\n", (unsigned)le32_to_cpu(a->type),
5663 (long long)ctx->ntfs_ino->mft_no);
5664 a->highest_vcn = cpu_to_sle64(NTFS_VCN_DELETE_MARK);
5665 ntfs_inode_mark_dirty(ctx->ntfs_ino);
5666 continue;
5669 switch (ntfs_attr_update_meta(a, na, m, holes, ctx)) {
5670 case -1: return -1;
5671 case -2: goto retry;
5672 case -3: goto put_err_out;
5676 * Determine maximum possible length of mapping pairs,
5677 * if we shall *not* expand space for mapping pairs.
5679 cur_max_mp_size = le32_to_cpu(a->length) -
5680 le16_to_cpu(a->mapping_pairs_offset);
5682 * Determine maximum possible length of mapping pairs in the
5683 * current mft record, if we shall expand space for mapping
5684 * pairs.
5686 exp_max_mp_size = le32_to_cpu(m->bytes_allocated) -
5687 le32_to_cpu(m->bytes_in_use) + cur_max_mp_size;
5688 /* Get the size for the rest of mapping pairs array. */
5689 mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, stop_rl,
5690 stop_vcn, exp_max_mp_size);
5691 if (mp_size <= 0) {
5692 ntfs_log_perror("%s: get MP size failed", __FUNCTION__);
5693 goto put_err_out;
5695 /* Test mapping pairs for fitting in the current mft record. */
5696 if (mp_size > exp_max_mp_size) {
5698 * Mapping pairs of $ATTRIBUTE_LIST attribute must fit
5699 * in the base mft record. Try to move out other
5700 * attributes and try again.
5702 if (na->type == AT_ATTRIBUTE_LIST) {
5703 ntfs_attr_put_search_ctx(ctx);
5704 if (ntfs_inode_free_space(na->ni, mp_size -
5705 cur_max_mp_size)) {
5706 ntfs_log_perror("Attribute list is too "
5707 "big. Defragment the "
5708 "volume\n");
5709 return -1;
5711 goto retry;
5714 /* Add attribute list if it isn't present, and retry. */
5715 if (!NInoAttrList(base_ni)) {
5716 ntfs_attr_put_search_ctx(ctx);
5717 if (ntfs_inode_add_attrlist(base_ni)) {
5718 ntfs_log_perror("Can not add attrlist");
5719 return -1;
5721 goto retry;
5725 * Set mapping pairs size to maximum possible for this
5726 * mft record. We shall write the rest of mapping pairs
5727 * to another MFT records.
5729 mp_size = exp_max_mp_size;
5732 /* Change space for mapping pairs if we need it. */
5733 if (((mp_size + 7) & ~7) != cur_max_mp_size) {
5734 if (ntfs_attr_record_resize(m, a,
5735 le16_to_cpu(a->mapping_pairs_offset) +
5736 mp_size)) {
5737 errno = EIO;
5738 ntfs_log_perror("Failed to resize attribute");
5739 goto put_err_out;
5743 /* Update lowest vcn. */
5744 a->lowest_vcn = cpu_to_sle64(stop_vcn);
5745 ntfs_inode_mark_dirty(ctx->ntfs_ino);
5746 if ((ctx->ntfs_ino->nr_extents == -1 ||
5747 NInoAttrList(ctx->ntfs_ino)) &&
5748 ctx->attr->type != AT_ATTRIBUTE_LIST) {
5749 ctx->al_entry->lowest_vcn = cpu_to_sle64(stop_vcn);
5750 ntfs_attrlist_mark_dirty(ctx->ntfs_ino);
5754 * Generate the new mapping pairs array directly into the
5755 * correct destination, i.e. the attribute record itself.
5757 if (!ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu(
5758 a->mapping_pairs_offset), mp_size, na->rl,
5759 stop_vcn, &stop_rl))
5760 finished_build = TRUE;
5761 if (stop_rl)
5762 stop_vcn = stop_rl->vcn;
5763 else
5764 stop_vcn = 0;
5765 if (!finished_build && errno != ENOSPC) {
5766 ntfs_log_perror("Failed to build mapping pairs");
5767 goto put_err_out;
5769 a->highest_vcn = cpu_to_sle64(stop_vcn - 1);
5771 /* Check whether error occurred. */
5772 if (errno != ENOENT) {
5773 ntfs_log_perror("%s: Attribute lookup failed", __FUNCTION__);
5774 goto put_err_out;
5777 * If the base extent was skipped in the above process,
5778 * we still may have to update the sizes.
5780 if (!first_updated) {
5781 le16 spcomp;
5783 ntfs_attr_reinit_search_ctx(ctx);
5784 if (!ntfs_attr_lookup(na->type, na->name, na->name_len,
5785 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
5786 a = ctx->attr;
5787 a->allocated_size = cpu_to_sle64(na->allocated_size);
5788 spcomp = na->data_flags
5789 & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
5790 if (spcomp)
5791 a->compressed_size = cpu_to_sle64(na->compressed_size);
5792 if ((na->type == AT_DATA) && (na->name == AT_UNNAMED)) {
5793 na->ni->allocated_size
5794 = (spcomp
5795 ? na->compressed_size
5796 : na->allocated_size);
5797 NInoFileNameSetDirty(na->ni);
5799 } else {
5800 ntfs_log_error("Failed to update sizes in base extent\n");
5801 goto put_err_out;
5805 /* Deallocate not used attribute extents and return with success. */
5806 if (finished_build) {
5807 ntfs_attr_reinit_search_ctx(ctx);
5808 ntfs_log_trace("Deallocate marked extents.\n");
5809 while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
5810 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
5811 if (sle64_to_cpu(ctx->attr->highest_vcn) !=
5812 NTFS_VCN_DELETE_MARK)
5813 continue;
5814 /* Remove unused attribute record. */
5815 if (ntfs_attr_record_rm(ctx)) {
5816 ntfs_log_perror("Could not remove unused attr");
5817 goto put_err_out;
5819 ntfs_attr_reinit_search_ctx(ctx);
5821 if (errno != ENOENT) {
5822 ntfs_log_perror("%s: Attr lookup failed", __FUNCTION__);
5823 goto put_err_out;
5825 ntfs_log_trace("Deallocate done.\n");
5826 ntfs_attr_put_search_ctx(ctx);
5827 goto ok;
5829 ntfs_attr_put_search_ctx(ctx);
5830 ctx = NULL;
5832 /* Allocate new MFT records for the rest of mapping pairs. */
5833 while (1) {
5834 /* Calculate size of rest mapping pairs. */
5835 mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol,
5836 na->rl, stop_vcn, INT_MAX);
5837 if (mp_size <= 0) {
5838 ntfs_log_perror("%s: get mp size failed", __FUNCTION__);
5839 goto put_err_out;
5841 /* Allocate new mft record. */
5842 ni = ntfs_mft_record_alloc(na->ni->vol, base_ni);
5843 if (!ni) {
5844 ntfs_log_perror("Could not allocate new MFT record");
5845 goto put_err_out;
5847 m = ni->mrec;
5849 * If mapping size exceed available space, set them to
5850 * possible maximum.
5852 cur_max_mp_size = le32_to_cpu(m->bytes_allocated) -
5853 le32_to_cpu(m->bytes_in_use) -
5854 (offsetof(ATTR_RECORD, compressed_size) +
5855 (((na->data_flags & ATTR_COMPRESSION_MASK)
5856 || NAttrSparse(na)) ?
5857 sizeof(a->compressed_size) : 0)) -
5858 ((sizeof(ntfschar) * na->name_len + 7) & ~7);
5859 if (mp_size > cur_max_mp_size)
5860 mp_size = cur_max_mp_size;
5861 /* Add attribute extent to new record. */
5862 err = ntfs_non_resident_attr_record_add(ni, na->type,
5863 na->name, na->name_len, stop_vcn, mp_size,
5864 na->data_flags);
5865 if (err == -1) {
5866 err = errno;
5867 ntfs_log_perror("Could not add attribute extent");
5868 if (ntfs_mft_record_free(na->ni->vol, ni))
5869 ntfs_log_perror("Could not free MFT record");
5870 errno = err;
5871 goto put_err_out;
5873 a = (ATTR_RECORD*)((u8*)m + err);
5875 err = ntfs_mapping_pairs_build(na->ni->vol, (u8*)a +
5876 le16_to_cpu(a->mapping_pairs_offset), mp_size, na->rl,
5877 stop_vcn, &stop_rl);
5878 if (stop_rl)
5879 stop_vcn = stop_rl->vcn;
5880 else
5881 stop_vcn = 0;
5882 if (err < 0 && errno != ENOSPC) {
5883 err = errno;
5884 ntfs_log_perror("Failed to build MP");
5885 if (ntfs_mft_record_free(na->ni->vol, ni))
5886 ntfs_log_perror("Couldn't free MFT record");
5887 errno = err;
5888 goto put_err_out;
5890 a->highest_vcn = cpu_to_sle64(stop_vcn - 1);
5891 ntfs_inode_mark_dirty(ni);
5892 /* All mapping pairs has been written. */
5893 if (!err)
5894 break;
5897 ret = 0;
5898 out:
5899 return ret;
5900 put_err_out:
5901 if (ctx)
5902 ntfs_attr_put_search_ctx(ctx);
5903 goto out;
5905 #undef NTFS_VCN_DELETE_MARK
5908 * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute
5909 * @na: non-resident ntfs open attribute for which we need update
5910 * @from_vcn: update runlist starting this VCN
5912 * Build mapping pairs from @na->rl and write them to the disk. Also, this
5913 * function updates sparse bit, allocated and compressed size (allocates/frees
5914 * space for this field if required).
5916 * @na->allocated_size should be set to correct value for the new runlist before
5917 * call to this function. Vice-versa @na->compressed_size will be calculated and
5918 * set to correct value during this function.
5920 * FIXME: This function does not update sparse bit and compressed size correctly
5921 * if called with @from_vcn != 0.
5923 * FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define.
5925 * On success return 0 and on error return -1 with errno set to the error code.
5926 * The following error codes are defined:
5927 * EINVAL - Invalid arguments passed.
5928 * ENOMEM - Not enough memory to complete operation.
5929 * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST
5930 * or there is no free MFT records left to allocate.
5932 int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
5934 int ret;
5936 ntfs_log_enter("Entering\n");
5937 ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn, HOLES_OK);
5938 ntfs_log_leave("\n");
5939 return ret;
5943 * ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute
5944 * @na: non-resident ntfs attribute to shrink
5945 * @newsize: new size (in bytes) to which to shrink the attribute
5947 * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes.
5949 * On success return 0 and on error return -1 with errno set to the error code.
5950 * The following error codes are defined:
5951 * ENOMEM - Not enough memory to complete operation.
5952 * ERANGE - @newsize is not valid for the attribute type of @na.
5954 static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize)
5956 ntfs_volume *vol;
5957 ntfs_attr_search_ctx *ctx;
5958 VCN first_free_vcn;
5959 s64 nr_freed_clusters;
5960 int err;
5962 ntfs_log_trace("Inode 0x%llx attr 0x%x new size %lld\n", (unsigned long long)
5963 na->ni->mft_no, na->type, (long long)newsize);
5965 vol = na->ni->vol;
5968 * Check the attribute type and the corresponding minimum size
5969 * against @newsize and fail if @newsize is too small.
5971 if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
5972 if (errno == ERANGE) {
5973 ntfs_log_trace("Eeek! Size bounds check failed. "
5974 "Aborting...\n");
5975 } else if (errno == ENOENT)
5976 errno = EIO;
5977 return -1;
5980 /* The first cluster outside the new allocation. */
5981 if (na->data_flags & ATTR_COMPRESSION_MASK)
5983 * For compressed files we must keep full compressions blocks,
5984 * but currently we do not decompress/recompress the last
5985 * block to truncate the data, so we may leave more allocated
5986 * clusters than really needed.
5988 first_free_vcn = (((newsize - 1)
5989 | (na->compression_block_size - 1)) + 1)
5990 >> vol->cluster_size_bits;
5991 else
5992 first_free_vcn = (newsize + vol->cluster_size - 1) >>
5993 vol->cluster_size_bits;
5995 * Compare the new allocation with the old one and only deallocate
5996 * clusters if there is a change.
5998 if ((na->allocated_size >> vol->cluster_size_bits) != first_free_vcn) {
5999 if (ntfs_attr_map_whole_runlist(na)) {
6000 ntfs_log_trace("Eeek! ntfs_attr_map_whole_runlist "
6001 "failed.\n");
6002 return -1;
6004 /* Deallocate all clusters starting with the first free one. */
6005 nr_freed_clusters = ntfs_cluster_free(vol, na, first_free_vcn,
6006 -1);
6007 if (nr_freed_clusters < 0) {
6008 ntfs_log_trace("Eeek! Freeing of clusters failed. "
6009 "Aborting...\n");
6010 return -1;
6013 /* Truncate the runlist itself. */
6014 if (ntfs_rl_truncate(&na->rl, first_free_vcn)) {
6016 * Failed to truncate the runlist, so just throw it
6017 * away, it will be mapped afresh on next use.
6019 free(na->rl);
6020 na->rl = NULL;
6021 ntfs_log_trace("Eeek! Run list truncation failed.\n");
6022 return -1;
6025 /* Prepare to mapping pairs update. */
6026 na->allocated_size = first_free_vcn << vol->cluster_size_bits;
6027 /* Write mapping pairs for new runlist. */
6028 if (ntfs_attr_update_mapping_pairs(na, 0 /*first_free_vcn*/)) {
6029 ntfs_log_trace("Eeek! Mapping pairs update failed. "
6030 "Leaving inconstant metadata. "
6031 "Run chkdsk.\n");
6032 return -1;
6036 /* Get the first attribute record. */
6037 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
6038 if (!ctx)
6039 return -1;
6041 if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
6042 0, NULL, 0, ctx)) {
6043 err = errno;
6044 if (err == ENOENT)
6045 err = EIO;
6046 ntfs_log_trace("Eeek! Lookup of first attribute extent failed. "
6047 "Leaving inconstant metadata.\n");
6048 goto put_err_out;
6051 /* Update data and initialized size. */
6052 na->data_size = newsize;
6053 ctx->attr->data_size = cpu_to_sle64(newsize);
6054 if (newsize < na->initialized_size) {
6055 na->initialized_size = newsize;
6056 ctx->attr->initialized_size = cpu_to_sle64(newsize);
6058 /* Update data size in the index. */
6059 if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
6060 if (na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30) {
6061 na->ni->data_size = na->data_size;
6062 na->ni->allocated_size = na->allocated_size;
6063 set_nino_flag(na->ni,KnownSize);
6065 } else {
6066 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
6067 na->ni->data_size = na->data_size;
6068 NInoFileNameSetDirty(na->ni);
6072 /* If the attribute now has zero size, make it resident. */
6073 if (!newsize) {
6074 if (ntfs_attr_make_resident(na, ctx)) {
6075 /* If couldn't make resident, just continue. */
6076 if (errno != EPERM)
6077 ntfs_log_error("Failed to make attribute "
6078 "resident. Leaving as is...\n");
6082 /* Set the inode dirty so it is written out later. */
6083 ntfs_inode_mark_dirty(ctx->ntfs_ino);
6084 /* Done! */
6085 ntfs_attr_put_search_ctx(ctx);
6086 return 0;
6087 put_err_out:
6088 ntfs_attr_put_search_ctx(ctx);
6089 errno = err;
6090 return -1;
6094 * ntfs_non_resident_attr_expand - expand a non-resident, open ntfs attribute
6095 * @na: non-resident ntfs attribute to expand
6096 * @newsize: new size (in bytes) to which to expand the attribute
6098 * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes,
6099 * by allocating new clusters.
6101 * On success return 0 and on error return -1 with errno set to the error code.
6102 * The following error codes are defined:
6103 * ENOMEM - Not enough memory to complete operation.
6104 * ERANGE - @newsize is not valid for the attribute type of @na.
6105 * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
6107 static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize,
6108 hole_type holes)
6110 LCN lcn_seek_from;
6111 VCN first_free_vcn;
6112 ntfs_volume *vol;
6113 ntfs_attr_search_ctx *ctx;
6114 runlist *rl, *rln;
6115 s64 org_alloc_size;
6116 int err;
6118 ntfs_log_trace("Inode %lld, attr 0x%x, new size %lld old size %lld\n",
6119 (unsigned long long)na->ni->mft_no, na->type,
6120 (long long)newsize, (long long)na->data_size);
6122 vol = na->ni->vol;
6125 * Check the attribute type and the corresponding maximum size
6126 * against @newsize and fail if @newsize is too big.
6128 if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
6129 if (errno == ENOENT)
6130 errno = EIO;
6131 ntfs_log_perror("%s: bounds check failed", __FUNCTION__);
6132 return -1;
6135 if (na->type == AT_DATA)
6136 NAttrSetDataAppending(na);
6137 /* Save for future use. */
6138 org_alloc_size = na->allocated_size;
6139 /* The first cluster outside the new allocation. */
6140 first_free_vcn = (newsize + vol->cluster_size - 1) >>
6141 vol->cluster_size_bits;
6143 * Compare the new allocation with the old one and only allocate
6144 * clusters if there is a change.
6146 if ((na->allocated_size >> vol->cluster_size_bits) < first_free_vcn) {
6147 #if PARTIAL_RUNLIST_UPDATING
6148 s64 start_update;
6151 * Update from the last previously allocated run,
6152 * as we may have to expand an existing hole.
6154 start_update = na->allocated_size >> vol->cluster_size_bits;
6155 if (start_update)
6156 start_update--;
6157 if (ntfs_attr_map_partial_runlist(na, start_update)) {
6158 ntfs_log_perror("failed to map partial runlist");
6159 return -1;
6161 #else
6162 if (ntfs_attr_map_whole_runlist(na)) {
6163 ntfs_log_perror("ntfs_attr_map_whole_runlist failed");
6164 return -1;
6166 #endif
6169 * If we extend $DATA attribute on NTFS 3+ volume, we can add
6170 * sparse runs instead of real allocation of clusters.
6172 if ((na->type == AT_DATA) && (vol->major_ver >= 3)
6173 && (holes != HOLES_NO)) {
6174 rl = ntfs_malloc(0x1000);
6175 if (!rl)
6176 return -1;
6178 rl[0].vcn = (na->allocated_size >>
6179 vol->cluster_size_bits);
6180 rl[0].lcn = LCN_HOLE;
6181 rl[0].length = first_free_vcn -
6182 (na->allocated_size >> vol->cluster_size_bits);
6183 rl[1].vcn = first_free_vcn;
6184 rl[1].lcn = LCN_ENOENT;
6185 rl[1].length = 0;
6186 } else {
6188 * Determine first after last LCN of attribute.
6189 * We will start seek clusters from this LCN to avoid
6190 * fragmentation. If there are no valid LCNs in the
6191 * attribute let the cluster allocator choose the
6192 * starting LCN.
6194 lcn_seek_from = -1;
6195 if (na->rl->length) {
6196 /* Seek to the last run list element. */
6197 for (rl = na->rl; (rl + 1)->length; rl++)
6200 * If the last LCN is a hole or similar seek
6201 * back to last valid LCN.
6203 while (rl->lcn < 0 && rl != na->rl)
6204 rl--;
6206 * Only set lcn_seek_from it the LCN is valid.
6208 if (rl->lcn >= 0)
6209 lcn_seek_from = rl->lcn + rl->length;
6212 rl = ntfs_cluster_alloc(vol, na->allocated_size >>
6213 vol->cluster_size_bits, first_free_vcn -
6214 (na->allocated_size >>
6215 vol->cluster_size_bits), lcn_seek_from,
6216 DATA_ZONE);
6217 if (!rl) {
6218 ntfs_log_perror("Cluster allocation failed "
6219 "(%lld)",
6220 (long long)first_free_vcn -
6221 ((long long)na->allocated_size >>
6222 vol->cluster_size_bits));
6223 return -1;
6227 /* Append new clusters to attribute runlist. */
6228 rln = ntfs_runlists_merge(na->rl, rl);
6229 if (!rln) {
6230 /* Failed, free just allocated clusters. */
6231 err = errno;
6232 ntfs_log_perror("Run list merge failed");
6233 ntfs_cluster_free_from_rl(vol, rl);
6234 free(rl);
6235 errno = err;
6236 return -1;
6238 na->rl = rln;
6240 /* Prepare to mapping pairs update. */
6241 na->allocated_size = first_free_vcn << vol->cluster_size_bits;
6242 #if PARTIAL_RUNLIST_UPDATING
6244 * Write mapping pairs for new runlist, unless this is
6245 * a temporary state before appending data.
6246 * If the update is not done, we must be sure to do
6247 * it later, and to get to a clean state even on errors.
6249 if ((holes != HOLES_DELAY)
6250 && ntfs_attr_update_mapping_pairs_i(na, start_update,
6251 holes)) {
6252 #else
6253 /* Write mapping pairs for new runlist. */
6254 if (ntfs_attr_update_mapping_pairs(na, 0)) {
6255 #endif
6256 err = errno;
6257 ntfs_log_perror("Mapping pairs update failed");
6258 goto rollback;
6262 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
6263 if (!ctx) {
6264 err = errno;
6265 if (na->allocated_size == org_alloc_size) {
6266 errno = err;
6267 return -1;
6268 } else
6269 goto rollback;
6272 if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
6273 0, NULL, 0, ctx)) {
6274 err = errno;
6275 ntfs_log_perror("Lookup of first attribute extent failed");
6276 if (err == ENOENT)
6277 err = EIO;
6278 if (na->allocated_size != org_alloc_size) {
6279 ntfs_attr_put_search_ctx(ctx);
6280 goto rollback;
6281 } else
6282 goto put_err_out;
6285 /* Update data size. */
6286 na->data_size = newsize;
6287 ctx->attr->data_size = cpu_to_sle64(newsize);
6288 /* Update data size in the index. */
6289 if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
6290 if (na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30) {
6291 na->ni->data_size = na->data_size;
6292 na->ni->allocated_size = na->allocated_size;
6293 set_nino_flag(na->ni,KnownSize);
6295 } else {
6296 if (na->type == AT_DATA && na->name == AT_UNNAMED) {
6297 na->ni->data_size = na->data_size;
6298 NInoFileNameSetDirty(na->ni);
6301 /* Set the inode dirty so it is written out later. */
6302 ntfs_inode_mark_dirty(ctx->ntfs_ino);
6303 /* Done! */
6304 ntfs_attr_put_search_ctx(ctx);
6305 return 0;
6306 rollback:
6307 /* Free allocated clusters. */
6308 if (ntfs_cluster_free(vol, na, org_alloc_size >>
6309 vol->cluster_size_bits, -1) < 0) {
6310 err = EIO;
6311 ntfs_log_perror("Leaking clusters");
6313 /* Now, truncate the runlist itself. */
6314 if (ntfs_rl_truncate(&na->rl, org_alloc_size >>
6315 vol->cluster_size_bits)) {
6317 * Failed to truncate the runlist, so just throw it away, it
6318 * will be mapped afresh on next use.
6320 free(na->rl);
6321 na->rl = NULL;
6322 ntfs_log_perror("Couldn't truncate runlist. Rollback failed");
6323 } else {
6324 /* Prepare to mapping pairs update. */
6325 na->allocated_size = org_alloc_size;
6326 /* Restore mapping pairs. */
6327 if (ntfs_attr_update_mapping_pairs(na, 0 /*na->allocated_size >>
6328 vol->cluster_size_bits*/)) {
6329 ntfs_log_perror("Failed to restore old mapping pairs");
6332 errno = err;
6333 return -1;
6334 put_err_out:
6335 ntfs_attr_put_search_ctx(ctx);
6336 errno = err;
6337 return -1;
6341 static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
6342 hole_type holes)
6344 int ret;
6346 ntfs_log_enter("Entering\n");
6347 ret = ntfs_non_resident_attr_expand_i(na, newsize, holes);
6348 ntfs_log_leave("\n");
6349 return ret;
6353 * ntfs_attr_truncate - resize an ntfs attribute
6354 * @na: open ntfs attribute to resize
6355 * @newsize: new size (in bytes) to which to resize the attribute
6356 * @holes: how to create a hole if expanding
6358 * Change the size of an open ntfs attribute @na to @newsize bytes. If the
6359 * attribute is made bigger and the attribute is resident the newly
6360 * "allocated" space is cleared and if the attribute is non-resident the
6361 * newly allocated space is marked as not initialised and no real allocation
6362 * on disk is performed.
6364 * On success return 0.
6365 * On error return values are:
6366 * STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT
6367 * STATUS_ERROR - otherwise
6368 * The following error codes are defined:
6369 * EINVAL - Invalid arguments were passed to the function.
6370 * EOPNOTSUPP - The desired resize is not implemented yet.
6371 * EACCES - Encrypted attribute.
6373 static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
6374 hole_type holes)
6376 int ret = STATUS_ERROR;
6377 s64 fullsize;
6378 BOOL compressed;
6380 if (!na || newsize < 0 ||
6381 (na->ni->mft_no == FILE_MFT && na->type == AT_DATA)) {
6382 ntfs_log_trace("Invalid arguments passed.\n");
6383 errno = EINVAL;
6384 return STATUS_ERROR;
6387 ntfs_log_enter("Entering for inode %lld, attr 0x%x, size %lld\n",
6388 (unsigned long long)na->ni->mft_no, na->type,
6389 (long long)newsize);
6391 if (na->data_size == newsize) {
6392 ntfs_log_trace("Size is already ok\n");
6393 ret = STATUS_OK;
6394 goto out;
6397 * Encrypted attributes are not supported. We return access denied,
6398 * which is what Windows NT4 does, too.
6400 if (na->data_flags & ATTR_IS_ENCRYPTED) {
6401 errno = EACCES;
6402 ntfs_log_trace("Cannot truncate encrypted attribute\n");
6403 goto out;
6406 * TODO: Implement making handling of compressed attributes.
6407 * Currently we can only expand the attribute or delete it,
6408 * and only for ATTR_IS_COMPRESSED. This is however possible
6409 * for resident attributes when there is no open fuse context
6410 * (important case : $INDEX_ROOT:$I30)
6412 compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
6413 != const_cpu_to_le16(0);
6414 if (compressed
6415 && NAttrNonResident(na)
6416 && ((na->data_flags & ATTR_COMPRESSION_MASK) != ATTR_IS_COMPRESSED)) {
6417 errno = EOPNOTSUPP;
6418 ntfs_log_perror("Failed to truncate compressed attribute");
6419 goto out;
6421 if (NAttrNonResident(na)) {
6423 * For compressed data, the last block must be fully
6424 * allocated, and we do not know the size of compression
6425 * block until the attribute has been made non-resident.
6426 * Moreover we can only process a single compression
6427 * block at a time (from where we are about to write),
6428 * so we silently do not allocate more.
6430 * Note : do not request upsizing of compressed files
6431 * unless being able to face the consequences !
6433 if (compressed && newsize && (newsize > na->data_size))
6434 fullsize = (na->initialized_size
6435 | (na->compression_block_size - 1)) + 1;
6436 else
6437 fullsize = newsize;
6438 if (fullsize > na->data_size)
6439 ret = ntfs_non_resident_attr_expand(na, fullsize,
6440 holes);
6441 else
6442 ret = ntfs_non_resident_attr_shrink(na, fullsize);
6443 } else
6444 ret = ntfs_resident_attr_resize(na, newsize);
6445 out:
6446 ntfs_log_leave("Return status %d\n", ret);
6447 return ret;
6451 * Resize an attribute, creating a hole if relevant
6454 int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
6456 int r;
6458 r = ntfs_attr_truncate_i(na, newsize, HOLES_OK);
6459 NAttrClearDataAppending(na);
6460 NAttrClearBeingNonResident(na);
6461 return (r);
6465 * Resize an attribute, avoiding hole creation
6468 int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize)
6470 return (ntfs_attr_truncate_i(na, newsize, HOLES_NO));
6474 * Stuff a hole in a compressed file
6476 * An unallocated hole must be aligned on compression block size.
6477 * If needed current block and target block are stuffed with zeroes.
6479 * Returns 0 if succeeded,
6480 * -1 if it failed (as explained in errno)
6483 static int stuff_hole(ntfs_attr *na, const s64 pos)
6485 s64 size;
6486 s64 begin_size;
6487 s64 end_size;
6488 char *buf;
6489 int ret;
6491 ret = 0;
6493 * If the attribute is resident, the compression block size
6494 * is not defined yet and we can make no decision.
6495 * So we first try resizing to the target and if the
6496 * attribute is still resident, we're done
6498 if (!NAttrNonResident(na)) {
6499 ret = ntfs_resident_attr_resize(na, pos);
6500 if (!ret && !NAttrNonResident(na))
6501 na->initialized_size = na->data_size = pos;
6503 if (!ret && NAttrNonResident(na)) {
6504 /* does the hole span over several compression block ? */
6505 if ((pos ^ na->initialized_size)
6506 & ~(na->compression_block_size - 1)) {
6507 begin_size = ((na->initialized_size - 1)
6508 | (na->compression_block_size - 1))
6509 + 1 - na->initialized_size;
6510 end_size = pos & (na->compression_block_size - 1);
6511 size = (begin_size > end_size ? begin_size : end_size);
6512 } else {
6513 /* short stuffing in a single compression block */
6514 begin_size = size = pos - na->initialized_size;
6515 end_size = 0;
6517 if (size)
6518 buf = (char*)ntfs_malloc(size);
6519 else
6520 buf = (char*)NULL;
6521 if (buf || !size) {
6522 memset(buf,0,size);
6523 /* stuff into current block */
6524 if (begin_size
6525 && (ntfs_attr_pwrite(na,
6526 na->initialized_size, begin_size, buf)
6527 != begin_size))
6528 ret = -1;
6529 /* create an unstuffed hole */
6530 if (!ret
6531 && ((na->initialized_size + end_size) < pos)
6532 && ntfs_non_resident_attr_expand(na,
6533 pos - end_size, HOLES_OK))
6534 ret = -1;
6535 else
6536 na->initialized_size
6537 = na->data_size = pos - end_size;
6538 /* stuff into the target block */
6539 if (!ret && end_size
6540 && (ntfs_attr_pwrite(na,
6541 na->initialized_size, end_size, buf)
6542 != end_size))
6543 ret = -1;
6544 if (buf)
6545 free(buf);
6546 } else
6547 ret = -1;
6549 /* make absolutely sure we have reached the target */
6550 if (!ret && (na->initialized_size != pos)) {
6551 ntfs_log_error("Failed to stuff a compressed file"
6552 "target %lld reached %lld\n",
6553 (long long)pos, (long long)na->initialized_size);
6554 errno = EIO;
6555 ret = -1;
6557 return (ret);
6561 * ntfs_attr_readall - read the entire data from an ntfs attribute
6562 * @ni: open ntfs inode in which the ntfs attribute resides
6563 * @type: attribute type
6564 * @name: attribute name in little endian Unicode or AT_UNNAMED or NULL
6565 * @name_len: length of attribute @name in Unicode characters (if @name given)
6566 * @data_size: if non-NULL then store here the data size
6568 * This function will read the entire content of an ntfs attribute.
6569 * If @name is AT_UNNAMED then look specifically for an unnamed attribute.
6570 * If @name is NULL then the attribute could be either named or not.
6571 * In both those cases @name_len is not used at all.
6573 * On success a buffer is allocated with the content of the attribute
6574 * and which needs to be freed when it's not needed anymore. If the
6575 * @data_size parameter is non-NULL then the data size is set there.
6577 * On error NULL is returned with errno set to the error code.
6579 void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
6580 ntfschar *name, u32 name_len, s64 *data_size)
6582 ntfs_attr *na;
6583 void *data, *ret = NULL;
6584 s64 size;
6586 ntfs_log_enter("Entering\n");
6588 na = ntfs_attr_open(ni, type, name, name_len);
6589 if (!na) {
6590 ntfs_log_perror("ntfs_attr_open failed");
6591 goto err_exit;
6593 data = ntfs_malloc(na->data_size);
6594 if (!data)
6595 goto out;
6597 size = ntfs_attr_pread(na, 0, na->data_size, data);
6598 if (size != na->data_size) {
6599 ntfs_log_perror("ntfs_attr_pread failed");
6600 free(data);
6601 goto out;
6603 ret = data;
6604 if (data_size)
6605 *data_size = size;
6606 out:
6607 ntfs_attr_close(na);
6608 err_exit:
6609 ntfs_log_leave("\n");
6610 return ret;
6614 * Read some data from a data attribute
6616 * Returns the amount of data read, negative if there was an error
6619 int ntfs_attr_data_read(ntfs_inode *ni,
6620 ntfschar *stream_name, int stream_name_len,
6621 char *buf, size_t size, off_t offset)
6623 ntfs_attr *na = NULL;
6624 int res, total = 0;
6626 na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
6627 if (!na) {
6628 res = -errno;
6629 goto exit;
6631 if ((size_t)offset < (size_t)na->data_size) {
6632 if (offset + size > (size_t)na->data_size)
6633 size = na->data_size - offset;
6634 while (size) {
6635 res = ntfs_attr_pread(na, offset, size, buf + total);
6636 if ((off_t)res < (off_t)size)
6637 ntfs_log_perror("ntfs_attr_pread partial read "
6638 "(%lld : %lld <> %d)",
6639 (long long)offset,
6640 (long long)size, res);
6641 if (res <= 0) {
6642 res = -errno;
6643 goto exit;
6645 size -= res;
6646 offset += res;
6647 total += res;
6650 res = total;
6651 exit:
6652 if (na)
6653 ntfs_attr_close(na);
6654 return res;
6659 * Write some data into a data attribute
6661 * Returns the amount of data written, negative if there was an error
6664 int ntfs_attr_data_write(ntfs_inode *ni, ntfschar *stream_name,
6665 int stream_name_len, const char *buf, size_t size, off_t offset)
6667 ntfs_attr *na = NULL;
6668 int res, total = 0;
6670 na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
6671 if (!na) {
6672 res = -errno;
6673 goto exit;
6675 while (size) {
6676 res = ntfs_attr_pwrite(na, offset, size, buf + total);
6677 if (res < (s64)size)
6678 ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "
6679 "%lld <> %d)", (long long)offset,
6680 (long long)size, res);
6681 if (res <= 0) {
6682 res = -errno;
6683 goto exit;
6685 size -= res;
6686 offset += res;
6687 total += res;
6689 res = total;
6690 exit:
6691 if (na)
6692 ntfs_attr_close(na);
6693 return res;
6697 int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, const ntfschar *name,
6698 u32 name_len)
6700 ntfs_attr_search_ctx *ctx;
6701 int ret;
6703 ntfs_log_trace("Entering\n");
6705 ctx = ntfs_attr_get_search_ctx(ni, NULL);
6706 if (!ctx)
6707 return 0;
6709 ret = ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, 0, NULL, 0,
6710 ctx);
6712 ntfs_attr_put_search_ctx(ctx);
6714 return !ret;
6717 int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,
6718 u32 name_len)
6720 ntfs_attr *na;
6721 int ret;
6723 ntfs_log_trace("Entering\n");
6725 if (!ni) {
6726 ntfs_log_error("%s: NULL inode pointer", __FUNCTION__);
6727 errno = EINVAL;
6728 return -1;
6731 na = ntfs_attr_open(ni, type, name, name_len);
6732 if (!na) {
6733 /* do not log removal of non-existent stream */
6734 if (type != AT_DATA) {
6735 ntfs_log_perror("Failed to open attribute 0x%02x of inode "
6736 "0x%llx", type, (unsigned long long)ni->mft_no);
6738 return -1;
6741 ret = ntfs_attr_rm(na);
6742 if (ret)
6743 ntfs_log_perror("Failed to remove attribute 0x%02x of inode "
6744 "0x%llx", type, (unsigned long long)ni->mft_no);
6745 ntfs_attr_close(na);
6747 return ret;
6750 /* Below macros are 32-bit ready. */
6751 #define BCX(x) ((x) - (((x) >> 1) & 0x77777777) - \
6752 (((x) >> 2) & 0x33333333) - \
6753 (((x) >> 3) & 0x11111111))
6754 #define BITCOUNT(x) (((BCX(x) + (BCX(x) >> 4)) & 0x0F0F0F0F) % 255)
6756 static u8 *ntfs_init_lut256(void)
6758 int i;
6759 u8 *lut;
6761 lut = ntfs_malloc(256);
6762 if (lut)
6763 for(i = 0; i < 256; i++)
6764 *(lut + i) = 8 - BITCOUNT(i);
6765 return lut;
6768 s64 ntfs_attr_get_free_bits(ntfs_attr *na)
6770 u8 *buf, *lut;
6771 s64 br = 0;
6772 s64 total = 0;
6773 s64 nr_free = 0;
6775 lut = ntfs_init_lut256();
6776 if (!lut)
6777 return -1;
6779 buf = ntfs_malloc(65536);
6780 if (!buf)
6781 goto out;
6783 while (1) {
6784 u32 *p;
6785 br = ntfs_attr_pread(na, total, 65536, buf);
6786 if (br <= 0)
6787 break;
6788 total += br;
6789 p = (u32 *)buf + br / 4 - 1;
6790 for (; (u8 *)p >= buf; p--) {
6791 nr_free += lut[ *p & 255] +
6792 lut[(*p >> 8) & 255] +
6793 lut[(*p >> 16) & 255] +
6794 lut[(*p >> 24) ];
6796 switch (br % 4) {
6797 case 3: nr_free += lut[*(buf + br - 3)];
6798 case 2: nr_free += lut[*(buf + br - 2)];
6799 case 1: nr_free += lut[*(buf + br - 1)];
6802 free(buf);
6803 out:
6804 free(lut);
6805 if (!total || br < 0)
6806 return -1;
6807 return nr_free;