Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-or-later
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
15struct object_id_index_key {
16 union {
17 u32 alignment;
18 struct guid guid;
19 } object_id;
20} __packed;
21
22struct 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/* Index entry in $Extend/$ObjId */
30struct 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 */
47static 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 /* do not use path_name_to inode - could reopen root */
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);
85put_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 */
100static 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 /* read the existing object id attribute */
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 */
128int 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}