@@ -2690,136 +2690,97 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
26902690 return rc ;
26912691}
26922692
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 )
27072699{
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 ;
27172704 __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 ;
27192709
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 );
27232727 if (rc )
27242728 return rc ;
27252729
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 ;
27442734
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 ;
27512758
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 ) {
27602763 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 ;
27952765 }
27962766
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 ) {
28032770 rc = - EIO ;
2804- goto qreparse_out ;
2771+ goto error ;
28052772 }
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 );
28182773
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 );
28232784 return rc ;
28242785}
28252786
0 commit comments