#include "ntfs.h"
#include "index.h"
#include "object_id.h"
struct object_id_index_key {
union {
u32 alignment;
struct guid guid;
} object_id;
} __packed;
struct object_id_index_data {
__le64 file_id;
struct guid birth_volume_id;
struct guid birth_object_id;
struct guid domain_id;
} __packed;
struct object_id_index {
struct index_entry_header header;
struct object_id_index_key key;
struct object_id_index_data data;
} __packed;
__le16 objid_index_name[] = {cpu_to_le16('$'), cpu_to_le16('O'), 0};
static struct ntfs_index_context *open_object_id_index(struct ntfs_volume *vol)
{
struct inode *dir_vi, *vi;
struct ntfs_inode *dir_ni;
struct ntfs_index_context *xo = NULL;
struct ntfs_name *name = NULL;
u64 mref;
int uname_len;
__le16 *uname;
uname_len = ntfs_nlstoucs(vol, "$ObjId", 6, &uname,
NTFS_MAX_NAME_LEN);
if (uname_len < 0)
return NULL;
dir_vi = ntfs_iget(vol->sb, FILE_Extend);
if (IS_ERR(dir_vi)) {
kmem_cache_free(ntfs_name_cache, uname);
return NULL;
}
dir_ni = NTFS_I(dir_vi);
mutex_lock_nested(&dir_ni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT);
mref = ntfs_lookup_inode_by_name(dir_ni, uname, uname_len, &name);
mutex_unlock(&dir_ni->mrec_lock);
kfree(name);
kmem_cache_free(ntfs_name_cache, uname);
if (IS_ERR_MREF(mref))
goto put_dir_vi;
vi = ntfs_iget(vol->sb, MREF(mref));
if (IS_ERR(vi))
goto put_dir_vi;
xo = ntfs_index_ctx_get(NTFS_I(vi), objid_index_name, 2);
if (!xo)
iput(vi);
put_dir_vi:
iput(dir_vi);
return xo;
}
static int remove_object_id_index(struct ntfs_inode *ni, struct ntfs_index_context *xo)
{
struct object_id_index_key key = {0};
s64 size;
if (ni->data_size == 0)
return -ENODATA;
size = ntfs_inode_attr_pread(VFS_I(ni), 0, sizeof(struct guid),
(char *)&key);
if (size != sizeof(struct guid))
return -ENODATA;
if (!ntfs_index_lookup(&key, sizeof(struct object_id_index_key), xo))
return ntfs_index_rm(xo);
return 0;
}
int ntfs_delete_object_id_index(struct ntfs_inode *ni)
{
struct ntfs_index_context *xo;
struct ntfs_inode *xoni;
struct inode *attr_vi;
int ret = 0;
attr_vi = ntfs_attr_iget(VFS_I(ni), AT_OBJECT_ID, AT_UNNAMED, 0);
if (IS_ERR(attr_vi))
return PTR_ERR(attr_vi);
xo = open_object_id_index(ni->vol);
if (xo) {
xoni = xo->idx_ni;
mutex_lock_nested(&xoni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT);
ret = remove_object_id_index(NTFS_I(attr_vi), xo);
if (!ret) {
ntfs_index_entry_mark_dirty(xo);
mark_mft_record_dirty(xoni);
}
ntfs_index_ctx_put(xo);
mutex_unlock(&xoni->mrec_lock);
iput(VFS_I(xoni));
}
iput(attr_vi);
return ret;
}