@@ -2690,136 +2690,97 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2690
2690
return rc ;
2691
2691
}
2692
2692
2693
- /*
2694
- * Recent Windows versions now create symlinks more frequently
2695
- * and they use the "reparse point" mechanism below. We can of course
2696
- * do symlinks nicely to Samba and other servers which support the
2697
- * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2698
- * "MF" symlinks optionally, but for recent Windows we really need to
2699
- * reenable the code below and fix the cifs_symlink callers to handle this.
2700
- * In the interim this code has been moved to its own config option so
2701
- * it is not compiled in by default until callers fixed up and more tested.
2702
- */
2703
- int
2704
- CIFSSMBQuerySymLink (const unsigned int xid , struct cifs_tcon * tcon ,
2705
- __u16 fid , char * * symlinkinfo ,
2706
- const struct nls_table * nls_codepage )
2693
+ int cifs_query_reparse_point (const unsigned int xid ,
2694
+ struct cifs_tcon * tcon ,
2695
+ struct cifs_sb_info * cifs_sb ,
2696
+ const char * full_path ,
2697
+ u32 * tag , struct kvec * rsp ,
2698
+ int * rsp_buftype )
2707
2699
{
2708
- int rc = 0 ;
2709
- int bytes_returned ;
2710
- struct smb_com_transaction_ioctl_req * pSMB ;
2711
- struct smb_com_transaction_ioctl_rsp * pSMBr ;
2712
- bool is_unicode ;
2713
- unsigned int sub_len ;
2714
- char * sub_start ;
2715
- struct reparse_symlink_data * reparse_buf ;
2716
- struct reparse_posix_data * posix_buf ;
2700
+ struct cifs_open_parms oparms ;
2701
+ TRANSACT_IOCTL_REQ * io_req = NULL ;
2702
+ TRANSACT_IOCTL_RSP * io_rsp = NULL ;
2703
+ struct cifs_fid fid ;
2717
2704
__u32 data_offset , data_count ;
2718
- char * end_of_smb ;
2705
+ __u8 * start , * end ;
2706
+ int io_rsp_len ;
2707
+ int oplock = 0 ;
2708
+ int rc ;
2719
2709
2720
- cifs_dbg (FYI , "In Windows reparse style QueryLink for fid %u\n" , fid );
2721
- rc = smb_init (SMB_COM_NT_TRANSACT , 23 , tcon , (void * * ) & pSMB ,
2722
- (void * * ) & pSMBr );
2710
+ cifs_tcon_dbg (FYI , "%s: path=%s\n" , __func__ , full_path );
2711
+
2712
+ if (cap_unix (tcon -> ses ))
2713
+ return - EOPNOTSUPP ;
2714
+
2715
+ oparms = (struct cifs_open_parms ) {
2716
+ .tcon = tcon ,
2717
+ .cifs_sb = cifs_sb ,
2718
+ .desired_access = FILE_READ_ATTRIBUTES ,
2719
+ .create_options = cifs_create_options (cifs_sb ,
2720
+ OPEN_REPARSE_POINT ),
2721
+ .disposition = FILE_OPEN ,
2722
+ .path = full_path ,
2723
+ .fid = & fid ,
2724
+ };
2725
+
2726
+ rc = CIFS_open (xid , & oparms , & oplock , NULL );
2723
2727
if (rc )
2724
2728
return rc ;
2725
2729
2726
- pSMB -> TotalParameterCount = 0 ;
2727
- pSMB -> TotalDataCount = 0 ;
2728
- pSMB -> MaxParameterCount = cpu_to_le32 (2 );
2729
- /* BB find exact data count max from sess structure BB */
2730
- pSMB -> MaxDataCount = cpu_to_le32 (CIFSMaxBufSize & 0xFFFFFF00 );
2731
- pSMB -> MaxSetupCount = 4 ;
2732
- pSMB -> Reserved = 0 ;
2733
- pSMB -> ParameterOffset = 0 ;
2734
- pSMB -> DataCount = 0 ;
2735
- pSMB -> DataOffset = 0 ;
2736
- pSMB -> SetupCount = 4 ;
2737
- pSMB -> SubCommand = cpu_to_le16 (NT_TRANSACT_IOCTL );
2738
- pSMB -> ParameterCount = pSMB -> TotalParameterCount ;
2739
- pSMB -> FunctionCode = cpu_to_le32 (FSCTL_GET_REPARSE_POINT );
2740
- pSMB -> IsFsctl = 1 ; /* FSCTL */
2741
- pSMB -> IsRootFlag = 0 ;
2742
- pSMB -> Fid = fid ; /* file handle always le */
2743
- pSMB -> ByteCount = 0 ;
2730
+ rc = smb_init (SMB_COM_NT_TRANSACT , 23 , tcon ,
2731
+ (void * * )& io_req , (void * * )& io_rsp );
2732
+ if (rc )
2733
+ goto error ;
2744
2734
2745
- rc = SendReceive (xid , tcon -> ses , (struct smb_hdr * ) pSMB ,
2746
- (struct smb_hdr * ) pSMBr , & bytes_returned , 0 );
2747
- if (rc ) {
2748
- cifs_dbg (FYI , "Send error in QueryReparseLinkInfo = %d\n" , rc );
2749
- goto qreparse_out ;
2750
- }
2735
+ io_req -> TotalParameterCount = 0 ;
2736
+ io_req -> TotalDataCount = 0 ;
2737
+ io_req -> MaxParameterCount = cpu_to_le32 (2 );
2738
+ /* BB find exact data count max from sess structure BB */
2739
+ io_req -> MaxDataCount = cpu_to_le32 (CIFSMaxBufSize & 0xFFFFFF00 );
2740
+ io_req -> MaxSetupCount = 4 ;
2741
+ io_req -> Reserved = 0 ;
2742
+ io_req -> ParameterOffset = 0 ;
2743
+ io_req -> DataCount = 0 ;
2744
+ io_req -> DataOffset = 0 ;
2745
+ io_req -> SetupCount = 4 ;
2746
+ io_req -> SubCommand = cpu_to_le16 (NT_TRANSACT_IOCTL );
2747
+ io_req -> ParameterCount = io_req -> TotalParameterCount ;
2748
+ io_req -> FunctionCode = cpu_to_le32 (FSCTL_GET_REPARSE_POINT );
2749
+ io_req -> IsFsctl = 1 ;
2750
+ io_req -> IsRootFlag = 0 ;
2751
+ io_req -> Fid = fid .netfid ;
2752
+ io_req -> ByteCount = 0 ;
2753
+
2754
+ rc = SendReceive (xid , tcon -> ses , (struct smb_hdr * )io_req ,
2755
+ (struct smb_hdr * )io_rsp , & io_rsp_len , 0 );
2756
+ if (rc )
2757
+ goto error ;
2751
2758
2752
- data_offset = le32_to_cpu (pSMBr -> DataOffset );
2753
- data_count = le32_to_cpu (pSMBr -> DataCount );
2754
- if (get_bcc (& pSMBr -> hdr ) < 2 || data_offset > 512 ) {
2755
- /* BB also check enough total bytes returned */
2756
- rc = - EIO ; /* bad smb */
2757
- goto qreparse_out ;
2758
- }
2759
- if (!data_count || (data_count > 2048 )) {
2759
+ data_offset = le32_to_cpu (io_rsp -> DataOffset );
2760
+ data_count = le32_to_cpu (io_rsp -> DataCount );
2761
+ if (get_bcc (& io_rsp -> hdr ) < 2 || data_offset > 512 ||
2762
+ !data_count || data_count > 2048 ) {
2760
2763
rc = - EIO ;
2761
- cifs_dbg (FYI , "Invalid return data count on get reparse info ioctl\n" );
2762
- goto qreparse_out ;
2763
- }
2764
- end_of_smb = 2 + get_bcc (& pSMBr -> hdr ) + (char * )& pSMBr -> ByteCount ;
2765
- reparse_buf = (struct reparse_symlink_data * )
2766
- ((char * )& pSMBr -> hdr .Protocol + data_offset );
2767
- if ((char * )reparse_buf >= end_of_smb ) {
2768
- rc = - EIO ;
2769
- goto qreparse_out ;
2770
- }
2771
- if (reparse_buf -> ReparseTag == cpu_to_le32 (IO_REPARSE_TAG_NFS )) {
2772
- cifs_dbg (FYI , "NFS style reparse tag\n" );
2773
- posix_buf = (struct reparse_posix_data * )reparse_buf ;
2774
-
2775
- if (posix_buf -> InodeType != cpu_to_le64 (NFS_SPECFILE_LNK )) {
2776
- cifs_dbg (FYI , "unsupported file type 0x%llx\n" ,
2777
- le64_to_cpu (posix_buf -> InodeType ));
2778
- rc = - EOPNOTSUPP ;
2779
- goto qreparse_out ;
2780
- }
2781
- is_unicode = true;
2782
- sub_len = le16_to_cpu (reparse_buf -> ReparseDataLength );
2783
- if (posix_buf -> PathBuffer + sub_len > end_of_smb ) {
2784
- cifs_dbg (FYI , "reparse buf beyond SMB\n" );
2785
- rc = - EIO ;
2786
- goto qreparse_out ;
2787
- }
2788
- * symlinkinfo = cifs_strndup_from_utf16 (posix_buf -> PathBuffer ,
2789
- sub_len , is_unicode , nls_codepage );
2790
- goto qreparse_out ;
2791
- } else if (reparse_buf -> ReparseTag !=
2792
- cpu_to_le32 (IO_REPARSE_TAG_SYMLINK )) {
2793
- rc = - EOPNOTSUPP ;
2794
- goto qreparse_out ;
2764
+ goto error ;
2795
2765
}
2796
2766
2797
- /* Reparse tag is NTFS symlink */
2798
- sub_start = le16_to_cpu (reparse_buf -> SubstituteNameOffset ) +
2799
- reparse_buf -> PathBuffer ;
2800
- sub_len = le16_to_cpu (reparse_buf -> SubstituteNameLength );
2801
- if (sub_start + sub_len > end_of_smb ) {
2802
- cifs_dbg (FYI , "reparse buf beyond SMB\n" );
2767
+ end = 2 + get_bcc (& io_rsp -> hdr ) + (__u8 * )& io_rsp -> ByteCount ;
2768
+ start = (__u8 * )& io_rsp -> hdr .Protocol + data_offset ;
2769
+ if (start >= end ) {
2803
2770
rc = - EIO ;
2804
- goto qreparse_out ;
2771
+ goto error ;
2805
2772
}
2806
- if (pSMBr -> hdr .Flags2 & SMBFLG2_UNICODE )
2807
- is_unicode = true;
2808
- else
2809
- is_unicode = false;
2810
-
2811
- /* BB FIXME investigate remapping reserved chars here */
2812
- * symlinkinfo = cifs_strndup_from_utf16 (sub_start , sub_len , is_unicode ,
2813
- nls_codepage );
2814
- if (!* symlinkinfo )
2815
- rc = - ENOMEM ;
2816
- qreparse_out :
2817
- cifs_buf_release (pSMB );
2818
2773
2819
- /*
2820
- * Note: On -EAGAIN error only caller can retry on handle based calls
2821
- * since file handle passed in no longer valid.
2822
- */
2774
+ * tag = le32_to_cpu (((struct reparse_data_buffer * )start )-> ReparseTag );
2775
+ rsp -> iov_base = io_rsp ;
2776
+ rsp -> iov_len = io_rsp_len ;
2777
+ * rsp_buftype = CIFS_LARGE_BUFFER ;
2778
+ CIFSSMBClose (xid , tcon , fid .netfid );
2779
+ return 0 ;
2780
+
2781
+ error :
2782
+ cifs_buf_release (io_req );
2783
+ CIFSSMBClose (xid , tcon , fid .netfid );
2823
2784
return rc ;
2824
2785
}
2825
2786
0 commit comments