diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df6a619a6821..36d3c128a58b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2072,7 +2072,91 @@ setACLerrorExit: | |||
2072 | return rc; | 2072 | return rc; |
2073 | } | 2073 | } |
2074 | 2074 | ||
2075 | #endif | 2075 | /* BB fix tabs in this function FIXME BB */ |
2076 | int | ||
2077 | CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, | ||
2078 | const int netfid, __u64 * pExtAttrBits, __u64 *pMask) | ||
2079 | { | ||
2080 | int rc = 0; | ||
2081 | struct smb_t2_qfi_req *pSMB = NULL; | ||
2082 | struct smb_t2_qfi_rsp *pSMBr = NULL; | ||
2083 | int bytes_returned; | ||
2084 | __u16 params, byte_count; | ||
2085 | |||
2086 | cFYI(1,("In GetExtAttr")); | ||
2087 | if(tcon == NULL) | ||
2088 | return -ENODEV; | ||
2089 | |||
2090 | GetExtAttrRetry: | ||
2091 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
2092 | (void **) &pSMBr); | ||
2093 | if (rc) | ||
2094 | return rc; | ||
2095 | |||
2096 | params = 2 /* level */ +2 /* fid */ + 2 /* rsrvd */; | ||
2097 | pSMB->t2.TotalDataCount = 0; | ||
2098 | pSMB->t2.MaxParameterCount = cpu_to_le16(2); | ||
2099 | /* BB find exact max data count below from sess structure BB */ | ||
2100 | pSMB->t2.MaxDataCount = cpu_to_le16(4000); | ||
2101 | pSMB->t2.MaxSetupCount = 0; | ||
2102 | pSMB->t2.Reserved = 0; | ||
2103 | pSMB->t2.Flags = 0; | ||
2104 | pSMB->t2.Timeout = 0; | ||
2105 | pSMB->t2.Reserved2 = 0; | ||
2106 | pSMB->t2.ParameterOffset = cpu_to_le16(offsetof( | ||
2107 | struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); | ||
2108 | pSMB->t2.DataCount = 0; | ||
2109 | pSMB->t2.DataOffset = 0; | ||
2110 | pSMB->t2.SetupCount = 1; | ||
2111 | pSMB->t2.Reserved3 = 0; | ||
2112 | pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); | ||
2113 | byte_count = params + 3 /* pad */ ; | ||
2114 | pSMB->t2.TotalParameterCount = cpu_to_le16(params); | ||
2115 | pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; | ||
2116 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); | ||
2117 | pSMB->Pad1 = 0; | ||
2118 | pSMB->Pad2 = 0; | ||
2119 | pSMB->Fid = netfid; | ||
2120 | pSMB->hdr.smb_buf_length += byte_count; | ||
2121 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | ||
2122 | |||
2123 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
2124 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
2125 | if (rc) { | ||
2126 | cFYI(1, ("error %d in GetExtAttr", rc)); | ||
2127 | } else { | ||
2128 | /* decode response */ | ||
2129 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
2130 | if (rc || (pSMBr->ByteCount < 2)) | ||
2131 | /* BB also check enough total bytes returned */ | ||
2132 | /* If rc should we check for EOPNOSUPP and | ||
2133 | disable the srvino flag? or in caller? */ | ||
2134 | rc = -EIO; /* bad smb */ | ||
2135 | else { | ||
2136 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
2137 | __u16 count = le16_to_cpu(pSMBr->t2.DataCount); | ||
2138 | struct file_chattr_info * pfinfo; | ||
2139 | /* BB Do we need a cast or hash here ? */ | ||
2140 | if(count != 16) { | ||
2141 | cFYI(1, ("Illegal size ret in GetExtAttr")); | ||
2142 | rc = -EIO; | ||
2143 | goto GetExtAttrOut; | ||
2144 | } | ||
2145 | pfinfo = (struct file_chattr_info *) | ||
2146 | (data_offset + (char *) &pSMBr->hdr.Protocol); | ||
2147 | *pExtAttrBits = le64_to_cpu(pfinfo->mode); | ||
2148 | *pMask = le64_to_cpu(pfinfo->mask); | ||
2149 | } | ||
2150 | } | ||
2151 | GetExtAttrOut: | ||
2152 | cifs_buf_release(pSMB); | ||
2153 | if (rc == -EAGAIN) | ||
2154 | goto GetExtAttrRetry; | ||
2155 | return rc; | ||
2156 | } | ||
2157 | |||
2158 | |||
2159 | #endif /* CONFIG_POSIX */ | ||
2076 | 2160 | ||
2077 | int | 2161 | int |
2078 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2162 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |