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