diff options
author | Steve French <smfrench@gmail.com> | 2014-09-16 08:18:19 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-10-16 16:20:20 -0400 |
commit | c22870ea2deb2841402133909cfa707a2c0b12ed (patch) | |
tree | 99a15884a9be669408c166a997b55944b5504388 /fs/cifs/link.c | |
parent | 5ab97578cbb3bf9a28dec4534cb86fbc35e600bb (diff) |
mfsymlinks support for SMB2.1/SMB3. Part 2 query symlink
Adds support on SMB2.1 and SMB3 mounts for emulation of symlinks
via the "Minshall/French" symlink format already used for cifs
mounts when mfsymlinks mount option is used (and also used by Apple).
http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks
This second patch adds support to query them (recognize them as symlinks
and read them). Third version of patch makes minor corrections
to error handling.
Signed-off-by: Steve French <smfrench@gmail.com>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r-- | fs/cifs/link.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1216f4f1c6c9..ce7d4bbf3120 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -28,7 +28,9 @@ | |||
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 | #ifdef CONFIG_CIFS_SMB2 | ||
31 | #include "smb2proto.h" | 32 | #include "smb2proto.h" |
33 | #endif | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * M-F Symlink Functions - Begin | 36 | * M-F Symlink Functions - Begin |
@@ -401,6 +403,72 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | |||
401 | return rc; | 403 | return rc; |
402 | } | 404 | } |
403 | 405 | ||
406 | /* | ||
407 | * SMB 2.1/SMB3 Protocol specific functions | ||
408 | */ | ||
409 | #ifdef CONFIG_CIFS_SMB2 | ||
410 | int | ||
411 | smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
412 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
413 | char *pbuf, unsigned int *pbytes_read) | ||
414 | { | ||
415 | int rc; | ||
416 | struct cifs_fid fid; | ||
417 | struct cifs_open_parms oparms; | ||
418 | struct cifs_io_parms io_parms; | ||
419 | int buf_type = CIFS_NO_BUFFER; | ||
420 | __le16 *utf16_path; | ||
421 | __u8 oplock = SMB2_OPLOCK_LEVEL_II; | ||
422 | struct smb2_file_all_info *pfile_info = NULL; | ||
423 | |||
424 | oparms.tcon = tcon; | ||
425 | oparms.cifs_sb = cifs_sb; | ||
426 | oparms.desired_access = GENERIC_READ; | ||
427 | oparms.create_options = CREATE_NOT_DIR; | ||
428 | if (backup_cred(cifs_sb)) | ||
429 | oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
430 | oparms.disposition = FILE_OPEN; | ||
431 | oparms.fid = &fid; | ||
432 | oparms.reconnect = false; | ||
433 | |||
434 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | ||
435 | if (utf16_path == NULL) | ||
436 | return -ENOMEM; | ||
437 | |||
438 | pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, | ||
439 | GFP_KERNEL); | ||
440 | |||
441 | if (pfile_info == NULL) { | ||
442 | kfree(utf16_path); | ||
443 | return -ENOMEM; | ||
444 | } | ||
445 | |||
446 | rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL); | ||
447 | if (rc) | ||
448 | goto qmf_out_open_fail; | ||
449 | |||
450 | if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | ||
451 | /* it's not a symlink */ | ||
452 | rc = -ENOENT; /* Is there a better rc to return? */ | ||
453 | goto qmf_out; | ||
454 | } | ||
455 | |||
456 | io_parms.netfid = fid.netfid; | ||
457 | io_parms.pid = current->tgid; | ||
458 | io_parms.tcon = tcon; | ||
459 | io_parms.offset = 0; | ||
460 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
461 | io_parms.persistent_fid = fid.persistent_fid; | ||
462 | io_parms.volatile_fid = fid.volatile_fid; | ||
463 | rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type); | ||
464 | qmf_out: | ||
465 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
466 | qmf_out_open_fail: | ||
467 | kfree(utf16_path); | ||
468 | kfree(pfile_info); | ||
469 | return rc; | ||
470 | } | ||
471 | |||
404 | int | 472 | int |
405 | smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | 473 | smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
406 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | 474 | struct cifs_sb_info *cifs_sb, const unsigned char *path, |
@@ -461,7 +529,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | |||
461 | kfree(utf16_path); | 529 | kfree(utf16_path); |
462 | return rc; | 530 | return rc; |
463 | } | 531 | } |
464 | 532 | #endif /* CONFIG_CIFS_SMB2 */ | |
465 | 533 | ||
466 | /* | 534 | /* |
467 | * M-F Symlink Functions - End | 535 | * M-F Symlink Functions - End |