size_t max_header_size;
size_t read_rsp_size;
__le16 lock_cmd;
+ unsigned int cap_unix;
+ unsigned int cap_nt_find;
+ unsigned int cap_large_files;
};
#define HEADER_SIZE(server) (server->vals->header_size)
unsigned int max_vcs; /* maximum number of smb sessions, at least
those that can be specified uniquely with
vcnumbers */
- int capabilities; /* allow selective disabling of caps by smb sess */
+ unsigned int capabilities; /* selective disabling of caps by smb sess */
int timeAdj; /* Adjust for difference in server time zone in sec */
__u64 CurrentMid; /* multiplex id - rotating counter */
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
__u64 Suid; /* remote smb uid */
uid_t linux_uid; /* overriding owner of files on the mount */
uid_t cred_uid; /* owner of credentials */
- int capabilities;
+ unsigned int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
TCP names - will ipv6 and sctp addresses fit? */
char *user_name; /* must not be null except during init of sess
which do not negotiate NTLM or POSIX dialects, but instead
negotiate one of the older LANMAN dialects */
#define CIFS_SES_LANMAN 8
+
+static inline bool
+cap_unix(struct cifs_ses *ses)
+{
+ return ses->server->vals->cap_unix & ses->capabilities;
+}
+
/*
* there is one of these for each connection to a resource on a particular
* session
}
/* tell server which Unix caps we support */
- if (tcon->ses->capabilities & CAP_UNIX) {
+ if (cap_unix(tcon->ses)) {
/* reset of caps checks mount to see if unix extensions
disabled for just this mount */
reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
ses->flags = 0;
ses->capabilities = server->capabilities;
if (linuxExtEnabled == 0)
- ses->capabilities &= (~CAP_UNIX);
+ ses->capabilities &= (~server->vals->cap_unix);
cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
server->sec_mode, server->capabilities, server->timeAdj);
goto out;
}
- if (ses->capabilities & CAP_UNIX)
+ if (cap_unix(ses))
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
out:
kfree(vol_info->username);
goto out;
}
- if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
- !tcon->broken_posix_open &&
+ if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_open(full_path, &newinode,
oplock = 0;
if (!tcon->broken_posix_open && tcon->unix_ext &&
- (tcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
/* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, &inode, inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */,
else
oplock = 0;
- if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
+ if (tcon->unix_ext && cap_unix(tcon->ses) &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
/*
* O_CREAT, O_EXCL and O_TRUNC already had their effect on the
* original open. Must mask them off for a reopen.
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- if ((tcon->ses->capabilities & CAP_UNIX) &&
+ if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
return cifs_push_posix_locks(cfile);
netfid = cfile->netfid;
cinode = CIFS_I(file->f_path.dentry->d_inode);
- if ((tcon->ses->capabilities & CAP_UNIX) &&
+ if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
posix_lck = true;
unsigned int current_read_size;
unsigned int rsize;
struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *pTcon;
+ struct cifs_tcon *tcon;
unsigned int xid;
char *current_offset;
struct cifsFileInfo *open_file;
return rc;
}
open_file = file->private_data;
- pTcon = tlink_tcon(open_file->tlink);
+ tcon = tlink_tcon(open_file->tlink);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid;
read_size > total_read;
total_read += bytes_read, current_offset += bytes_read) {
current_read_size = min_t(uint, read_size - total_read, rsize);
-
- /* For windows me and 9x we do not want to request more
- than it negotiated since it will refuse the read then */
- if ((pTcon->ses) &&
- !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
+ /*
+ * For windows me and 9x we do not want to request more than it
+ * negotiated since it will refuse the read then.
+ */
+ if ((tcon->ses) && !(tcon->ses->capabilities &
+ tcon->ses->server->vals->cap_large_files)) {
current_read_size = min_t(uint, current_read_size,
CIFSMaxBufSize);
}
}
io_parms.netfid = open_file->netfid;
io_parms.pid = pid;
- io_parms.tcon = pTcon;
+ io_parms.tcon = tcon;
io_parms.offset = *poffset;
io_parms.length = current_read_size;
rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
return rc;
}
} else {
- cifs_stats_bytes_read(pTcon, total_read);
+ cifs_stats_bytes_read(tcon, total_read);
*poffset += bytes_read;
}
}
goto unlink_out;
}
- if ((tcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = CIFSPOSIXDelFile(xid, tcon, full_path,
SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
unsigned int xid;
struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
+ struct cifs_tcon *tcon;
char *full_path = NULL;
struct inode *newinode = NULL;
struct cifs_fattr fattr;
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
- pTcon = tlink_tcon(tlink);
+ tcon = tlink_tcon(tlink);
xid = get_xid();
goto mkdir_out;
}
- if ((pTcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
+ if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
u32 oplock = 0;
FILE_UNIX_BASIC_INFO *pInfo =
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
}
mode &= ~current_umask();
- rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
+ rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
mode, NULL /* netfid */, pInfo, &oplock,
full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
}
mkdir_retry_old:
/* BB add setting the equivalent of mode via CreateX w/ACLs */
- rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
+ rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
cFYI(1, "cifs_mkdir returned 0x%x", rc);
d_drop(direntry);
} else {
mkdir_get_info:
- if (pTcon->unix_ext)
+ if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid);
else
if (inode->i_mode & S_ISGID)
mode |= S_ISGID;
- if (pTcon->unix_ext) {
+ if (tcon->unix_ext) {
struct cifs_unix_set_info_args args = {
.mode = mode,
.ctime = NO_CHANGE_64,
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
}
- CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
+ CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cifsInode = CIFS_I(newinode);
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
pInfo.Attributes = cpu_to_le32(dosattrs);
- tmprc = CIFSSMBSetPathInfo(xid, pTcon,
+ tmprc = CIFSSMBSetPathInfo(xid, tcon,
full_path, &pInfo,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
* but there doesn't seem to be any harm in allowing the client to
* read them.
*/
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
- && !(tcon->ses->capabilities & CAP_UNIX)) {
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
+ !cap_unix(tcon->ses)) {
rc = -EACCES;
goto out;
}
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX))
+ if ((rc != 0) && cap_unix(tcon->ses))
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
cifs_sb->local_nls);
struct cifsFileInfo *cifsFile;
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
struct tcon_link *tlink = NULL;
- struct cifs_tcon *pTcon;
+ struct cifs_tcon *tcon;
if (file->private_data == NULL) {
tlink = cifs_sb_tlink(cifs_sb);
}
file->private_data = cifsFile;
cifsFile->tlink = cifs_get_tlink(tlink);
- pTcon = tlink_tcon(tlink);
+ tcon = tlink_tcon(tlink);
} else {
cifsFile = file->private_data;
- pTcon = tlink_tcon(cifsFile->tlink);
+ tcon = tlink_tcon(cifsFile->tlink);
}
cifsFile->invalidHandle = true;
ffirst_retry:
/* test for Unix extensions */
/* but now check for them on the share/mount not on the SMB session */
-/* if (pTcon->ses->capabilities & CAP_UNIX) { */
- if (pTcon->unix_ext)
+ /* if (cap_unix(tcon->ses) { */
+ if (tcon->unix_ext)
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
- else if ((pTcon->ses->capabilities &
- (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
+ else if ((tcon->ses->capabilities &
+ tcon->ses->server->vals->cap_nt_find) == 0) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
if (backup_cred(cifs_sb))
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
- rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
+ rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb->local_nls,
&cifsFile->netfid, search_flags, &cifsFile->srch_inf,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
.max_header_size = MAX_CIFS_HDR_SIZE,
.read_rsp_size = sizeof(READ_RSP),
.lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
+ .cap_unix = CAP_UNIX,
+ .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
+ .cap_large_files = CAP_LARGE_FILES,
};
.header_size = sizeof(struct smb2_hdr),
.max_header_size = MAX_SMB2_HDR_SIZE,
.lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
};
/* BB Do we need to validate the SecurityMode? */
server->sec_mode = le16_to_cpu(rsp->SecurityMode);
server->capabilities = le32_to_cpu(rsp->Capabilities);
+ /* Internal types */
+ server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
&rsp->hdr);
#define SMB2_GLOBAL_CAP_DFS 0x00000001
#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
+/* Internal types */
+#define SMB2_NT_FIND 0x00100000
+#define SMB2_LARGE_FILES 0x00200000
struct smb2_negotiate_rsp {
struct smb2_hdr hdr;