aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r--fs/cifs/link.c162
1 files changed, 29 insertions, 133 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 63f644000ce..cd83c53fcbb 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -107,63 +107,51 @@ void *
107cifs_follow_link(struct dentry *direntry, struct nameidata *nd) 107cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
108{ 108{
109 struct inode *inode = direntry->d_inode; 109 struct inode *inode = direntry->d_inode;
110 int rc = -EACCES; 110 int rc = -ENOMEM;
111 int xid; 111 int xid;
112 char *full_path = NULL; 112 char *full_path = NULL;
113 char *target_path = ERR_PTR(-ENOMEM); 113 char *target_path = NULL;
114 struct cifs_sb_info *cifs_sb; 114 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
115 struct cifsTconInfo *pTcon; 115 struct cifsTconInfo *tcon = cifs_sb->tcon;
116 116
117 xid = GetXid(); 117 xid = GetXid();
118 118
119 full_path = build_path_from_dentry(direntry); 119 /*
120 120 * For now, we just handle symlinks with unix extensions enabled.
121 if (!full_path) 121 * Eventually we should handle NTFS reparse points, and MacOS
122 goto out_no_free; 122 * symlink support. For instance...
123 123 *
124 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); 124 * rc = CIFSSMBQueryReparseLinkInfo(...)
125 cifs_sb = CIFS_SB(inode->i_sb); 125 *
126 pTcon = cifs_sb->tcon; 126 * For now, just return -EACCES when the server doesn't support posix
127 target_path = kmalloc(PATH_MAX, GFP_KERNEL); 127 * extensions. Note that we still allow querying symlinks when posix
128 if (!target_path) { 128 * extensions are manually disabled. We could disable these as well
129 target_path = ERR_PTR(-ENOMEM); 129 * but there doesn't seem to be any harm in allowing the client to
130 * read them.
131 */
132 if (!(tcon->ses->capabilities & CAP_UNIX)) {
133 rc = -EACCES;
130 goto out; 134 goto out;
131 } 135 }
132 136
133 /* We could change this to: 137 full_path = build_path_from_dentry(direntry);
134 if (pTcon->unix_ext) 138 if (!full_path)
135 but there does not seem any point in refusing to 139 goto out;
136 get symlink info if we can, even if unix extensions
137 turned off for this mount */
138
139 if (pTcon->ses->capabilities & CAP_UNIX)
140 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
141 target_path,
142 PATH_MAX-1,
143 cifs_sb->local_nls);
144 else {
145 /* BB add read reparse point symlink code here */
146 /* rc = CIFSSMBQueryReparseLinkInfo */
147 /* BB Add code to Query ReparsePoint info */
148 /* BB Add MAC style xsymlink check here if enabled */
149 }
150
151 if (rc == 0) {
152 140
153/* BB Add special case check for Samba DFS symlinks */ 141 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
154 142
155 target_path[PATH_MAX-1] = 0; 143 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
156 } else { 144 cifs_sb->local_nls);
145 kfree(full_path);
146out:
147 if (rc != 0) {
157 kfree(target_path); 148 kfree(target_path);
158 target_path = ERR_PTR(rc); 149 target_path = ERR_PTR(rc);
159 } 150 }
160 151
161out:
162 kfree(full_path);
163out_no_free:
164 FreeXid(xid); 152 FreeXid(xid);
165 nd_set_link(nd, target_path); 153 nd_set_link(nd, target_path);
166 return NULL; /* No cookie */ 154 return NULL;
167} 155}
168 156
169int 157int
@@ -224,98 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
224 return rc; 212 return rc;
225} 213}
226 214
227int
228cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
229{
230 struct inode *inode = direntry->d_inode;
231 int rc = -EACCES;
232 int xid;
233 int oplock = 0;
234 struct cifs_sb_info *cifs_sb;
235 struct cifsTconInfo *pTcon;
236 char *full_path = NULL;
237 char *tmpbuffer;
238 int len;
239 __u16 fid;
240
241 xid = GetXid();
242 cifs_sb = CIFS_SB(inode->i_sb);
243 pTcon = cifs_sb->tcon;
244
245/* BB would it be safe against deadlock to grab this sem
246 even though rename itself grabs the sem and calls lookup? */
247/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
248 full_path = build_path_from_dentry(direntry);
249/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
250
251 if (full_path == NULL) {
252 FreeXid(xid);
253 return -ENOMEM;
254 }
255
256 cFYI(1,
257 ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
258 full_path, inode, pBuffer, buflen));
259 if (buflen > PATH_MAX)
260 len = PATH_MAX;
261 else
262 len = buflen;
263 tmpbuffer = kmalloc(len, GFP_KERNEL);
264 if (tmpbuffer == NULL) {
265 kfree(full_path);
266 FreeXid(xid);
267 return -ENOMEM;
268 }
269
270/* BB add read reparse point symlink code and
271 Unix extensions symlink code here BB */
272/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
273 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
274 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
275 tmpbuffer,
276 len - 1,
277 cifs_sb->local_nls);
278 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
279 cERROR(1, ("SFU style symlinks not implemented yet"));
280 /* add open and read as in fs/cifs/inode.c */
281 } else {
282 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
283 OPEN_REPARSE_POINT, &fid, &oplock, NULL,
284 cifs_sb->local_nls,
285 cifs_sb->mnt_cifs_flags &
286 CIFS_MOUNT_MAP_SPECIAL_CHR);
287 if (!rc) {
288 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
289 tmpbuffer,
290 len - 1,
291 fid,
292 cifs_sb->local_nls);
293 if (CIFSSMBClose(xid, pTcon, fid)) {
294 cFYI(1, ("Error closing junction point "
295 "(open for ioctl)"));
296 }
297 /* If it is a DFS junction earlier we would have gotten
298 PATH_NOT_COVERED returned from server so we do
299 not need to request the DFS info here */
300 }
301 }
302 /* BB Anything else to do to handle recursive links? */
303 /* BB Should we be using page ops here? */
304
305 /* BB null terminate returned string in pBuffer? BB */
306 if (rc == 0) {
307 rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
308 cFYI(1,
309 ("vfs_readlink called from cifs_readlink returned %d",
310 rc));
311 }
312
313 kfree(tmpbuffer);
314 kfree(full_path);
315 FreeXid(xid);
316 return rc;
317}
318
319void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) 215void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
320{ 216{
321 char *p = nd_get_link(nd); 217 char *p = nd_get_link(nd);