1*5218cd10SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 2*5218cd10SNamjae Jeon /* 3*5218cd10SNamjae Jeon * Pocessing of object ids 4*5218cd10SNamjae Jeon * 5*5218cd10SNamjae Jeon * Part of this file is based on code from the NTFS-3G. 6*5218cd10SNamjae Jeon * 7*5218cd10SNamjae Jeon * Copyright (c) 2009-2019 Jean-Pierre Andre 8*5218cd10SNamjae Jeon * Copyright (c) 2026 LG Electronics Co., Ltd. 9*5218cd10SNamjae Jeon */ 10*5218cd10SNamjae Jeon 11*5218cd10SNamjae Jeon #include "ntfs.h" 12*5218cd10SNamjae Jeon #include "index.h" 13*5218cd10SNamjae Jeon #include "object_id.h" 14*5218cd10SNamjae Jeon 15*5218cd10SNamjae Jeon struct object_id_index_key { 16*5218cd10SNamjae Jeon union { 17*5218cd10SNamjae Jeon u32 alignment; 18*5218cd10SNamjae Jeon struct guid guid; 19*5218cd10SNamjae Jeon } object_id; 20*5218cd10SNamjae Jeon } __packed; 21*5218cd10SNamjae Jeon 22*5218cd10SNamjae Jeon struct object_id_index_data { 23*5218cd10SNamjae Jeon __le64 file_id; 24*5218cd10SNamjae Jeon struct guid birth_volume_id; 25*5218cd10SNamjae Jeon struct guid birth_object_id; 26*5218cd10SNamjae Jeon struct guid domain_id; 27*5218cd10SNamjae Jeon } __packed; 28*5218cd10SNamjae Jeon 29*5218cd10SNamjae Jeon /* Index entry in $Extend/$ObjId */ 30*5218cd10SNamjae Jeon struct object_id_index { 31*5218cd10SNamjae Jeon struct index_entry_header header; 32*5218cd10SNamjae Jeon struct object_id_index_key key; 33*5218cd10SNamjae Jeon struct object_id_index_data data; 34*5218cd10SNamjae Jeon } __packed; 35*5218cd10SNamjae Jeon 36*5218cd10SNamjae Jeon __le16 objid_index_name[] = {cpu_to_le16('$'), cpu_to_le16('O'), 0}; 37*5218cd10SNamjae Jeon 38*5218cd10SNamjae Jeon /* 39*5218cd10SNamjae Jeon * open_object_id_index - Open the $Extend/$ObjId file and its index 40*5218cd10SNamjae Jeon * @vol: NTFS volume structure 41*5218cd10SNamjae Jeon * 42*5218cd10SNamjae Jeon * Opens the $ObjId system file and retrieves its index context. 43*5218cd10SNamjae Jeon * 44*5218cd10SNamjae Jeon * Return: The index context if opened successfully, or NULL if an error 45*5218cd10SNamjae Jeon * occurred. 46*5218cd10SNamjae Jeon */ 47*5218cd10SNamjae Jeon static struct ntfs_index_context *open_object_id_index(struct ntfs_volume *vol) 48*5218cd10SNamjae Jeon { 49*5218cd10SNamjae Jeon struct inode *dir_vi, *vi; 50*5218cd10SNamjae Jeon struct ntfs_inode *dir_ni; 51*5218cd10SNamjae Jeon struct ntfs_index_context *xo = NULL; 52*5218cd10SNamjae Jeon struct ntfs_name *name = NULL; 53*5218cd10SNamjae Jeon u64 mref; 54*5218cd10SNamjae Jeon int uname_len; 55*5218cd10SNamjae Jeon __le16 *uname; 56*5218cd10SNamjae Jeon 57*5218cd10SNamjae Jeon uname_len = ntfs_nlstoucs(vol, "$ObjId", 6, &uname, 58*5218cd10SNamjae Jeon NTFS_MAX_NAME_LEN); 59*5218cd10SNamjae Jeon if (uname_len < 0) 60*5218cd10SNamjae Jeon return NULL; 61*5218cd10SNamjae Jeon 62*5218cd10SNamjae Jeon /* do not use path_name_to inode - could reopen root */ 63*5218cd10SNamjae Jeon dir_vi = ntfs_iget(vol->sb, FILE_Extend); 64*5218cd10SNamjae Jeon if (IS_ERR(dir_vi)) { 65*5218cd10SNamjae Jeon kmem_cache_free(ntfs_name_cache, uname); 66*5218cd10SNamjae Jeon return NULL; 67*5218cd10SNamjae Jeon } 68*5218cd10SNamjae Jeon dir_ni = NTFS_I(dir_vi); 69*5218cd10SNamjae Jeon 70*5218cd10SNamjae Jeon mutex_lock_nested(&dir_ni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT); 71*5218cd10SNamjae Jeon mref = ntfs_lookup_inode_by_name(dir_ni, uname, uname_len, &name); 72*5218cd10SNamjae Jeon mutex_unlock(&dir_ni->mrec_lock); 73*5218cd10SNamjae Jeon kfree(name); 74*5218cd10SNamjae Jeon kmem_cache_free(ntfs_name_cache, uname); 75*5218cd10SNamjae Jeon if (IS_ERR_MREF(mref)) 76*5218cd10SNamjae Jeon goto put_dir_vi; 77*5218cd10SNamjae Jeon 78*5218cd10SNamjae Jeon vi = ntfs_iget(vol->sb, MREF(mref)); 79*5218cd10SNamjae Jeon if (IS_ERR(vi)) 80*5218cd10SNamjae Jeon goto put_dir_vi; 81*5218cd10SNamjae Jeon 82*5218cd10SNamjae Jeon xo = ntfs_index_ctx_get(NTFS_I(vi), objid_index_name, 2); 83*5218cd10SNamjae Jeon if (!xo) 84*5218cd10SNamjae Jeon iput(vi); 85*5218cd10SNamjae Jeon put_dir_vi: 86*5218cd10SNamjae Jeon iput(dir_vi); 87*5218cd10SNamjae Jeon return xo; 88*5218cd10SNamjae Jeon } 89*5218cd10SNamjae Jeon 90*5218cd10SNamjae Jeon 91*5218cd10SNamjae Jeon /* 92*5218cd10SNamjae Jeon * remove_object_id_index - Remove an object id index entry if attribute present 93*5218cd10SNamjae Jeon * @ni: NTFS inode structure containing the attribute 94*5218cd10SNamjae Jeon * @xo: Index context for the object id index 95*5218cd10SNamjae Jeon * 96*5218cd10SNamjae Jeon * Reads the existing object ID attribute and removes it from the index. 97*5218cd10SNamjae Jeon * 98*5218cd10SNamjae Jeon * Return: 0 on success, or a negative error code on failure. 99*5218cd10SNamjae Jeon */ 100*5218cd10SNamjae Jeon static int remove_object_id_index(struct ntfs_inode *ni, struct ntfs_index_context *xo) 101*5218cd10SNamjae Jeon { 102*5218cd10SNamjae Jeon struct object_id_index_key key = {0}; 103*5218cd10SNamjae Jeon s64 size; 104*5218cd10SNamjae Jeon 105*5218cd10SNamjae Jeon if (ni->data_size == 0) 106*5218cd10SNamjae Jeon return -ENODATA; 107*5218cd10SNamjae Jeon 108*5218cd10SNamjae Jeon /* read the existing object id attribute */ 109*5218cd10SNamjae Jeon size = ntfs_inode_attr_pread(VFS_I(ni), 0, sizeof(struct guid), 110*5218cd10SNamjae Jeon (char *)&key); 111*5218cd10SNamjae Jeon if (size != sizeof(struct guid)) 112*5218cd10SNamjae Jeon return -ENODATA; 113*5218cd10SNamjae Jeon 114*5218cd10SNamjae Jeon if (!ntfs_index_lookup(&key, sizeof(struct object_id_index_key), xo)) 115*5218cd10SNamjae Jeon return ntfs_index_rm(xo); 116*5218cd10SNamjae Jeon 117*5218cd10SNamjae Jeon return 0; 118*5218cd10SNamjae Jeon } 119*5218cd10SNamjae Jeon 120*5218cd10SNamjae Jeon /* 121*5218cd10SNamjae Jeon * ntfs_delete_object_id_index - Delete an object_id index entry 122*5218cd10SNamjae Jeon * @ni: NTFS inode structure 123*5218cd10SNamjae Jeon * 124*5218cd10SNamjae Jeon * Opens the object ID index and removes the entry corresponding to the inode. 125*5218cd10SNamjae Jeon * 126*5218cd10SNamjae Jeon * Return: 0 on success, or a negative error code on failure. 127*5218cd10SNamjae Jeon */ 128*5218cd10SNamjae Jeon int ntfs_delete_object_id_index(struct ntfs_inode *ni) 129*5218cd10SNamjae Jeon { 130*5218cd10SNamjae Jeon struct ntfs_index_context *xo; 131*5218cd10SNamjae Jeon struct ntfs_inode *xoni; 132*5218cd10SNamjae Jeon struct inode *attr_vi; 133*5218cd10SNamjae Jeon int ret = 0; 134*5218cd10SNamjae Jeon 135*5218cd10SNamjae Jeon attr_vi = ntfs_attr_iget(VFS_I(ni), AT_OBJECT_ID, AT_UNNAMED, 0); 136*5218cd10SNamjae Jeon if (IS_ERR(attr_vi)) 137*5218cd10SNamjae Jeon return PTR_ERR(attr_vi); 138*5218cd10SNamjae Jeon 139*5218cd10SNamjae Jeon /* 140*5218cd10SNamjae Jeon * read the existing object id and un-index it 141*5218cd10SNamjae Jeon */ 142*5218cd10SNamjae Jeon xo = open_object_id_index(ni->vol); 143*5218cd10SNamjae Jeon if (xo) { 144*5218cd10SNamjae Jeon xoni = xo->idx_ni; 145*5218cd10SNamjae Jeon mutex_lock_nested(&xoni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT); 146*5218cd10SNamjae Jeon ret = remove_object_id_index(NTFS_I(attr_vi), xo); 147*5218cd10SNamjae Jeon if (!ret) { 148*5218cd10SNamjae Jeon ntfs_index_entry_mark_dirty(xo); 149*5218cd10SNamjae Jeon mark_mft_record_dirty(xoni); 150*5218cd10SNamjae Jeon } 151*5218cd10SNamjae Jeon ntfs_index_ctx_put(xo); 152*5218cd10SNamjae Jeon mutex_unlock(&xoni->mrec_lock); 153*5218cd10SNamjae Jeon iput(VFS_I(xoni)); 154*5218cd10SNamjae Jeon } 155*5218cd10SNamjae Jeon 156*5218cd10SNamjae Jeon iput(attr_vi); 157*5218cd10SNamjae Jeon return ret; 158*5218cd10SNamjae Jeon } 159