- Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathsymlink.c
80 lines (70 loc) · 1.9 KB
/
symlink.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2018 Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
*/
#include<linux/fs.h>
#include<linux/slab.h>
#include"apfs.h"
/**
* apfs_get_link - Follow a symbolic link
* @dentry: dentry for the link
* @inode: inode for the link
* @done: delayed call to free the returned buffer after use
*
* Returns a pointer to a buffer containing the target path, or an appropriate
* error pointer in case of failure.
*/
staticconstchar*apfs_get_link(structdentry*dentry, structinode*inode,
structdelayed_call*done)
{
structsuper_block*sb=inode->i_sb;
structapfs_nxsb_info*nxi=APFS_NXI(sb);
char*target=NULL;
interr;
intsize;
down_read(&nxi->nx_big_sem);
if (!dentry) {
err=-ECHILD;
goto fail;
}
size=__apfs_xattr_get(inode, APFS_XATTR_NAME_SYMLINK,
NULL/* buffer */, 0/* size */);
if (size<0) { /* TODO: return a better error code */
apfs_err(sb, "symlink size read failed");
err=size;
goto fail;
}
target=kmalloc(size, GFP_KERNEL);
if (!target) {
err=-ENOMEM;
goto fail;
}
size=__apfs_xattr_get(inode, APFS_XATTR_NAME_SYMLINK, target, size);
if (size<0) {
apfs_err(sb, "symlink read failed");
err=size;
goto fail;
}
if (size==0||*(target+size-1) !=0) {
/* Target path must be NULL-terminated */
apfs_err(sb, "bad link target in inode 0x%llx", apfs_ino(inode));
err=-EFSCORRUPTED;
goto fail;
}
up_read(&nxi->nx_big_sem);
set_delayed_call(done, kfree_link, target);
returntarget;
fail:
kfree(target);
up_read(&nxi->nx_big_sem);
returnERR_PTR(err);
}
conststructinode_operationsapfs_symlink_inode_operations= {
.get_link=apfs_get_link,
.getattr=apfs_getattr,
.listxattr=apfs_listxattr,
.update_time=apfs_update_time,
#ifLINUX_VERSION_CODE<KERNEL_VERSION(4, 10, 0) /* Now this is the default */
.readlink=generic_readlink,
#endif
};