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 */
__ntfs_inode_allocate(ntfs_volume * vol)60 static 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 */
ntfs_inode_allocate(ntfs_volume * vol)80 ntfs_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 */
__ntfs_inode_release(ntfs_inode * ni)93 static 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 */
__ntfs_inode_add_to_cache(ntfs_inode * ni)107 void __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 */
ntfs_inode_open(ntfs_volume * vol,const MFT_REF mref)137 ntfs_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 }
220 get_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;
244 put_err_out:
245 if (!err)
246 err = errno;
247 ntfs_attr_put_search_ctx(ctx);
248 err_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 */
ntfs_inode_close(ntfs_inode * ni)280 int 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 */
ntfs_extent_inode_open(ntfs_inode * base_ni,const leMFT_REF mref)396 ntfs_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;
460 err_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 */
ntfs_inode_attach_all_extents(ntfs_inode * ni)474 int 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 */
ntfs_inode_sync_standard_information(ntfs_inode * ni)526 static 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 */
ntfs_inode_sync_file_name(ntfs_inode * ni)565 static 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;
651 err_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 */
ntfs_inode_sync(ntfs_inode * ni)677 int 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 */
ntfs_inode_add_attrlist(ntfs_inode * ni)808 int 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;
951 remove_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);
969 rollback:
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);
998 put_err_out:
999 ntfs_attr_put_search_ctx(ctx);
1000 err_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 */
ntfs_inode_free_space(ntfs_inode * ni,int size)1013 int 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 }
1119 put_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 */
ntfs_inode_update_times(ntfs_inode * ni,ntfs_time_update_flags mask)1135 void 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 */
ntfs_inode_badclus_bad(u64 mft_no,ATTR_RECORD * attr)1170 int 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