diff options
author | Stefan Metzmacher <metze@samba.org> | 2010-07-31 03:14:16 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-09-29 15:04:30 -0400 |
commit | c69c1b6eaea1b3e1eecf7ad2fba0208ac4a11131 (patch) | |
tree | ad267df56902eaaf89afd9bb2431ce6cff3ea2af /fs/cifs/link.c | |
parent | 3eb9a8893a76cf1cda3b41c3212eb2cfe83eae0e (diff) |
cifs: implement CIFSParseMFSymlink()
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r-- | fs/cifs/link.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 473ca8033656..12eb491d4c52 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -28,6 +28,68 @@ | |||
28 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
31 | #include "md5.h" | ||
32 | |||
33 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) | ||
34 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) | ||
35 | #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) | ||
36 | #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024) | ||
37 | #define CIFS_MF_SYMLINK_FILE_SIZE \ | ||
38 | (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN) | ||
39 | |||
40 | #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n" | ||
41 | #define CIFS_MF_SYMLINK_MD5_FORMAT \ | ||
42 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n" | ||
43 | #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \ | ||
44 | md5_hash[0], md5_hash[1], md5_hash[2], md5_hash[3], \ | ||
45 | md5_hash[4], md5_hash[5], md5_hash[6], md5_hash[7], \ | ||
46 | md5_hash[8], md5_hash[9], md5_hash[10], md5_hash[11],\ | ||
47 | md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15] | ||
48 | |||
49 | static int | ||
50 | CIFSParseMFSymlink(const u8 *buf, | ||
51 | unsigned int buf_len, | ||
52 | unsigned int *_link_len, | ||
53 | char **_link_str) | ||
54 | { | ||
55 | int rc; | ||
56 | unsigned int link_len; | ||
57 | const char *md5_str1; | ||
58 | const char *link_str; | ||
59 | struct MD5Context md5_ctx; | ||
60 | u8 md5_hash[16]; | ||
61 | char md5_str2[34]; | ||
62 | |||
63 | if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) | ||
64 | return -EINVAL; | ||
65 | |||
66 | md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET]; | ||
67 | link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET]; | ||
68 | |||
69 | rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len); | ||
70 | if (rc != 1) | ||
71 | return -EINVAL; | ||
72 | |||
73 | cifs_MD5_init(&md5_ctx); | ||
74 | cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); | ||
75 | cifs_MD5_final(md5_hash, &md5_ctx); | ||
76 | |||
77 | snprintf(md5_str2, sizeof(md5_str2), | ||
78 | CIFS_MF_SYMLINK_MD5_FORMAT, | ||
79 | CIFS_MF_SYMLINK_MD5_ARGS(md5_hash)); | ||
80 | |||
81 | if (strncmp(md5_str1, md5_str2, 17) != 0) | ||
82 | return -EINVAL; | ||
83 | |||
84 | if (_link_str) { | ||
85 | *_link_str = kstrndup(link_str, link_len, GFP_KERNEL); | ||
86 | if (!*_link_str) | ||
87 | return -ENOMEM; | ||
88 | } | ||
89 | |||
90 | *_link_len = link_len; | ||
91 | return 0; | ||
92 | } | ||
31 | 93 | ||
32 | int | 94 | int |
33 | cifs_hardlink(struct dentry *old_file, struct inode *inode, | 95 | cifs_hardlink(struct dentry *old_file, struct inode *inode, |