1987da915Sopenharmony_ci/** 2987da915Sopenharmony_ci * efs.c - Limited processing of encrypted files 3987da915Sopenharmony_ci * 4987da915Sopenharmony_ci * This module is part of ntfs-3g library 5987da915Sopenharmony_ci * 6987da915Sopenharmony_ci * Copyright (c) 2009 Martin Bene 7987da915Sopenharmony_ci * Copyright (c) 2009-2010 Jean-Pierre Andre 8987da915Sopenharmony_ci * 9987da915Sopenharmony_ci * This program/include file is free software; you can redistribute it and/or 10987da915Sopenharmony_ci * modify it under the terms of the GNU General Public License as published 11987da915Sopenharmony_ci * by the Free Software Foundation; either version 2 of the License, or 12987da915Sopenharmony_ci * (at your option) any later version. 13987da915Sopenharmony_ci * 14987da915Sopenharmony_ci * This program/include file is distributed in the hope that it will be 15987da915Sopenharmony_ci * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 16987da915Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17987da915Sopenharmony_ci * GNU General Public License for more details. 18987da915Sopenharmony_ci * 19987da915Sopenharmony_ci * You should have received a copy of the GNU General Public License 20987da915Sopenharmony_ci * along with this program (in the main directory of the NTFS-3G 21987da915Sopenharmony_ci * distribution in the file COPYING); if not, write to the Free Software 22987da915Sopenharmony_ci * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23987da915Sopenharmony_ci */ 24987da915Sopenharmony_ci 25987da915Sopenharmony_ci#ifdef HAVE_CONFIG_H 26987da915Sopenharmony_ci#include "config.h" 27987da915Sopenharmony_ci#endif 28987da915Sopenharmony_ci 29987da915Sopenharmony_ci#ifdef HAVE_STDLIB_H 30987da915Sopenharmony_ci#include <stdlib.h> 31987da915Sopenharmony_ci#endif 32987da915Sopenharmony_ci#ifdef HAVE_ERRNO_H 33987da915Sopenharmony_ci#include <errno.h> 34987da915Sopenharmony_ci#endif 35987da915Sopenharmony_ci#ifdef HAVE_STRING_H 36987da915Sopenharmony_ci#include <string.h> 37987da915Sopenharmony_ci#endif 38987da915Sopenharmony_ci#ifdef HAVE_SYS_STAT_H 39987da915Sopenharmony_ci#include <sys/stat.h> 40987da915Sopenharmony_ci#endif 41987da915Sopenharmony_ci 42987da915Sopenharmony_ci#ifdef HAVE_SYS_SYSMACROS_H 43987da915Sopenharmony_ci#include <sys/sysmacros.h> 44987da915Sopenharmony_ci#endif 45987da915Sopenharmony_ci 46987da915Sopenharmony_ci#include "types.h" 47987da915Sopenharmony_ci#include "debug.h" 48987da915Sopenharmony_ci#include "attrib.h" 49987da915Sopenharmony_ci#include "inode.h" 50987da915Sopenharmony_ci#include "dir.h" 51987da915Sopenharmony_ci#include "efs.h" 52987da915Sopenharmony_ci#include "index.h" 53987da915Sopenharmony_ci#include "logging.h" 54987da915Sopenharmony_ci#include "misc.h" 55987da915Sopenharmony_ci#include "efs.h" 56987da915Sopenharmony_ci#include "xattrs.h" 57987da915Sopenharmony_ci 58987da915Sopenharmony_cistatic ntfschar logged_utility_stream_name[] = { 59987da915Sopenharmony_ci const_cpu_to_le16('$'), 60987da915Sopenharmony_ci const_cpu_to_le16('E'), 61987da915Sopenharmony_ci const_cpu_to_le16('F'), 62987da915Sopenharmony_ci const_cpu_to_le16('S'), 63987da915Sopenharmony_ci const_cpu_to_le16(0) 64987da915Sopenharmony_ci} ; 65987da915Sopenharmony_ci 66987da915Sopenharmony_ci 67987da915Sopenharmony_ci/* 68987da915Sopenharmony_ci * Get the ntfs EFS info into an extended attribute 69987da915Sopenharmony_ci */ 70987da915Sopenharmony_ci 71987da915Sopenharmony_ciint ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size) 72987da915Sopenharmony_ci{ 73987da915Sopenharmony_ci EFS_ATTR_HEADER *efs_info; 74987da915Sopenharmony_ci s64 attr_size = 0; 75987da915Sopenharmony_ci 76987da915Sopenharmony_ci if (ni) { 77987da915Sopenharmony_ci if (ni->flags & FILE_ATTR_ENCRYPTED) { 78987da915Sopenharmony_ci efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni, 79987da915Sopenharmony_ci AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0, 80987da915Sopenharmony_ci &attr_size); 81987da915Sopenharmony_ci if (efs_info 82987da915Sopenharmony_ci && (le32_to_cpu(efs_info->length) == attr_size)) { 83987da915Sopenharmony_ci if (attr_size <= (s64)size) { 84987da915Sopenharmony_ci if (value) 85987da915Sopenharmony_ci memcpy(value,efs_info,attr_size); 86987da915Sopenharmony_ci else { 87987da915Sopenharmony_ci errno = EFAULT; 88987da915Sopenharmony_ci attr_size = 0; 89987da915Sopenharmony_ci } 90987da915Sopenharmony_ci } else 91987da915Sopenharmony_ci if (size) { 92987da915Sopenharmony_ci errno = ERANGE; 93987da915Sopenharmony_ci attr_size = 0; 94987da915Sopenharmony_ci } 95987da915Sopenharmony_ci free (efs_info); 96987da915Sopenharmony_ci } else { 97987da915Sopenharmony_ci if (efs_info) { 98987da915Sopenharmony_ci free(efs_info); 99987da915Sopenharmony_ci ntfs_log_error("Bad efs_info for inode %lld\n", 100987da915Sopenharmony_ci (long long)ni->mft_no); 101987da915Sopenharmony_ci } else { 102987da915Sopenharmony_ci ntfs_log_error("Could not get efsinfo" 103987da915Sopenharmony_ci " for inode %lld\n", 104987da915Sopenharmony_ci (long long)ni->mft_no); 105987da915Sopenharmony_ci } 106987da915Sopenharmony_ci errno = EIO; 107987da915Sopenharmony_ci attr_size = 0; 108987da915Sopenharmony_ci } 109987da915Sopenharmony_ci } else { 110987da915Sopenharmony_ci errno = ENODATA; 111987da915Sopenharmony_ci ntfs_log_trace("Inode %lld is not encrypted\n", 112987da915Sopenharmony_ci (long long)ni->mft_no); 113987da915Sopenharmony_ci } 114987da915Sopenharmony_ci } 115987da915Sopenharmony_ci return (attr_size ? (int)attr_size : -errno); 116987da915Sopenharmony_ci} 117987da915Sopenharmony_ci 118987da915Sopenharmony_ci/* 119987da915Sopenharmony_ci * Fix all encrypted AT_DATA attributes of an inode 120987da915Sopenharmony_ci * 121987da915Sopenharmony_ci * The fix may require making an attribute non resident, which 122987da915Sopenharmony_ci * requires more space in the MFT record, and may cause some 123987da915Sopenharmony_ci * attribute to be expelled and the full record to be reorganized. 124987da915Sopenharmony_ci * When this happens, the search for data attributes has to be 125987da915Sopenharmony_ci * reinitialized. 126987da915Sopenharmony_ci * 127987da915Sopenharmony_ci * Returns zero if successful. 128987da915Sopenharmony_ci * -1 if there is a problem. 129987da915Sopenharmony_ci */ 130987da915Sopenharmony_ci 131987da915Sopenharmony_cistatic int fixup_loop(ntfs_inode *ni) 132987da915Sopenharmony_ci{ 133987da915Sopenharmony_ci ntfs_attr_search_ctx *ctx; 134987da915Sopenharmony_ci ntfs_attr *na; 135987da915Sopenharmony_ci ATTR_RECORD *a; 136987da915Sopenharmony_ci BOOL restart; 137987da915Sopenharmony_ci int cnt; 138987da915Sopenharmony_ci int maxcnt; 139987da915Sopenharmony_ci int res = 0; 140987da915Sopenharmony_ci 141987da915Sopenharmony_ci maxcnt = 0; 142987da915Sopenharmony_ci do { 143987da915Sopenharmony_ci restart = FALSE; 144987da915Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(ni, NULL); 145987da915Sopenharmony_ci if (!ctx) { 146987da915Sopenharmony_ci ntfs_log_error("Failed to get ctx for efs\n"); 147987da915Sopenharmony_ci res = -1; 148987da915Sopenharmony_ci } 149987da915Sopenharmony_ci cnt = 0; 150987da915Sopenharmony_ci while (!restart && !res 151987da915Sopenharmony_ci && !ntfs_attr_lookup(AT_DATA, NULL, 0, 152987da915Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx)) { 153987da915Sopenharmony_ci cnt++; 154987da915Sopenharmony_ci a = ctx->attr; 155987da915Sopenharmony_ci na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA, 156987da915Sopenharmony_ci (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)), 157987da915Sopenharmony_ci a->name_length); 158987da915Sopenharmony_ci if (!na) { 159987da915Sopenharmony_ci ntfs_log_error("can't open DATA Attribute\n"); 160987da915Sopenharmony_ci res = -1; 161987da915Sopenharmony_ci } 162987da915Sopenharmony_ci if (na && !(ctx->attr->flags & ATTR_IS_ENCRYPTED)) { 163987da915Sopenharmony_ci if (!NAttrNonResident(na) 164987da915Sopenharmony_ci && ntfs_attr_make_non_resident(na, ctx)) { 165987da915Sopenharmony_ci /* 166987da915Sopenharmony_ci * ntfs_attr_make_non_resident fails if there 167987da915Sopenharmony_ci * is not enough space in the MFT record. 168987da915Sopenharmony_ci * When this happens, force making non-resident 169987da915Sopenharmony_ci * so that some other attribute is expelled. 170987da915Sopenharmony_ci */ 171987da915Sopenharmony_ci if (ntfs_attr_force_non_resident(na)) { 172987da915Sopenharmony_ci res = -1; 173987da915Sopenharmony_ci } else { 174987da915Sopenharmony_ci /* make sure there is some progress */ 175987da915Sopenharmony_ci if (cnt <= maxcnt) { 176987da915Sopenharmony_ci errno = EIO; 177987da915Sopenharmony_ci ntfs_log_error("Multiple failure" 178987da915Sopenharmony_ci " making non resident\n"); 179987da915Sopenharmony_ci res = -1; 180987da915Sopenharmony_ci } else { 181987da915Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 182987da915Sopenharmony_ci ctx = (ntfs_attr_search_ctx*)NULL; 183987da915Sopenharmony_ci restart = TRUE; 184987da915Sopenharmony_ci maxcnt = cnt; 185987da915Sopenharmony_ci } 186987da915Sopenharmony_ci } 187987da915Sopenharmony_ci } 188987da915Sopenharmony_ci if (!restart && !res 189987da915Sopenharmony_ci && ntfs_efs_fixup_attribute(ctx, na)) { 190987da915Sopenharmony_ci ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n"); 191987da915Sopenharmony_ci res = -1; 192987da915Sopenharmony_ci } 193987da915Sopenharmony_ci } 194987da915Sopenharmony_ci if (na) 195987da915Sopenharmony_ci ntfs_attr_close(na); 196987da915Sopenharmony_ci } 197987da915Sopenharmony_ci } while (restart && !res); 198987da915Sopenharmony_ci if (ctx) 199987da915Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 200987da915Sopenharmony_ci return (res); 201987da915Sopenharmony_ci} 202987da915Sopenharmony_ci 203987da915Sopenharmony_ci/* 204987da915Sopenharmony_ci * Set the efs data from an extended attribute 205987da915Sopenharmony_ci * Warning : the new data is not checked 206987da915Sopenharmony_ci * Returns 0, or -1 if there is a problem 207987da915Sopenharmony_ci */ 208987da915Sopenharmony_ci 209987da915Sopenharmony_ciint ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size, 210987da915Sopenharmony_ci int flags) 211987da915Sopenharmony_ci 212987da915Sopenharmony_ci{ 213987da915Sopenharmony_ci int res; 214987da915Sopenharmony_ci int written; 215987da915Sopenharmony_ci ntfs_attr *na; 216987da915Sopenharmony_ci const EFS_ATTR_HEADER *info_header; 217987da915Sopenharmony_ci 218987da915Sopenharmony_ci res = 0; 219987da915Sopenharmony_ci if (ni && value && size) { 220987da915Sopenharmony_ci if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) { 221987da915Sopenharmony_ci if (ni->flags & FILE_ATTR_ENCRYPTED) { 222987da915Sopenharmony_ci ntfs_log_trace("Inode %lld already encrypted\n", 223987da915Sopenharmony_ci (long long)ni->mft_no); 224987da915Sopenharmony_ci errno = EEXIST; 225987da915Sopenharmony_ci } else { 226987da915Sopenharmony_ci /* 227987da915Sopenharmony_ci * Possible problem : if encrypted file was 228987da915Sopenharmony_ci * restored in a compressed directory, it was 229987da915Sopenharmony_ci * restored as compressed. 230987da915Sopenharmony_ci * TODO : decompress first. 231987da915Sopenharmony_ci */ 232987da915Sopenharmony_ci ntfs_log_error("Inode %lld cannot be encrypted and compressed\n", 233987da915Sopenharmony_ci (long long)ni->mft_no); 234987da915Sopenharmony_ci errno = EIO; 235987da915Sopenharmony_ci } 236987da915Sopenharmony_ci return -1; 237987da915Sopenharmony_ci } 238987da915Sopenharmony_ci info_header = (const EFS_ATTR_HEADER*)value; 239987da915Sopenharmony_ci /* make sure we get a likely efsinfo */ 240987da915Sopenharmony_ci if (le32_to_cpu(info_header->length) != size) { 241987da915Sopenharmony_ci errno = EINVAL; 242987da915Sopenharmony_ci return (-1); 243987da915Sopenharmony_ci } 244987da915Sopenharmony_ci if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM, 245987da915Sopenharmony_ci (ntfschar*)NULL,0)) { 246987da915Sopenharmony_ci if (!(flags & XATTR_REPLACE)) { 247987da915Sopenharmony_ci /* 248987da915Sopenharmony_ci * no logged_utility_stream attribute : add one, 249987da915Sopenharmony_ci * apparently, this does not feed the new value in 250987da915Sopenharmony_ci */ 251987da915Sopenharmony_ci res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM, 252987da915Sopenharmony_ci logged_utility_stream_name,4, 253987da915Sopenharmony_ci (u8*)NULL,(s64)size); 254987da915Sopenharmony_ci } else { 255987da915Sopenharmony_ci errno = ENODATA; 256987da915Sopenharmony_ci res = -1; 257987da915Sopenharmony_ci } 258987da915Sopenharmony_ci } else { 259987da915Sopenharmony_ci errno = EEXIST; 260987da915Sopenharmony_ci res = -1; 261987da915Sopenharmony_ci } 262987da915Sopenharmony_ci if (!res) { 263987da915Sopenharmony_ci /* 264987da915Sopenharmony_ci * open and update the existing efs data 265987da915Sopenharmony_ci */ 266987da915Sopenharmony_ci na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, 267987da915Sopenharmony_ci logged_utility_stream_name, 4); 268987da915Sopenharmony_ci if (na) { 269987da915Sopenharmony_ci /* resize attribute */ 270987da915Sopenharmony_ci res = ntfs_attr_truncate(na, (s64)size); 271987da915Sopenharmony_ci /* overwrite value if any */ 272987da915Sopenharmony_ci if (!res && value) { 273987da915Sopenharmony_ci written = (int)ntfs_attr_pwrite(na, 274987da915Sopenharmony_ci (s64)0, (s64)size, value); 275987da915Sopenharmony_ci if (written != (s64)size) { 276987da915Sopenharmony_ci ntfs_log_error("Failed to " 277987da915Sopenharmony_ci "update efs data\n"); 278987da915Sopenharmony_ci errno = EIO; 279987da915Sopenharmony_ci res = -1; 280987da915Sopenharmony_ci } 281987da915Sopenharmony_ci } 282987da915Sopenharmony_ci ntfs_attr_close(na); 283987da915Sopenharmony_ci } else 284987da915Sopenharmony_ci res = -1; 285987da915Sopenharmony_ci } 286987da915Sopenharmony_ci if (!res) { 287987da915Sopenharmony_ci /* Don't handle AT_DATA Attribute(s) if inode is a directory */ 288987da915Sopenharmony_ci if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { 289987da915Sopenharmony_ci /* iterate over AT_DATA attributes */ 290987da915Sopenharmony_ci /* set encrypted flag, truncate attribute to match padding bytes */ 291987da915Sopenharmony_ci 292987da915Sopenharmony_ci if (fixup_loop(ni)) 293987da915Sopenharmony_ci return -1; 294987da915Sopenharmony_ci } 295987da915Sopenharmony_ci ni->flags |= FILE_ATTR_ENCRYPTED; 296987da915Sopenharmony_ci NInoSetDirty(ni); 297987da915Sopenharmony_ci NInoFileNameSetDirty(ni); 298987da915Sopenharmony_ci } 299987da915Sopenharmony_ci } else { 300987da915Sopenharmony_ci errno = EINVAL; 301987da915Sopenharmony_ci res = -1; 302987da915Sopenharmony_ci } 303987da915Sopenharmony_ci return (res ? -1 : 0); 304987da915Sopenharmony_ci} 305987da915Sopenharmony_ci 306987da915Sopenharmony_ci/* 307987da915Sopenharmony_ci * Fixup raw encrypted AT_DATA Attribute 308987da915Sopenharmony_ci * read padding length from last two bytes 309987da915Sopenharmony_ci * truncate attribute, make non-resident, 310987da915Sopenharmony_ci * set data size to match padding length 311987da915Sopenharmony_ci * set ATTR_IS_ENCRYPTED flag on attribute 312987da915Sopenharmony_ci * 313987da915Sopenharmony_ci * Return 0 if successful 314987da915Sopenharmony_ci * -1 if failed (errno tells why) 315987da915Sopenharmony_ci */ 316987da915Sopenharmony_ci 317987da915Sopenharmony_ciint ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na) 318987da915Sopenharmony_ci{ 319987da915Sopenharmony_ci s64 newsize; 320987da915Sopenharmony_ci s64 oldsize; 321987da915Sopenharmony_ci le16 appended_bytes; 322987da915Sopenharmony_ci u16 padding_length; 323987da915Sopenharmony_ci ntfs_inode *ni; 324987da915Sopenharmony_ci BOOL close_ctx = FALSE; 325987da915Sopenharmony_ci 326987da915Sopenharmony_ci if (!na) { 327987da915Sopenharmony_ci ntfs_log_error("no na specified for efs_fixup_attribute\n"); 328987da915Sopenharmony_ci goto err_out; 329987da915Sopenharmony_ci } 330987da915Sopenharmony_ci if (!ctx) { 331987da915Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(na->ni, NULL); 332987da915Sopenharmony_ci if (!ctx) { 333987da915Sopenharmony_ci ntfs_log_error("Failed to get ctx for efs\n"); 334987da915Sopenharmony_ci goto err_out; 335987da915Sopenharmony_ci } 336987da915Sopenharmony_ci close_ctx = TRUE; 337987da915Sopenharmony_ci if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, 338987da915Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx)) { 339987da915Sopenharmony_ci ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); 340987da915Sopenharmony_ci goto err_out; 341987da915Sopenharmony_ci } 342987da915Sopenharmony_ci } else { 343987da915Sopenharmony_ci if (!NAttrNonResident(na)) { 344987da915Sopenharmony_ci ntfs_log_error("Cannot make non resident" 345987da915Sopenharmony_ci " when a context has been allocated\n"); 346987da915Sopenharmony_ci goto err_out; 347987da915Sopenharmony_ci } 348987da915Sopenharmony_ci } 349987da915Sopenharmony_ci 350987da915Sopenharmony_ci /* no extra bytes are added to void attributes */ 351987da915Sopenharmony_ci oldsize = na->data_size; 352987da915Sopenharmony_ci if (oldsize) { 353987da915Sopenharmony_ci /* make sure size is valid for a raw encrypted stream */ 354987da915Sopenharmony_ci if ((oldsize & 511) != 2) { 355987da915Sopenharmony_ci ntfs_log_error("Bad raw encrypted stream\n"); 356987da915Sopenharmony_ci goto err_out; 357987da915Sopenharmony_ci } 358987da915Sopenharmony_ci /* read padding length from last two bytes of attribute */ 359987da915Sopenharmony_ci if (ntfs_attr_pread(na, oldsize - 2, 2, &appended_bytes) != 2) { 360987da915Sopenharmony_ci ntfs_log_error("Error reading padding length\n"); 361987da915Sopenharmony_ci goto err_out; 362987da915Sopenharmony_ci } 363987da915Sopenharmony_ci padding_length = le16_to_cpu(appended_bytes); 364987da915Sopenharmony_ci if (padding_length > 511 || padding_length > na->data_size-2) { 365987da915Sopenharmony_ci errno = EINVAL; 366987da915Sopenharmony_ci ntfs_log_error("invalid padding length %d for data_size %lld\n", 367987da915Sopenharmony_ci padding_length, (long long)oldsize); 368987da915Sopenharmony_ci goto err_out; 369987da915Sopenharmony_ci } 370987da915Sopenharmony_ci newsize = oldsize - padding_length - 2; 371987da915Sopenharmony_ci /* 372987da915Sopenharmony_ci * truncate attribute to possibly free clusters allocated 373987da915Sopenharmony_ci * for the last two bytes, but do not truncate to new size 374987da915Sopenharmony_ci * to avoid losing useful data 375987da915Sopenharmony_ci */ 376987da915Sopenharmony_ci if (ntfs_attr_truncate(na, oldsize - 2)) { 377987da915Sopenharmony_ci ntfs_log_error("Error truncating attribute\n"); 378987da915Sopenharmony_ci goto err_out; 379987da915Sopenharmony_ci } 380987da915Sopenharmony_ci } else 381987da915Sopenharmony_ci newsize = 0; 382987da915Sopenharmony_ci 383987da915Sopenharmony_ci /* 384987da915Sopenharmony_ci * Encrypted AT_DATA Attributes MUST be non-resident 385987da915Sopenharmony_ci * This has to be done after the attribute is resized, as 386987da915Sopenharmony_ci * resizing down to zero may cause the attribute to be made 387987da915Sopenharmony_ci * resident. 388987da915Sopenharmony_ci */ 389987da915Sopenharmony_ci if (!NAttrNonResident(na) 390987da915Sopenharmony_ci && ntfs_attr_make_non_resident(na, ctx)) { 391987da915Sopenharmony_ci if (!close_ctx 392987da915Sopenharmony_ci || ntfs_attr_force_non_resident(na)) { 393987da915Sopenharmony_ci ntfs_log_error("Error making DATA attribute non-resident\n"); 394987da915Sopenharmony_ci goto err_out; 395987da915Sopenharmony_ci } else { 396987da915Sopenharmony_ci /* 397987da915Sopenharmony_ci * must reinitialize context after forcing 398987da915Sopenharmony_ci * non-resident. We need a context for updating 399987da915Sopenharmony_ci * the state, and at this point, we are sure 400987da915Sopenharmony_ci * the context is not used elsewhere. 401987da915Sopenharmony_ci */ 402987da915Sopenharmony_ci ntfs_attr_reinit_search_ctx(ctx); 403987da915Sopenharmony_ci if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, 404987da915Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx)) { 405987da915Sopenharmony_ci ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); 406987da915Sopenharmony_ci goto err_out; 407987da915Sopenharmony_ci } 408987da915Sopenharmony_ci } 409987da915Sopenharmony_ci } 410987da915Sopenharmony_ci ni = na->ni; 411987da915Sopenharmony_ci if (!na->name_len) { 412987da915Sopenharmony_ci ni->data_size = newsize; 413987da915Sopenharmony_ci ni->allocated_size = na->allocated_size; 414987da915Sopenharmony_ci } 415987da915Sopenharmony_ci NInoSetDirty(ni); 416987da915Sopenharmony_ci NInoFileNameSetDirty(ni); 417987da915Sopenharmony_ci 418987da915Sopenharmony_ci ctx->attr->data_size = cpu_to_sle64(newsize); 419987da915Sopenharmony_ci if (sle64_to_cpu(ctx->attr->initialized_size) > newsize) 420987da915Sopenharmony_ci ctx->attr->initialized_size = ctx->attr->data_size; 421987da915Sopenharmony_ci ctx->attr->flags |= ATTR_IS_ENCRYPTED; 422987da915Sopenharmony_ci if (close_ctx) 423987da915Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 424987da915Sopenharmony_ci 425987da915Sopenharmony_ci return (0); 426987da915Sopenharmony_cierr_out: 427987da915Sopenharmony_ci if (close_ctx && ctx) 428987da915Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 429987da915Sopenharmony_ci return (-1); 430987da915Sopenharmony_ci} 431