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