/** * ntfs_index_entry_mark_dirty - mark an index entry dirty * @ictx: ntfs index context describing the index entry * * Mark the index entry described by the index entry context @ictx dirty. * * If the index entry is in the index root attribute, simply mark the inode * containing the index root attribute dirty. This ensures the mftrecord, and * hence the index root attribute, will be written out to disk later. * * If the index entry is in an index block belonging to the index allocation * attribute, set ib_dirty to TRUE, thus index block will be updated during * ntfs_index_ctx_put. */ void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx) { if (ictx->is_in_root) ntfs_inode_mark_dirty(ictx->actx->ntfs_ino); else ictx->ib_dirty = TRUE; }
static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_BLOCK *ib) { INDEX_ENTRY *ie_roam; int ret = STATUS_ERROR; ntfs_log_trace("Entering\n"); ie_roam = ntfs_ie_dup_novcn(ie); if (!ie_roam) return STATUS_ERROR; ntfs_ie_delete(ih, ie); if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) ntfs_inode_mark_dirty(icx->actx->ntfs_ino); else if (ntfs_ib_write(icx, ib)) goto out; ntfs_index_ctx_reinit(icx); ret = ntfs_ie_add(icx, ie_roam); out: free(ie_roam); return ret; }
int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni, const void *key, const int keylen) { int ret = STATUS_ERROR; ntfs_index_context *icx; icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); if (!icx) return -1; while (1) { if (ntfs_index_lookup(key, keylen, icx)) goto err_out; if ((((FILE_NAME_ATTR *)icx->data)->file_attributes & FILE_ATTR_REPARSE_POINT) && !ntfs_possible_symlink(ni)) { errno = EOPNOTSUPP; goto err_out; } ret = ntfs_index_rm(icx); if (ret == STATUS_ERROR) goto err_out; else if (ret == STATUS_OK) break; ntfs_inode_mark_dirty(icx->actx->ntfs_ino); ntfs_index_ctx_reinit(icx); } ntfs_inode_mark_dirty(icx->actx->ntfs_ino); out: ntfs_index_ctx_put(icx); return ret; err_out: ret = STATUS_ERROR; ntfs_log_perror("Delete failed"); goto out; }
/** * ntfs_inode_sync_standard_information - update standard information attribute * @ni: ntfs inode to update standard information * * Return 0 on success or -1 on error with errno set to the error code. */ static int ntfs_inode_sync_standard_information(ntfs_inode *ni) { ntfs_attr_search_ctx *ctx; STANDARD_INFORMATION *std_info; u32 lth; le32 lthle; ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no); ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) return -1; if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { ntfs_log_perror("Failed to sync standard info (inode %lld)", (long long)ni->mft_no); ntfs_attr_put_search_ctx(ctx); return -1; } std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); std_info->file_attributes = ni->flags; if (test_nino_flag(ni, TimesDirty)) { std_info->creation_time = utc2ntfs(ni->creation_time); std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time); std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); std_info->last_access_time = utc2ntfs(ni->last_access_time); } /* JPA update v3.x extensions, ensuring consistency */ lthle = ctx->attr->length; lth = le32_to_cpu(lthle); if (test_nino_flag(ni, v3_Extensions) && (lth <= sizeof(STANDARD_INFORMATION))) ntfs_log_error("bad sync of standard information\n"); if (lth > sizeof(STANDARD_INFORMATION)) { std_info->owner_id = ni->owner_id; std_info->security_id = ni->security_id; std_info->quota_charged = ni->quota_charged; std_info->usn = ni->usn; } ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_attr_put_search_ctx(ctx); return 0; }
/* JPA static */ int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) { INDEX_HEADER *ih; int allocated_size, new_size; int ret = STATUS_ERROR; #ifdef DEBUG /* removed by JPA to make function usable for security indexes char *fn; fn = ntfs_ie_filename_get(ie); ntfs_log_trace("file: '%s'\n", fn); ntfs_attr_name_free(&fn); */ #endif while (1) { if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx)) { errno = EEXIST; ntfs_log_perror("Index already have such entry"); goto err_out; } if (errno != ENOENT) { ntfs_log_perror("Failed to find place for new entry"); goto err_out; } if (icx->is_in_root) ih = &icx->ir->index; else ih = &icx->ib->index; allocated_size = le32_to_cpu(ih->allocated_size); new_size = le32_to_cpu(ih->index_length) + le16_to_cpu(ie->length); if (new_size <= allocated_size) break; ntfs_log_trace("index block sizes: allocated: %d needed: %d\n", allocated_size, new_size); if (icx->is_in_root) { if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR) goto err_out; } else { if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR) goto err_out; } ntfs_inode_mark_dirty(icx->actx->ntfs_ino); ntfs_index_ctx_reinit(icx); } ntfs_ie_insert(ih, ie, icx->entry); ntfs_index_entry_mark_dirty(icx); ret = STATUS_OK; err_out: ntfs_log_trace("%s\n", ret ? "Failed" : "Done"); return ret; }
int ntfs_inode_set_times(ntfs_inode *ni, const char *value, size_t size, int flags) { ntfs_attr_search_ctx *ctx; STANDARD_INFORMATION *std_info; FILE_NAME_ATTR *fn; const u64 *times; ntfs_time now; int cnt; int ret; ret = -1; if ((size >= 8) && !(flags & XATTR_CREATE)) { times = (const u64*)value; now = ntfs_current_time(); /* update the standard information attribute */ ctx = ntfs_attr_get_search_ctx(ni, NULL); if (ctx) { if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { ntfs_log_perror("Failed to get standard info (inode %lld)", (long long)ni->mft_no); } else { std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); /* * Mark times set to avoid overwriting * them when the inode is closed. * The inode structure must also be updated * (with loss of precision) because of cacheing. * TODO : use NTFS precision in inode, and * return sub-second times in getattr() */ set_nino_flag(ni, TimesSet); std_info->creation_time = cpu_to_le64(times[0]); ni->creation_time = std_info->creation_time; if (size >= 16) { std_info->last_data_change_time = cpu_to_le64(times[1]); ni->last_data_change_time = std_info->last_data_change_time; } if (size >= 24) { std_info->last_access_time = cpu_to_le64(times[2]); ni->last_access_time = std_info->last_access_time; } std_info->last_mft_change_time = now; ni->last_mft_change_time = now; ntfs_inode_mark_dirty(ctx->ntfs_ino); NInoFileNameSetDirty(ni); /* update the file names attributes */ ntfs_attr_reinit_search_ctx(ctx); cnt = 0; while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { fn = (FILE_NAME_ATTR*)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); fn->creation_time = cpu_to_le64(times[0]); if (size >= 16) fn->last_data_change_time = cpu_to_le64(times[1]); if (size >= 24) fn->last_access_time = cpu_to_le64(times[2]); fn->last_mft_change_time = now; cnt++; } if (cnt) ret = 0; else { ntfs_log_perror("Failed to get file names (inode %lld)", (long long)ni->mft_no); } } ntfs_attr_put_search_ctx(ctx); } } else if (size < 8) errno = ERANGE; else errno = EEXIST; return (ret); }