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