1/**
2 * inode.c - Inode handling code. Originated from the Linux-NTFS project.
3 *
4 * Copyright (c) 2002-2005 Anton Altaparmakov
5 * Copyright (c) 2002-2008 Szabolcs Szakacsits
6 * Copyright (c) 2004-2007 Yura Pakhuchiy
7 * Copyright (c) 2004-2005 Richard Russon
8 *
9 * This program/include file is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program/include file is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the NTFS-3G
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#ifdef HAVE_STDLIB_H
30#include <stdlib.h>
31#endif
32#ifdef HAVE_STRING_H
33#include <string.h>
34#endif
35#ifdef HAVE_ERRNO_H
36#include <errno.h>
37#endif
38
39#include "compat.h"
40#include "types.h"
41#include "attrib.h"
42#include "inode.h"
43#include "debug.h"
44#include "mft.h"
45#include "attrlist.h"
46#include "runlist.h"
47#include "lcnalloc.h"
48#include "index.h"
49#include "dir.h"
50#include "ntfstime.h"
51#include "logging.h"
52#include "misc.h"
53
54ntfs_inode *ntfs_inode_base(ntfs_inode *ni)
55{
56	if (ni->nr_extents == -1)
57		return ni->base_ni;
58	return ni;
59}
60
61/**
62 * ntfs_inode_mark_dirty - set the inode (and its base inode if it exists) dirty
63 * @ni:		ntfs inode to set dirty
64 *
65 * Set the inode @ni dirty so it is written out later (at the latest at
66 * ntfs_inode_close() time). If @ni is an extent inode, set the base inode
67 * dirty, too.
68 *
69 * This function cannot fail.
70 */
71void ntfs_inode_mark_dirty(ntfs_inode *ni)
72{
73	NInoSetDirty(ni);
74	if (ni->nr_extents == -1)
75		NInoSetDirty(ni->base_ni);
76}
77
78/**
79 * __ntfs_inode_allocate - Create and initialise an NTFS inode object
80 * @vol:
81 *
82 * Description...
83 *
84 * Returns:
85 */
86static ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol)
87{
88	ntfs_inode *ni;
89
90	ni = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
91	if (ni)
92		ni->vol = vol;
93	return ni;
94}
95
96/**
97 * ntfs_inode_allocate - Create an NTFS inode object
98 * @vol:
99 *
100 * Description...
101 *
102 * Returns:
103 */
104ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol)
105{
106	return __ntfs_inode_allocate(vol);
107}
108
109/**
110 * __ntfs_inode_release - Destroy an NTFS inode object
111 * @ni:
112 *
113 * Description...
114 *
115 * Returns:
116 */
117static void __ntfs_inode_release(ntfs_inode *ni)
118{
119	if (NInoDirty(ni))
120		ntfs_log_error("Releasing dirty inode %lld!\n",
121			       (long long)ni->mft_no);
122	if (NInoAttrList(ni) && ni->attr_list)
123		free(ni->attr_list);
124	free(ni->mrec);
125	free(ni);
126	return;
127}
128
129/**
130 * ntfs_inode_open - open an inode ready for access
131 * @vol:	volume to get the inode from
132 * @mref:	inode number / mft record number to open
133 *
134 * Allocate an ntfs_inode structure and initialize it for the given inode
135 * specified by @mref. @mref specifies the inode number / mft record to read,
136 * including the sequence number, which can be 0 if no sequence number checking
137 * is to be performed.
138 *
139 * Then, allocate a buffer for the mft record, read the mft record from the
140 * volume @vol, and attach it to the ntfs_inode structure (->mrec). The
141 * mft record is mst deprotected and sanity checked for validity and we abort
142 * if deprotection or checks fail.
143 *
144 * Finally, search for an attribute list attribute in the mft record and if one
145 * is found, load the attribute list attribute value and attach it to the
146 * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate
147 * this.
148 *
149 * Return a pointer to the ntfs_inode structure on success or NULL on error,
150 * with errno set to the error code.
151 */
152ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
153{
154	s64 l;
155	ntfs_inode *ni = NULL;
156	ntfs_attr_search_ctx *ctx;
157	STANDARD_INFORMATION *std_info;
158
159	ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
160	if (!vol) {
161		errno = EINVAL;
162		goto out;
163	}
164	ni = __ntfs_inode_allocate(vol);
165	if (!ni)
166		goto out;
167	if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL))
168		goto err_out;
169	if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) {
170		errno = ENOENT;
171		goto err_out;
172	}
173	ni->mft_no = MREF(mref);
174	ctx = ntfs_attr_get_search_ctx(ni, NULL);
175	if (!ctx)
176		goto err_out;
177	/* Receive some basic information about inode. */
178	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
179				0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
180		ntfs_log_perror("No STANDARD_INFORMATION in base record\n");
181		goto put_err_out;
182	}
183	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
184			le16_to_cpu(ctx->attr->value_offset));
185	ni->flags = std_info->file_attributes;
186	ni->creation_time = ntfs2utc(std_info->creation_time);
187	ni->last_data_change_time = ntfs2utc(std_info->last_data_change_time);
188	ni->last_mft_change_time = ntfs2utc(std_info->last_mft_change_time);
189	ni->last_access_time = ntfs2utc(std_info->last_access_time);
190	/* Set attribute list information. */
191	if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
192			ctx)) {
193		if (errno != ENOENT)
194			goto put_err_out;
195		/* Attribute list attribute does not present. */
196		goto get_size;
197	}
198	NInoSetAttrList(ni);
199	l = ntfs_get_attribute_value_length(ctx->attr);
200	if (!l)
201		goto put_err_out;
202	if (l > 0x40000) {
203		errno = EIO;
204		ntfs_log_perror("Too large attrlist (%lld)\n", (long long)l);
205		goto put_err_out;
206	}
207	ni->attr_list_size = l;
208	ni->attr_list = ntfs_malloc(ni->attr_list_size);
209	if (!ni->attr_list)
210		goto put_err_out;
211	l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list);
212	if (!l)
213		goto put_err_out;
214	if (l != ni->attr_list_size) {
215		errno = EIO;
216		ntfs_log_perror("Unexpected attrlist size (%lld <> %u)\n",
217				(long long)l, ni->attr_list_size);
218		goto put_err_out;
219	}
220get_size:
221	if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
222		if (errno != ENOENT)
223			goto put_err_out;
224		/* Directory or special file. */
225		ni->data_size = ni->allocated_size = 0;
226	} else {
227		if (ctx->attr->non_resident) {
228			ni->data_size = sle64_to_cpu(ctx->attr->data_size);
229			if (ctx->attr->flags &
230					(ATTR_IS_COMPRESSED | ATTR_IS_SPARSE))
231				ni->allocated_size = sle64_to_cpu(
232						ctx->attr->compressed_size);
233			else
234				ni->allocated_size = sle64_to_cpu(
235						ctx->attr->allocated_size);
236		} else {
237			ni->data_size = le32_to_cpu(ctx->attr->value_length);
238			ni->allocated_size = (ni->data_size + 7) & ~7;
239		}
240	}
241	ntfs_attr_put_search_ctx(ctx);
242out:
243	ntfs_log_leave("\n");
244	return ni;
245
246put_err_out:
247	ntfs_attr_put_search_ctx(ctx);
248err_out:
249	__ntfs_inode_release(ni);
250	ni = NULL;
251	goto out;
252}
253
254/**
255 * ntfs_inode_close - close an ntfs inode and free all associated memory
256 * @ni:		ntfs inode to close
257 *
258 * Make sure the ntfs inode @ni is clean.
259 *
260 * If the ntfs inode @ni is a base inode, close all associated extent inodes,
261 * then deallocate all memory attached to it, and finally free the ntfs inode
262 * structure itself.
263 *
264 * If it is an extent inode, we disconnect it from its base inode before we
265 * destroy it.
266 *
267 * It is OK to pass NULL to this function, it is just noop in this case.
268 *
269 * Return 0 on success or -1 on error with errno set to the error code. On
270 * error, @ni has not been freed. The user should attempt to handle the error
271 * and call ntfs_inode_close() again. The following error codes are defined:
272 *
273 *	EBUSY	@ni and/or its attribute list runlist is/are dirty and the
274 *		attempt to write it/them to disk failed.
275 *	EINVAL	@ni is invalid (probably it is an extent inode).
276 *	EIO	I/O error while trying to write inode to disk.
277 */
278int ntfs_inode_close(ntfs_inode *ni)
279{
280	int ret = -1;
281
282	if (!ni)
283		return 0;
284
285	ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no);
286
287	/* If we have dirty metadata, write it out. */
288	if (NInoDirty(ni) || NInoAttrListDirty(ni)) {
289		if (ntfs_inode_sync(ni)) {
290			if (errno != EIO)
291				errno = EBUSY;
292			goto err;
293		}
294	}
295	/* Is this a base inode with mapped extent inodes? */
296	if (ni->nr_extents > 0) {
297		while (ni->nr_extents > 0) {
298			if (ntfs_inode_close(ni->extent_nis[0])) {
299				if (errno != EIO)
300					errno = EBUSY;
301				goto err;
302			}
303		}
304	} else if (ni->nr_extents == -1) {
305		ntfs_inode **tmp_nis;
306		ntfs_inode *base_ni;
307		s32 i;
308
309		/*
310		 * If the inode is an extent inode, disconnect it from the
311		 * base inode before destroying it.
312		 */
313		base_ni = ni->base_ni;
314		for (i = 0; i < base_ni->nr_extents; ++i) {
315			tmp_nis = base_ni->extent_nis;
316			if (tmp_nis[i] != ni)
317				continue;
318			/* Found it. Disconnect. */
319			memmove(tmp_nis + i, tmp_nis + i + 1,
320					(base_ni->nr_extents - i - 1) *
321					sizeof(ntfs_inode *));
322			/* Buffer should be for multiple of four extents. */
323			if ((--base_ni->nr_extents) & 3) {
324				i = -1;
325				break;
326			}
327			/*
328			 * ElectricFence is unhappy with realloc(x,0) as free(x)
329			 * thus we explicitly separate these two cases.
330			 */
331			if (base_ni->nr_extents) {
332				/* Resize the memory buffer. */
333				tmp_nis = realloc(tmp_nis, base_ni->nr_extents *
334						  sizeof(ntfs_inode *));
335				/* Ignore errors, they don't really matter. */
336				if (tmp_nis)
337					base_ni->extent_nis = tmp_nis;
338			} else if (tmp_nis)
339				free(tmp_nis);
340			/* Allow for error checking. */
341			i = -1;
342			break;
343		}
344
345		/*
346		 *  We could successfully sync, so only log this error
347		 *  and try to sync other inode extents too.
348		 */
349		if (i != -1)
350			ntfs_log_error("Extent inode %lld was not found\n",
351				       (long long)ni->mft_no);
352	}
353
354	__ntfs_inode_release(ni);
355	ret = 0;
356err:
357	ntfs_log_leave("\n");
358	return ret;
359}
360
361/**
362 * ntfs_extent_inode_open - load an extent inode and attach it to its base
363 * @base_ni:	base ntfs inode
364 * @mref:	mft reference of the extent inode to load (in little endian)
365 *
366 * First check if the extent inode @mref is already attached to the base ntfs
367 * inode @base_ni, and if so, return a pointer to the attached extent inode.
368 *
369 * If the extent inode is not already attached to the base inode, allocate an
370 * ntfs_inode structure and initialize it for the given inode @mref. @mref
371 * specifies the inode number / mft record to read, including the sequence
372 * number, which can be 0 if no sequence number checking is to be performed.
373 *
374 * Then, allocate a buffer for the mft record, read the mft record from the
375 * volume @base_ni->vol, and attach it to the ntfs_inode structure (->mrec).
376 * The mft record is mst deprotected and sanity checked for validity and we
377 * abort if deprotection or checks fail.
378 *
379 * Finally attach the ntfs inode to its base inode @base_ni and return a
380 * pointer to the ntfs_inode structure on success or NULL on error, with errno
381 * set to the error code.
382 *
383 * Note, extent inodes are never closed directly. They are automatically
384 * disposed off by the closing of the base inode.
385 */
386ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
387{
388	u64 mft_no = MREF_LE(mref);
389	ntfs_inode *ni = NULL;
390	ntfs_inode **extent_nis;
391	int i;
392
393	if (!base_ni) {
394		errno = EINVAL;
395		ntfs_log_perror("%s", __FUNCTION__);
396		return NULL;
397	}
398
399	ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n",
400			(unsigned long long)mft_no,
401			(unsigned long long)base_ni->mft_no);
402
403	/* Is the extent inode already open and attached to the base inode? */
404	if (base_ni->nr_extents > 0) {
405		extent_nis = base_ni->extent_nis;
406		for (i = 0; i < base_ni->nr_extents; i++) {
407			u16 seq_no;
408
409			ni = extent_nis[i];
410			if (mft_no != ni->mft_no)
411				continue;
412			/* Verify the sequence number if given. */
413			seq_no = MSEQNO_LE(mref);
414			if (seq_no && seq_no != le16_to_cpu(
415					ni->mrec->sequence_number)) {
416				errno = EIO;
417				ntfs_log_perror("Found stale extent mft "
418					"reference mft=%lld",
419					(long long)ni->mft_no);
420				goto out;
421			}
422			goto out;
423		}
424	}
425	/* Wasn't there, we need to load the extent inode. */
426	ni = __ntfs_inode_allocate(base_ni->vol);
427	if (!ni)
428		goto out;
429	if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec, NULL))
430		goto err_out;
431	ni->mft_no = mft_no;
432	ni->nr_extents = -1;
433	ni->base_ni = base_ni;
434	/* Attach extent inode to base inode, reallocating memory if needed. */
435	if (!(base_ni->nr_extents & 3)) {
436		i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
437
438		extent_nis = ntfs_malloc(i);
439		if (!extent_nis)
440			goto err_out;
441		if (base_ni->nr_extents) {
442			memcpy(extent_nis, base_ni->extent_nis,
443					i - 4 * sizeof(ntfs_inode *));
444			free(base_ni->extent_nis);
445		}
446		base_ni->extent_nis = extent_nis;
447	}
448	base_ni->extent_nis[base_ni->nr_extents++] = ni;
449out:
450	ntfs_log_leave("\n");
451	return ni;
452err_out:
453	__ntfs_inode_release(ni);
454	ni = NULL;
455	goto out;
456}
457
458/**
459 * ntfs_inode_attach_all_extents - attach all extents for target inode
460 * @ni:		opened ntfs inode for which perform attach
461 *
462 * Return 0 on success and -1 on error with errno set to the error code.
463 */
464int ntfs_inode_attach_all_extents(ntfs_inode *ni)
465{
466	ATTR_LIST_ENTRY *ale;
467	u64 prev_attached = 0;
468
469	if (!ni) {
470		ntfs_log_trace("Invalid arguments.\n");
471		errno = EINVAL;
472		return -1;
473	}
474
475	if (ni->nr_extents == -1)
476		ni = ni->base_ni;
477
478	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
479
480	/* Inode haven't got attribute list, thus nothing to attach. */
481	if (!NInoAttrList(ni))
482		return 0;
483
484	if (!ni->attr_list) {
485		ntfs_log_trace("Corrupt in-memory struct.\n");
486		errno = EINVAL;
487		return -1;
488	}
489
490	/* Walk through attribute list and attach all extents. */
491	errno = 0;
492	ale = (ATTR_LIST_ENTRY *)ni->attr_list;
493	while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
494		if (ni->mft_no != MREF_LE(ale->mft_reference) &&
495				prev_attached != MREF_LE(ale->mft_reference)) {
496			if (!ntfs_extent_inode_open(ni, ale->mft_reference)) {
497				ntfs_log_trace("Couldn't attach extent inode.\n");
498				return -1;
499			}
500			prev_attached = MREF_LE(ale->mft_reference);
501		}
502		ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));
503	}
504	return 0;
505}
506
507/**
508 * ntfs_inode_sync_standard_information - update standard information attribute
509 * @ni:		ntfs inode to update standard information
510 *
511 * Return 0 on success or -1 on error with errno set to the error code.
512 */
513static int ntfs_inode_sync_standard_information(ntfs_inode *ni)
514{
515	ntfs_attr_search_ctx *ctx;
516	STANDARD_INFORMATION *std_info;
517
518	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);
519
520	ctx = ntfs_attr_get_search_ctx(ni, NULL);
521	if (!ctx)
522		return -1;
523	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
524			     0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
525		ntfs_log_perror("Failed to sync standard info (inode %lld)",
526				(long long)ni->mft_no);
527		ntfs_attr_put_search_ctx(ctx);
528		return -1;
529	}
530	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
531			le16_to_cpu(ctx->attr->value_offset));
532	std_info->file_attributes = ni->flags;
533	std_info->creation_time = utc2ntfs(ni->creation_time);
534	std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time);
535	std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
536	std_info->last_access_time = utc2ntfs(ni->last_access_time);
537	ntfs_inode_mark_dirty(ctx->ntfs_ino);
538	ntfs_attr_put_search_ctx(ctx);
539	return 0;
540}
541
542/**
543 * ntfs_inode_sync_file_name - update FILE_NAME attributes
544 * @ni:		ntfs inode to update FILE_NAME attributes
545 *
546 * Update all FILE_NAME attributes for inode @ni in the index.
547 *
548 * Return 0 on success or -1 on error with errno set to the error code.
549 */
550static int ntfs_inode_sync_file_name(ntfs_inode *ni)
551{
552	ntfs_attr_search_ctx *ctx = NULL;
553	ntfs_index_context *ictx;
554	ntfs_inode *index_ni;
555	FILE_NAME_ATTR *fn;
556	int err = 0;
557
558	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);
559
560	ctx = ntfs_attr_get_search_ctx(ni, NULL);
561	if (!ctx) {
562		err = errno;
563		goto err_out;
564	}
565	/* Walk through all FILE_NAME attributes and update them. */
566	while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
567		fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +
568				le16_to_cpu(ctx->attr->value_offset));
569		if (MREF_LE(fn->parent_directory) == ni->mft_no) {
570			/*
571			 * WARNING: We cheat here and obtain 2 attribute
572			 * search contexts for one inode (first we obtained
573			 * above, second will be obtained inside
574			 * ntfs_index_lookup), it's acceptable for library,
575			 * but will deadlock in the kernel.
576			 */
577			index_ni = ni;
578		} else
579			index_ni = ntfs_inode_open(ni->vol,
580					le64_to_cpu(fn->parent_directory));
581		if (!index_ni) {
582			if (!err)
583				err = errno;
584			ntfs_log_perror("Failed to open inode %lld with index",
585				(long long)le64_to_cpu(fn->parent_directory));
586			continue;
587		}
588		ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);
589		if (!ictx) {
590			if (!err)
591				err = errno;
592			ntfs_log_perror("Failed to get index ctx, inode %lld",
593					(long long)index_ni->mft_no);
594			if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
595				err = errno;
596			continue;
597		}
598		if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {
599			if (!err) {
600				if (errno == ENOENT)
601					err = EIO;
602				else
603					err = errno;
604			}
605			ntfs_log_perror("Index lookup failed, inode %lld",
606					(long long)index_ni->mft_no);
607			ntfs_index_ctx_put(ictx);
608			if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
609				err = errno;
610			continue;
611		}
612		/* Update flags and file size. */
613		fn = (FILE_NAME_ATTR *)ictx->data;
614		fn->file_attributes =
615				(fn->file_attributes & ~FILE_ATTR_VALID_FLAGS) |
616				(ni->flags & FILE_ATTR_VALID_FLAGS);
617		fn->allocated_size = cpu_to_sle64(ni->allocated_size);
618		fn->data_size = cpu_to_sle64(ni->data_size);
619		fn->creation_time = utc2ntfs(ni->creation_time);
620		fn->last_data_change_time = utc2ntfs(ni->last_data_change_time);
621		fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
622		fn->last_access_time = utc2ntfs(ni->last_access_time);
623		ntfs_index_entry_mark_dirty(ictx);
624		ntfs_index_ctx_put(ictx);
625		if ((ni != index_ni) && ntfs_inode_close(index_ni) && !err)
626			err = errno;
627	}
628	/* Check for real error occurred. */
629	if (errno != ENOENT) {
630		err = errno;
631		ntfs_log_perror("Attribute lookup failed, inode %lld",
632				(long long)ni->mft_no);
633		goto err_out;
634	}
635	ntfs_attr_put_search_ctx(ctx);
636	if (err) {
637		errno = err;
638		return -1;
639	}
640	return 0;
641err_out:
642	if (ctx)
643		ntfs_attr_put_search_ctx(ctx);
644	errno = err;
645	return -1;
646}
647
648/**
649 * ntfs_inode_sync - write the inode (and its dirty extents) to disk
650 * @ni:		ntfs inode to write
651 *
652 * Write the inode @ni to disk as well as its dirty extent inodes if such
653 * exist and @ni is a base inode. If @ni is an extent inode, only @ni is
654 * written completely disregarding its base inode and any other extent inodes.
655 *
656 * For a base inode with dirty extent inodes if any writes fail for whatever
657 * reason, the failing inode is skipped and the sync process is continued. At
658 * the end the error condition that brought about the failure is returned. Thus
659 * the smallest amount of data loss possible occurs.
660 *
661 * Return 0 on success or -1 on error with errno set to the error code.
662 * The following error codes are defined:
663 *	EINVAL	- Invalid arguments were passed to the function.
664 *	EBUSY	- Inode and/or one of its extents is busy, try again later.
665 *	EIO	- I/O error while writing the inode (or one of its extents).
666 */
667int ntfs_inode_sync(ntfs_inode *ni)
668{
669	int ret = 0;
670	int err = 0;
671
672	if (!ni) {
673		errno = EINVAL;
674		ntfs_log_error("Failed to sync NULL inode\n");
675		return -1;
676	}
677
678	ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no);
679
680	/* Update STANDARD_INFORMATION. */
681	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
682			ntfs_inode_sync_standard_information(ni)) {
683		if (!err || errno == EIO) {
684			err = errno;
685			if (err != EIO)
686				err = EBUSY;
687		}
688	}
689
690	/* Update FILE_NAME's in the index. */
691	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
692			NInoFileNameTestAndClearDirty(ni) &&
693			ntfs_inode_sync_file_name(ni)) {
694		if (!err || errno == EIO) {
695			err = errno;
696			if (err != EIO)
697				err = EBUSY;
698		}
699		ntfs_log_perror("Failed to sync FILE_NAME (inode %lld)",
700				(long long)ni->mft_no);
701		NInoFileNameSetDirty(ni);
702	}
703
704	/* Write out attribute list from cache to disk. */
705	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
706			NInoAttrList(ni) && NInoAttrListTestAndClearDirty(ni)) {
707		ntfs_attr *na;
708
709		na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
710		if (!na) {
711			if (!err || errno == EIO) {
712				err = errno;
713				if (err != EIO)
714					err = EBUSY;
715				ntfs_log_perror("Attribute list sync failed "
716						"(open, inode %lld)",
717						(long long)ni->mft_no);
718			}
719			NInoAttrListSetDirty(ni);
720			goto sync_inode;
721		}
722
723		if (na->data_size == ni->attr_list_size) {
724			if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,
725				        ni->attr_list) != ni->attr_list_size) {
726				if (!err || errno == EIO) {
727					err = errno;
728					if (err != EIO)
729						err = EBUSY;
730					ntfs_log_perror("Attribute list sync "
731						"failed (write, inode %lld)",
732						(long long)ni->mft_no);
733				}
734				NInoAttrListSetDirty(ni);
735			}
736		} else {
737			err = EIO;
738			ntfs_log_error("Attribute list sync failed (bad size, "
739				       "inode %lld)\n", (long long)ni->mft_no);
740			NInoAttrListSetDirty(ni);
741		}
742		ntfs_attr_close(na);
743	}
744
745sync_inode:
746	/* Write this inode out to the $MFT (and $MFTMirr if applicable). */
747	if (NInoTestAndClearDirty(ni)) {
748		if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) {
749			if (!err || errno == EIO) {
750				err = errno;
751				if (err != EIO)
752					err = EBUSY;
753			}
754			NInoSetDirty(ni);
755			ntfs_log_perror("MFT record sync failed, inode %lld",
756					(long long)ni->mft_no);
757		}
758	}
759
760	/* If this is a base inode with extents write all dirty extents, too. */
761	if (ni->nr_extents > 0) {
762		s32 i;
763
764		for (i = 0; i < ni->nr_extents; ++i) {
765			ntfs_inode *eni;
766
767			eni = ni->extent_nis[i];
768			if (!NInoTestAndClearDirty(eni))
769				continue;
770
771			if (ntfs_mft_record_write(eni->vol, eni->mft_no,
772						  eni->mrec)) {
773				if (!err || errno == EIO) {
774					err = errno;
775					if (err != EIO)
776						err = EBUSY;
777				}
778				NInoSetDirty(eni);
779				ntfs_log_perror("Extent MFT record sync failed,"
780						" inode %lld/%lld",
781						(long long)ni->mft_no,
782						(long long)eni->mft_no);
783			}
784		}
785	}
786
787	if (err) {
788		errno = err;
789		ret = -1;
790	}
791
792	ntfs_log_leave("\n");
793	return ret;
794}
795
796/**
797 * ntfs_inode_add_attrlist - add attribute list to inode and fill it
798 * @ni: opened ntfs inode to which add attribute list
799 *
800 * Return 0 on success or -1 on error with errno set to the error code.
801 * The following error codes are defined:
802 *	EINVAL	- Invalid arguments were passed to the function.
803 *	EEXIST	- Attribute list already exist.
804 *	EIO	- Input/Ouput error occurred.
805 *	ENOMEM	- Not enough memory to perform add.
806 */
807int ntfs_inode_add_attrlist(ntfs_inode *ni)
808{
809	int err;
810	ntfs_attr_search_ctx *ctx;
811	u8 *al = NULL, *aln;
812	int al_len = 0;
813	ATTR_LIST_ENTRY *ale = NULL;
814	ntfs_attr *na;
815
816	if (!ni) {
817		errno = EINVAL;
818		ntfs_log_perror("%s", __FUNCTION__);
819		return -1;
820	}
821
822	ntfs_log_trace("inode %llu\n", (unsigned long long) ni->mft_no);
823
824	if (NInoAttrList(ni) || ni->nr_extents) {
825		errno = EEXIST;
826		ntfs_log_perror("Inode already has attribute list");
827		return -1;
828	}
829
830	/* Form attribute list. */
831	ctx = ntfs_attr_get_search_ctx(ni, NULL);
832	if (!ctx) {
833		err = errno;
834		goto err_out;
835	}
836	/* Walk through all attributes. */
837	while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
838
839		int ale_size;
840
841		if (ctx->attr->type == AT_ATTRIBUTE_LIST) {
842			err = EIO;
843			ntfs_log_perror("Attribute list already present");
844			goto put_err_out;
845		}
846
847		ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
848					ctx->attr->name_length + 7) & ~7;
849		al_len += ale_size;
850
851		aln = realloc(al, al_len);
852		if (!aln) {
853			err = errno;
854			ntfs_log_perror("Failed to realloc %d bytes", al_len);
855			goto put_err_out;
856		}
857		ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));
858		al = aln;
859
860		memset(ale, 0, ale_size);
861
862		/* Add attribute to attribute list. */
863		ale->type = ctx->attr->type;
864		ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) +
865			sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7);
866		ale->name_length = ctx->attr->name_length;
867		ale->name_offset = (u8 *)ale->name - (u8 *)ale;
868		if (ctx->attr->non_resident)
869			ale->lowest_vcn = ctx->attr->lowest_vcn;
870		else
871			ale->lowest_vcn = 0;
872		ale->mft_reference = MK_LE_MREF(ni->mft_no,
873			le16_to_cpu(ni->mrec->sequence_number));
874		ale->instance = ctx->attr->instance;
875		memcpy(ale->name, (u8 *)ctx->attr +
876				le16_to_cpu(ctx->attr->name_offset),
877				ctx->attr->name_length * sizeof(ntfschar));
878		ale = (ATTR_LIST_ENTRY *)(al + al_len);
879	}
880	/* Check for real error occurred. */
881	if (errno != ENOENT) {
882		err = errno;
883		ntfs_log_perror("%s: Attribute lookup failed, inode %lld",
884				__FUNCTION__, (long long)ni->mft_no);
885		goto put_err_out;
886	}
887
888	/* Set in-memory attribute list. */
889	ni->attr_list = al;
890	ni->attr_list_size = al_len;
891	NInoSetAttrList(ni);
892	NInoAttrListSetDirty(ni);
893
894	/* Free space if there is not enough it for $ATTRIBUTE_LIST. */
895	if (le32_to_cpu(ni->mrec->bytes_allocated) -
896			le32_to_cpu(ni->mrec->bytes_in_use) <
897			offsetof(ATTR_RECORD, resident_end)) {
898		if (ntfs_inode_free_space(ni,
899				offsetof(ATTR_RECORD, resident_end))) {
900			/* Failed to free space. */
901			err = errno;
902			ntfs_log_perror("Failed to free space for attrlist");
903			goto rollback;
904		}
905	}
906
907	/* Add $ATTRIBUTE_LIST to mft record. */
908	if (ntfs_resident_attr_record_add(ni,
909				AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) {
910		err = errno;
911		ntfs_log_perror("Couldn't add $ATTRIBUTE_LIST to MFT");
912		goto rollback;
913	}
914
915	/* Resize it. */
916	na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
917	if (!na) {
918		err = errno;
919		ntfs_log_perror("Failed to open just added $ATTRIBUTE_LIST");
920		goto remove_attrlist_record;
921	}
922	if (ntfs_attr_truncate(na, al_len)) {
923		err = errno;
924		ntfs_log_perror("Failed to resize just added $ATTRIBUTE_LIST");
925		ntfs_attr_close(na);
926		goto remove_attrlist_record;;
927	}
928
929	ntfs_attr_put_search_ctx(ctx);
930	ntfs_attr_close(na);
931	return 0;
932
933remove_attrlist_record:
934	/* Prevent ntfs_attr_recorm_rm from freeing attribute list. */
935	ni->attr_list = NULL;
936	NInoClearAttrList(ni);
937	/* Remove $ATTRIBUTE_LIST record. */
938	ntfs_attr_reinit_search_ctx(ctx);
939	if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0,
940				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
941		if (ntfs_attr_record_rm(ctx))
942			ntfs_log_perror("Rollback failed to remove attrlist");
943	} else
944		ntfs_log_perror("Rollback failed to find attrlist");
945	/* Setup back in-memory runlist. */
946	ni->attr_list = al;
947	ni->attr_list_size = al_len;
948	NInoSetAttrList(ni);
949rollback:
950	/*
951	 * Scan attribute list for attributes that placed not in the base MFT
952	 * record and move them to it.
953	 */
954	ntfs_attr_reinit_search_ctx(ctx);
955	ale = (ATTR_LIST_ENTRY*)al;
956	while ((u8*)ale < al + al_len) {
957		if (MREF_LE(ale->mft_reference) != ni->mft_no) {
958			if (!ntfs_attr_lookup(ale->type, ale->name,
959						ale->name_length,
960						CASE_SENSITIVE,
961						sle64_to_cpu(ale->lowest_vcn),
962						NULL, 0, ctx)) {
963				if (ntfs_attr_record_move_to(ctx, ni))
964					ntfs_log_perror("Rollback failed to "
965							"move attribute");
966			} else
967				ntfs_log_perror("Rollback failed to find attr");
968			ntfs_attr_reinit_search_ctx(ctx);
969		}
970		ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length));
971	}
972	/* Remove in-memory attribute list. */
973	ni->attr_list = NULL;
974	ni->attr_list_size = 0;
975	NInoClearAttrList(ni);
976	NInoAttrListClearDirty(ni);
977put_err_out:
978	ntfs_attr_put_search_ctx(ctx);
979err_out:
980	free(al);
981	errno = err;
982	return -1;
983}
984
985/**
986 * ntfs_inode_free_space - free space in the MFT record of an inode
987 * @ni:		ntfs inode in which MFT record needs more free space
988 * @size:	amount of space needed to free
989 *
990 * Return 0 on success or -1 on error with errno set to the error code.
991 */
992int ntfs_inode_free_space(ntfs_inode *ni, int size)
993{
994	ntfs_attr_search_ctx *ctx;
995	int freed;
996
997	if (!ni || size < 0) {
998		errno = EINVAL;
999		ntfs_log_perror("%s: ni=%p size=%d", __FUNCTION__, ni, size);
1000		return -1;
1001	}
1002
1003	ntfs_log_trace("Entering for inode %lld, size %d\n",
1004		       (unsigned long long)ni->mft_no, size);
1005
1006	freed = (le32_to_cpu(ni->mrec->bytes_allocated) -
1007				le32_to_cpu(ni->mrec->bytes_in_use));
1008
1009	if (size <= freed)
1010		return 0;
1011
1012	ctx = ntfs_attr_get_search_ctx(ni, NULL);
1013	if (!ctx)
1014		return -1;
1015	/*
1016	 * $STANDARD_INFORMATION and $ATTRIBUTE_LIST must stay in the base MFT
1017	 * record, so position search context on the first attribute after them.
1018	 */
1019	if (ntfs_attr_position(AT_FILE_NAME, ctx))
1020		goto put_err_out;
1021
1022	while (1) {
1023		int record_size;
1024		/*
1025		 * Check whether attribute is from different MFT record. If so,
1026		 * find next, because we don't need such.
1027		 */
1028		while (ctx->ntfs_ino->mft_no != ni->mft_no) {
1029retry:
1030			if (ntfs_attr_position(AT_UNUSED, ctx))
1031				goto put_err_out;
1032		}
1033
1034		if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT &&
1035		    ctx->attr->type == AT_DATA)
1036			goto retry;
1037
1038		if (ctx->attr->type == AT_INDEX_ROOT)
1039			goto retry;
1040
1041		record_size = le32_to_cpu(ctx->attr->length);
1042
1043		if (ntfs_attr_record_move_away(ctx, 0)) {
1044			ntfs_log_perror("Failed to move out attribute #2");
1045			break;
1046		}
1047		freed += record_size;
1048
1049		/* Check whether we are done. */
1050		if (size <= freed) {
1051			ntfs_attr_put_search_ctx(ctx);
1052			return 0;
1053		}
1054		/*
1055		 * Reposition to first attribute after $STANDARD_INFORMATION
1056		 * and $ATTRIBUTE_LIST instead of simply skipping this attribute
1057		 * because in the case when we have got only in-memory attribute
1058		 * list then ntfs_attr_lookup will fail when it tries to find
1059		 * $ATTRIBUTE_LIST.
1060		 */
1061		ntfs_attr_reinit_search_ctx(ctx);
1062		if (ntfs_attr_position(AT_FILE_NAME, ctx))
1063			break;
1064	}
1065put_err_out:
1066	ntfs_attr_put_search_ctx(ctx);
1067	if (errno == ENOSPC)
1068		ntfs_log_trace("No attributes left that could be moved out.\n");
1069	return -1;
1070}
1071
1072/**
1073 * ntfs_inode_update_times - update selected time fields for ntfs inode
1074 * @ni:		ntfs inode for which update time fields
1075 * @mask:	select which time fields should be updated
1076 *
1077 * This function updates time fields to current time. Fields to update are
1078 * selected using @mask (see enum @ntfs_time_update_flags for posssible values).
1079 */
1080void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
1081{
1082	time_t now;
1083
1084	if (!ni) {
1085		ntfs_log_error("%s(): Invalid arguments.\n", __FUNCTION__);
1086		return;
1087	}
1088
1089	if ((ni->mft_no < FILE_first_user && ni->mft_no != FILE_root) ||
1090			NVolReadOnly(ni->vol) || !mask)
1091		return;
1092
1093	now = time(NULL);
1094	if (mask & NTFS_UPDATE_ATIME)
1095		ni->last_access_time = now;
1096	if (mask & NTFS_UPDATE_MTIME)
1097		ni->last_data_change_time = now;
1098	if (mask & NTFS_UPDATE_CTIME)
1099		ni->last_mft_change_time = now;
1100
1101	NInoFileNameSetDirty(ni);
1102	NInoSetDirty(ni);
1103}
1104
1105/**
1106 * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute
1107 * @mft_no:		mft record number where @attr is present
1108 * @attr:		attribute record used to check for the $Bad attribute
1109 *
1110 * Check if the mft record given by @mft_no and @attr contains the bad sector
1111 * list. Please note that mft record numbers describing $Badclus extent inodes
1112 * will not match the current $Badclus:$Bad check.
1113 *
1114 * On success return 1 if the file is $Badclus:$Bad, otherwise return 0.
1115 * On error return -1 with errno set to the error code.
1116 */
1117int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr)
1118{
1119	int len, ret = 0;
1120	ntfschar *ustr;
1121
1122	if (!attr) {
1123		ntfs_log_error("Invalid argument.\n");
1124		errno = EINVAL;
1125		return -1;
1126	}
1127
1128	if (mft_no != FILE_BadClus)
1129	       	return 0;
1130
1131	if (attr->type != AT_DATA)
1132	       	return 0;
1133
1134	if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) {
1135		ntfs_log_perror("Couldn't convert '$Bad' to Unicode");
1136		return -1;
1137	}
1138
1139	if (ustr && ntfs_names_are_equal(ustr, len,
1140			(ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)),
1141			attr->name_length, 0, NULL, 0))
1142		ret = 1;
1143
1144	ntfs_ucsfree(ustr);
1145
1146	return ret;
1147}
1148