b04bb382ab587c530dc48000adba6a314cec1763
[ntfsprogs.git] / libntfs / attrib.c
1 /*
2  * attrib.c - Attribute handling code. Part of the Linux-NTFS project.
3  *
4  * Copyright (c) 2000-2003 Anton Altaparmakov
5  * Copyright (c) 2002 Richard Russon
6  *
7  * This program/include file is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program/include file is distributed in the hope that it will be
13  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program (in the main directory of the Linux-NTFS
19  * distribution in the file COPYING); if not, write to the Free Software
20  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27
28 #include "compat.h"
29
30 #include "attrib.h"
31 #include "disk_io.h"
32 #include "mft.h"
33 #include "debug.h"
34 #include "mst.h"
35 #include "volume.h"
36 #include "types.h"
37 #include "layout.h"
38 #include "inode.h"
39 #include "runlist.h"
40 #include "lcnalloc.h"
41 #include "dir.h"
42
43 uchar_t AT_UNNAMED[] = { const_cpu_to_le16('\0') };
44
45 /**
46  * ntfs_get_attribute_value_length
47  */
48 s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a)
49 {
50         if (!a) {
51                 errno = EINVAL;
52                 return 0;
53         }
54         errno = 0;
55         if (a->non_resident)
56                 return sle64_to_cpu(a->data_size);
57         else
58                 return (s64)le32_to_cpu(a->value_length);
59         errno = EINVAL;
60         return 0;
61 }
62
63 /**
64  * ntfs_get_attribute_value
65  */
66 s64 ntfs_get_attribute_value(const ntfs_volume *vol, const MFT_RECORD *m,
67                           const ATTR_RECORD *a, u8 *b)
68 {
69         /* Sanity checks. */
70         if (!vol || !m || !a || !b) {
71                 errno = EINVAL;
72                 return 0;
73         }
74         /* Complex attribute? */
75         if (a->flags) {
76                 puts("Enountered non-zero attribute flags. Cannot handle this "
77                      "yet.");
78                 errno = ENOTSUP;
79                 return 0;
80         }
81         if (!a->non_resident) {         /* Attribute is resident. */
82                 /* Sanity check. */
83                 if (le32_to_cpu(a->value_length) +
84                     le16_to_cpu(a->value_offset) > le32_to_cpu(a->length)) {
85                         return 0;
86                 }
87                 memcpy(b, (char*)a + le16_to_cpu(a->value_offset),
88                                         le32_to_cpu(a->value_length));
89                 errno = 0;
90                 return (s64)le32_to_cpu(a->value_length);
91         } else {                        /* Attribute is not resident. */
92                 runlist *rl;
93                 s64 total, r;
94                 int i;
95
96                 /* If no data, return 0. */
97                 if (!(a->data_size)) {
98                         errno = 0;
99                         return 0;
100                 }
101                 /*
102                  * FIXME: What about attribute lists?!? (AIA)
103                  */
104                 /* Decompress the mapping pairs array into a runlist. */
105                 rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
106                 if (!rl) {
107                         errno = EINVAL;
108                         return 0;
109                 }
110                 /*
111                  * FIXED: We were overflowing here in a nasty fashion when we
112                  * reach the last cluster in the runlist as the buffer will
113                  * only be big enough to hold data_size bytes while we are
114                  * reading in allocated_size bytes which is usually larger
115                  * than data_size, since the actual data is unlikely to have a
116                  * size equal to a multiple of the cluster size!
117                  */
118                 /* Now load all clusters in the runlist into b. */
119                 for (i = 0, total = 0; rl[i].length; i++) {
120                         if (!rl[i+1].length) {
121                                 unsigned char *intbuf = NULL;
122                                 /*
123                                  * We have reached the last run so we were
124                                  * going to overflow when executing the
125                                  * ntfs_pread() which is BAAAAAAAD!
126                                  * Temporary fix:
127                                  *      Allocate a new buffer with size:
128                                  *      rl[i].length << vol->cluster_size_bits,
129                                  *      do the read into our buffer, then
130                                  *      memcpy the correct amount of data into
131                                  *      the caller supplied buffer, free our
132                                  *      buffer, and continue.
133                                  */
134                                 intbuf = malloc(rl[i].length <<
135                                                         vol->cluster_size_bits);
136                                 if (!intbuf) {
137                                         int eo = errno;
138                                         perror("Couldn't allocate memory for "
139                                                         "internal buffer.\n");
140                                         free(rl);
141                                         errno = eo;
142                                         return 0;
143                                 }
144                                 /*
145                                  * FIXME: If compressed file: Only read if
146                                  * lcn != -1. Otherwise, we are dealing with a
147                                  * sparse run and we just memset the user buffer
148                                  * to 0 for the length of the run, which should
149                                  * be 16 (= compression unit size).
150                                  * FIXME: Really only when file is compressed,
151                                  * or can we have sparse runs in uncompressed
152                                  * files as well?
153                                  */
154                                 r = ntfs_pread(vol->dev, rl[i].lcn <<
155                                                 vol->cluster_size_bits,
156                                                 rl[i].length <<
157                                                 vol->cluster_size_bits, intbuf);
158                                 if (r != rl[i].length <<
159                                                 vol->cluster_size_bits) {
160 #define ESTR "Error reading attribute value"
161                                         if (r == -1) {
162                                                 int eo = errno;
163                                                 perror(ESTR);
164                                                 errno = eo;
165                                         } else if (r < rl[i].length <<
166                                                         vol->cluster_size_bits
167                                                         ) {
168                                                 fprintf(stderr, ESTR ": Ran "
169                                                         "out of input data.\n");
170                                                 errno = EIO;
171                                         } else {
172                                                 fprintf(stderr, ESTR ": "
173                                                            "unknown error\n");
174                                                 errno = EIO;
175                                         }
176 #undef ESTR
177                                         free(rl);
178                                         return 0;
179                                 }
180                                 memcpy(b + total, intbuf,
181                                        sle64_to_cpu(a->data_size) - total);
182                                 free(intbuf);
183                                 total = sle64_to_cpu(a->data_size);
184                         } else {
185                                 /*
186                                  * FIXME: If compressed file: Only read if
187                                  * lcn != -1. Otherwise, we are dealing with a
188                                  * sparse run and we just memset the user buffer
189                                  * to 0 for the length of the run, which should
190                                  * be 16 (= compression unit size).
191                                  */
192                                 r = ntfs_pread(vol->dev, rl[i].lcn <<
193                                                 vol->cluster_size_bits,
194                                                 rl[i].length <<
195                                                 vol->cluster_size_bits,
196                                                 b + total);
197                                 if (r != rl[i].length <<
198                                                 vol->cluster_size_bits) {
199 #define ESTR "Error reading attribute value"
200                                         if (r == -1) {
201                                                 int eo = errno;
202                                                 perror(ESTR);
203                                                 errno = eo;
204                                         } else if (r < rl[i].length <<
205                                                         vol->cluster_size_bits
206                                                         ) {
207                                                 fprintf(stderr, ESTR ": Ran "
208                                                         "out of input data.\n");
209                                                 errno = EIO;
210                                         } else {
211                                                 fprintf(stderr, ESTR ": "
212                                                            "unknown error\n");
213                                                 errno = EIO;
214                                         }
215 #undef ESTR
216                                         return 0;
217                                 }
218                                 total += r;
219                         }
220                 }
221                 free(rl);
222                 return total;
223         }
224         errno = EINVAL;
225         return 0;
226 }
227
228 /* Already cleaned up code below, but still look for FIXME:... */
229
230 /**
231  * Internal:
232  *
233  * __ntfs_attr_init - primary initialization of an ntfs attribute structure
234  * @na:         ntfs attribute to initialize
235  * @ni:         ntfs inode with which to initialize the ntfs attribute
236  * @type:       attribute type
237  * @name:       attribute name in little endian Unicode or NULL
238  * @name_len:   length of attribute @name in Unicode characters (if @name given)
239  *
240  * Initialize the ntfs attribute @na with @ni, @type, @name, and @name_len.
241  */
242 static __inline__ void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni,
243                 const ATTR_TYPES type, uchar_t *name, const u32 name_len)
244 {
245         na->rl = NULL;
246         na->ni = ni;
247         na->type = type;
248         if (name) {
249                 na->name     = name;
250                 na->name_len = name_len;
251         } else {
252                 na->name     = AT_UNNAMED;
253                 na->name_len = 0;
254         }
255 }
256
257 /**
258  * ntfs_attr_init - initialize an ntfs_attr with data sizes and status
259  * @na:
260  * @non_resident:
261  * @compressed:
262  * @ecnrypted:
263  * @sparse:
264  * @allocated_size:
265  * @data_size:
266  * @initialized_size:
267  * @compressed_size:
268  * @compression_unit:
269  *
270  * Final initialization for an ntfs attribute.
271  */
272 void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
273                 const BOOL compressed, const BOOL encrypted, const BOOL sparse,
274                 const s64 allocated_size, const s64 data_size,
275                 const s64 initialized_size, const s64 compressed_size,
276                 const u8 compression_unit)
277 {
278         if (!NAttrInitialized(na)) {
279                 if (non_resident)
280                         NAttrSetNonResident(na);
281                 if (compressed)
282                         NAttrSetCompressed(na);
283                 if (encrypted)
284                         NAttrSetEncrypted(na);
285                 if (sparse)
286                         NAttrSetSparse(na);
287                 na->allocated_size = allocated_size;
288                 na->data_size = data_size;
289                 na->initialized_size = initialized_size;
290                 if (compressed || sparse) {
291                         ntfs_volume *vol = na->ni->vol;
292
293                         na->compressed_size = compressed_size;
294                         na->compression_block_clusters = 1 << compression_unit;
295                         na->compression_block_size = 1 << (compression_unit +
296                                         vol->cluster_size_bits);
297                         na->compression_block_size_bits = ffs(
298                                         na->compression_block_size) - 1;
299                 }
300                 NAttrSetInitialized(na);
301         }
302 }
303
304 /**
305  * ntfs_attr_open - open an ntfs attribute for access
306  * @ni:         open ntfs inode in which the ntfs attribute resides
307  * @type:       attribute type
308  * @name:       attribute name in little endian Unicode or NULL
309  * @name_len:   length of attribute @name in Unicode characters (if @name given)
310  *
311  * Allocate a new ntfs attribute structure, initialize it with @ni, @type,
312  * @name, and @name_len, then return it. Return NULL on error with
313  * errno set to the error code.
314  *
315  * If looking for an unnamed attribute set @name to NULL. @name_len is not used
316  * at all in that case.
317  */
318 ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
319                 uchar_t *name, const u32 name_len)
320 {
321         ntfs_attr_search_ctx *ctx;
322         ntfs_attr *na;
323         ATTR_RECORD *a;
324         int err;
325
326         Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x.\n", __FUNCTION__,
327                         (unsigned long long)ni->mft_no, type);
328         if (!ni || !ni->vol || !ni->mrec) {
329                 errno = EINVAL;
330                 return NULL;
331         }
332         na = calloc(sizeof(ntfs_attr), 1);
333         if (!na)
334                 return NULL;
335         __ntfs_attr_init(na, ni, type, name, name_len);
336
337         ctx = ntfs_attr_get_search_ctx(ni, NULL);
338         if (!ctx) {
339                 err = errno;
340                 goto err_out;
341         }
342
343         if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx)) {
344                 err = errno;
345                 goto put_err_out;
346         }
347         a = ctx->attr;
348         if (a->non_resident) {
349                 BOOL cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
350                 ntfs_attr_init(na, TRUE, a->flags & ATTR_IS_COMPRESSED,
351                                 a->flags & ATTR_IS_ENCRYPTED,
352                                 a->flags & ATTR_IS_SPARSE,
353                                 sle64_to_cpu(a->allocated_size),
354                                 sle64_to_cpu(a->data_size),
355                                 sle64_to_cpu(a->initialized_size),
356                                 cs ? sle64_to_cpu(a->compressed_size) : 0,
357                                 cs ? a->compression_unit : 0);
358         } else {
359                 s64 l = le32_to_cpu(a->value_length);
360                 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |
361                                 ATTR_IS_SPARSE)) {
362                         err = EIO;
363                         goto put_err_out;
364                 }
365                 ntfs_attr_init(na, FALSE, FALSE, FALSE, FALSE, l, l, l, 0, 0);
366         }
367         ntfs_attr_put_search_ctx(ctx);
368         return na;
369 put_err_out:
370         ntfs_attr_put_search_ctx(ctx);
371 err_out:
372         errno = err;
373         return NULL;
374 }
375
376 /**
377  * ntfs_attr_close - free an ntfs attribute structure
378  * @na:         ntfs attribute structure to free
379  *
380  * Release all memory associated with the ntfs attribute @na and then release
381  * @na itself.
382  */
383 void ntfs_attr_close(ntfs_attr *na)
384 {
385         if (NAttrNonResident(na) && na->rl)
386                 free(na->rl);
387         /* Don't release if using an internal constant. */
388         if (na->name != AT_UNNAMED && na->name != I30)
389                 free(na->name);
390         free(na);
391         return;
392 }
393
394 /**
395  * ntfs_attr_map_runlist - map (a part of) a runlist of an ntfs attribute
396  * @na:         ntfs attribute for which to map (part of) a runlist
397  * @vcn:        map runlist part containing this vcn
398  *
399  * Map the part of a runlist containing the @vcn of an the ntfs attribute @na.
400  *
401  * Return 0 on success and -1 on error with errno set to the error code.
402  */
403 int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
404 {
405         ntfs_attr_search_ctx *ctx;
406         int err;
407
408         Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x, vcn 0x%Lx.\n",
409                         __FUNCTION__, (unsigned long long)na->ni->mft_no,
410                         na->type, (long long)vcn);
411
412         ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
413         if (!ctx)
414                 return -1;
415
416         /* Find the attribute in the mft record. */
417         if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
418                         vcn, NULL, 0, ctx)) {
419                 runlist_element *rl;
420
421                 /* Decode the runlist. */
422                 rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr,
423                                 na->rl);
424                 if (rl) {
425                         na->rl = rl;
426
427                         ntfs_attr_put_search_ctx(ctx);
428                         return 0;
429                 }
430         }
431         err = errno;
432         ntfs_attr_put_search_ctx(ctx);
433         errno = err;
434         return -1;
435 }
436
437 /**
438  * ntfs_attr_vcn_to_lcn - convert a vcn into a lcn given an ntfs attribute
439  * @na:         ntfs attribute whose runlist to use for conversion
440  * @vcn:        vcn to convert
441  *
442  * Convert the virtual cluster number @vcn of an attribute into a logical
443  * cluster number (lcn) of a device using the runlist @na->rl to map vcns to
444  * their corresponding lcns.
445  *
446  * If the @vcn is not mapped yet, attempt to map the attribute extent
447  * containing the @vcn and retry the vcn to lcn conversion.
448  *
449  * Since lcns must be >= 0, we use negative return values with special meaning:
450  *
451  * Return value         Meaning / Description
452  * ==========================================
453  *  -1 = LCN_HOLE       Hole / not allocated on disk.
454  *  -3 = LCN_ENOENT     There is no such vcn in the attribute.
455  *  -4 = LCN_EINVAL     Input parameter error.
456  *  -5 = LCN_EIO        Corrupt fs, disk i/o error, or not enough memory.
457  */
458 LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn)
459 {
460         LCN lcn;
461         BOOL is_retry = FALSE;
462
463         if (!na || !NAttrNonResident(na) || vcn < 0)
464                 return (LCN)LCN_EINVAL;
465 retry:
466         /* Convert vcn to lcn. If that fails map the runlist and retry once. */
467         lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
468         if (lcn >= 0)
469                 return lcn;
470         if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
471                 is_retry = TRUE;
472                 goto retry;
473         }
474         /*
475          * If the attempt to map the runlist failed, or we are getting
476          * LCN_RL_NOT_MAPPED despite having mapped the attribute extent
477          * successfully, something is really badly wrong...
478          */
479         if (!is_retry || lcn == (LCN)LCN_RL_NOT_MAPPED)
480                 return (LCN)LCN_EIO;
481         /* lcn contains the appropriate error code. */
482         return lcn;
483 }
484
485 /**
486  * ntfs_attr_find_vcn - find a vcn in the runlist of an ntfs attribute
487  * @na:         ntfs attribute whose runlist to search
488  * @vcn:        vcn to find
489  *
490  * Find the virtual cluster number @vcn in the runlist of the ntfs attribute
491  * @na and return the the address of the runlist element containing the @vcn.
492  *
493  * Note you need to distinguish between the lcn of the returned runlist
494  * element being >= 0 and LCN_HOLE. In the later case you have to return zeroes
495  * on read and allocate clusters on write. You need to update the runlist, the
496  * attribute itself as well as write the modified mft record to disk.
497  *
498  * If there is an error return NULL with errno set to the error code. The
499  * following error codes are defined:
500  *      EINVAL          Input parameter error.
501  *      ENOENT          There is no such vcn in the runlist.
502  *      ENOMEM          Not enough memory.
503  *      EIO             I/O error or corrupt metadata.
504  */
505 runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn)
506 {
507         runlist_element *rl;
508         BOOL is_retry = FALSE;
509
510         if (!na || !NAttrNonResident(na) || vcn < 0) {
511                 errno = EINVAL;
512                 return NULL;
513         }
514 retry:
515         rl = na->rl;
516         if (!rl)
517                 goto map_rl;
518         if (vcn < rl[0].vcn)
519                 goto map_rl;
520         while (rl->length) {
521                 if (vcn < rl[1].vcn) {
522                         if (rl->lcn >= (LCN)LCN_HOLE)
523                                 return rl;
524                         break;
525                 }
526                 rl++;
527         }
528         switch (rl->lcn) {
529         case (LCN)LCN_RL_NOT_MAPPED:
530                 goto map_rl;
531         case (LCN)LCN_ENOENT:
532                 errno = ENOENT;
533                 break;
534         case (LCN)LCN_EINVAL:
535                 errno = EINVAL;
536                 break;
537         default:
538                 errno = EIO;
539                 break;
540         }
541         return NULL;
542 map_rl:
543         /* The @vcn is in an unmapped region, map the runlist and retry. */
544         if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
545                 is_retry = TRUE;
546                 goto retry;
547         }
548         /*
549          * If we already retried or the mapping attempt failed something has
550          * gone badly wrong. EINVAL and ENOENT coming from a failed mapping
551          * attempt are equivalent to errors for us as they should not happen
552          * in our code paths.
553          */
554         if (is_retry || errno == EINVAL || errno == ENOENT)
555                 errno = EIO;
556         return NULL;
557 }
558
559 /**
560  * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
561  * @na:         ntfs attribute to read from
562  * @pos:        byte position in the attribute to begin reading from
563  * @count:      number of bytes to read
564  * @b:          output data buffer
565  *
566  * This function will read @count bytes starting at offset @pos from the ntfs
567  * attribute @na into the data buffer @b.
568  *
569  * On success, return the number of successfully read bytes. If this number is
570  * lower than @count this means that the read reached end of file or that an
571  * error was encountered during the read so that the read is partial. 0 means
572  * end of file or nothing was read (also return 0 when @count is 0).
573  *
574  * On error and nothing has been read, return -1 with errno set appropriately
575  * to the return code of ntfs_pread(), or to EINVAL in case of invalid
576  * arguments.
577  */
578 s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
579 {
580         s64 br, to_read, ofs, total, total2;
581         ntfs_volume *vol;
582         runlist_element *rl;
583
584         Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x, pos 0x%Lx, "
585                         "count 0x%Lx.\n", __FUNCTION__,
586                         (unsigned long long)na->ni->mft_no, na->type,
587                         (long long)pos, (long long)count);
588         if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
589                 errno = EINVAL;
590                 return -1;
591         }
592         vol = na->ni->vol;
593         /*
594          * Encrypted attributes are not supported. We return access denied,
595          * which is what Windows NT4 does, too.
596          */
597         if (NAttrEncrypted(na)) {
598                 errno = EACCES;
599                 return -1;
600         }
601         /* If this is a compressed attribute it needs special treatment. */
602         if (NAttrCompressed(na)) {
603                 // TODO: Implement reading compressed attributes! (AIA)
604                 // return ntfs_attr_pread_compressed(ntfs_attr *na,
605                 //              const s64 pos, s64 count, void *b);
606                 errno = ENOTSUP;
607                 return -1;
608         }
609         if (!count)
610                 return 0;
611         /* Truncate reads beyond end of attribute. */
612         if (pos + count > na->data_size) {
613                 if (pos >= na->data_size)
614                         return 0;
615                 count = na->data_size - pos;
616         }
617         /* If it is a resident attribute, get the value from the mft record. */
618         if (!NAttrNonResident(na)) {
619                 ntfs_attr_search_ctx *ctx;
620                 char *val;
621
622                 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
623                 if (!ctx)
624                         return -1;
625                 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
626                                 0, NULL, 0, ctx)) {
627                         int eo;
628 res_err_out:
629                         eo = errno;
630                         ntfs_attr_put_search_ctx(ctx);
631                         errno = eo;
632                         return -1;
633                 }
634                 val = (char*)ctx->attr + le16_to_cpu(ctx->attr->value_offset);
635                 if (val < (char*)ctx->attr || val +
636                                 le32_to_cpu(ctx->attr->value_length) >
637                                 (char*)ctx->mrec + vol->mft_record_size) {
638                         errno = EIO;
639                         goto res_err_out;
640                 }
641                 memcpy(b, val + pos, count);
642                 ntfs_attr_put_search_ctx(ctx);
643                 return count;
644         }
645         total = total2 = 0;
646         /* Zero out reads beyond initialized size. */
647         if (pos + count > na->initialized_size) {
648                 if (pos >= na->initialized_size) {
649                         memset(b, 0, count);
650                         return count;
651                 }
652                 total2 = pos + count - na->initialized_size;
653                 count -= total2;
654                 memset((u8*)b + count, 0, total2);
655         }
656         /* Find the runlist element containing the vcn. */
657         rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
658         if (!rl) {
659                 /*
660                  * If the vcn is not present it is an out of bounds read.
661                  * However, we already truncated the read to the data_size,
662                  * so getting this here is an error.
663                  */
664                 if (errno == ENOENT)
665                         errno = EIO;
666                 return -1;
667         }
668         /*
669          * Gather the requested data into the linear destination buffer. Note,
670          * a partial final vcn is taken care of by the @count capping of read
671          * length.
672          */
673         ofs = pos - (rl->vcn << vol->cluster_size_bits);
674         for (; count; rl++, ofs = 0) {
675                 if (!rl->length)
676                         goto rl_err_out;
677                 if (rl->lcn < (LCN)0) {
678                         if (rl->lcn != (LCN)LCN_HOLE)
679                                 goto rl_err_out;
680                         /* It is a hole, just zero the matching @b range. */
681                         to_read = min(count, (rl->length <<
682                                         vol->cluster_size_bits) - ofs);
683                         memset(b, 0, to_read);
684                         /* Update progress counters. */
685                         total += to_read;
686                         count -= to_read;
687                         (u8*)b += to_read;
688                         continue;
689                 }
690                 /* It is a real lcn, read it into @dst. */
691                 to_read = min(count, (rl->length << vol->cluster_size_bits) -
692                                 ofs);
693 retry:
694                 Dprintf("%s(): Reading 0x%Lx bytes from vcn 0x%Lx, lcn 0x%Lx, "
695                                 "ofs 0x%Lx.\n", __FUNCTION__, to_read,
696                                 rl->vcn, rl->lcn, ofs);
697                 br = ntfs_pread(vol->dev, (rl->lcn << vol->cluster_size_bits) +
698                                 ofs, to_read, b);
699                 /* If everything ok, update progress counters and continue. */
700                 if (br > 0) {
701                         total += br;
702                         count -= br;
703                         (u8*)b += br;
704                         continue;
705                 }
706                 /* If the syscall was interrupted, try again. */
707                 if (br == (s64)-1 && errno == EINTR)
708                         goto retry;
709                 if (total)
710                         return total;
711                 if (!br)
712                         errno = EIO;
713                 return -1;
714         }
715         /* Finally, return the number of bytes read. */
716         return total + total2;
717 rl_err_out:
718         if (total)
719                 return total;
720         errno = EIO;
721         return -1;
722 }
723
724 /**
725  * ntfs_attr_pwrite - positioned write to an ntfs attribute
726  * @na:         ntfs attribute to write to
727  * @pos:        position in the attribute to write to
728  * @count:      number of bytes to write
729  * @b:          data buffer to write to disk
730  *
731  * This function will write @count bytes from data buffer @b to ntfs attribute
732  * @na at position @pos.
733  *
734  * On success, return the number of successfully written bytes. If this number
735  * is lower than @count this means that an error was encountered during the
736  * write so that the write is partial. 0 means nothing was written (also return
737  * 0 when @count is 0).
738  *
739  * On error and nothing has been written, return -1 with errno set
740  * appropriately to the return code of ntfs_pwrite(), or to EINVAL in case of
741  * invalid arguments.
742  *
743  * NOTE: Currently changes in length of the attribute @na are not implemented.
744  * Thus if such a change is requested we return -1 with errno set to ENOTSUP.
745  */
746 s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, void *b)
747 {
748         s64 written, to_write, ofs, total, old_initialized_size;
749         ntfs_volume *vol;
750         ntfs_attr_search_ctx *ctx = NULL;
751         runlist_element *rl;
752         int eo;
753         struct {
754                 unsigned int initialized_size   : 1;
755         } need_to_undo = { 0 };
756
757         Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x, pos 0x%Lx, "
758                         "count 0x%Lx.\n", __FUNCTION__, na->ni->mft_no,
759                         na->type, (long long)pos, (long long)count);
760         if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
761                 errno = EINVAL;
762                 return -1;
763         }
764         vol = na->ni->vol;
765         /*
766          * Encrypted attributes are not supported. We return access denied,
767          * which is what Windows NT4 does, too.
768          */
769         if (NAttrEncrypted(na)) {
770                 errno = EACCES;
771                 return -1;
772         }
773         /* If this is a compressed attribute it needs special treatment. */
774         if (NAttrCompressed(na)) {
775                 // TODO: Implement writing compressed attributes! (AIA)
776                 // return ntfs_attr_pwrite_compressed(ntfs_attr *na,
777                 //              const s64 pos, s64 count, void *b);
778                 errno = ENOTSUP;
779                 return -1;
780         }
781         if (!count)
782                 return 0;
783         /* If the write reaches beyond the end, extend the attribute. */
784         if (pos + count > na->data_size) {
785                 // TODO: Need to extend the attribute. For now, just do a
786                 // partial write or abort if completely out of bounds. (AIA)
787                 if (pos >= na->data_size) {
788                         errno = ENOTSUP;
789                         return -1;
790                 }
791                 count = na->data_size - pos;
792         }
793         old_initialized_size = na->initialized_size;
794         /* If it is a resident attribute, write the data to the mft record. */
795         if (!NAttrNonResident(na)) {
796                 char *val;
797
798                 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
799                 if (!ctx)
800                         goto err_out;
801                 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
802                                 0, NULL, 0, ctx))
803                         goto err_out;
804                 val = (char*)ctx->attr + le16_to_cpu(ctx->attr->value_offset);
805                 if (val < (char*)ctx->attr || val +
806                                 le32_to_cpu(ctx->attr->value_length) >
807                                 (char*)ctx->mrec + vol->mft_record_size) {
808                         errno = EIO;
809                         goto err_out;
810                 }
811                 memcpy(val + pos, b, count);
812                 if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
813                                 ctx->mrec)) {
814                         /*
815                          * NOTE: We are in a bad state at this moment. We have
816                          * dirtied the mft record but we failed to commit it to
817                          * disk. Since we have read the mft record ok before,
818                          * it is unlikely to fail writing it, so is ok to just
819                          * return error here... (AIA)
820                          */
821                         goto err_out;
822                 }
823                 ntfs_attr_put_search_ctx(ctx);
824                 return count;
825         }
826         total = 0;
827         /* Find the runlist element containing the vcn. */
828         rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
829         if (!rl) {
830                 /*
831                  * If the vcn is not present it is an out of bounds write.
832                  * However, we already extended the size of the attribute,
833                  * so getting this here must be an error of some kind.
834                  */
835                 if (errno == ENOENT)
836                         errno = EIO;
837                 goto err_out;
838         }
839         /* Handle writes beyond initialized_size. */
840         if (pos + count > na->initialized_size) {
841                 /* Set initialized_size to @pos + @count. */
842                 ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
843                 if (!ctx)
844                         goto err_out;
845                 if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
846                                 0, NULL, 0, ctx))
847                         goto err_out;
848                 /* If write starts beyond initialized_size, zero the gap. */
849                 if (pos > na->initialized_size) {
850                         // TODO: Need to write zeroes in the region from
851                         // na->initialized_size to @pos, then update the
852                         // initialized size to equal @pos. If any sparse runs
853                         // are encountered while filling the gap, need to
854                         // honour them, i.e. do not instantiate them. Then can
855                         // continue as if pos <= na->initialized_size, i.e. can
856                         // just fall through and continue. (AIA)
857                         errno = ENOTSUP;
858                         goto err_out;
859                 }
860                 ctx->attr->initialized_size = scpu_to_le64(pos + count);
861                 if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
862                                 ctx->mrec)) {
863                         /*
864                          * Undo the change in the in-memory copy and send it
865                          * back for writing.
866                          */
867                         ctx->attr->initialized_size =
868                                         scpu_to_le64(old_initialized_size);
869                         ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
870                                         ctx->mrec);
871                         goto err_out;
872                 }
873                 na->initialized_size = pos + count;
874                 ntfs_attr_put_search_ctx(ctx);
875                 ctx = NULL;
876                 /*
877                  * NOTE: At this point the initialized_size in the mft record
878                  * has been updated BUT there is random data on disk thus if
879                  * we decide to abort, we MUST change the initialized_size
880                  * again.
881                  */
882                 need_to_undo.initialized_size = 1;
883         }
884         /*
885          * Scatter the data from the linear data buffer to the volume. Note, a
886          * partial final vcn is taken care of by the @count capping of write
887          * length.
888          */
889         ofs = pos - (rl->vcn << vol->cluster_size_bits);
890         for (; count; rl++, ofs = 0) {
891                 if (!rl->length) {
892                         errno = EIO;
893                         goto rl_err_out;
894                 }
895                 if (rl->lcn < (LCN)0) {
896                         s64 t;
897                         int cnt;
898
899                         if (rl->lcn != (LCN)LCN_HOLE) {
900                                 errno = EIO;
901                                 goto rl_err_out;
902                         }
903                         /*
904                          * It is a hole. Check if the data buffer is zero in
905                          * this region and if not instantiate the hole.
906                          */
907                         to_write = min(count, (rl->length <<
908                                         vol->cluster_size_bits) - ofs);
909                         written = to_write / sizeof(unsigned long);
910                         eo = 0;
911                         for (t = 0; t < written; t++) {
912                                 if (((unsigned long*)b)[t]) {
913                                         eo = 1;
914                                         break;
915                                 }
916                         }
917                         cnt = to_write & (sizeof(unsigned long) - 1);
918                         if (cnt && !eo) {
919                                 int i;
920                                 u8 *b2;
921
922                                 b2 = (u8*)b + (to_write &
923                                                 ~(sizeof(unsigned long) - 1));
924                                 for (i = 0; i < cnt; i++) {
925                                         if (b2[i]) {
926                                                 eo = 1;
927                                                 break;
928                                         }
929                                 }
930                         }
931                         if (eo) {
932                                 // TODO: Need to instantiate the hole. Then get
933                                 // the runlist element again checking if it is
934                                 // ok and fall through to do the writing. (AIA)
935                                 errno = ENOTSUP;
936                                 goto rl_err_out;
937                         }
938                         /*
939                          * The buffer region is zero, update progress counters
940                          * and proceed with next run.
941                          */
942                         total += to_write;
943                         count -= to_write;
944                         (u8*)b += to_write;
945                         continue;
946                 }
947                 /* It is a real lcn, write it to the volume. */
948                 to_write = min(count, (rl->length << vol->cluster_size_bits) -
949                                 ofs);
950 retry:
951                 Dprintf("%s(): Writing 0x%Lx bytes to vcn 0x%Lx, lcn 0x%Lx, "
952                                 "ofs 0x%Lx.\n", __FUNCTION__, to_write,
953                                 rl->vcn, rl->lcn, ofs);
954                 if (!NVolReadOnly(vol))
955                         written = ntfs_pwrite(vol->dev, (rl->lcn <<
956                                         vol->cluster_size_bits) + ofs,
957                                         to_write, b);
958                 else
959                         written = to_write;
960                 /* If everything ok, update progress counters and continue. */
961                 if (written > 0) {
962                         total += written;
963                         count -= written;
964                         (u8*)b += written;
965                         continue;
966                 }
967                 /* If the syscall was interrupted, try again. */
968                 if (written == (s64)-1 && errno == EINTR)
969                         goto retry;
970                 if (!written)
971                         errno = EIO;
972                 goto rl_err_out;
973         }
974 done:
975         if (ctx)
976                 ntfs_attr_put_search_ctx(ctx);
977         /* Finally, return the number of bytes written. */
978         return total;
979 rl_err_out:
980         eo = errno;
981         if (total) {
982                 if (need_to_undo.initialized_size) {
983                         if (pos + total > na->initialized_size)
984                                 goto done;
985                         // TODO: Need to try to change initialized_size. If it
986                         // succeeds goto done, otherwise goto err_out. (AIA)
987                         errno = ENOTSUP;
988                         goto err_out;
989                 }
990                 goto done;
991         }
992         errno = eo;
993 err_out:
994         eo = errno;
995         if (need_to_undo.initialized_size) {
996                 int err;
997
998                 err = 0;
999                 if (!ctx) {
1000                         ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
1001                         if (!ctx)
1002                                 err = 1;
1003                 } else
1004                         ntfs_attr_reinit_search_ctx(ctx);
1005                 if (!err) {
1006                         err = ntfs_attr_lookup(na->type, na->name,
1007                                         na->name_len, 0, 0, NULL, 0, ctx);
1008                         if (!err) {
1009                                 na->initialized_size = old_initialized_size;
1010                                 ctx->attr->initialized_size = scpu_to_le64(
1011                                                 old_initialized_size);
1012                                 err = ntfs_mft_record_write(vol,
1013                                                 ctx->ntfs_ino->mft_no,
1014                                                 ctx->mrec);
1015                         }
1016                 }
1017                 if (err) {
1018                         Dputs("Eeek! Failed to recover from error. Leaving "
1019                                         "metadata in inconsistent state! Run "
1020                                         "chkdsk!");
1021                         // FIXME: At this stage could try to recover by filling
1022                         // old_initialized_size -> new_initialized_size with
1023                         // data or at least zeroes. (AIA)
1024                 }
1025         }
1026         if (ctx)
1027                 ntfs_attr_put_search_ctx(ctx);
1028         errno = eo;
1029         return -1;
1030 }
1031
1032 /**
1033  * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read
1034  * @na:         multi sector transfer protected ntfs attribute to read from
1035  * @pos:        byte position in the attribute to begin reading from
1036  * @bk_cnt:     number of mst protected blocks to read
1037  * @bk_size:    size of each mst protected block in bytes
1038  * @b:          output data buffer
1039  *
1040  * This function will read @bk_cnt blocks of size @bk_size bytes each starting
1041  * at offset @pos from the ntfs attribute @na into the data buffer @b.
1042  *
1043  * On success, the multi sector transfer fixups are applied and the number of
1044  * read blocks is returned. If this number is lower than @bk_cnt this means
1045  * that the read has either reached end of attribute or that an error was
1046  * encountered during the read so that the read is partial. 0 means end of
1047  * attribute or nothing to read (also return 0 when @bk_cnt or @bk_size are 0).
1048  *
1049  * On error and nothing has been read, return -1 with errno set appropriately
1050  * to the return code of ntfs_attr_pread() or to EINVAL in case of invalid
1051  * arguments.
1052  *
1053  * NOTE: If an incomplete multi sector transfer is detected the magic is
1054  * changed to BAAD but no error is returned, i.e. it is possible that any of
1055  * the returned blocks have multi sector transfer errors. This should be
1056  * detected by the caller by checking each block with is_baad_recordp(&block).
1057  * The reasoning is that we want to fixup as many blocks as possible and we
1058  * want to return even bad ones to the caller so, e.g. in case of ntfsck, the
1059  * errors can be repaired.
1060  */
1061 s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
1062                 const u32 bk_size, void *b)
1063 {
1064         s64 br;
1065         u8 *end;
1066
1067         Dprintf("%s(): Entering for inode 0x%Lx, attr type 0x%x, pos 0x%Lx.\n",
1068                         __FUNCTION__, (unsigned long long)na->ni->mft_no,
1069                         na->type, (long long)pos);
1070         if (bk_cnt < 0 || bk_size % NTFS_SECTOR_SIZE) {
1071                 errno = EINVAL;
1072                 return -1;
1073         }
1074         br = ntfs_attr_pread(na, pos, bk_cnt * bk_size, b);
1075         if (br <= 0)
1076                 return br;
1077         br /= bk_size;
1078         for (end = (u8*)b + br * bk_size; (u8*)b < end; (u8*)b += bk_size)
1079                 ntfs_mst_post_read_fixup((NTFS_RECORD*)b, bk_size);
1080         /* Finally, return the number of blocks read. */
1081         return br;
1082 }
1083
1084 /**
1085  * ntfs_attr_mst_pwrite - multi sector transfer protected ntfs attribute write
1086  * @na:         multi sector transfer protected ntfs attribute to write to
1087  * @pos:        position in the attribute to write to
1088  * @bk_cnt:     number of mst protected blocks to write
1089  * @bk_size:    size of each mst protected block in bytes
1090  * @b:          data buffer to write to disk
1091  *
1092  * This function will write @bk_cnt blocks of size @bk_size bytes each from
1093  * data buffer @b to multi sector transfer (mst) protected ntfs attribute @na
1094  * at position @pos.
1095  *
1096  * On success, return the number of successfully written blocks. If this number
1097  * is lower than @bk_cnt this means that an error was encountered during the
1098  * write so that the write is partial. 0 means nothing was written (also
1099  * return 0 when @bk_cnt or @bk_size are 0).
1100  *
1101  * On error and nothing has been written, return -1 with errno set
1102  * appropriately to the return code of ntfs_attr_pwrite(), or to EINVAL in case
1103  * of invalid arguments.
1104  *
1105  * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
1106  * deprotect algorithm (no checking). This saves us from making a copy before
1107  * the write and at the same time causes the usn to be incremented in the
1108  * buffer. This conceptually fits in better with the idea that cached data is
1109  * always deprotected and protection is performed when the data is actually
1110  * going to hit the disk and the cache is immediately deprotected again
1111  * simulating an mst read on the written data. This way cache coherency is
1112  * achieved.
1113  */
1114 s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, s64 bk_cnt,
1115                 const u32 bk_size, void *b)
1116 {
1117         s64 written, i;
1118
1119         Dprintf("%s(): Entering for inode 0x%Lx, attr type 0x%x, pos 0x%Lx.\n",
1120                         __FUNCTION__, (unsigned long long)na->ni->mft_no,
1121                         na->type, (long long)pos);
1122         if (bk_cnt < 0 || bk_size % NTFS_SECTOR_SIZE) {
1123                 errno = EINVAL;
1124                 return -1;
1125         }
1126         if (!bk_cnt)
1127                 return 0;
1128         /* Prepare data for writing. */
1129         for (i = 0; i < bk_cnt; ++i) {
1130                 int err;
1131
1132                 err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
1133                                 ((u8*)b + i * bk_size), bk_size);
1134                 if (err < 0) {
1135                         /* Abort write at this position. */
1136                         if (!i)
1137                                 return err;
1138                         bk_cnt = i;
1139                         break;
1140                 }
1141         }
1142         /* Write the prepared data. */
1143         written = ntfs_attr_pwrite(na, pos, bk_cnt * bk_size, b);
1144         /* Quickly deprotect the data again. */
1145         for (i = 0; i < bk_cnt; ++i)
1146                 ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)b + i * bk_size));
1147         if (written <= 0)
1148                 return written;
1149         /* Finally, return the number of complete blocks written. */
1150         return written / bk_size;
1151 }
1152
1153 /**
1154  * Internal:
1155  *
1156  * ntfs_attr_find - find (next) attribute in mft record
1157  * @type:       attribute type to find
1158  * @name:       attribute name to find (optional, i.e. NULL means don't care)
1159  * @name_len:   attribute name length (only needed if @name present)
1160  * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
1161  * @val:        attribute value to find (optional, resident attributes only)
1162  * @val_len:    attribute value length
1163  * @ctx:        search context with mft record and attribute to search from
1164  *
1165  * You shouldn't need to call this function directly. Use lookup_attr() instead.
1166  *
1167  * ntfs_attr_find() takes a search context @ctx as parameter and searches the
1168  * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
1169  * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
1170  * returns 0 and @ctx->attr will point to the found attribute. If not found,
1171  * ntfs_attr_find() returns -1, with errno set to the error code and @ctx->attr
1172  * is undefined (i.e. do not rely on it not changing).
1173  *
1174  * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
1175  * is FALSE, the search begins after @ctx->attr.
1176  *
1177  * If @type is zero (i.e. AT_UNUSED), return the first found attribute, i.e.
1178  * one can enumerate all attributes by setting @type to zero and then calling
1179  * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
1180  * indicate that there are no more entries. During the enumeration, each
1181  * successful call of ntfs_attr_find() will return the next attribute in the
1182  * mft record @ctx->mrec.
1183  *
1184  * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
1185  * AT_END is not a valid attribute, its length is zero for example, thus it is
1186  * safer to return error instead of success in this case. This also allows us
1187  * to interoperate cleanly with ntfs_external_attr_find().
1188  *
1189  * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
1190  * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
1191  * match both named and unnamed attributes.
1192  *
1193  * If @ic is IGNORE_CASE, the @name comparisson is not case sensitive and
1194  * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
1195  * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
1196  * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
1197  * sensitive. When @name is present, @name_len is the @name length in Unicode
1198  * characters.
1199  *
1200  * If @name is not present (NULL), we assume that the unnamed attribute is
1201  * being searched for.
1202  *
1203  * Finally, the resident attribute value @val is looked for, if present.
1204  * If @val is not present (NULL), @val_len is ignored.
1205  *
1206  * ntfs_attr_find() only searches the specified mft record and it ignores the
1207  * presence of an attribute list attribute (unless it is the one being searched
1208  * for, obviously). If you need to take attribute lists into consideration, use
1209  * ntfs_attr_lookup() instead (see below). This also means that you cannot use
1210  * ntfs_attr_find() to search for extent records of non-resident attributes, as
1211  * extents with lowest_vcn != 0 are usually described by the attribute list
1212  * attribute only. - Note that it is possible that the first extent is only in
1213  * the attribute list while the last extent is in the base mft record, so don't
1214  * rely on being able to find the first extent in the base mft record.
1215  *
1216  * Warning: Never use @val when looking for attribute types which can be
1217  *          non-resident as this most likely will result in a crash!
1218  */
1219 static int ntfs_attr_find(const ATTR_TYPES type, const uchar_t *name,
1220                 const u32 name_len, const IGNORE_CASE_BOOL ic,
1221                 const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
1222 {
1223         ATTR_RECORD *a;
1224         ntfs_volume *vol;
1225         uchar_t *upcase;
1226         u32 upcase_len;
1227
1228         if (!ctx || !ctx->mrec || !ctx->attr) {
1229                 errno = EINVAL;
1230                 return -1;
1231         }
1232         if (ic == IGNORE_CASE) {
1233                 vol = ctx->ntfs_ino->vol;
1234                 upcase = vol->upcase;
1235                 upcase_len = vol->upcase_len;
1236         } else {
1237                 vol = NULL;
1238                 upcase = NULL;
1239                 upcase_len = 0;
1240         }
1241         /*
1242          * Iterate over attributes in mft record starting at @ctx->attr, or the
1243          * attribute following that, if @ctx->is_first is TRUE.
1244          */
1245         if (ctx->is_first) {
1246                 a = ctx->attr;
1247                 ctx->is_first = FALSE;
1248         } else
1249                 a = (ATTR_RECORD*)((char*)ctx->attr +
1250                                 le32_to_cpu(ctx->attr->length));
1251         for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
1252                 if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
1253                                 le32_to_cpu(ctx->mrec->bytes_allocated))
1254                         break;
1255                 ctx->attr = a;
1256                 /* We catch $END with this more general check, too... */
1257                 if ((type && (le32_to_cpu(a->type) > le32_to_cpu(type))) ||
1258                                 (a->type == AT_END)) {
1259                         errno = ENOENT;
1260                         return -1;
1261                 }
1262                 if (!a->length)
1263                         break;
1264                 /* If this is an enumeration return this attribute. */
1265                 if (!type)
1266                         return 0;
1267                 if (a->type != type)
1268                         continue;
1269                 /*
1270                  * If @name is AT_UNNAMED we want an unnamed attribute.
1271                  * If @name is present, compare the two names.
1272                  * Otherwise, match any attribute.
1273                  */
1274                 if (name == AT_UNNAMED) {
1275                         /* The search failed if the found attribute is named. */
1276                         if (a->name_length) {
1277                                 errno = ENOENT;
1278                                 return -1;
1279                         }
1280                 } else if (name && !ntfs_names_are_equal(name, name_len,
1281                             (uchar_t*)((char*)a + le16_to_cpu(a->name_offset)),
1282                             a->name_length, ic, upcase, upcase_len)) {
1283                         register int rc;
1284
1285                         rc = ntfs_names_collate(name, name_len,
1286                                         (uchar_t*)((char*)a +
1287                                         le16_to_cpu(a->name_offset)),
1288                                         a->name_length, 1, IGNORE_CASE,
1289                                         upcase, upcase_len);
1290                         /*
1291                          * If @name collates before a->name, there is no
1292                          * matching attribute.
1293                          */
1294                         if (rc == -1) {
1295                                 errno = ENOENT;
1296                                 return -1;
1297                         }
1298                         /* If the strings are not equal, continue search. */
1299                         if (rc)
1300                                 continue;
1301                         rc = ntfs_names_collate(name, name_len,
1302                                         (uchar_t*)((char*)a +
1303                                         le16_to_cpu(a->name_offset)),
1304                                         a->name_length, 1, CASE_SENSITIVE,
1305                                         upcase, upcase_len);
1306                         if (rc == -1) {
1307                                 errno = ENOENT;
1308                                 return -1;
1309                         }
1310                         if (rc)
1311                                 continue;
1312                 }
1313                 /*
1314                  * The names match or @name not present and attribute is
1315                  * unnamed. If no @val specified, we have found the attribute
1316                  * and are done.
1317                  */
1318                 if (!val)
1319                         return 0;
1320                 /* @val is present; compare values. */
1321                 else {
1322                         register int rc;
1323
1324                         rc = memcmp(val, (char*)a +le16_to_cpu(a->value_offset),
1325                                         min(val_len,
1326                                         le32_to_cpu(a->value_length)));
1327                         /*
1328                          * If @val collates before the current attribute's
1329                          * value, there is no matching attribute.
1330                          */
1331                         if (!rc) {
1332                                 register u32 avl;
1333                                 avl = le32_to_cpu(a->value_length);
1334                                 if (val_len == avl)
1335                                         return 0;
1336                                 if (val_len < avl) {
1337                                         errno = ENOENT;
1338                                         return -1;
1339                                 }
1340                         } else if (rc < 0) {
1341                                 errno = ENOENT;
1342                                 return -1;
1343                         }
1344                 }
1345         }
1346         Dputs("ntfs_attr_find(): File is corrupt. Run chkdsk.");
1347         errno = EIO;
1348         return -1;
1349 }
1350
1351 /**
1352  * Internal:
1353  *
1354  * ntfs_external_attr_find - find an attribute in the attribute list of an inode
1355  * @type:       attribute type to find
1356  * @name:       attribute name to find (optional, i.e. NULL means don't care)
1357  * @name_len:   attribute name length (only needed if @name present)
1358  * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
1359  * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
1360  * @val:        attribute value to find (optional, resident attributes only)
1361  * @val_len:    attribute value length
1362  * @ctx:        search context with mft record and attribute to search from
1363  *
1364  * You shouldn't need to call this function directly. Use ntfs_attr_lookup()
1365  * instead.
1366  *
1367  * Find an attribute by searching the attribute list for the corresponding
1368  * attribute list entry. Having found the entry, map the mft record for read
1369  * if the attribute is in a different mft record/inode, find the attribute in
1370  * there and return it.
1371  *
1372  * If @type is zero (i.e. AT_UNUSED), return the first found attribute, i.e.
1373  * one can enumerate all attributes by setting @type to zero and then calling
1374  * ntfs_external_attr_find() repeatedly until it returns -1 with errno set to
1375  * ENOENT to indicate that there are no more entries. During the enumeration,
1376  * each successful call of ntfs_external_attr_find() will return the next
1377  * attribute described by the attribute list of the base mft record described
1378  * by the search context @ctx.
1379  *
1380  * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
1381  * AT_END is not a valid attribute, its length is zero for example, thus it is
1382  * safer to return error instead of success in this case.
1383  *
1384  * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
1385  * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
1386  * match both named and unnamed attributes.
1387  *
1388  * On first search @ctx->ntfs_ino must be the inode of the base mft record and
1389  * @ctx must have been obtained from a call to ntfs_attr_get_search_ctx().
1390  * On subsequent calls, @ctx->ntfs_ino can be any extent inode, too
1391  * (@ctx->base_ntfs_ino is then the base inode).
1392  *
1393  * After finishing with the attribute/mft record you need to call
1394  * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
1395  * mapped extent inodes, etc).
1396  *
1397  * Return 0 if the search was successful and -1 if not, with errno set to the
1398  * error code.
1399  *
1400  * On success, @ctx->attr is the found attribute and it is in mft record
1401  * @ctx->mrec.
1402  *
1403  * On error, @ctx->attr is the attribute which collates just after the attribute
1404  * being searched for in the base ntfs inode, i.e. if one wants to add the
1405  * attribute to the mft record this is the correct place to insert it into,
1406  * and if there is not enough space, the attribute should be placed in an
1407  * extent mft record. @ctx->al_entry points to the position within
1408  * @ctx->base_ntfs_ino->attr_list at which the new attribute's attribute list
1409  * entry should be inserted.
1410  *
1411  * The following error codes are defined:
1412  *      ENOENT  Attribute not found, not an error as such.
1413  *      EINVAL  Invalid arguments.
1414  *      EIO     I/O error or corrupt data structures found.
1415  *      ENOMEM  Not enough memory to allocate necessary buffers.
1416  */
1417 static int ntfs_external_attr_find(ATTR_TYPES type, const uchar_t *name,
1418                 const u32 name_len, const IGNORE_CASE_BOOL ic,
1419                 const VCN lowest_vcn, const u8 *val, const u32 val_len,
1420                 ntfs_attr_search_ctx *ctx)
1421 {
1422         ntfs_inode *base_ni, *ni;
1423         ntfs_volume *vol;
1424         ATTR_LIST_ENTRY *al_entry, *next_al_entry;
1425         char *al_start, *al_end;
1426         ATTR_RECORD *a;
1427         uchar_t *al_name;
1428         u32 al_name_len;
1429         BOOL is_first_search = FALSE;
1430
1431         ni = ctx->ntfs_ino;
1432         base_ni = ctx->base_ntfs_ino;
1433         Dprintf("Entering for inode %Lu, attribute type 0x%x.\n",
1434                         (unsigned long long)ni->mft_no, type);
1435         if (!base_ni) {
1436                 /* First call happens with the base mft record. */
1437                 base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino;
1438                 ctx->base_mrec = ctx->mrec;
1439         }
1440         if (type == AT_END)
1441                 goto not_found;
1442         if (ni == base_ni)
1443                 ctx->base_attr = ctx->attr;
1444         vol = base_ni->vol;
1445         al_start = base_ni->attr_list;
1446         al_end = al_start + base_ni->attr_list_size;
1447         if (!ctx->al_entry) {
1448                 ctx->al_entry = (ATTR_LIST_ENTRY*)al_start;
1449                 is_first_search = TRUE;
1450         }
1451         /*
1452          * Iterate over entries in attribute list starting at @ctx->al_entry,
1453          * or the entry following that, if @ctx->is_first is TRUE.
1454          */
1455         if (ctx->is_first) {
1456                 al_entry = ctx->al_entry;
1457                 ctx->is_first = FALSE;
1458                 /*
1459                  * If an enumeration and the first attribute is higher than
1460                  * the attribute list itself, need to return the attribute list
1461                  * attribute.
1462                  */
1463                 if (!type && is_first_search && le16_to_cpu(al_entry->type) >
1464                                 le16_to_cpu(AT_ATTRIBUTE_LIST))
1465                         goto find_attr_list_attr;
1466         } else {
1467                 al_entry = (ATTR_LIST_ENTRY*)((char*)ctx->al_entry +
1468                                 le16_to_cpu(ctx->al_entry->length));
1469                 /*
1470                  * If this is an enumeration and the attribute list attribute
1471                  * is the next one in the enumeration sequence, just return the
1472                  * attribute list attribute from the base mft record as it is
1473                  * not listed in the attribute list itself.
1474                  */
1475                 if (!type && le16_to_cpu(ctx->al_entry->type) <
1476                                 le16_to_cpu(AT_ATTRIBUTE_LIST) &&
1477                                 le16_to_cpu(al_entry->type) >
1478                                 le16_to_cpu(AT_ATTRIBUTE_LIST)) {
1479                         int rc;
1480 find_attr_list_attr:
1481
1482                         /* Check for bogus calls. */
1483                         if (name || name_len || val || val_len || lowest_vcn) {
1484                                 errno = EINVAL;
1485                                 return -1;
1486                         }
1487
1488                         /* We want the base record. */
1489                         ctx->ntfs_ino = base_ni;
1490                         ctx->mrec = ctx->base_mrec;
1491                         ctx->is_first = TRUE;
1492                         /* Sanity checks are performed elsewhere. */
1493                         ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
1494                                         le16_to_cpu(ctx->mrec->attrs_offset));
1495
1496                         /* Find the attribute list attribute. */
1497                         rc = ntfs_attr_find(AT_ATTRIBUTE_LIST, NULL, 0,
1498                                         IGNORE_CASE, NULL, 0, ctx);
1499
1500                         /*
1501                          * Setup the search context so the correct
1502                          * attribute is returned next time round.
1503                          */
1504                         ctx->al_entry = al_entry;
1505                         ctx->is_first = TRUE;
1506
1507                         /* Got it. Done. */
1508                         if (!rc)
1509                                return 0;
1510
1511                         /* Error! If other than not found return it. */
1512                         if (errno != ENOENT)
1513                                 return rc;
1514
1515                         /* Not found?!? Absurd! Must be a bug... )-: */
1516                         Dprintf("%s(): BUG! Attribute list attribute not found "
1517                                         "but it exists! Returning error "
1518                                         "(EINVAL).", __FUNCTION__);
1519                         errno = EINVAL;
1520                         return -1;
1521                 }
1522         }
1523         for (;; al_entry = next_al_entry) {
1524                 /* Out of bounds check. */
1525                 if ((u8*)al_entry < base_ni->attr_list ||
1526                                 (char*)al_entry > al_end)
1527                         break;  /* Inode is corrupt. */
1528                 ctx->al_entry = al_entry;
1529                 /* Catch the end of the attribute list. */
1530                 if ((char*)al_entry == al_end)
1531                         goto not_found;
1532                 if (!al_entry->length)
1533                         break;
1534                 if ((char*)al_entry + 6 > al_end || (char*)al_entry +
1535                                 le16_to_cpu(al_entry->length) > al_end)
1536                         break;
1537                 next_al_entry = (ATTR_LIST_ENTRY*)((char*)al_entry +
1538                                 le16_to_cpu(al_entry->length));
1539                 if (type) {
1540                         if (le32_to_cpu(al_entry->type) > le32_to_cpu(type))
1541                                 goto not_found;
1542                         if (type != al_entry->type)
1543                                 continue;
1544                 }
1545                 al_name_len = al_entry->name_length;
1546                 al_name = (uchar_t*)((char*)al_entry + al_entry->name_offset);
1547                 /*
1548                  * If !@type we want the attribute represented by this
1549                  * attribute list entry.
1550                  */
1551                 if (!type)
1552                         goto is_enumeration;
1553                 /*
1554                  * If @name is AT_UNNAMED we want an unnamed attribute.
1555                  * If @name is present, compare the two names.
1556                  * Otherwise, match any attribute.
1557                  */
1558                 if (name == AT_UNNAMED) {
1559                         if (al_name_len)
1560                                 goto not_found;
1561                 } else if (name && !ntfs_names_are_equal(al_name, al_name_len,
1562                                 name, name_len, ic, vol->upcase,
1563                                 vol->upcase_len)) {
1564                         register int rc;
1565
1566                         rc = ntfs_names_collate(name, name_len, al_name,
1567                                         al_name_len, 1, IGNORE_CASE,
1568                                         vol->upcase, vol->upcase_len);
1569                         /*
1570                          * If @name collates before al_name, there is no
1571                          * matching attribute.
1572                          */
1573                         if (rc == -1)
1574                                 goto not_found;
1575                         /* If the strings are not equal, continue search. */
1576                         if (rc)
1577                                 continue;
1578                         /*
1579                          * FIXME: Reverse engineering showed 0, IGNORE_CASE but
1580                          * that is inconsistent with ntfs_attr_find(). The
1581                          * subsequent rc checks were also different. Perhaps I
1582                          * made a mistake in one of the two. Need to recheck
1583                          * which is correct or at least see what is going
1584                          * on... (AIA)
1585                          */
1586                         rc = ntfs_names_collate(name, name_len, al_name,
1587                                         al_name_len, 1, CASE_SENSITIVE,
1588                                         vol->upcase, vol->upcase_len);
1589                         if (rc == -1)
1590                                 goto not_found;
1591                         if (rc)
1592                                 continue;
1593                 }
1594                 /*
1595                  * The names match or @name not present and attribute is
1596                  * unnamed. Now check @lowest_vcn. Continue search if the
1597                  * next attribute list entry still fits @lowest_vcn. Otherwise
1598                  * we have reached the right one or the search has failed.
1599                  */
1600                 if (lowest_vcn && (char*)next_al_entry >= al_start          &&
1601                                 (char*)next_al_entry + 6 < al_end           &&
1602                                 (char*)next_al_entry + le16_to_cpu(
1603                                         next_al_entry->length) <= al_end    &&
1604                                 sle64_to_cpu(next_al_entry->lowest_vcn) <=
1605                                         lowest_vcn                          &&
1606                                 next_al_entry->type == al_entry->type       &&
1607                                 next_al_entry->name_length == al_name_len   &&
1608                                 ntfs_names_are_equal((uchar_t*)((char*)
1609                                         next_al_entry +
1610                                         next_al_entry->name_offset),
1611                                         next_al_entry->name_length,
1612                                         al_name, al_name_len, CASE_SENSITIVE,
1613                                         vol->upcase, vol->upcase_len))
1614                         continue;
1615 is_enumeration:
1616                 if (MREF_LE(al_entry->mft_reference) == ni->mft_no) {
1617                         if (MSEQNO_LE(al_entry->mft_reference) !=
1618                                         le16_to_cpu(
1619                                         ni->mrec->sequence_number)) {
1620                                 Dputs("Found stale mft reference in attribute "
1621                                                 "list!");
1622                                 break;
1623                         }
1624                 } else { /* Mft references do not match. */
1625                         /* Do we want the base record back? */
1626                         if (MREF_LE(al_entry->mft_reference) ==
1627                                         base_ni->mft_no) {
1628                                 ni = ctx->ntfs_ino = base_ni;
1629                                 ctx->mrec = ctx->base_mrec;
1630                         } else {
1631                                 /* We want an extent record. */
1632                                 ni = ntfs_extent_inode_open(base_ni,
1633                                                 al_entry->mft_reference);
1634                                 if (!ni) {
1635                                         Dperror("Failed to map extent inode");
1636                                         break;
1637                                 }
1638                                 ctx->ntfs_ino = ni;
1639                                 ctx->mrec = ni->mrec;
1640                         }
1641                         ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec +
1642                                         le16_to_cpu(ctx->mrec->attrs_offset));
1643                 }
1644                 /*
1645                  * ctx->ntfs_ino, ctx->mrec, and ctx->attr now point to the
1646                  * mft record containing the attribute represented by the
1647                  * current al_entry.
1648                  */
1649                 /*
1650                  * We could call into ntfs_attr_find() to find the right
1651                  * attribute in this mft record but this would be less
1652                  * efficient and not quite accurate as ntfs_attr_find() ignores
1653                  * the attribute instance numbers for example which become
1654                  * important when one plays with attribute lists. Also, because
1655                  * a proper match has been found in the attribute list entry
1656                  * above, the comparison can now be optimized. So it is worth
1657                  * re-implementing a simplified ntfs_attr_find() here.
1658                  */
1659                 a = ctx->attr;
1660                 /*
1661                  * Use a manual loop so we can still use break and continue
1662                  * with the same meanings as above.
1663                  */
1664 do_next_attr_loop:
1665                 if ((char*)a < (char*)ctx->mrec || (char*)a > (char*)ctx->mrec +
1666                                 le32_to_cpu(ctx->mrec->bytes_allocated))
1667                         break;
1668                 if (a->type == AT_END)
1669                         continue;
1670                 if (!a->length)
1671                         break;
1672                 if (al_entry->instance != a->instance)
1673                         goto do_next_attr;
1674                 /*
1675                  * If the type and/or the name are/is mismatched between the
1676                  * attribute list entry and the attribute record, there is
1677                  * corruption so we break and return error EIO.
1678                  */
1679                 if (al_entry->type != a->type)
1680                         break;
1681                 if (!ntfs_names_are_equal((uchar_t*)((char*)a +
1682                                 le16_to_cpu(a->name_offset)),
1683                                 a->name_length, al_name,
1684                                 al_name_len, CASE_SENSITIVE,
1685                                 vol->upcase, vol->upcase_len))
1686                         break;
1687                 ctx->attr = a;
1688                 /*
1689                  * If no @val specified or @val specified and it matches, we
1690                  * have found it! Also, if !@type, it is an enumeration, so we
1691                  * want the current attribute.
1692                  */
1693                 if (!type || !val || (!a->non_resident &&
1694                                 le32_to_cpu(a->value_length) == val_len &&
1695                                 !memcmp((char*)a + le16_to_cpu(a->value_offset),
1696                                 val, val_len))) {
1697                         return 0;
1698                 }
1699 do_next_attr:
1700                 /* Proceed to the next attribute in the current mft record. */
1701                 a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
1702                 goto do_next_attr_loop;
1703         }
1704         if (ni != base_ni) {
1705                 ctx->ntfs_ino = base_ni;
1706                 ctx->mrec = ctx->base_mrec;
1707                 ctx->attr = ctx->base_attr;
1708         }
1709         Dputs("Inode is corrupt.");
1710         errno = EIO;
1711         return -1;
1712 not_found:
1713         /*
1714          * Seek to the end of the base mft record, i.e. when we return false,
1715          * ctx->mrec and ctx->attr indicate where the attribute should be
1716          * inserted into the attribute record.
1717          * And of course ctx->al_entry points to the end of the attribute
1718          * list inside ctx->base_ntfs_ino->attr_list.
1719          *
1720          * FIXME: Do we really want to do this here? Think about it... (AIA)
1721          */
1722         ntfs_attr_reinit_search_ctx(ctx);
1723         /*
1724          * If we were enumerating and reached the end, we can't just use !@type
1725          * because that would return the first attribute instead of the last
1726          * one. Thus we just change @type to AT_END which causes
1727          * ntfs_attr_find() to seek to the end. We also do the same when an
1728          * attribute extent was searched for (i.e. @lowest_vcn != 0), as we
1729          * otherwise rewind the search back to the first extent and we get
1730          * that extent returned twice during a search for all extents.
1731          */
1732         if (!type || lowest_vcn)
1733                 type = AT_END;
1734         return ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx);
1735 }
1736
1737 /**
1738  * ntfs_attr_lookup - find an attribute in an ntfs inode
1739  * @type:       attribute type to find
1740  * @name:       attribute name to find (optional, i.e. NULL means don't care)
1741  * @name_len:   attribute name length (only needed if @name present)
1742  * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
1743  * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
1744  * @val:        attribute value to find (optional, resident attributes only)
1745  * @val_len:    attribute value length
1746  * @ctx:        search context with mft record and attribute to search from
1747  *
1748  * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
1749  * be the base mft record and @ctx must have been obtained from a call to
1750  * ntfs_attr_get_search_ctx().
1751  *
1752  * This function transparently handles attribute lists and @ctx is used to
1753  * continue searches where they were left off at.
1754  *
1755  * If @type is zero (i.e. AT_UNUSED), return the first found attribute, i.e.
1756  * one can enumerate all attributes by setting @type to zero and then calling
1757  * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
1758  * to indicate that there are no more entries. During the enumeration, each
1759  * successful call of ntfs_attr_lookup() will return the next attribute, with
1760  * the current attribute being described by the search context @ctx.
1761  *
1762  * If @type is AT_END, seek to the end of the attribute and return -1 with
1763  * errno set to ENOENT. AT_END is not a valid attribute, its length is zero for
1764  * example, thus it is safer to return error instead of success in this case.
1765  * It should never ne needed to do this, but we implement the functionality
1766  * because it allows for simpler code inside ntfs_external_attr_find().
1767  *
1768  * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
1769  * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
1770  * match both named and unnamed attributes.
1771  *
1772  * After finishing with the attribute/mft record you need to call
1773  * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
1774  * mapped extent inodes, etc).
1775  *
1776  * Return 0 if the search was successful and -1 if not, with errno set to the
1777  * error code.
1778  *
1779  * On success, @ctx->attr is the found attribute and it is in mft record
1780  * @ctx->mrec.
1781  *
1782  * On error, @ctx->attr is the attribute which collates just after the attribute
1783  * being searched for, i.e. if one wants to add the attribute to the mft
1784  * record this is the correct place to insert it into. @ctx->al_entry points to
1785  * the position within @ctx->base_ntfs_ino->attr_list at which the new
1786  * attribute's attribute list entry should be inserted.
1787  *
1788  * The following error codes are defined:
1789  *      ENOENT  Attribute not found, not an error as such.
1790  *      EINVAL  Invalid arguments.
1791  *      EIO     I/O error or corrupt data structures found.
1792  *      ENOMEM  Not enough memory to allocate necessary buffers.
1793  */
1794 int ntfs_attr_lookup(const ATTR_TYPES type, const uchar_t *name,
1795                 const u32 name_len, const IGNORE_CASE_BOOL ic,
1796                 const VCN lowest_vcn, const u8 *val, const u32 val_len,
1797                 ntfs_attr_search_ctx *ctx)
1798 {
1799         ntfs_inode *base_ni;
1800
1801         if (!ctx || !ctx->mrec || !ctx->attr) {
1802                 errno = EINVAL;
1803                 return -1;
1804         }
1805         if (ctx->base_ntfs_ino)
1806                 base_ni = ctx->base_ntfs_ino;
1807         else
1808                 base_ni = ctx->ntfs_ino;
1809         if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
1810                 return ntfs_attr_find(type, name, name_len, ic, val, val_len,
1811                                 ctx);
1812         return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn,
1813                         val, val_len, ctx);
1814 }
1815
1816 /**
1817  * Internal:
1818  *
1819  * ntfs_attr_init_search_ctx - initialize an attribute search context
1820  * @ctx:        attribute search context to initialize
1821  * @ni:         ntfs inode with which to initialize the search context
1822  * @mrec:       mft record with which to initialize the search context
1823  *
1824  * Initialize the attribute search context @ctx with @ni and @mrec.
1825  */
1826 static __inline__ void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
1827                 ntfs_inode *ni, MFT_RECORD *mrec)
1828 {
1829         if (ni && !mrec)
1830                 mrec = ni->mrec;
1831         ctx->mrec = mrec;
1832         /* Sanity checks are performed elsewhere. */
1833         ctx->attr = (ATTR_RECORD*)((char*)mrec +
1834                         le16_to_cpu(mrec->attrs_offset));
1835         ctx->is_first = TRUE;
1836         ctx->ntfs_ino = ni;
1837         ctx->al_entry = NULL;
1838         ctx->base_ntfs_ino = NULL;
1839         ctx->base_mrec = NULL;
1840         ctx->base_attr = NULL;
1841 }
1842
1843 /**
1844  * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
1845  * @ctx:        attribute search context to reinitialize
1846  *
1847  * Reinitialize the attribute search context @ctx.
1848  *
1849  * This is used when a search for a new attribute is being started to reset
1850  * the search context to the beginning.
1851  */
1852 void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
1853 {
1854         if (!ctx->base_ntfs_ino) {
1855                 /* No attribute list. */
1856                 ctx->is_first = TRUE;
1857                 /* Sanity checks are performed elsewhere. */
1858                 ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec +
1859                                 le16_to_cpu(ctx->mrec->attrs_offset));
1860                 return;
1861         } /* Attribute list. */
1862         ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
1863         return;
1864 }
1865
1866 /**
1867  * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
1868  * @ctx:        address of pointer in which to return the new search context
1869  * @ni:         ntfs inode with which to initialize the search context
1870  * @mrec:       mft record with which to initialize the search context
1871  *
1872  * Allocate a new attribute search context, initialize it with @ni and @mrec,
1873  * and return it. Return NULL on error with errno set to ENOMEM.
1874  *
1875  * @ni can be NULL if the search context is only going to be used for searching
1876  * for the attribute list attribute and for searches ignoring the contents of
1877  * the attribute list attribute.
1878  *
1879  * If @ni is specified, @mrec can be NULL, in which case the mft record is
1880  * taken from @ni.
1881  *
1882  * If both @ni and @mrec are specified, the mft record is taken from @mrec and
1883  * the value of @ni->mrec is ignored.
1884  */
1885 ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
1886 {
1887         ntfs_attr_search_ctx *ctx = malloc(sizeof(ntfs_attr_search_ctx));
1888         if (ctx)
1889                 ntfs_attr_init_search_ctx(ctx, ni, mrec);
1890         return ctx;
1891 }
1892
1893 /**
1894  * ntfs_attr_put_search_ctx - release an attribute search context
1895  * @ctx:        attribute search context to free
1896  *
1897  * Release the attribute search context @ctx.
1898  */
1899 void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
1900 {
1901         free(ctx);
1902         return;
1903 }
1904
1905 /**
1906  * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file
1907  * @vol:        ntfs volume to which the attribute belongs
1908  * @type:       attribute type which to find
1909  *
1910  * Search for the attribute definition record corresponding to the attribute
1911  * @type in the $AttrDef system file.
1912  *
1913  * Return the attribute type definition record if found and NULL if not found
1914  * or an error occured. On error the error code is stored in errno. The
1915  * following error codes are defined:
1916  *      ENOENT  - The attribute @type is not specified in $AttrDef.
1917  *      EINVAL  - Invalid parameters (e.g. @vol is not valid).
1918  */
1919 ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
1920                 const ATTR_TYPES type)
1921 {
1922         ATTR_DEF *ad;
1923
1924         if (!vol || !vol->attrdef || !type) {
1925                 errno = EINVAL;
1926                 return NULL;
1927         }
1928         for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef <
1929                         vol->attrdef_len && ad->type; ++ad) {
1930                 /* We haven't found it yet, carry on searching. */
1931                 if (le32_to_cpu(ad->type) < le32_to_cpu(type))
1932                         continue;
1933                 /* We found the attribute; return it. */
1934                 if (ad->type == type)
1935                         return ad;
1936                 /* We have gone too far already. No point in continuing. */
1937                 break;
1938         }
1939         /* Attribute not found?!? */
1940         errno = ENOENT;
1941         return NULL;
1942 }
1943
1944 /**
1945  * ntfs_attr_size_bounds_check - check a size of an attribute type for validity
1946  * @vol:        ntfs volume to which the attribute belongs
1947  * @type:       attribute type which to check
1948  * @size:       size which to check
1949  *
1950  * Check whether the @size in bytes is valid for an attribute of @type on the
1951  * ntfs volume @vol. This information is obtained from $AttrDef system file.
1952  *
1953  * Return 0 if valid and -1 if not valid or an error occured. On error the
1954  * error code is stored in errno. The following error codes are defined:
1955  *      ERANGE  - @size is not valid for the attribute @type.
1956  *      ENOENT  - The attribute @type is not specified in $AttrDef.
1957  *      EINVAL  - Invalid parameters (e.g. @size is < 0 or @vol is not valid).
1958  */
1959 int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
1960                 const s64 size)
1961 {
1962         ATTR_DEF *ad;
1963
1964         if (size < 0) {
1965                 errno = EINVAL;
1966                 return -1;
1967         }
1968         ad = ntfs_attr_find_in_attrdef(vol, type);
1969         if (!ad)
1970                 return -1;
1971         /* We found the attribute. - Do the bounds check. */
1972         if (size >= le64_to_cpu(ad->min_size) &&
1973                         size <= le64_to_cpu(ad->max_size))
1974                 return 0;
1975         /* @size is out of range! */
1976         errno = ERANGE;
1977         return -1;
1978 }
1979
1980 /**
1981  * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident
1982  * @vol:        ntfs volume to which the attribute belongs
1983  * @type:       attribute type which to check
1984  *
1985  * Check whether the attribute of @type on the ntfs volume @vol is allowed to
1986  * be non-resident. This information is obtained from $AttrDef system file.
1987  *
1988  * Return 0 if the attribute is allowed to be non-resident and -1 if not or an
1989  * error occured. On error the error code is stored in errno. The following
1990  * error codes are defined:
1991  *      EPERM   - The attribute is not allowed to be non-resident.
1992  *      ENOENT  - The attribute @type is not specified in $AttrDef.
1993  *      EINVAL  - Invalid parameters (e.g. @vol is not valid).
1994  */
1995 int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type)
1996 {
1997         ATTR_DEF *ad;
1998
1999         /*
2000          * $DATA is always allowed to be non-resident even if $AttrDef does not
2001          * specify this in the flags of the $DATA attribute definition record.
2002          */
2003         if (type == AT_DATA)
2004                 return 0;
2005         /* Find the attribute definition record in $AttrDef. */
2006         ad = ntfs_attr_find_in_attrdef(vol, type);
2007         if (!ad)
2008                 return -1;
2009         /* Check the flags and return the result. */
2010         if (ad->flags & CAN_BE_NON_RESIDENT)
2011                 return 0;
2012         errno = EPERM;
2013         return -1;
2014 }
2015
2016 /**
2017  * ntfs_attr_record_resize - resize an attribute record
2018  * @m:          mft record containing attribute record
2019  * @a:          attribute record to resize
2020  * @new_size:   new size in bytes to which to resize the attribute record @a
2021  *
2022  * Resize the attribute record @a, i.e. the resident part of the attribute, in
2023  * the mft record @m to @new_size bytes.
2024  *
2025  * Return 0 on success and -1 on error with errno set to the error code.
2026  * The following error codes are defined:
2027  *      ENOSPC  - Not enough space in the mft record @m to perform the resize.
2028  * Note that on error no modifications have been performed whatsoever.
2029  *
2030  * Warning: If you make a record smaller without having copied all the data you
2031  *          are interested in the data may be overwritten!
2032  */
2033 static int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
2034 {
2035         /* Align to 8 bytes, just in case the caller hasn't. */
2036         new_size = (new_size + 7) & ~7;
2037
2038         /* If the actual attribute length has changed, move things around. */
2039         if (new_size != le32_to_cpu(a->length)) {
2040                 u32 new_muse = le32_to_cpu(m->bytes_in_use) -
2041                                 le32_to_cpu(a->length) + new_size;
2042                 /* Not enough space in this mft record. */
2043                 if (new_muse > le32_to_cpu(m->bytes_allocated)) {
2044                         errno = ENOSPC;
2045                         return -1;
2046                 }
2047                 /* Move attributes following @a to their new location. */
2048                 memmove((u8*)a + new_size, (u8*)a + le32_to_cpu(a->length),
2049                                 le32_to_cpu(m->bytes_in_use) - ((u8*)a -
2050                                 (u8*)m) - le32_to_cpu(a->length));
2051                 /* Adjust @m to reflect the change in used space. */
2052                 m->bytes_in_use = cpu_to_le32(new_muse);
2053                 /* Adjust @a to reflect the new size. */
2054                 a->length = cpu_to_le32(new_size);
2055         }
2056         return 0;
2057 }
2058
2059 /**
2060  * ntfs_resident_attr_value_resize - resize the value of a resident attribute
2061  * @m:          mft record containing attribute record
2062  * @a:          attribute record whose value to resize
2063  * @new_size:   new size in bytes to which to resize the attribute value of @a
2064  *
2065  * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
2066  * If the value is made bigger, the newly "allocated" space is cleared.
2067  *
2068  * Return 0 on success and -1 on error with errno set to the error code.
2069  * The following error codes are defined:
2070  *      ENOSPC  - Not enough space in the mft record @m to perform the resize.
2071  * Note that on error no modifications have been performed whatsoever.
2072  */
2073 int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
2074                 const u32 new_size)
2075 {
2076         /*
2077          * Check that the attribute name hasn't been placed after the
2078          * attribute value/mapping pairs array. If it has we need to move it.
2079          * TODO: Implement the move. For now just abort. (AIA)
2080          */
2081         if (a->name_length) {
2082                 BOOL move_name = FALSE;
2083                 if (a->non_resident) {
2084                         if (le16_to_cpu(a->name_offset) >=
2085                                         le16_to_cpu(a->mapping_pairs_offset))
2086                                 move_name = TRUE;
2087                 } else {
2088                         if (le16_to_cpu(a->name_offset) >=
2089                                         le16_to_cpu(a->value_offset))
2090                                 move_name = TRUE;
2091                                 
2092                 }
2093                 if (move_name) {
2094                         // FIXME: Eeek!
2095                         fprintf(stderr, "%s(): Eeek! Name is placed after the "
2096                                         "%s. Aborting...\n", __FUNCTION__,
2097                                         a->non_resident ? "mapping pairs array":
2098                                         "attribute value");
2099                         errno = ENOTSUP;
2100                         return -1;
2101                 }
2102         }
2103         /* Resize the resident part of the attribute record. */
2104         if (ntfs_attr_record_resize(m, a, (le16_to_cpu(a->value_offset) +
2105                         new_size + 7) & ~7) < 0) {
2106                 if (errno != ENOSPC) {
2107                         int eo = errno;
2108
2109                         // FIXME: Eeek!
2110                         fprintf(stderr, "%s(): Eeek! Attribute record resize "
2111                                         "failed. Aborting...\n", __FUNCTION__);
2112                         errno = eo;
2113                 }
2114                 return -1;
2115         }
2116         /*
2117          * If we made the attribute value bigger, clear the area between the
2118          * old size and @new_size.
2119          */
2120         if (new_size > le32_to_cpu(a->value_length))
2121                 memset((u8*)a + le16_to_cpu(a->value_offset) +
2122                                 le32_to_cpu(a->value_length), 0, new_size -
2123                                 le32_to_cpu(a->value_length));
2124         /* Finally update the length of the attribute value. */
2125         a->value_length = cpu_to_le32(new_size);
2126         return 0;
2127 }
2128
2129 /**
2130  * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
2131  * @na:         open ntfs attribute to make non-resident
2132  * @ctx:        ntfs search context describing the attribute
2133  *
2134  * Convert a resident ntfs attribute to a non-resident one.
2135  *
2136  * Return 0 on success and -1 on error with errno set to the error code.
2137  *
2138  * NOTE to self: No changes in the attribute list are required to move from
2139  *               a resident to a non-resident attribute.
2140  *
2141  * Warning: We do not set the inode dirty and we do not write out anything!
2142  *          We expect the caller to do this as this is a fairly low level
2143  *          function and it is likely there will be further changes made.
2144  */
2145 static int ntfs_attr_make_non_resident(ntfs_attr *na,
2146                 ntfs_attr_search_ctx *ctx)
2147 {
2148         s64 new_allocated_size, bw;
2149         ntfs_volume *vol = na->ni->vol;
2150         ATTR_REC *a = ctx->attr;
2151         runlist *rl;
2152         int mp_size, mp_ofs, name_ofs, arec_size, err;
2153
2154         /* Some preliminary sanity checking. */
2155         if (NAttrNonResident(na)) {
2156                 // FIXME: Eeek!
2157                 fprintf(stderr, "%s(): Eeek! Trying to make non-resident "
2158                                 "attribute non-resident. Aborting...\n",
2159                                 __FUNCTION__);
2160                 errno = EINVAL;
2161                 return -1;
2162         }
2163         /*
2164          * Check that the attribute name hasn't been placed after the
2165          * attribute value. If it has we need to move it.
2166          * TODO: Implement the move. For now just abort. (AIA)
2167          */
2168         if (a->name_length && le16_to_cpu(a->name_offset) >=
2169                         le16_to_cpu(a->value_offset)) {
2170                 // FIXME: Eeek!
2171                 fprintf(stderr, "%s(): Eeek! Name is placed after the "
2172                                 "attribute value. Aborting...\n", __FUNCTION__);
2173                 errno = ENOTSUP;
2174                 return -1;
2175         }
2176
2177         new_allocated_size = (le32_to_cpu(a->value_length) + vol->cluster_size
2178                         - 1) & ~(vol->cluster_size - 1);
2179
2180         /* Start by allocating clusters to hold the attribute value. */
2181         rl = ntfs_cluster_alloc(vol, new_allocated_size >>
2182                         vol->cluster_size_bits, -1, DATA_ZONE);
2183         if (!rl) {
2184                 if (errno != ENOSPC) {
2185                         int eo = errno;
2186
2187                         // FIXME: Eeek!
2188                         fprintf(stderr, "%s(): Eeek! Failed to allocate "
2189                                         "cluster(s). Aborting...\n",
2190                                         __FUNCTION__);
2191                         errno = eo;
2192                 }
2193                 return -1;
2194         }
2195
2196         /*
2197          * Setup the in-memory attribute structure to be non-resident so that
2198          * we can use ntfs_attr_pwrite().
2199          */
2200         NAttrSetNonResident(na);
2201         na->rl = rl;
2202         na->allocated_size = new_allocated_size;
2203         na->data_size = na->initialized_size = le32_to_cpu(a->value_length);
2204         /*
2205          * For now just clear all of these as we don't support them when
2206          * writing.
2207          */
2208         NAttrClearCompressed(na);
2209         NAttrClearSparse(na);
2210         NAttrClearEncrypted(na);
2211         
2212         /* Now copy the attribute value to the allocated cluster(s). */
2213         bw = ntfs_attr_pwrite(na, 0, le32_to_cpu(a->value_length),
2214                         (u8*)a + le16_to_cpu(a->value_offset));
2215         if (bw != le32_to_cpu(a->value_length)) {
2216                 err = errno;
2217                 // FIXME: Eeek!
2218                 fprintf(stderr, "%s(): Eeek! Failed to write out attribute "
2219                                 "value (bw = %Li, errno = %i). Aborting...\n",
2220                                 __FUNCTION__, (long long)bw, err);
2221                 if (bw >= 0)
2222                         err = EIO;
2223                 goto cluster_free_err_out;
2224         }
2225
2226         /* Determine the size of the mapping pairs array. */
2227         mp_size = ntfs_get_size_for_mapping_pairs(vol, rl);
2228         if (mp_size < 0) {
2229                 err = errno;
2230                 // FIXME: Eeek!
2231                 fprintf(stderr, "%s(): Eeek! Failed to get size for mapping "
2232                                 "pairs array. Aborting...\n", __FUNCTION__);
2233                 goto cluster_free_err_out;
2234         }
2235
2236         /* Calculate new offsets for the name and the mapping pairs array. */
2237         name_ofs = (sizeof(ATTR_REC) - sizeof(a->compressed_size) + 7) & ~7;
2238         mp_ofs = (name_ofs + a->name_length + 7) & ~7;
2239
2240         /*
2241          * Determine the size of the resident part of the non-resident
2242          * attribute record. (Not compressed thus no compressed_size element
2243          * present.)
2244          */
2245         arec_size = (mp_ofs + mp_size + 7) & ~7;
2246
2247         /* Sanity check. */
2248         if (a->name_length && (le16_to_cpu(a->name_offset) + a->name_length >
2249                         arec_size)) {
2250                 // FIXME: Eeek!
2251                 fprintf(stderr, "%s(): Eeek! Name exceeds new record size! "
2252                                 "Not supported. Aborting...\n", __FUNCTION__);
2253                 err = ENOTSUP;
2254                 goto cluster_free_err_out;
2255         }
2256
2257         /* Resize the resident part of the attribute record. */
2258         if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
2259                 err = errno;
2260                 if (err != ENOSPC) {
2261                         // FIXME: Eeek!
2262                         fprintf(stderr, "%s(): Eeek! Failed to resize "
2263                                         "attribute record. Aborting...\n",
2264                                         __FUNCTION__);
2265                 }
2266                 goto cluster_free_err_out;
2267         }
2268
2269         /*
2270          * Convert the resident part of the attribute record to describe a
2271          * non-resident attribute.
2272          */
2273         a->non_resident = 1;
2274
2275         /* Move the attribute name if it exists and update the offset. */
2276         if (a->name_length)
2277                 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
2278                                 a->name_length * sizeof(uchar_t));
2279         a->name_offset = cpu_to_le16(name_ofs);
2280
2281         /* Update the flags to match the in-memory ones. */
2282         a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED |
2283                         ATTR_COMPRESSION_MASK);
2284
2285         /* Setup the fields specific to non-resident attributes. */
2286         a->lowest_vcn = scpu_to_le64(0);
2287         if (na->data_size != 0)
2288                 a->highest_vcn = scpu_to_le64(0);
2289         else
2290                 a->highest_vcn = scpu_to_le64(-1);
2291
2292         a->mapping_pairs_offset = cpu_to_le16(mp_ofs);
2293
2294         a->compression_unit = 0;
2295
2296         memset(&a->reserved1, 0, sizeof(a->reserved1));
2297
2298         a->allocated_size = scpu_to_le64(new_allocated_size);
2299         a->data_size = a->initialized_size = scpu_to_le64(na->data_size);
2300
2301         /* Generate the mapping pairs array in the attribute record. */
2302         if (ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, arec_size - mp_ofs,
2303                         rl) < 0) {
2304                 err = errno;
2305                 // FIXME: Eeek! We need rollback! (AIA)
2306                 fprintf(stderr, "%s(): Eeek! Failed to build mapping pairs. "
2307                                 "Leaving corrupt attribute record on disk. "
2308                                 "In memory runlist is still intact! Error "
2309                                 "code is %i. FIXME: Need to rollback "
2310                                 "instead!\n", __FUNCTION__, err);
2311                 errno = err;
2312                 return -1;
2313         }
2314
2315         /* Done! */
2316         return 0;
2317
2318 cluster_free_err_out:
2319         if (ntfs_cluster_free(vol, na, 0, -1) < 0)
2320                 fprintf(stderr, "%s(): Eeek! Failed to release allocated "
2321                                 "clusters in error code path. Leaving "
2322                                 "inconsistent metadata...\n", __FUNCTION__);
2323         NAttrClearNonResident(na);
2324         na->allocated_size = na->data_size;
2325         na->rl = NULL;
2326         free(rl);
2327         errno = err;
2328         return -1;
2329 }
2330
2331 /**
2332  * ntfs_resident_attr_resize - resize a resident, open ntfs attribute
2333  * @na:         resident ntfs attribute to resize
2334  * @newsize:    new size (in bytes) to which to resize the attribute
2335  *
2336  * Change the size of a resident, open ntfs attribute @na to @newsize bytes.
2337  *
2338  * On success return 0 and on error return -1 with errno set to the error code.
2339  * The following error codes are defined:
2340  *      ENOTSUP - The desired resize is not implemented yet.
2341  *      ENOMEM  - Not enough memory to complete operation.
2342  *      ERANGE  - @newsize is not valid for the attribute type of @na.
2343  */
2344 static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
2345 {
2346         ntfs_attr_search_ctx *ctx;
2347         ntfs_volume *vol;
2348         int err;
2349
2350         Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x.\n", __FUNCTION__,
2351                         (unsigned long long)na->ni->mft_no, na->type);
2352         /* Get the attribute record that needs modification. */
2353         ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
2354         if (!ctx)
2355                 return -1;
2356         if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, 0, NULL, 0,
2357                         ctx)) {
2358                 err = errno;
2359                 goto put_err_out;
2360         }
2361         vol = na->ni->vol;
2362         /*
2363          * Check the attribute type and the corresponding minimum and maximum
2364          * sizes against @newsize and fail if @newsize is out of bounds.
2365          */
2366         if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
2367                 err = errno;
2368                 if (err == ERANGE) {
2369                         // FIXME: Eeek!
2370                         fprintf(stderr, "%s(): Eeek! Size bounds check "
2371                                         "failed. Aborting...\n", __FUNCTION__);
2372                 } else if (err == ENOENT)
2373                         err = EIO;
2374                 goto put_err_out;
2375         }
2376         /*
2377          * If @newsize is bigger than the mft record we need to make the
2378          * attribute non-resident if the attribute type supports it. If it is
2379          * smaller we can go ahead and attempt the resize.
2380          */
2381         if (newsize < vol->mft_record_size) {
2382                 /* Perform the resize of the attribute record. */
2383                 if (!ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
2384                                 newsize)) {
2385                         /* Update the ntfs attribute structure, too. */
2386                         na->allocated_size = na->data_size =
2387                                         na->initialized_size = newsize;
2388                         if (NAttrCompressed(na) || NAttrSparse(na))
2389                                 na->compressed_size = newsize;
2390                         goto resize_done;
2391                 }
2392                 /* Error! If not enough space, just continue. */
2393                 if (errno != ENOSPC) {
2394                         err = errno;
2395                         // FIXME: Eeek!
2396                         if (err != ENOTSUP)
2397                                 fprintf(stderr, "%s(): Eeek! Failed to resize "
2398                                                 "resident part of attribute. "
2399                                                 "Aborting...\n", __FUNCTION__);
2400                         goto put_err_out;
2401                 }
2402         }
2403         /* There is not enough space in the mft record to perform the resize. */
2404
2405         /* Check if the attribute is allowed to be non-resident. */
2406         if (!ntfs_attr_can_be_non_resident(vol, na->type)) {
2407                 /* Make the attribute non-resident. */
2408                 if (!ntfs_attr_make_non_resident(na, ctx)) {
2409                         // TODO: Attribute is now non-resident. Resize it!
2410                         // goto resize_done;
2411                         fprintf(stderr, "%s(): TODO: Resize attribute now that "
2412                                         "it is non-resident.\n", __FUNCTION__);
2413                         ntfs_inode_mark_dirty(ctx->ntfs_ino);
2414                         err = ENOTSUP;
2415                         goto put_err_out;
2416                 }
2417                 /* Error! If not enough space, just continue. */
2418                 if (errno != ENOSPC) {
2419                         err = errno;
2420                         // FIXME: Eeek!
2421                         fprintf(stderr, "%s(): Eeek! Failed to make attribute "
2422                                         "non-resident. Aborting...\n",
2423                                         __FUNCTION__);
2424                         goto put_err_out;
2425                 }
2426         } else {
2427                 /*
2428                  * If the attribute can be non-resident but an error occured
2429                  * while making it non-resident, abort.
2430                  */
2431                 if (errno != EPERM) {
2432                         err = errno;
2433                         goto put_err_out;
2434                 }
2435                 /* Attribute is not allowed to be non-resident, continue. */
2436         }
2437
2438         // TODO: Try to make other attributes non-resident.
2439
2440         // TODO: Move the attribute to a new mft record, creating an attribute
2441         // list attribute or modifying it if it is already present.
2442
2443         err = ENOTSUP;
2444         goto put_err_out;
2445
2446 resize_done:
2447         /*
2448          * Set the inode (and its base inode if it exists) dirty so it is
2449          * written out later.
2450          */
2451         ntfs_inode_mark_dirty(ctx->ntfs_ino);
2452         /* Done! */
2453         ntfs_attr_put_search_ctx(ctx);
2454         return 0;
2455 put_err_out:
2456         ntfs_attr_put_search_ctx(ctx);
2457         errno = err;
2458         return -1;
2459 }
2460
2461 static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
2462 {
2463         // FIXME: For now we cheat and assume there is no attribute list
2464         //        present. (AIA)
2465         if (NInoAttrList(na->ni)) {
2466                 errno = ENOTSUP;
2467                 return -1;
2468         }
2469
2470         /* Make sure this is not $MFT/$BITMAP or Windows will not boot! */
2471         if (na->type == AT_BITMAP && na->ni->mft_no == FILE_MFT) {
2472                 errno = EPERM;
2473                 return -1;
2474         }
2475
2476         errno = ENOTSUP;
2477         return -1;
2478
2479         //NAttrClearNonResident(na);
2480         //return 0;
2481 }
2482
2483 /**
2484  * ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute
2485  * @na:         non-resident ntfs attribute to shrink
2486  * @newsize:    new size (in bytes) to which to shrink the attribute
2487  *
2488  * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes.
2489  *
2490  * On success return 0 and on error return -1 with errno set to the error code.
2491  * The following error codes are defined:
2492  *      ENOTSUP - The desired resize is not implemented yet.
2493  *      ENOMEM  - Not enough memory to complete operation.
2494  *      ERANGE  - @newsize is not valid for the attribute type of @na.
2495  */
2496 static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize)
2497 {
2498         ntfs_volume *vol;
2499         ntfs_attr_search_ctx *ctx;
2500         ATTR_RECORD *a;
2501         MFT_RECORD *m;
2502         VCN first_free_vcn;
2503         s64 nr_freed_clusters;
2504         u32 new_alen, new_muse;
2505         int err, mp_size;
2506
2507         Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x.\n", __FUNCTION__,
2508                         (unsigned long long)na->ni->mft_no, na->type);
2509
2510         vol = na->ni->vol;
2511
2512         /* Get the first attribute record that needs modification. */
2513         ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
2514         if (!ctx)
2515                 return -1;
2516         if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, newsize >>
2517                         vol->cluster_size_bits, NULL, 0, ctx)) {
2518                 err = errno;
2519                 if (err == ENOENT)
2520                         err = EIO;
2521                 goto put_err_out;
2522         }
2523         a = ctx->attr;
2524         m = ctx->mrec;
2525         /*
2526          * Check the attribute type and the corresponding minimum size
2527          * against @newsize and fail if @newsize is too small.
2528          */
2529         if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
2530                 err = errno;
2531                 if (err == ERANGE) {
2532                         // FIXME: Eeek!
2533                         fprintf(stderr, "%s(): Eeek! Size bounds check "
2534                                         "failed. Aborting...\n", __FUNCTION__);
2535                 } else if (err == ENOENT)
2536                         err = EIO;
2537                 goto put_err_out;
2538         }
2539
2540         // When extents/an attribute list is/are present it is very complicated:
2541         // TODO: For the current extent:
2542         //      TODO: free the required clusters
2543         //      FIXME: how do we deal with extents that haven't been loaded yet?
2544         //              do we just fault them in first so that the runlist is
2545         //              complete and we are done with deallocations in one go?
2546         //      TODO: update the run list in na->rl
2547         //      TODO: update the sizes, etc in the ntfs attribute structure na
2548         //      TODO: update the mapping pairs array
2549         //      TODO: mark the inode dirty
2550         // TODO: For all subsequent extents:
2551         //      TODO: free all clusters specified by the extent (FIXME: unless
2552         //              already done above!)
2553         //      TODO: completely delete each extent attribute record from its
2554         //              mft record
2555         //      TODO: free the mft record if there are no attributes left in it
2556         //              (to do so update the $MFT/$Bitmap as well as the mft
2557         //               record header in use flag, etc)
2558         //      TODO: write the updated mft record to disk
2559         //      TODO: remove the extent inode from the list of loaded extent
2560         //              inodes in the base inode
2561         //      TODO: free all memory associated with the extent inode
2562         // TODO: update the attribute list attribute in ni->attr_list, removing
2563         //       all entries corresponding to deleted attributes
2564         // TODO: if the attribute list attribute is resident:
2565         //              TODO: update the actual attribute in the base mft
2566         //                      record from ni->attr_list
2567         //       if the attribute list attribute is not resident:
2568         //              TODO: update the attribute list attribute run list in
2569         //                      ni->attr_list_rl, freeing any no longer used
2570         //                      clusters
2571         //              TODO: mark the inode attribute list as containing
2572         //                      dirty data
2573         //              TODO: update the mapping pairs array from
2574         //                      ni->attr_list_rl
2575         // TODO: mark the base inode dirty
2576
2577         // TODO: Implement attribute list support as desribed above. (AIA)
2578         if (NInoAttrList(na->ni)) {
2579                 err = ENOTSUP;
2580                 goto put_err_out;
2581         }
2582         // FIXME: We now know that we don't have an attribute list. Thus we
2583         //        are in the base inode only and hence it is all easier, even
2584         //        if we are cheating for now... (AIA)
2585
2586         /* The first cluster outside the new allocation. */
2587         first_free_vcn = (newsize + vol->cluster_size - 1) >>
2588                         vol->cluster_size_bits;
2589         /*
2590          * Compare the new allocation with the old one and only deallocate
2591          * clusters if there is a change.
2592          */
2593         if ((na->allocated_size >> vol->cluster_size_bits) != first_free_vcn) {
2594                 /* Deallocate all clusters starting with the first free one. */
2595                 nr_freed_clusters = ntfs_cluster_free(vol, na, first_free_vcn,
2596                                 -1);
2597                 if (nr_freed_clusters < 0) {
2598                         err = errno;
2599                         // FIXME: Eeek!
2600                         fprintf(stderr, "%s(): Eeek! Freeing of clusters "
2601                                         "failed. Aborting...\n", __FUNCTION__);
2602                         goto put_err_out;
2603                 }
2604                 /* Truncate the runlist itself. */
2605                 if (ntfs_rl_truncate(&na->rl, first_free_vcn)) {
2606                         err = errno;
2607                         // FIXME: Eeek! We need rollback! (AIA)
2608                         fprintf(stderr, "%s(): Eeek! Run list truncation "
2609                                         "failed. Leaving inconsistent "
2610                                         "metadata!\n", __FUNCTION__);
2611                         goto put_err_out;
2612                 }
2613                 /* Update the attribute record and the ntfs_attr structure. */
2614                 na->allocated_size = first_free_vcn << vol->cluster_size_bits;
2615                 a->allocated_size = scpu_to_le64(na->allocated_size);
2616                 if (NAttrCompressed(na) || NAttrSparse(na)) {
2617                         na->compressed_size -= nr_freed_clusters <<
2618                                         vol->cluster_size_bits;
2619                         // FIXME: Bug catcher. Remove later... (AIA)
2620                         if (!newsize && na->compressed_size) {
2621                                 fprintf(stderr, "%s(): Eeek! !newsize but "
2622                                                 "na->compressed_size not zero "
2623                                                 "(= %Li)! Fixing up by hand!\n",
2624                                                 __FUNCTION__, (long long)
2625                                                 na->compressed_size);
2626                                 na->compressed_size = 0;
2627                         }
2628                         a->compressed_size = scpu_to_le64(na->compressed_size);
2629
2630                         // FIXME: Bug catcher. Remove later... (AIA)
2631                         if (na->compressed_size < 0) {
2632                                 // FIXME: Eeek! BUG!
2633                                 fprintf(stderr, "%s(): Eeek! Compressed size "
2634                                                 "is negative. Leaving "
2635                                                 "inconsistent metadata!\n",
2636                                                 __FUNCTION__);
2637                                 err = EIO;
2638                                 goto put_err_out;
2639                         }
2640                 }
2641                 /*
2642                  * Reminder: It is ok for a->highest_vcn to be -1 for zero
2643                  * length files.
2644                  */
2645                 if (a->highest_vcn)
2646                         a->highest_vcn = scpu_to_le64(first_free_vcn - 1);
2647                 /* Get the size for the new mapping pairs array. */
2648                 mp_size = ntfs_get_size_for_mapping_pairs(vol, na->rl);
2649                 if (mp_size <= 0) {
2650                         err = errno;
2651                         // FIXME: Eeek! We need rollback! (AIA)
2652                         fprintf(stderr, "%s(): Eeek! Get size for mapping "
2653                                         "pairs failed. Leaving inconsistent "
2654                                         "metadata!\n", __FUNCTION__);
2655                         goto put_err_out;
2656                 }
2657                 /*
2658                  * Generate the new mapping pairs array directly into the
2659                  * correct destination, i.e. the attribute record itself.
2660                  */
2661                 if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
2662                                 a->mapping_pairs_offset), mp_size, na->rl)) {
2663                         err = errno;
2664                         // FIXME: Eeek! We need rollback! (AIA)
2665                         fprintf(stderr, "%s(): Eeek! Mapping pairs build "
2666                                         "failed. Leaving inconsistent "
2667                                         "metadata!\n", __FUNCTION__);
2668                         goto put_err_out;
2669                 }
2670                 /*
2671                  * Check that the attribute name hasn't been placed after the
2672                  * attribute value/mapping pairs array. If it has we need to
2673                  * move it. TODO: Implement the move. For now just abort. (AIA)
2674                  */
2675                 if (a->name_length) {
2676                         BOOL move_name = FALSE;
2677                         if (a->non_resident) {
2678                                 if (le16_to_cpu(a->name_offset) >= le16_to_cpu(
2679                                                 a->mapping_pairs_offset))
2680                                         move_name = TRUE;
2681                         } else {
2682                                 if (le16_to_cpu(a->name_offset) >=
2683                                                 le16_to_cpu(a->value_offset))
2684                                         move_name = TRUE;
2685                                         
2686                         }
2687                         if (move_name) {
2688                                 // FIXME: Eeek!
2689                                 fprintf(stderr, "%s(): Eeek! Name is placed "
2690                                                 "after the %s. Aborting...\n",
2691                                                 __FUNCTION__, a->non_resident ?
2692                                                 "mapping pairs array":
2693                                                 "attribute value");
2694                                 err = ENOTSUP;
2695                                 goto put_err_out;
2696                         }
2697                 }
2698                 /*
2699                  * Calculate the new attribute length and mft record bytes
2700                  * used.
2701                  */
2702                 new_alen = (le16_to_cpu(a->mapping_pairs_offset) + mp_size +
2703                                 7) & ~7;
2704                 new_muse = le32_to_cpu(m->bytes_in_use) -
2705                                 le32_to_cpu(a->length) + new_alen;
2706                 if (new_muse > le32_to_cpu(m->bytes_allocated)) {
2707                         // FIXME: Eeek! BUG()
2708                         fprintf(stderr, "%s(): Eeek! Ran out of space in mft "
2709                                         "record. Leaving inconsistent "
2710                                         "metadata!\n", __FUNCTION__);
2711                         err = EIO;
2712                         goto put_err_out;
2713                 }
2714                 /* Move the following attributes forward. */
2715                 memmove((u8*)a + new_alen, (u8*)a + le32_to_cpu(a->length),
2716                                 le32_to_cpu(m->bytes_in_use) - ((u8*)a -
2717                                 (u8*)m) - le32_to_cpu(a->length));
2718                 /* Update the sizes of the attribute and mft records. */
2719                 a->length = cpu_to_le32(new_alen);
2720                 m->bytes_in_use = cpu_to_le32(new_muse);
2721         }
2722         /* Update the attribute record and the ntfs attribute structure. */
2723         na->data_size = newsize;
2724         a->data_size = scpu_to_le64(newsize);
2725         if (newsize < na->initialized_size) {
2726                 na->initialized_size = newsize;
2727                 a->initialized_size = scpu_to_le64(newsize);
2728         }
2729         /* If the attribute now has zero size, make it resident. */
2730         if (!newsize) {
2731                 if (ntfs_attr_make_resident(na, ctx)) {
2732                         /* If couldn't make resident, just continue. */
2733                         if (errno != EPERM)
2734                                 Dprintf("%s(): Failed to make attribute "
2735                                                 "resident. Leaving as is...\n",
2736                                                 __FUNCTION__);
2737                 }
2738         }
2739         /* Set the inode dirty so it is written out later. */
2740         ntfs_inode_mark_dirty(ctx->ntfs_ino);
2741         /* Done! */
2742         ntfs_attr_put_search_ctx(ctx);
2743         return 0;
2744 put_err_out:
2745         ntfs_attr_put_search_ctx(ctx);
2746         errno = err;
2747         return -1;
2748 }
2749
2750 /**
2751  * ntfs_attr_truncate - resize an ntfs attribute
2752  * @na:         open ntfs attribute to resize
2753  * @newsize:    new size (in bytes) to which to resize the attribute
2754  *
2755  * Change the size of an open ntfs attribute @na to @newsize bytes. If the
2756  * attribute is made bigger and the attribute is resident the newly
2757  * "allocated" space is cleared and if the attribute is non-resident the
2758  * newly allocated space is marked as not initialised and no real allocation
2759  * on disk is performed. FIXME: Do we have to create sparse runs or can we just
2760  * leave the runlist to finish below data_size, i.e. can we have
2761  * allocated_size < data_size? I guess that what we can't and thus we will have
2762  * to set the sparse bit of the attribute and create sparse runs to ensure that
2763  * allocated_size is >= data_size. We don't need to clear the partial run at
2764  * the end of the real allocation because we leave initialized_size low enough.
2765  * FIXME: Do we want that? Alternatively, we leave initialized_size = data_size
2766  * and do clear the partial run. The latter approach would be more inline with
2767  * what windows would do, even though windows wouldn't even make the attribute
2768  * sparse, it would just allocate clusters instead. TODO: Check what happens on
2769  * WinXP and .NET. FIXME: Make sure to check what NT4 does with an NTFS1.2
2770  * volume that has sparse files. I suspect it will blow up so we will need to
2771  * perform allocations of clusters, like NT4 would do for NTFS1.2 while we can
2772  * use sparse attributes on NTFS3.x.
2773  *
2774  * On success return 0 and on error return -1 with errno set to the error code.
2775  * The following error codes are defined:
2776  *      EINVAL  - Invalid arguments were passed to the function.
2777  *      ENOTSUP - The desired resize is not implemented yet.
2778  *
2779  * NOTE: At present attributes can only be made smaller using this function,
2780  *       never bigger.
2781  */
2782 int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
2783 {
2784         if (!na || newsize < 0) {
2785                 errno = EINVAL;
2786                 return -1;
2787         }
2788         /*
2789          * Encrypted attributes are not supported. We return access denied,
2790          * which is what Windows NT4 does, too.
2791          */
2792         if (NAttrEncrypted(na)) {
2793                 errno = EACCES;
2794                 return -1;
2795         }
2796         /*
2797          * TODO: Implement making non-resident attributes bigger/filling in of
2798          * uninitialized holes as well as handling of compressed attributes.
2799          */
2800         if ((NAttrNonResident(na) && newsize > na->initialized_size) ||
2801                         NAttrCompressed(na)) {
2802                 errno = ENOTSUP;
2803                 return -1;
2804         }
2805
2806         if (NAttrNonResident(na))
2807                 return ntfs_non_resident_attr_shrink(na, newsize);
2808         return ntfs_resident_attr_resize(na, newsize);
2809 }
2810