📄 inode.c
字号:
goto rollback; } } /* Add $ATTRIBUTE_LIST to mft record. */ if (ntfs_resident_attr_record_add(ni, AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) { err = errno; ntfs_log_trace("Couldn't add $ATTRIBUTE_LIST to MFT record.\n"); goto rollback; } /* Resize it. */ na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); if (!na) { err = errno; ntfs_log_trace("Failed to open just added $ATTRIBUTE_LIST.\n"); goto remove_attrlist_record; } if (ntfs_attr_truncate(na, al_len)) { err = errno; ntfs_log_trace("Failed to resize just added $ATTRIBUTE_LIST.\n"); ntfs_attr_close(na); goto remove_attrlist_record;; } /* Done! */ ntfs_attr_close(na); return 0;remove_attrlist_record: /* Prevent ntfs_attr_recorm_rm from freeing attribute list. */ ni->attr_list = NULL; NInoClearAttrList(ni); /* Remove $ATTRIBUTE_LIST record. */ ntfs_attr_reinit_search_ctx(ctx); if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { if (ntfs_attr_record_rm(ctx)) ntfs_log_trace("Rollback failed. Failed to remove attribute " "list record.\n"); } else ntfs_log_trace("Rollback failed. Couldn't find attribute list " "record.\n"); /* Setup back in-memory runlist. */ ni->attr_list = al; ni->attr_list_size = al_len; NInoSetAttrList(ni);rollback: /* * Scan attribute list for attributes that placed not in the base MFT * record and move them to it. */ ntfs_attr_reinit_search_ctx(ctx); ale = (ATTR_LIST_ENTRY*)al; while ((u8*)ale < al + al_len) { if (MREF_LE(ale->mft_reference) != ni->mft_no) { if (!ntfs_attr_lookup(ale->type, ale->name, ale->name_length, CASE_SENSITIVE, sle64_to_cpu(ale->lowest_vcn), NULL, 0, ctx)) { if (ntfs_attr_record_move_to(ctx, ni)) ntfs_log_trace("Rollback failed. Couldn't " "back attribute to base MFT record.\n"); } else ntfs_log_trace("Rollback failed. ntfs_attr_lookup " "failed.\n"); ntfs_attr_reinit_search_ctx(ctx); } ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length)); } /* Remove in-memory attribute list. */ ni->attr_list = NULL; ni->attr_list_size = 0; NInoClearAttrList(ni); NInoAttrListClearDirty(ni);put_err_out: ntfs_attr_put_search_ctx(ctx);err_out: free(al); errno = err; return -1;}/** * ntfs_inode_free_space - free space in the MFT record of inode * @ni: ntfs inode in which MFT record free space * @size: amount of space needed to free * * Return 0 on success or -1 on error with errno set to the error code. */int ntfs_inode_free_space(ntfs_inode *ni, int size){ ntfs_attr_search_ctx *ctx; int freed, err; if (!ni || size < 0) { ntfs_log_trace("Invalid arguments.\n"); errno = EINVAL; return -1; } ntfs_log_trace("Entering for inode 0x%llx, size %d.\n", (long long) ni->mft_no, size); freed = (le32_to_cpu(ni->mrec->bytes_allocated) - le32_to_cpu(ni->mrec->bytes_in_use)); if (size <= freed) return 0; ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) { err = errno; ntfs_log_trace("Failed to get attribute search context.\n"); errno = err; return -1; } /* * Chkdsk complain if $STANDARD_INFORMATION is not in the base MFT * record. FIXME: I'm not sure in this, need to recheck. For now simply * do not move $STANDARD_INFORMATION at all. * * Also we can't move $ATTRIBUTE_LIST from base MFT_RECORD, so position * search context on first attribute after $STANDARD_INFORMATION and * $ATTRIBUTE_LIST. * * Why we reposition instead of simply skip this attributes during * enumeration? Because in case we have got only in-memory attribute * list ntfs_attr_lookup will fail when it will try to find * $ATTRIBUTE_LIST. */ if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { if (errno != ENOENT) { err = errno; ntfs_log_trace("Attribute lookup failed.\n"); goto put_err_out; } if (ctx->attr->type == AT_END) { err = ENOSPC; goto put_err_out; } } while (1) { int record_size; /* * Check whether attribute is from different MFT record. If so, * find next, because we don't need such. */ while (ctx->ntfs_ino->mft_no != ni->mft_no) { if (ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { err = errno; if (errno != ENOENT) { ntfs_log_trace("Attribute lookup failed.\n"); } else err = ENOSPC; goto put_err_out; } } record_size = le32_to_cpu(ctx->attr->length); /* Move away attribute. */ if (ntfs_attr_record_move_away(ctx, 0)) { err = errno; ntfs_log_trace("Failed to move out attribute.\n"); break; } freed += record_size; /* Check whether we done. */ if (size <= freed) { ntfs_attr_put_search_ctx(ctx); return 0; } /* * Reposition to first attribute after $STANDARD_INFORMATION and * $ATTRIBUTE_LIST (see comments upwards). */ ntfs_attr_reinit_search_ctx(ctx); if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { if (errno != ENOENT) { err = errno; ntfs_log_trace("Attribute lookup failed.\n"); break; } if (ctx->attr->type == AT_END) { err = ENOSPC; break; } } }put_err_out: ntfs_attr_put_search_ctx(ctx); if (err == ENOSPC) ntfs_log_trace("No attributes left that can be moved out.\n"); errno = err; return -1;}/** * ntfs_inode_update_atime - update access time for ntfs inode * @ni: ntfs inode for which update access time * * This function usually get called when user read not metadata from inode. * Do not update time for system files. */void ntfs_inode_update_atime(ntfs_inode *ni){ if (!NVolReadOnly(ni->vol) && !NVolNoATime(ni->vol) && (ni->mft_no >= FILE_first_user || ni->mft_no == FILE_root)) { ni->last_access_time = time(NULL); NInoFileNameSetDirty(ni); NInoSetDirty(ni); }}/** * ntfs_inode_update_time - update all times for ntfs inode * @ni: ntfs inode for which update times * * This function updates last access, mft and data change times. Usually * get called when user write not metadata to inode. Do not update time for * system files. */void ntfs_inode_update_time(ntfs_inode *ni){ if (!NVolReadOnly(ni->vol) && !NVolNoATime(ni->vol) && (ni->mft_no >= FILE_first_user || ni->mft_no == FILE_root)) { time_t now; now = time(NULL); ni->last_access_time = now; ni->last_data_change_time = now; ni->last_mft_change_time = now; NInoFileNameSetDirty(ni); NInoSetDirty(ni); }}/** * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute * @mft_no: mft record number where @attr is present * @attr: attribute record used to check for the $Bad attribute * * Check if the mft record given by @mft_no and @attr contains the bad sector * list. Please note that mft record numbers describing $Badclus extent inodes * will not match the current $Badclus:$Bad check. * * On success return 1 if the file is $Badclus:$Bad, otherwise return 0. * On error return -1 with errno set to the error code. */int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr){ int len, ret = 0; ntfschar *ustr; if (!attr) { ntfs_log_error("Invalid argument.\n"); errno = EINVAL; return -1; } if (mft_no != FILE_BadClus) return 0; if (attr->type != AT_DATA) return 0; if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) { ntfs_log_perror("Couldn't convert '$Bad' to Unicode"); return -1; } if (ustr && ntfs_names_are_equal(ustr, len, (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)), attr->name_length, 0, NULL, 0)) ret = 1; ntfs_ucsfree(ustr); return ret;}#ifndef __VISOPSYS__#ifdef NTFS_RICH#include "rich.h"/** * ntfs_inode_close2 - Close an inode, freeing any resources * @ni: * * Description... * * Returns: */int ntfs_inode_close2(ntfs_inode *ni){ if (!ni) return 0; ntfs_log_trace ("inode %p, mft %lld, refcount %d\n", ni, MREF(ni->mft_no), ni->ref_count); ni->ref_count--; if (ni->ref_count > 0) return 0; // unlink // ino->private_data // XXX temporary until we have commit/rollback NInoClearDirty(ni); return ntfs_inode_close(ni);}/** * ntfs_inode_open2 - Open an inode and initialise it * @vol: * @mref: * * Description... * * Returns: */ntfs_inode * ntfs_inode_open2(ntfs_volume *vol, const MFT_REF mref){ ntfs_inode *ino = NULL; struct ntfs_dir *dir; if (!vol) return NULL; ntfs_log_trace ("\n"); switch (mref) { case FILE_Bitmap: ino = vol->lcnbmp_ni; break; case FILE_MFT: ino = vol->mft_ni; break; case FILE_MFTMirr: ino = vol->mftmirr_ni; break; case FILE_Volume: ino = vol->vol_ni; break; case FILE_root: dir = vol->private_data; if (dir) ino = dir->inode; break; } if (ino) { ntfs_log_debug("inode reuse %lld\n", mref); ino->ref_count++; return ino; } ino = ntfs_inode_open(vol, mref); if (!ino) return NULL; /* if (mref != FILE_root) ntfs_inode_dir_map (ino); */ // link // ino->private_data ino->private_data = NULL; ino->ref_count = 1; ntfs_log_debug("inode open %lld, 0x%llx\n", MREF(mref), mref); return ino;}/** * ntfs_inode_open3 - Open an inode and initialise it * @vol: * @mref: * * Description... * * Returns: */ntfs_inode * ntfs_inode_open3(ntfs_volume *vol, const MFT_REF mref){ ntfs_inode *ino = NULL; if (!vol) return NULL; ntfs_log_trace ("\n"); ino = calloc(1, sizeof(*ino)); if (!ino) return NULL; ino->mrec = malloc(vol->mft_record_size); if (!ino->mrec) { free(ino); return NULL; } ino->mft_no = mref; ino->vol = vol; ino->data_size = -1; ino->allocated_size = -1; ino->private_data = NULL; ino->ref_count = 1; if (1 != ntfs_attr_mst_pread(vol->mft_na, MREF(mref) * vol->mft_record_size, 1, vol->mft_record_size, ino->mrec)) { //ntfs_inode_close2(ino); ??? free(ino->mrec); free(ino); return NULL; } NInoSetDirty(ino); return ino;}#endif /* NTFS_RICH */#endif /* __VISOPSYS__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -