mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-14 12:49:08 +00:00
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French: "CIFS update including case insensitive file name matching improvements for UTF-8 to Unicode, various small cifs fixes, SMB2/SMB3 leasing improvements, support for following SMB2 symlinks, SMB3 packet signing improvements" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: (25 commits) CIFS: Respect epoch value from create lease context v2 CIFS: Add create lease v2 context for SMB3 CIFS: Move parsing lease buffer to ops struct CIFS: Move creating lease buffer to ops struct CIFS: Store lease state itself rather than a mapped oplock value CIFS: Replace clientCanCache* bools with an integer [CIFS] quiet sparse compile warning cifs: Start using per session key for smb2/3 for signature generation cifs: Add a variable specific to NTLMSSP for key exchange. cifs: Process post session setup code in respective dialect functions. CIFS: convert to use le32_add_cpu() CIFS: Fix missing lease break CIFS: Fix a memory leak when a lease break comes cifs: add winucase_convert.pl to Documentation/ directory cifs: convert case-insensitive dentry ops to use new case conversion routines cifs: add new case-insensitive conversion routines that are based on wchar_t's [CIFS] Add Scott to list of cifs contributors cifs: Move and expand MAX_SERVER_SIZE definition cifs: Expand max share name length to 256 cifs: Move string length definitions to uapi ...
This commit is contained in:
commit
7b7a2f0a31
@ -39,6 +39,7 @@ Shaggy (Dave Kleikamp) for innumerable small fs suggestions and some good cleanu
|
||||
Gunter Kukkukk (testing and suggestions for support of old servers)
|
||||
Igor Mammedov (DFS support)
|
||||
Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
|
||||
Scott Lovenberg
|
||||
|
||||
Test case and Bug Report contributors
|
||||
-------------------------------------
|
62
Documentation/filesystems/cifs/winucase_convert.pl
Executable file
62
Documentation/filesystems/cifs/winucase_convert.pl
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# winucase_convert.pl -- convert "Windows 8 Upper Case Mapping Table.txt" to
|
||||
# a two-level set of C arrays.
|
||||
#
|
||||
# Copyright 2013: Jeff Layton <jlayton@redhat.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
while(<>) {
|
||||
next if (!/^0x(..)(..)\t0x(....)\t/);
|
||||
$firstchar = hex($1);
|
||||
$secondchar = hex($2);
|
||||
$uppercase = hex($3);
|
||||
|
||||
$top[$firstchar][$secondchar] = $uppercase;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
next if (!$top[$i]);
|
||||
|
||||
printf("static const wchar_t t2_%2.2x[256] = {", $i);
|
||||
for ($j = 0; $j < 256; $j++) {
|
||||
if (($j % 8) == 0) {
|
||||
print "\n\t";
|
||||
} else {
|
||||
print " ";
|
||||
}
|
||||
printf("0x%4.4x,", $top[$i][$j] ? $top[$i][$j] : 0);
|
||||
}
|
||||
print "\n};\n\n";
|
||||
}
|
||||
|
||||
printf("static const wchar_t *const toplevel[256] = {", $i);
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
if (($i % 8) == 0) {
|
||||
print "\n\t";
|
||||
} elsif ($top[$i]) {
|
||||
print " ";
|
||||
} else {
|
||||
print " ";
|
||||
}
|
||||
|
||||
if ($top[$i]) {
|
||||
printf("t2_%2.2x,", $i);
|
||||
} else {
|
||||
print "NULL,";
|
||||
}
|
||||
}
|
||||
print "\n};\n\n";
|
@ -6,7 +6,7 @@ obj-$(CONFIG_CIFS) += cifs.o
|
||||
cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
|
||||
link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \
|
||||
cifs_unicode.o nterr.o xattr.o cifsencrypt.o \
|
||||
readdir.o ioctl.o sess.o export.o smb1ops.o
|
||||
readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o
|
||||
|
||||
cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
|
||||
|
||||
|
@ -91,6 +91,8 @@ extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
#endif
|
||||
|
||||
wchar_t cifs_toupper(wchar_t in);
|
||||
|
||||
/*
|
||||
* UniStrcat: Concatenate the second string to the first
|
||||
*
|
||||
|
@ -255,6 +255,7 @@ cifs_alloc_inode(struct super_block *sb)
|
||||
cifs_inode->server_eof = 0;
|
||||
cifs_inode->uniqueid = 0;
|
||||
cifs_inode->createtime = 0;
|
||||
cifs_inode->epoch = 0;
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
|
||||
#endif
|
||||
@ -357,6 +358,18 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
|
||||
seq_printf(s, "loose");
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_show_nls(struct seq_file *s, struct nls_table *cur)
|
||||
{
|
||||
struct nls_table *def;
|
||||
|
||||
/* Display iocharset= option if it's not default charset */
|
||||
def = load_nls_default();
|
||||
if (def != cur)
|
||||
seq_printf(s, ",iocharset=%s", cur->charset);
|
||||
unload_nls(def);
|
||||
}
|
||||
|
||||
/*
|
||||
* cifs_show_options() is for displaying mount options in /proc/mounts.
|
||||
* Not all settable options are displayed but most of the important
|
||||
@ -418,6 +431,9 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
seq_printf(s, ",file_mode=0%ho,dir_mode=0%ho",
|
||||
cifs_sb->mnt_file_mode,
|
||||
cifs_sb->mnt_dir_mode);
|
||||
|
||||
cifs_show_nls(s, cifs_sb->local_nls);
|
||||
|
||||
if (tcon->seal)
|
||||
seq_printf(s, ",seal");
|
||||
if (tcon->nocase)
|
||||
@ -718,7 +734,7 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
|
||||
written = generic_file_aio_write(iocb, iov, nr_segs, pos);
|
||||
|
||||
if (CIFS_I(inode)->clientCanCacheAll)
|
||||
if (CIFS_CACHE_WRITE(CIFS_I(inode)))
|
||||
return written;
|
||||
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
@ -743,7 +759,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
|
||||
* We need to be sure that all dirty pages are written and the
|
||||
* server has the newest file length.
|
||||
*/
|
||||
if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
|
||||
if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
|
||||
inode->i_mapping->nrpages != 0) {
|
||||
rc = filemap_fdatawait(inode->i_mapping);
|
||||
if (rc) {
|
||||
@ -767,8 +783,10 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
|
||||
|
||||
static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
|
||||
{
|
||||
/* note that this is called by vfs setlease with i_lock held
|
||||
to protect *lease from going away */
|
||||
/*
|
||||
* Note that this is called by vfs setlease with i_lock held to
|
||||
* protect *lease from going away.
|
||||
*/
|
||||
struct inode *inode = file_inode(file);
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
|
||||
@ -776,20 +794,19 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
|
||||
return -EINVAL;
|
||||
|
||||
/* check if file is oplocked */
|
||||
if (((arg == F_RDLCK) &&
|
||||
(CIFS_I(inode)->clientCanCacheRead)) ||
|
||||
((arg == F_WRLCK) &&
|
||||
(CIFS_I(inode)->clientCanCacheAll)))
|
||||
if (((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
|
||||
((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode))))
|
||||
return generic_setlease(file, arg, lease);
|
||||
else if (tlink_tcon(cfile->tlink)->local_lease &&
|
||||
!CIFS_I(inode)->clientCanCacheRead)
|
||||
/* If the server claims to support oplock on this
|
||||
file, then we still need to check oplock even
|
||||
if the local_lease mount option is set, but there
|
||||
are servers which do not support oplock for which
|
||||
this mount option may be useful if the user
|
||||
knows that the file won't be changed on the server
|
||||
by anyone else */
|
||||
!CIFS_CACHE_READ(CIFS_I(inode)))
|
||||
/*
|
||||
* If the server claims to support oplock on this file, then we
|
||||
* still need to check oplock even if the local_lease mount
|
||||
* option is set, but there are servers which do not support
|
||||
* oplock for which this mount option may be useful if the user
|
||||
* knows that the file won't be changed on the server by anyone
|
||||
* else.
|
||||
*/
|
||||
return generic_setlease(file, arg, lease);
|
||||
else
|
||||
return -EAGAIN;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "cifsacl.h"
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <uapi/linux/cifs/cifs_mount.h>
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
#include "smb2pdu.h"
|
||||
#endif
|
||||
@ -41,12 +42,7 @@
|
||||
#define MAX_SES_INFO 2
|
||||
#define MAX_TCON_INFO 4
|
||||
|
||||
#define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
|
||||
#define MAX_SERVER_SIZE 15
|
||||
#define MAX_SHARE_SIZE 80
|
||||
#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */
|
||||
#define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */
|
||||
#define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */
|
||||
#define MAX_TREE_SIZE (2 + CIFS_NI_MAXHOST + 1 + CIFS_MAX_SHARE_LEN + 1)
|
||||
|
||||
#define CIFS_MIN_RCV_POOL 4
|
||||
|
||||
@ -135,6 +131,7 @@ struct cifs_secmech {
|
||||
|
||||
/* per smb session structure/fields */
|
||||
struct ntlmssp_auth {
|
||||
bool sesskey_per_smbsess; /* whether session key is per smb session */
|
||||
__u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */
|
||||
__u32 server_flags; /* sent by server in type 2 ntlmssp exchange */
|
||||
unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */
|
||||
@ -308,6 +305,9 @@ struct smb_version_operations {
|
||||
int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
|
||||
const char *, const char *,
|
||||
struct cifs_sb_info *);
|
||||
/* query symlink target */
|
||||
int (*query_symlink)(const unsigned int, struct cifs_tcon *,
|
||||
const char *, char **, struct cifs_sb_info *);
|
||||
/* open a file for non-posix mounts */
|
||||
int (*open)(const unsigned int, struct cifs_open_parms *,
|
||||
__u32 *, FILE_ALL_INFO *);
|
||||
@ -361,18 +361,24 @@ struct smb_version_operations {
|
||||
/* push brlocks from the cache to the server */
|
||||
int (*push_mand_locks)(struct cifsFileInfo *);
|
||||
/* get lease key of the inode */
|
||||
void (*get_lease_key)(struct inode *, struct cifs_fid *fid);
|
||||
void (*get_lease_key)(struct inode *, struct cifs_fid *);
|
||||
/* set lease key of the inode */
|
||||
void (*set_lease_key)(struct inode *, struct cifs_fid *fid);
|
||||
void (*set_lease_key)(struct inode *, struct cifs_fid *);
|
||||
/* generate new lease key */
|
||||
void (*new_lease_key)(struct cifs_fid *fid);
|
||||
/* The next two functions will need to be changed to per smb session */
|
||||
void (*generate_signingkey)(struct TCP_Server_Info *server);
|
||||
int (*calc_signature)(struct smb_rqst *rqst,
|
||||
struct TCP_Server_Info *server);
|
||||
int (*query_mf_symlink)(const unsigned char *path, char *pbuf,
|
||||
unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
|
||||
unsigned int xid);
|
||||
void (*new_lease_key)(struct cifs_fid *);
|
||||
int (*generate_signingkey)(struct cifs_ses *);
|
||||
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
|
||||
int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *,
|
||||
struct cifs_sb_info *, unsigned int);
|
||||
/* if we can do cache read operations */
|
||||
bool (*is_read_op)(__u32);
|
||||
/* set oplock level for the inode */
|
||||
void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int,
|
||||
bool *);
|
||||
/* create lease context buffer for CREATE request */
|
||||
char * (*create_lease_buf)(u8 *, u8);
|
||||
/* parse lease context buffer and return oplock/epoch info */
|
||||
__u8 (*parse_lease_buf)(void *, unsigned int *);
|
||||
};
|
||||
|
||||
struct smb_version_values {
|
||||
@ -390,9 +396,9 @@ struct smb_version_values {
|
||||
unsigned int cap_unix;
|
||||
unsigned int cap_nt_find;
|
||||
unsigned int cap_large_files;
|
||||
unsigned int oplock_read;
|
||||
__u16 signing_enabled;
|
||||
__u16 signing_required;
|
||||
size_t create_lease_size;
|
||||
};
|
||||
|
||||
#define HEADER_SIZE(server) (server->vals->header_size)
|
||||
@ -548,7 +554,6 @@ struct TCP_Server_Info {
|
||||
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 */
|
||||
char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
|
||||
/* 16th byte of RFC1001 workstation name is always null */
|
||||
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
|
||||
__u32 sequence_number; /* for signing, protected by srv_mutex */
|
||||
@ -731,6 +736,7 @@ struct cifs_ses {
|
||||
bool need_reconnect:1; /* connection reset, uid now invalid */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
__u16 session_flags;
|
||||
char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
};
|
||||
|
||||
@ -935,6 +941,8 @@ struct cifs_fid {
|
||||
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
|
||||
#endif
|
||||
struct cifs_pending_open *pending_open;
|
||||
unsigned int epoch;
|
||||
bool purge_cache;
|
||||
};
|
||||
|
||||
struct cifs_fid_locks {
|
||||
@ -1032,6 +1040,17 @@ cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
|
||||
struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
|
||||
void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
|
||||
|
||||
#define CIFS_CACHE_READ_FLG 1
|
||||
#define CIFS_CACHE_HANDLE_FLG 2
|
||||
#define CIFS_CACHE_RH_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_HANDLE_FLG)
|
||||
#define CIFS_CACHE_WRITE_FLG 4
|
||||
#define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)
|
||||
#define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)
|
||||
|
||||
#define CIFS_CACHE_READ(cinode) (cinode->oplock & CIFS_CACHE_READ_FLG)
|
||||
#define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG)
|
||||
#define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG)
|
||||
|
||||
/*
|
||||
* One of these for each file inode
|
||||
*/
|
||||
@ -1043,8 +1062,8 @@ struct cifsInodeInfo {
|
||||
/* BB add in lists for dirty pages i.e. write caching info for oplock */
|
||||
struct list_head openFileList;
|
||||
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
|
||||
bool clientCanCacheRead; /* read oplock */
|
||||
bool clientCanCacheAll; /* read and writebehind oplock */
|
||||
unsigned int oplock; /* oplock/lease level we have */
|
||||
unsigned int epoch; /* used to track lease state changes */
|
||||
bool delete_pending; /* DELETE_ON_CLOSE is set */
|
||||
bool invalid_mapping; /* pagecache is invalid */
|
||||
unsigned long time; /* jiffies of last update of inode */
|
||||
@ -1502,7 +1521,7 @@ extern mempool_t *cifs_mid_poolp;
|
||||
extern struct smb_version_operations smb1_operations;
|
||||
extern struct smb_version_values smb1_values;
|
||||
#define SMB20_VERSION_STRING "2.0"
|
||||
/*extern struct smb_version_operations smb20_operations; */ /* not needed yet */
|
||||
extern struct smb_version_operations smb20_operations;
|
||||
extern struct smb_version_values smb20_values;
|
||||
#define SMB21_VERSION_STRING "2.1"
|
||||
extern struct smb_version_operations smb21_operations;
|
||||
|
@ -1495,11 +1495,12 @@ struct reparse_data {
|
||||
__u32 ReparseTag;
|
||||
__u16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__u16 AltNameOffset;
|
||||
__u16 AltNameLen;
|
||||
__u16 TargetNameOffset;
|
||||
__u16 TargetNameLen;
|
||||
char LinkNamesBuf[1];
|
||||
__u16 SubstituteNameOffset;
|
||||
__u16 SubstituteNameLength;
|
||||
__u16 PrintNameOffset;
|
||||
__u16 PrintNameLength;
|
||||
__u32 Flags;
|
||||
char PathBuffer[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cifs_quota_data {
|
||||
|
@ -357,13 +357,9 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName, char **syminfo,
|
||||
const struct nls_table *nls_codepage);
|
||||
#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
|
||||
extern int CIFSSMBQueryReparseLinkInfo(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
char *symlinkinfo, const int buflen, __u16 fid,
|
||||
const struct nls_table *nls_codepage);
|
||||
#endif /* temporarily unused until cifs_symlink fixed */
|
||||
extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u16 fid, char **symlinkinfo,
|
||||
const struct nls_table *nls_codepage);
|
||||
extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fileName, const int disposition,
|
||||
const int access_flags, const int omode,
|
||||
@ -435,7 +431,7 @@ extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
|
||||
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
|
||||
extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
|
||||
extern int calc_seckey(struct cifs_ses *);
|
||||
extern void generate_smb3signingkey(struct TCP_Server_Info *);
|
||||
extern int generate_smb3signingkey(struct cifs_ses *);
|
||||
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
extern int calc_lanman_hash(const char *password, const char *cryptkey,
|
||||
|
@ -3067,7 +3067,6 @@ querySymLinkRetry:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
|
||||
/*
|
||||
* Recent Windows versions now create symlinks more frequently
|
||||
* and they use the "reparse point" mechanism below. We can of course
|
||||
@ -3079,18 +3078,22 @@ querySymLinkRetry:
|
||||
* it is not compiled in by default until callers fixed up and more tested.
|
||||
*/
|
||||
int
|
||||
CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
char *symlinkinfo, const int buflen, __u16 fid,
|
||||
const struct nls_table *nls_codepage)
|
||||
CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u16 fid, char **symlinkinfo,
|
||||
const struct nls_table *nls_codepage)
|
||||
{
|
||||
int rc = 0;
|
||||
int bytes_returned;
|
||||
struct smb_com_transaction_ioctl_req *pSMB;
|
||||
struct smb_com_transaction_ioctl_rsp *pSMBr;
|
||||
bool is_unicode;
|
||||
unsigned int sub_len;
|
||||
char *sub_start;
|
||||
struct reparse_data *reparse_buf;
|
||||
__u32 data_offset, data_count;
|
||||
char *end_of_smb;
|
||||
|
||||
cifs_dbg(FYI, "In Windows reparse style QueryLink for path %s\n",
|
||||
searchName);
|
||||
cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
|
||||
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
|
||||
(void **) &pSMBr);
|
||||
if (rc)
|
||||
@ -3119,66 +3122,55 @@ CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
|
||||
} else { /* decode response */
|
||||
__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||
__u32 data_count = le32_to_cpu(pSMBr->DataCount);
|
||||
if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
|
||||
/* BB also check enough total bytes returned */
|
||||
rc = -EIO; /* bad smb */
|
||||
goto qreparse_out;
|
||||
}
|
||||
if (data_count && (data_count < 2048)) {
|
||||
char *end_of_smb = 2 /* sizeof byte count */ +
|
||||
get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
|
||||
|
||||
struct reparse_data *reparse_buf =
|
||||
(struct reparse_data *)
|
||||
((char *)&pSMBr->hdr.Protocol
|
||||
+ data_offset);
|
||||
if ((char *)reparse_buf >= end_of_smb) {
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
if ((reparse_buf->LinkNamesBuf +
|
||||
reparse_buf->TargetNameOffset +
|
||||
reparse_buf->TargetNameLen) > end_of_smb) {
|
||||
cifs_dbg(FYI, "reparse buf beyond SMB\n");
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
|
||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
cifs_from_ucs2(symlinkinfo, (__le16 *)
|
||||
(reparse_buf->LinkNamesBuf +
|
||||
reparse_buf->TargetNameOffset),
|
||||
buflen,
|
||||
reparse_buf->TargetNameLen,
|
||||
nls_codepage, 0);
|
||||
} else { /* ASCII names */
|
||||
strncpy(symlinkinfo,
|
||||
reparse_buf->LinkNamesBuf +
|
||||
reparse_buf->TargetNameOffset,
|
||||
min_t(const int, buflen,
|
||||
reparse_buf->TargetNameLen));
|
||||
}
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
|
||||
}
|
||||
symlinkinfo[buflen] = 0; /* just in case so the caller
|
||||
does not go off the end of the buffer */
|
||||
cifs_dbg(FYI, "readlink result - %s\n", symlinkinfo);
|
||||
goto qreparse_out;
|
||||
}
|
||||
|
||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||
data_count = le32_to_cpu(pSMBr->DataCount);
|
||||
if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
|
||||
/* BB also check enough total bytes returned */
|
||||
rc = -EIO; /* bad smb */
|
||||
goto qreparse_out;
|
||||
}
|
||||
if (!data_count || (data_count > 2048)) {
|
||||
rc = -EIO;
|
||||
cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
|
||||
goto qreparse_out;
|
||||
}
|
||||
end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
|
||||
reparse_buf = (struct reparse_data *)
|
||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
||||
if ((char *)reparse_buf >= end_of_smb) {
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
|
||||
reparse_buf->PrintNameLength) > end_of_smb) {
|
||||
cifs_dbg(FYI, "reparse buf beyond SMB\n");
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
|
||||
sub_len = reparse_buf->SubstituteNameLength;
|
||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
|
||||
is_unicode = true;
|
||||
else
|
||||
is_unicode = false;
|
||||
|
||||
/* BB FIXME investigate remapping reserved chars here */
|
||||
*symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
|
||||
nls_codepage);
|
||||
if (!*symlinkinfo)
|
||||
rc = -ENOMEM;
|
||||
qreparse_out:
|
||||
cifs_buf_release(pSMB);
|
||||
|
||||
/* Note: On -EAGAIN error only caller can retry on handle based calls
|
||||
since file handle passed in no longer valid */
|
||||
|
||||
/*
|
||||
* Note: On -EAGAIN error only caller can retry on handle based calls
|
||||
* since file handle passed in no longer valid.
|
||||
*/
|
||||
return rc;
|
||||
}
|
||||
#endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
|
||||
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
|
||||
|
@ -379,6 +379,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
try_to_freeze();
|
||||
|
||||
/* we should try only the port we connected to before */
|
||||
mutex_lock(&server->srv_mutex);
|
||||
rc = generic_ip_connect(server);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "reconnect error %d\n", rc);
|
||||
@ -390,6 +391,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
server->tcpStatus = CifsNeedNegotiate;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
}
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
} while (server->tcpStatus == CifsNeedReconnect);
|
||||
|
||||
return rc;
|
||||
@ -1114,7 +1116,7 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
|
||||
break;
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
case Smb_20:
|
||||
vol->ops = &smb21_operations; /* currently identical with 2.1 */
|
||||
vol->ops = &smb20_operations;
|
||||
vol->vals = &smb20_values;
|
||||
break;
|
||||
case Smb_21:
|
||||
@ -1575,8 +1577,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
|
||||
if (strnlen(string, MAX_USERNAME_SIZE) >
|
||||
MAX_USERNAME_SIZE) {
|
||||
if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
|
||||
CIFS_MAX_USERNAME_LEN) {
|
||||
printk(KERN_WARNING "CIFS: username too long\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
@ -2221,13 +2223,13 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
|
||||
/* anything else takes username/password */
|
||||
if (strncmp(ses->user_name,
|
||||
vol->username ? vol->username : "",
|
||||
MAX_USERNAME_SIZE))
|
||||
CIFS_MAX_USERNAME_LEN))
|
||||
return 0;
|
||||
if (strlen(vol->username) != 0 &&
|
||||
ses->password != NULL &&
|
||||
strncmp(ses->password,
|
||||
vol->password ? vol->password : "",
|
||||
MAX_PASSWORD_SIZE))
|
||||
CIFS_MAX_PASSWORD_LEN))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -2352,7 +2354,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
|
||||
}
|
||||
|
||||
len = delim - payload;
|
||||
if (len > MAX_USERNAME_SIZE || len <= 0) {
|
||||
if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
|
||||
cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
|
||||
len);
|
||||
rc = -EINVAL;
|
||||
@ -2369,7 +2371,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
|
||||
cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
|
||||
|
||||
len = key->datalen - (len + 1);
|
||||
if (len > MAX_PASSWORD_SIZE || len <= 0) {
|
||||
if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
|
||||
cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
|
||||
rc = -EINVAL;
|
||||
kfree(vol->username);
|
||||
@ -3826,33 +3828,8 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (server->ops->sess_setup)
|
||||
rc = server->ops->sess_setup(xid, ses, nls_info);
|
||||
|
||||
if (rc) {
|
||||
if (rc)
|
||||
cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
|
||||
} else {
|
||||
mutex_lock(&server->srv_mutex);
|
||||
if (!server->session_estab) {
|
||||
server->session_key.response = ses->auth_key.response;
|
||||
server->session_key.len = ses->auth_key.len;
|
||||
server->sequence_number = 0x2;
|
||||
server->session_estab = true;
|
||||
ses->auth_key.response = NULL;
|
||||
if (server->ops->generate_signingkey)
|
||||
server->ops->generate_signingkey(server);
|
||||
}
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
|
||||
cifs_dbg(FYI, "CIFS Session Established successfully\n");
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
ses->status = CifsGood;
|
||||
ses->need_reconnect = false;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
}
|
||||
|
||||
kfree(ses->auth_key.response);
|
||||
ses->auth_key.response = NULL;
|
||||
ses->auth_key.len = 0;
|
||||
kfree(ses->ntlmssp);
|
||||
ses->ntlmssp = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifs_fs_sb.h"
|
||||
#include "cifs_unicode.h"
|
||||
|
||||
static void
|
||||
renew_parental_timestamps(struct dentry *direntry)
|
||||
@ -834,12 +835,17 @@ static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
|
||||
{
|
||||
struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
|
||||
unsigned long hash;
|
||||
int i;
|
||||
wchar_t c;
|
||||
int i, charlen;
|
||||
|
||||
hash = init_name_hash();
|
||||
for (i = 0; i < q->len; i++)
|
||||
hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
|
||||
hash);
|
||||
for (i = 0; i < q->len; i += charlen) {
|
||||
charlen = codepage->char2uni(&q->name[i], q->len - i, &c);
|
||||
/* error out if we can't convert the character */
|
||||
if (unlikely(charlen < 0))
|
||||
return charlen;
|
||||
hash = partial_name_hash(cifs_toupper(c), hash);
|
||||
}
|
||||
q->hash = end_name_hash(hash);
|
||||
|
||||
return 0;
|
||||
@ -849,11 +855,47 @@ static int cifs_ci_compare(const struct dentry *parent, const struct dentry *den
|
||||
unsigned int len, const char *str, const struct qstr *name)
|
||||
{
|
||||
struct nls_table *codepage = CIFS_SB(parent->d_sb)->local_nls;
|
||||
wchar_t c1, c2;
|
||||
int i, l1, l2;
|
||||
|
||||
if ((name->len == len) &&
|
||||
(nls_strnicmp(codepage, name->name, str, len) == 0))
|
||||
return 0;
|
||||
return 1;
|
||||
/*
|
||||
* We make the assumption here that uppercase characters in the local
|
||||
* codepage are always the same length as their lowercase counterparts.
|
||||
*
|
||||
* If that's ever not the case, then this will fail to match it.
|
||||
*/
|
||||
if (name->len != len)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < len; i += l1) {
|
||||
/* Convert characters in both strings to UTF-16. */
|
||||
l1 = codepage->char2uni(&str[i], len - i, &c1);
|
||||
l2 = codepage->char2uni(&name->name[i], name->len - i, &c2);
|
||||
|
||||
/*
|
||||
* If we can't convert either character, just declare it to
|
||||
* be 1 byte long and compare the original byte.
|
||||
*/
|
||||
if (unlikely(l1 < 0 && l2 < 0)) {
|
||||
if (str[i] != name->name[i])
|
||||
return 1;
|
||||
l1 = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here, we again ass|u|me that upper/lowercase versions of
|
||||
* a character are the same length in the local NLS.
|
||||
*/
|
||||
if (l1 != l2)
|
||||
return 1;
|
||||
|
||||
/* Now compare uppercase versions of these characters */
|
||||
if (cifs_toupper(c1) != cifs_toupper(c2))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dentry_operations cifs_ci_dentry_ops = {
|
||||
|
@ -313,8 +313,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
|
||||
* If the server returned a read oplock and we have mandatory brlocks,
|
||||
* set oplock level to None.
|
||||
*/
|
||||
if (oplock == server->vals->oplock_read &&
|
||||
cifs_has_mand_locks(cinode)) {
|
||||
if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
|
||||
cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
|
||||
oplock = 0;
|
||||
}
|
||||
@ -324,6 +323,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
|
||||
oplock = fid->pending_open->oplock;
|
||||
list_del(&fid->pending_open->olist);
|
||||
|
||||
fid->purge_cache = false;
|
||||
server->ops->set_fid(cfile, fid, oplock);
|
||||
|
||||
list_add(&cfile->tlist, &tcon->openFileList);
|
||||
@ -334,6 +334,9 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
|
||||
list_add_tail(&cfile->flist, &cinode->openFileList);
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
|
||||
if (fid->purge_cache)
|
||||
cifs_invalidate_mapping(inode);
|
||||
|
||||
file->private_data = cfile;
|
||||
return cfile;
|
||||
}
|
||||
@ -1524,12 +1527,12 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
|
||||
* read won't conflict with non-overlapted locks due to
|
||||
* pagereading.
|
||||
*/
|
||||
if (!CIFS_I(inode)->clientCanCacheAll &&
|
||||
CIFS_I(inode)->clientCanCacheRead) {
|
||||
if (!CIFS_CACHE_WRITE(CIFS_I(inode)) &&
|
||||
CIFS_CACHE_READ(CIFS_I(inode))) {
|
||||
cifs_invalidate_mapping(inode);
|
||||
cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
|
||||
inode);
|
||||
CIFS_I(inode)->clientCanCacheRead = false;
|
||||
CIFS_I(inode)->oplock = 0;
|
||||
}
|
||||
|
||||
rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
|
||||
@ -2213,7 +2216,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
|
||||
cifs_dbg(FYI, "Sync file - name: %s datasync: 0x%x\n",
|
||||
file->f_path.dentry->d_name.name, datasync);
|
||||
|
||||
if (!CIFS_I(inode)->clientCanCacheRead) {
|
||||
if (!CIFS_CACHE_READ(CIFS_I(inode))) {
|
||||
rc = cifs_invalidate_mapping(inode);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
|
||||
@ -2577,7 +2580,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
ssize_t written;
|
||||
|
||||
if (cinode->clientCanCacheAll) {
|
||||
if (CIFS_CACHE_WRITE(cinode)) {
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
|
||||
&& ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
@ -2591,7 +2594,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
|
||||
* these pages but not on the region from pos to ppos+len-1.
|
||||
*/
|
||||
written = cifs_user_writev(iocb, iov, nr_segs, pos);
|
||||
if (written > 0 && cinode->clientCanCacheRead) {
|
||||
if (written > 0 && CIFS_CACHE_READ(cinode)) {
|
||||
/*
|
||||
* Windows 7 server can delay breaking level2 oplock if a write
|
||||
* request comes - break it on the client to prevent reading
|
||||
@ -2600,7 +2603,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
|
||||
cifs_invalidate_mapping(inode);
|
||||
cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n",
|
||||
inode);
|
||||
cinode->clientCanCacheRead = false;
|
||||
cinode->oplock = 0;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
@ -2957,7 +2960,7 @@ cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
|
||||
* on pages affected by this read but not on the region from pos to
|
||||
* pos+len-1.
|
||||
*/
|
||||
if (!cinode->clientCanCacheRead)
|
||||
if (!CIFS_CACHE_READ(cinode))
|
||||
return cifs_user_readv(iocb, iov, nr_segs, pos);
|
||||
|
||||
if (cap_unix(tcon->ses) &&
|
||||
@ -3093,7 +3096,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
if (!CIFS_I(inode)->clientCanCacheRead) {
|
||||
if (!CIFS_CACHE_READ(CIFS_I(inode))) {
|
||||
rc = cifs_invalidate_mapping(inode);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -3526,7 +3529,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
|
||||
* is, when the page lies beyond the EOF, or straddles the EOF
|
||||
* and the write will cover all of the existing data.
|
||||
*/
|
||||
if (CIFS_I(mapping->host)->clientCanCacheRead) {
|
||||
if (CIFS_CACHE_READ(CIFS_I(mapping->host))) {
|
||||
i_size = i_size_read(mapping->host);
|
||||
if (page_start >= i_size ||
|
||||
(offset == 0 && (pos + len) >= i_size)) {
|
||||
@ -3609,20 +3612,20 @@ void cifs_oplock_break(struct work_struct *work)
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
int rc = 0;
|
||||
|
||||
if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead &&
|
||||
if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
|
||||
cifs_has_mand_locks(cinode)) {
|
||||
cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
|
||||
inode);
|
||||
cinode->clientCanCacheRead = false;
|
||||
cinode->oplock = 0;
|
||||
}
|
||||
|
||||
if (inode && S_ISREG(inode->i_mode)) {
|
||||
if (cinode->clientCanCacheRead)
|
||||
if (CIFS_CACHE_READ(cinode))
|
||||
break_lease(inode, O_RDONLY);
|
||||
else
|
||||
break_lease(inode, O_WRONLY);
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if (cinode->clientCanCacheRead == 0) {
|
||||
if (!CIFS_CACHE_READ(cinode)) {
|
||||
rc = filemap_fdatawait(inode->i_mapping);
|
||||
mapping_set_error(inode->i_mapping, rc);
|
||||
cifs_invalidate_mapping(inode);
|
||||
|
@ -101,7 +101,7 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
|
||||
}
|
||||
|
||||
/* don't bother with revalidation if we have an oplock */
|
||||
if (cifs_i->clientCanCacheRead) {
|
||||
if (CIFS_CACHE_READ(cifs_i)) {
|
||||
cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
|
||||
__func__, cifs_i->uniqueid);
|
||||
return;
|
||||
@ -549,6 +549,10 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
|
||||
* when Unix extensions are disabled - fake it.
|
||||
*/
|
||||
fattr->cf_nlink = 2;
|
||||
} else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
|
||||
fattr->cf_mode = S_IFLNK;
|
||||
fattr->cf_dtype = DT_LNK;
|
||||
fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
|
||||
} else {
|
||||
fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
|
||||
fattr->cf_dtype = DT_REG;
|
||||
@ -646,7 +650,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||
cifs_dbg(FYI, "Getting info on %s\n", full_path);
|
||||
|
||||
if ((data == NULL) && (*inode != NULL)) {
|
||||
if (CIFS_I(*inode)->clientCanCacheRead) {
|
||||
if (CIFS_CACHE_READ(CIFS_I(*inode))) {
|
||||
cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
|
||||
goto cgii_exit;
|
||||
}
|
||||
@ -1657,7 +1661,7 @@ cifs_inode_needs_reval(struct inode *inode)
|
||||
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
|
||||
if (cifs_i->clientCanCacheRead)
|
||||
if (CIFS_CACHE_READ(cifs_i))
|
||||
return false;
|
||||
|
||||
if (!lookupCacheEnabled)
|
||||
@ -1800,7 +1804,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
* We need to be sure that all dirty pages are written and the server
|
||||
* has actual ctime, mtime and file length.
|
||||
*/
|
||||
if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
|
||||
if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
|
||||
inode->i_mapping->nrpages != 0) {
|
||||
rc = filemap_fdatawait(inode->i_mapping);
|
||||
if (rc) {
|
||||
|
@ -509,6 +509,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
@ -519,25 +520,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||
goto out;
|
||||
}
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
/*
|
||||
* For now, we just handle symlinks with unix extensions enabled.
|
||||
* Eventually we should handle NTFS reparse points, and MacOS
|
||||
* symlink support. For instance...
|
||||
*
|
||||
* rc = CIFSSMBQueryReparseLinkInfo(...)
|
||||
*
|
||||
* For now, just return -EACCES when the server doesn't support posix
|
||||
* extensions. Note that we still allow querying symlinks when posix
|
||||
* extensions are manually disabled. We could disable these as well
|
||||
* 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) &&
|
||||
!cap_unix(tcon->ses)) {
|
||||
rc = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
server = tcon->ses->server;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (!full_path)
|
||||
@ -559,6 +542,9 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||
if ((rc != 0) && cap_unix(tcon->ses))
|
||||
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
|
||||
cifs_sb->local_nls);
|
||||
else if (rc != 0 && server->ops->query_symlink)
|
||||
rc = server->ops->query_symlink(xid, tcon, full_path,
|
||||
&target_path, cifs_sb);
|
||||
|
||||
kfree(full_path);
|
||||
out:
|
||||
|
@ -105,6 +105,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
|
||||
}
|
||||
kfree(buf_to_free->user_name);
|
||||
kfree(buf_to_free->domainName);
|
||||
kfree(buf_to_free->auth_key.response);
|
||||
kfree(buf_to_free);
|
||||
}
|
||||
|
||||
@ -545,19 +546,15 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
|
||||
oplock &= 0xF;
|
||||
|
||||
if (oplock == OPLOCK_EXCLUSIVE) {
|
||||
cinode->clientCanCacheAll = true;
|
||||
cinode->clientCanCacheRead = true;
|
||||
cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG;
|
||||
cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else if (oplock == OPLOCK_READ) {
|
||||
cinode->clientCanCacheAll = false;
|
||||
cinode->clientCanCacheRead = true;
|
||||
cinode->oplock = CIFS_CACHE_READ_FLG;
|
||||
cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else {
|
||||
cinode->clientCanCacheAll = false;
|
||||
cinode->clientCanCacheRead = false;
|
||||
}
|
||||
} else
|
||||
cinode->oplock = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -172,6 +172,9 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
|
||||
if (cifs_dfs_is_possible(cifs_sb) &&
|
||||
(fattr->cf_cifsattrs & ATTR_REPARSE))
|
||||
fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
|
||||
} else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
|
||||
fattr->cf_mode = S_IFLNK;
|
||||
fattr->cf_dtype = DT_LNK;
|
||||
} else {
|
||||
fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
|
||||
fattr->cf_dtype = DT_REG;
|
||||
|
@ -226,7 +226,7 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
|
||||
*(bcc_ptr+1) = 0;
|
||||
} else {
|
||||
bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
|
||||
MAX_USERNAME_SIZE, nls_cp);
|
||||
CIFS_MAX_USERNAME_LEN, nls_cp);
|
||||
}
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* account for null termination */
|
||||
@ -246,8 +246,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
|
||||
/* BB what about null user mounts - check that we do this BB */
|
||||
/* copy user */
|
||||
if (ses->user_name != NULL) {
|
||||
strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
|
||||
bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
|
||||
strncpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
|
||||
bcc_ptr += strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
|
||||
}
|
||||
/* else null user mount */
|
||||
*bcc_ptr = 0;
|
||||
@ -428,7 +428,8 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
|
||||
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
|
||||
if (ses->server->sign) {
|
||||
flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||
if (!ses->server->session_estab)
|
||||
if (!ses->server->session_estab ||
|
||||
ses->ntlmssp->sesskey_per_smbsess)
|
||||
flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
|
||||
}
|
||||
|
||||
@ -466,7 +467,8 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
|
||||
if (ses->server->sign) {
|
||||
flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||
if (!ses->server->session_estab)
|
||||
if (!ses->server->session_estab ||
|
||||
ses->ntlmssp->sesskey_per_smbsess)
|
||||
flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
|
||||
}
|
||||
|
||||
@ -501,7 +503,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||
} else {
|
||||
int len;
|
||||
len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
|
||||
MAX_USERNAME_SIZE, nls_cp);
|
||||
CIFS_MAX_USERNAME_LEN, nls_cp);
|
||||
len *= 2; /* unicode is 2 bytes each */
|
||||
sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
|
||||
sec_blob->DomainName.Length = cpu_to_le16(len);
|
||||
@ -517,7 +519,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||
} else {
|
||||
int len;
|
||||
len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
|
||||
MAX_USERNAME_SIZE, nls_cp);
|
||||
CIFS_MAX_USERNAME_LEN, nls_cp);
|
||||
len *= 2; /* unicode is 2 bytes each */
|
||||
sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
|
||||
sec_blob->UserName.Length = cpu_to_le16(len);
|
||||
@ -629,7 +631,8 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
||||
type = select_sectype(ses->server, ses->sectype);
|
||||
cifs_dbg(FYI, "sess setup type %d\n", type);
|
||||
if (type == Unspecified) {
|
||||
cifs_dbg(VFS, "Unable to select appropriate authentication method!");
|
||||
cifs_dbg(VFS,
|
||||
"Unable to select appropriate authentication method!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -640,6 +643,8 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
||||
ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
|
||||
if (!ses->ntlmssp)
|
||||
return -ENOMEM;
|
||||
ses->ntlmssp->sesskey_per_smbsess = false;
|
||||
|
||||
}
|
||||
|
||||
ssetup_ntlmssp_authenticate:
|
||||
@ -815,8 +820,9 @@ ssetup_ntlmssp_authenticate:
|
||||
ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
|
||||
GFP_KERNEL);
|
||||
if (!ses->auth_key.response) {
|
||||
cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory",
|
||||
msg->sesskey_len);
|
||||
cifs_dbg(VFS,
|
||||
"Kerberos can't allocate (%u bytes) memory",
|
||||
msg->sesskey_len);
|
||||
rc = -ENOMEM;
|
||||
goto ssetup_exit;
|
||||
}
|
||||
@ -1005,5 +1011,37 @@ ssetup_exit:
|
||||
if ((phase == NtLmChallenge) && (rc == 0))
|
||||
goto ssetup_ntlmssp_authenticate;
|
||||
|
||||
if (!rc) {
|
||||
mutex_lock(&ses->server->srv_mutex);
|
||||
if (!ses->server->session_estab) {
|
||||
if (ses->server->sign) {
|
||||
ses->server->session_key.response =
|
||||
kmemdup(ses->auth_key.response,
|
||||
ses->auth_key.len, GFP_KERNEL);
|
||||
if (!ses->server->session_key.response) {
|
||||
rc = -ENOMEM;
|
||||
mutex_unlock(&ses->server->srv_mutex);
|
||||
goto keycp_exit;
|
||||
}
|
||||
ses->server->session_key.len =
|
||||
ses->auth_key.len;
|
||||
}
|
||||
ses->server->sequence_number = 0x2;
|
||||
ses->server->session_estab = true;
|
||||
}
|
||||
mutex_unlock(&ses->server->srv_mutex);
|
||||
|
||||
cifs_dbg(FYI, "CIFS session established successfully\n");
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
ses->status = CifsGood;
|
||||
ses->need_reconnect = false;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
}
|
||||
|
||||
keycp_exit:
|
||||
kfree(ses->auth_key.response);
|
||||
ses->auth_key.response = NULL;
|
||||
kfree(ses->ntlmssp);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -700,7 +700,7 @@ cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
|
||||
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
||||
cfile->fid.netfid = fid->netfid;
|
||||
cifs_set_oplock_level(cinode, oplock);
|
||||
cinode->can_cache_brlcks = cinode->clientCanCacheAll;
|
||||
cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -837,7 +837,7 @@ cifs_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
|
||||
{
|
||||
return CIFSSMBLock(0, tcon, fid->netfid, current->tgid, 0, 0, 0, 0,
|
||||
LOCKING_ANDX_OPLOCK_RELEASE, false,
|
||||
cinode->clientCanCacheRead ? 1 : 0);
|
||||
CIFS_CACHE_READ(cinode) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -881,6 +881,43 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
|
||||
(__u8)type, wait, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *full_path, char **target_path,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
int rc;
|
||||
int oplock = 0;
|
||||
__u16 netfid;
|
||||
|
||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
||||
|
||||
rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
|
||||
FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid,
|
||||
&oplock, NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path,
|
||||
cifs_sb->local_nls);
|
||||
if (rc) {
|
||||
CIFSSMBClose(xid, tcon, netfid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
convert_delimiter(*target_path, '/');
|
||||
CIFSSMBClose(xid, tcon, netfid);
|
||||
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool
|
||||
cifs_is_read_op(__u32 oplock)
|
||||
{
|
||||
return oplock == OPLOCK_READ;
|
||||
}
|
||||
|
||||
struct smb_version_operations smb1_operations = {
|
||||
.send_cancel = send_nt_cancel,
|
||||
.compare_fids = cifs_compare_fids,
|
||||
@ -927,6 +964,7 @@ struct smb_version_operations smb1_operations = {
|
||||
.rename_pending_delete = cifs_rename_pending_delete,
|
||||
.rename = CIFSSMBRename,
|
||||
.create_hardlink = CIFSCreateHardLink,
|
||||
.query_symlink = cifs_query_symlink,
|
||||
.open = cifs_open_file,
|
||||
.set_fid = cifs_set_fid,
|
||||
.close = cifs_close_file,
|
||||
@ -945,6 +983,7 @@ struct smb_version_operations smb1_operations = {
|
||||
.mand_unlock_range = cifs_unlock_range,
|
||||
.push_mand_locks = cifs_push_mandatory_locks,
|
||||
.query_mf_symlink = open_query_close_cifs_symlink,
|
||||
.is_read_op = cifs_is_read_op,
|
||||
};
|
||||
|
||||
struct smb_version_values smb1_values = {
|
||||
@ -960,7 +999,6 @@ struct smb_version_values smb1_values = {
|
||||
.cap_unix = CAP_UNIX,
|
||||
.cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
|
||||
.cap_large_files = CAP_LARGE_FILES,
|
||||
.oplock_read = OPLOCK_READ,
|
||||
.signing_enabled = SECMODE_SIGN_ENABLED,
|
||||
.signing_required = SECMODE_SIGN_REQUIRED,
|
||||
};
|
||||
|
@ -34,29 +34,6 @@
|
||||
#include "fscache.h"
|
||||
#include "smb2proto.h"
|
||||
|
||||
void
|
||||
smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
|
||||
{
|
||||
oplock &= 0xFF;
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
|
||||
return;
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
|
||||
oplock == SMB2_OPLOCK_LEVEL_BATCH) {
|
||||
cinode->clientCanCacheAll = true;
|
||||
cinode->clientCanCacheRead = true;
|
||||
cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else if (oplock == SMB2_OPLOCK_LEVEL_II) {
|
||||
cinode->clientCanCacheAll = false;
|
||||
cinode->clientCanCacheRead = true;
|
||||
cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else {
|
||||
cinode->clientCanCacheAll = false;
|
||||
cinode->clientCanCacheRead = false;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
__u32 *oplock, FILE_ALL_INFO *buf)
|
||||
@ -86,7 +63,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
|
||||
memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
|
||||
|
||||
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data);
|
||||
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
@ -60,7 +60,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
@ -136,7 +136,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
return -ENOMEM;
|
||||
|
||||
rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN, 0, smb2_data,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN,
|
||||
OPEN_REPARSE_POINT, smb2_data,
|
||||
SMB2_OP_QUERY_INFO);
|
||||
if (rc)
|
||||
goto out;
|
||||
@ -191,8 +192,8 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
|
||||
CREATE_DELETE_ON_CLOSE, NULL,
|
||||
SMB2_OP_DELETE);
|
||||
CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
|
||||
NULL, SMB2_OP_DELETE);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -171,6 +171,10 @@ smb2_check_message(char *buf, unsigned int length)
|
||||
if (4 + len != clc_len) {
|
||||
cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
|
||||
clc_len, 4 + len, mid);
|
||||
/* create failed on symlink */
|
||||
if (command == SMB2_CREATE_HE &&
|
||||
hdr->Status == STATUS_STOPPED_ON_SYMLINK)
|
||||
return 0;
|
||||
/* Windows 7 server returns 24 bytes more */
|
||||
if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
|
||||
return 0;
|
||||
@ -376,23 +380,15 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
|
||||
__le32
|
||||
smb2_get_lease_state(struct cifsInodeInfo *cinode)
|
||||
{
|
||||
if (cinode->clientCanCacheAll)
|
||||
return SMB2_LEASE_WRITE_CACHING | SMB2_LEASE_READ_CACHING;
|
||||
else if (cinode->clientCanCacheRead)
|
||||
return SMB2_LEASE_READ_CACHING;
|
||||
return 0;
|
||||
}
|
||||
__le32 lease = 0;
|
||||
|
||||
__u8 smb2_map_lease_to_oplock(__le32 lease_state)
|
||||
{
|
||||
if (lease_state & SMB2_LEASE_WRITE_CACHING) {
|
||||
if (lease_state & SMB2_LEASE_HANDLE_CACHING)
|
||||
return SMB2_OPLOCK_LEVEL_BATCH;
|
||||
else
|
||||
return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
|
||||
} else if (lease_state & SMB2_LEASE_READ_CACHING)
|
||||
return SMB2_OPLOCK_LEVEL_II;
|
||||
return 0;
|
||||
if (CIFS_CACHE_WRITE(cinode))
|
||||
lease |= SMB2_LEASE_WRITE_CACHING;
|
||||
if (CIFS_CACHE_HANDLE(cinode))
|
||||
lease |= SMB2_LEASE_HANDLE_CACHING;
|
||||
if (CIFS_CACHE_READ(cinode))
|
||||
lease |= SMB2_LEASE_READ_CACHING;
|
||||
return lease;
|
||||
}
|
||||
|
||||
struct smb2_lease_break_work {
|
||||
@ -417,19 +413,77 @@ cifs_ses_oplock_break(struct work_struct *work)
|
||||
}
|
||||
|
||||
static bool
|
||||
smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
|
||||
smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
|
||||
struct smb2_lease_break_work *lw)
|
||||
{
|
||||
bool found;
|
||||
__u8 lease_state;
|
||||
struct list_head *tmp;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
struct cifs_pending_open *open;
|
||||
struct cifsInodeInfo *cinode;
|
||||
int ack_req = le32_to_cpu(rsp->Flags &
|
||||
SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
|
||||
|
||||
lease_state = le32_to_cpu(rsp->NewLeaseState);
|
||||
|
||||
list_for_each(tmp, &tcon->openFileList) {
|
||||
cfile = list_entry(tmp, struct cifsFileInfo, tlist);
|
||||
cinode = CIFS_I(cfile->dentry->d_inode);
|
||||
|
||||
if (memcmp(cinode->lease_key, rsp->LeaseKey,
|
||||
SMB2_LEASE_KEY_SIZE))
|
||||
continue;
|
||||
|
||||
cifs_dbg(FYI, "found in the open list\n");
|
||||
cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
|
||||
le32_to_cpu(rsp->NewLeaseState));
|
||||
|
||||
server->ops->set_oplock_level(cinode, lease_state, 0, NULL);
|
||||
|
||||
if (ack_req)
|
||||
cfile->oplock_break_cancelled = false;
|
||||
else
|
||||
cfile->oplock_break_cancelled = true;
|
||||
|
||||
queue_work(cifsiod_wq, &cfile->oplock_break);
|
||||
kfree(lw);
|
||||
return true;
|
||||
}
|
||||
|
||||
found = false;
|
||||
list_for_each_entry(open, &tcon->pending_opens, olist) {
|
||||
if (memcmp(open->lease_key, rsp->LeaseKey,
|
||||
SMB2_LEASE_KEY_SIZE))
|
||||
continue;
|
||||
|
||||
if (!found && ack_req) {
|
||||
found = true;
|
||||
memcpy(lw->lease_key, open->lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
lw->tlink = cifs_get_tlink(open->tlink);
|
||||
queue_work(cifsiod_wq, &lw->lease_break);
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "found in the pending open list\n");
|
||||
cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
|
||||
le32_to_cpu(rsp->NewLeaseState));
|
||||
|
||||
open->oplock = lease_state;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool
|
||||
smb2_is_valid_lease_break(char *buffer)
|
||||
{
|
||||
struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
|
||||
struct list_head *tmp, *tmp1, *tmp2;
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifs_ses *ses;
|
||||
struct cifs_tcon *tcon;
|
||||
struct cifsInodeInfo *cinode;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cifs_pending_open *open;
|
||||
struct smb2_lease_break_work *lw;
|
||||
bool found;
|
||||
int ack_req = le32_to_cpu(rsp->Flags &
|
||||
SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
|
||||
|
||||
lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
|
||||
if (!lw)
|
||||
@ -442,71 +496,26 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
|
||||
|
||||
/* look up tcon based on tid & uid */
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
list_for_each(tmp, &server->smb_ses_list) {
|
||||
ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
|
||||
list_for_each(tmp, &cifs_tcp_ses_list) {
|
||||
server = list_entry(tmp, struct TCP_Server_Info, tcp_ses_list);
|
||||
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
list_for_each(tmp1, &ses->tcon_list) {
|
||||
tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
|
||||
list_for_each(tmp1, &server->smb_ses_list) {
|
||||
ses = list_entry(tmp1, struct cifs_ses, smb_ses_list);
|
||||
|
||||
cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
|
||||
list_for_each(tmp2, &tcon->openFileList) {
|
||||
cfile = list_entry(tmp2, struct cifsFileInfo,
|
||||
tlist);
|
||||
cinode = CIFS_I(cfile->dentry->d_inode);
|
||||
|
||||
if (memcmp(cinode->lease_key, rsp->LeaseKey,
|
||||
SMB2_LEASE_KEY_SIZE))
|
||||
continue;
|
||||
|
||||
cifs_dbg(FYI, "found in the open list\n");
|
||||
cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
|
||||
le32_to_cpu(rsp->NewLeaseState));
|
||||
|
||||
smb2_set_oplock_level(cinode,
|
||||
smb2_map_lease_to_oplock(rsp->NewLeaseState));
|
||||
|
||||
if (ack_req)
|
||||
cfile->oplock_break_cancelled = false;
|
||||
else
|
||||
cfile->oplock_break_cancelled = true;
|
||||
|
||||
queue_work(cifsiod_wq, &cfile->oplock_break);
|
||||
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
found = false;
|
||||
list_for_each_entry(open, &tcon->pending_opens, olist) {
|
||||
if (memcmp(open->lease_key, rsp->LeaseKey,
|
||||
SMB2_LEASE_KEY_SIZE))
|
||||
continue;
|
||||
|
||||
if (!found && ack_req) {
|
||||
found = true;
|
||||
memcpy(lw->lease_key, open->lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
lw->tlink = cifs_get_tlink(open->tlink);
|
||||
queue_work(cifsiod_wq,
|
||||
&lw->lease_break);
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
list_for_each(tmp2, &ses->tcon_list) {
|
||||
tcon = list_entry(tmp2, struct cifs_tcon,
|
||||
tcon_list);
|
||||
cifs_stats_inc(
|
||||
&tcon->stats.cifs_stats.num_oplock_brks);
|
||||
if (smb2_tcon_has_lease(tcon, rsp, lw)) {
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "found in the pending open list\n");
|
||||
cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
|
||||
le32_to_cpu(rsp->NewLeaseState));
|
||||
|
||||
open->oplock =
|
||||
smb2_map_lease_to_oplock(rsp->NewLeaseState);
|
||||
}
|
||||
if (found) {
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return true;
|
||||
}
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
}
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
kfree(lw);
|
||||
@ -532,7 +541,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
|
||||
if (rsp->StructureSize !=
|
||||
smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
|
||||
if (le16_to_cpu(rsp->StructureSize) == 44)
|
||||
return smb2_is_valid_lease_break(buffer, server);
|
||||
return smb2_is_valid_lease_break(buffer);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@ -560,14 +569,15 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
|
||||
cifs_dbg(FYI, "file id match, oplock break\n");
|
||||
cinode = CIFS_I(cfile->dentry->d_inode);
|
||||
|
||||
if (!cinode->clientCanCacheAll &&
|
||||
if (!CIFS_CACHE_WRITE(cinode) &&
|
||||
rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
|
||||
cfile->oplock_break_cancelled = true;
|
||||
else
|
||||
cfile->oplock_break_cancelled = false;
|
||||
|
||||
smb2_set_oplock_level(cinode,
|
||||
rsp->OplockLevel ? SMB2_OPLOCK_LEVEL_II : 0);
|
||||
server->ops->set_oplock_level(cinode,
|
||||
rsp->OplockLevel ? SMB2_OPLOCK_LEVEL_II : 0,
|
||||
0, NULL);
|
||||
|
||||
queue_work(cifsiod_wq, &cfile->oplock_break);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "smb2proto.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifs_unicode.h"
|
||||
#include "smb2status.h"
|
||||
#include "smb2glob.h"
|
||||
|
||||
@ -229,7 +230,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
@ -376,10 +377,13 @@ static void
|
||||
smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
|
||||
{
|
||||
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
||||
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
|
||||
|
||||
cfile->fid.persistent_fid = fid->persistent_fid;
|
||||
cfile->fid.volatile_fid = fid->volatile_fid;
|
||||
smb2_set_oplock_level(cinode, oplock);
|
||||
cinode->can_cache_brlcks = cinode->clientCanCacheAll;
|
||||
server->ops->set_oplock_level(cinode, oplock, fid->epoch,
|
||||
&fid->purge_cache);
|
||||
cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -463,7 +467,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
oparms.fid = fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
kfree(utf16_path);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "open dir failed\n");
|
||||
@ -530,7 +534,7 @@ smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
|
||||
|
||||
return SMB2_oplock_break(0, tcon, fid->persistent_fid,
|
||||
fid->volatile_fid,
|
||||
cinode->clientCanCacheRead ? 1 : 0);
|
||||
CIFS_CACHE_READ(cinode) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -550,7 +554,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL);
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
buf->f_type = SMB2_MAGIC_NUMBER;
|
||||
@ -596,6 +600,315 @@ smb2_new_lease_key(struct cifs_fid *fid)
|
||||
get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *full_path, char **target_path,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
int rc;
|
||||
__le16 *utf16_path;
|
||||
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
||||
struct cifs_open_parms oparms;
|
||||
struct cifs_fid fid;
|
||||
struct smb2_err_rsp *err_buf = NULL;
|
||||
struct smb2_symlink_err_rsp *symlink;
|
||||
unsigned int sub_len, sub_offset;
|
||||
|
||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
||||
|
||||
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
|
||||
if (!utf16_path)
|
||||
return -ENOMEM;
|
||||
|
||||
oparms.tcon = tcon;
|
||||
oparms.desired_access = FILE_READ_ATTRIBUTES;
|
||||
oparms.disposition = FILE_OPEN;
|
||||
oparms.create_options = 0;
|
||||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
|
||||
|
||||
if (!rc || !err_buf) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
/* open must fail on symlink - reset rc */
|
||||
rc = 0;
|
||||
symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
|
||||
sub_len = le16_to_cpu(symlink->SubstituteNameLength);
|
||||
sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
|
||||
*target_path = cifs_strndup_from_utf16(
|
||||
(char *)symlink->PathBuffer + sub_offset,
|
||||
sub_len, true, cifs_sb->local_nls);
|
||||
if (!(*target_path)) {
|
||||
kfree(utf16_path);
|
||||
return -ENOMEM;
|
||||
}
|
||||
convert_delimiter(*target_path, '/');
|
||||
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
unsigned int epoch, bool *purge_cache)
|
||||
{
|
||||
oplock &= 0xFF;
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
|
||||
return;
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
|
||||
cinode->oplock = CIFS_CACHE_RHW_FLG;
|
||||
cifs_dbg(FYI, "Batch Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
|
||||
cinode->oplock = CIFS_CACHE_RW_FLG;
|
||||
cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else if (oplock == SMB2_OPLOCK_LEVEL_II) {
|
||||
cinode->oplock = CIFS_CACHE_READ_FLG;
|
||||
cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
|
||||
&cinode->vfs_inode);
|
||||
} else
|
||||
cinode->oplock = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
unsigned int epoch, bool *purge_cache)
|
||||
{
|
||||
char message[5] = {0};
|
||||
|
||||
oplock &= 0xFF;
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
|
||||
return;
|
||||
|
||||
cinode->oplock = 0;
|
||||
if (oplock & SMB2_LEASE_READ_CACHING_HE) {
|
||||
cinode->oplock |= CIFS_CACHE_READ_FLG;
|
||||
strcat(message, "R");
|
||||
}
|
||||
if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) {
|
||||
cinode->oplock |= CIFS_CACHE_HANDLE_FLG;
|
||||
strcat(message, "H");
|
||||
}
|
||||
if (oplock & SMB2_LEASE_WRITE_CACHING_HE) {
|
||||
cinode->oplock |= CIFS_CACHE_WRITE_FLG;
|
||||
strcat(message, "W");
|
||||
}
|
||||
if (!cinode->oplock)
|
||||
strcat(message, "None");
|
||||
cifs_dbg(FYI, "%s Lease granted on inode %p\n", message,
|
||||
&cinode->vfs_inode);
|
||||
}
|
||||
|
||||
static void
|
||||
smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
|
||||
unsigned int epoch, bool *purge_cache)
|
||||
{
|
||||
unsigned int old_oplock = cinode->oplock;
|
||||
|
||||
smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
|
||||
|
||||
if (purge_cache) {
|
||||
*purge_cache = false;
|
||||
if (old_oplock == CIFS_CACHE_READ_FLG) {
|
||||
if (cinode->oplock == CIFS_CACHE_READ_FLG &&
|
||||
(epoch - cinode->epoch > 0))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == CIFS_CACHE_RH_FLG &&
|
||||
(epoch - cinode->epoch > 1))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
|
||||
(epoch - cinode->epoch > 1))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == 0 &&
|
||||
(epoch - cinode->epoch > 0))
|
||||
*purge_cache = true;
|
||||
} else if (old_oplock == CIFS_CACHE_RH_FLG) {
|
||||
if (cinode->oplock == CIFS_CACHE_RH_FLG &&
|
||||
(epoch - cinode->epoch > 0))
|
||||
*purge_cache = true;
|
||||
else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
|
||||
(epoch - cinode->epoch > 1))
|
||||
*purge_cache = true;
|
||||
}
|
||||
cinode->epoch = epoch;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
smb2_is_read_op(__u32 oplock)
|
||||
{
|
||||
return oplock == SMB2_OPLOCK_LEVEL_II;
|
||||
}
|
||||
|
||||
static bool
|
||||
smb21_is_read_op(__u32 oplock)
|
||||
{
|
||||
return (oplock & SMB2_LEASE_READ_CACHING_HE) &&
|
||||
!(oplock & SMB2_LEASE_WRITE_CACHING_HE);
|
||||
}
|
||||
|
||||
static __le32
|
||||
map_oplock_to_lease(u8 oplock)
|
||||
{
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
|
||||
return SMB2_LEASE_WRITE_CACHING | SMB2_LEASE_READ_CACHING;
|
||||
else if (oplock == SMB2_OPLOCK_LEVEL_II)
|
||||
return SMB2_LEASE_READ_CACHING;
|
||||
else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
|
||||
return SMB2_LEASE_HANDLE_CACHING | SMB2_LEASE_READ_CACHING |
|
||||
SMB2_LEASE_WRITE_CACHING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
smb2_create_lease_buf(u8 *lease_key, u8 oplock)
|
||||
{
|
||||
struct create_lease *buf;
|
||||
|
||||
buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
|
||||
buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
|
||||
buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
|
||||
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease, lcontext));
|
||||
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
|
||||
buf->ccontext.NameOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease, Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
buf->Name[0] = 'R';
|
||||
buf->Name[1] = 'q';
|
||||
buf->Name[2] = 'L';
|
||||
buf->Name[3] = 's';
|
||||
return (char *)buf;
|
||||
}
|
||||
|
||||
static char *
|
||||
smb3_create_lease_buf(u8 *lease_key, u8 oplock)
|
||||
{
|
||||
struct create_lease_v2 *buf;
|
||||
|
||||
buf = kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
|
||||
buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
|
||||
buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
|
||||
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease_v2, lcontext));
|
||||
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
|
||||
buf->ccontext.NameOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease_v2, Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
buf->Name[0] = 'R';
|
||||
buf->Name[1] = 'q';
|
||||
buf->Name[2] = 'L';
|
||||
buf->Name[3] = 's';
|
||||
return (char *)buf;
|
||||
}
|
||||
|
||||
static __u8
|
||||
smb2_parse_lease_buf(void *buf, unsigned int *epoch)
|
||||
{
|
||||
struct create_lease *lc = (struct create_lease *)buf;
|
||||
|
||||
*epoch = 0; /* not used */
|
||||
if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
|
||||
return SMB2_OPLOCK_LEVEL_NOCHANGE;
|
||||
return le32_to_cpu(lc->lcontext.LeaseState);
|
||||
}
|
||||
|
||||
static __u8
|
||||
smb3_parse_lease_buf(void *buf, unsigned int *epoch)
|
||||
{
|
||||
struct create_lease_v2 *lc = (struct create_lease_v2 *)buf;
|
||||
|
||||
*epoch = le16_to_cpu(lc->lcontext.Epoch);
|
||||
if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
|
||||
return SMB2_OPLOCK_LEVEL_NOCHANGE;
|
||||
return le32_to_cpu(lc->lcontext.LeaseState);
|
||||
}
|
||||
|
||||
struct smb_version_operations smb20_operations = {
|
||||
.compare_fids = smb2_compare_fids,
|
||||
.setup_request = smb2_setup_request,
|
||||
.setup_async_request = smb2_setup_async_request,
|
||||
.check_receive = smb2_check_receive,
|
||||
.add_credits = smb2_add_credits,
|
||||
.set_credits = smb2_set_credits,
|
||||
.get_credits_field = smb2_get_credits_field,
|
||||
.get_credits = smb2_get_credits,
|
||||
.get_next_mid = smb2_get_next_mid,
|
||||
.read_data_offset = smb2_read_data_offset,
|
||||
.read_data_length = smb2_read_data_length,
|
||||
.map_error = map_smb2_to_linux_error,
|
||||
.find_mid = smb2_find_mid,
|
||||
.check_message = smb2_check_message,
|
||||
.dump_detail = smb2_dump_detail,
|
||||
.clear_stats = smb2_clear_stats,
|
||||
.print_stats = smb2_print_stats,
|
||||
.is_oplock_break = smb2_is_valid_oplock_break,
|
||||
.need_neg = smb2_need_neg,
|
||||
.negotiate = smb2_negotiate,
|
||||
.negotiate_wsize = smb2_negotiate_wsize,
|
||||
.negotiate_rsize = smb2_negotiate_rsize,
|
||||
.sess_setup = SMB2_sess_setup,
|
||||
.logoff = SMB2_logoff,
|
||||
.tree_connect = SMB2_tcon,
|
||||
.tree_disconnect = SMB2_tdis,
|
||||
.is_path_accessible = smb2_is_path_accessible,
|
||||
.can_echo = smb2_can_echo,
|
||||
.echo = SMB2_echo,
|
||||
.query_path_info = smb2_query_path_info,
|
||||
.get_srv_inum = smb2_get_srv_inum,
|
||||
.query_file_info = smb2_query_file_info,
|
||||
.set_path_size = smb2_set_path_size,
|
||||
.set_file_size = smb2_set_file_size,
|
||||
.set_file_info = smb2_set_file_info,
|
||||
.mkdir = smb2_mkdir,
|
||||
.mkdir_setinfo = smb2_mkdir_setinfo,
|
||||
.rmdir = smb2_rmdir,
|
||||
.unlink = smb2_unlink,
|
||||
.rename = smb2_rename_path,
|
||||
.create_hardlink = smb2_create_hardlink,
|
||||
.query_symlink = smb2_query_symlink,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
.flush = smb2_flush_file,
|
||||
.async_readv = smb2_async_readv,
|
||||
.async_writev = smb2_async_writev,
|
||||
.sync_read = smb2_sync_read,
|
||||
.sync_write = smb2_sync_write,
|
||||
.query_dir_first = smb2_query_dir_first,
|
||||
.query_dir_next = smb2_query_dir_next,
|
||||
.close_dir = smb2_close_dir,
|
||||
.calc_smb_size = smb2_calc_size,
|
||||
.is_status_pending = smb2_is_status_pending,
|
||||
.oplock_response = smb2_oplock_response,
|
||||
.queryfs = smb2_queryfs,
|
||||
.mand_lock = smb2_mand_lock,
|
||||
.mand_unlock_range = smb2_unlock_range,
|
||||
.push_mand_locks = smb2_push_mandatory_locks,
|
||||
.get_lease_key = smb2_get_lease_key,
|
||||
.set_lease_key = smb2_set_lease_key,
|
||||
.new_lease_key = smb2_new_lease_key,
|
||||
.calc_signature = smb2_calc_signature,
|
||||
.is_read_op = smb2_is_read_op,
|
||||
.set_oplock_level = smb2_set_oplock_level,
|
||||
.create_lease_buf = smb2_create_lease_buf,
|
||||
.parse_lease_buf = smb2_parse_lease_buf,
|
||||
};
|
||||
|
||||
struct smb_version_operations smb21_operations = {
|
||||
.compare_fids = smb2_compare_fids,
|
||||
.setup_request = smb2_setup_request,
|
||||
@ -638,6 +951,7 @@ struct smb_version_operations smb21_operations = {
|
||||
.unlink = smb2_unlink,
|
||||
.rename = smb2_rename_path,
|
||||
.create_hardlink = smb2_create_hardlink,
|
||||
.query_symlink = smb2_query_symlink,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
@ -660,9 +974,12 @@ struct smb_version_operations smb21_operations = {
|
||||
.set_lease_key = smb2_set_lease_key,
|
||||
.new_lease_key = smb2_new_lease_key,
|
||||
.calc_signature = smb2_calc_signature,
|
||||
.is_read_op = smb21_is_read_op,
|
||||
.set_oplock_level = smb21_set_oplock_level,
|
||||
.create_lease_buf = smb2_create_lease_buf,
|
||||
.parse_lease_buf = smb2_parse_lease_buf,
|
||||
};
|
||||
|
||||
|
||||
struct smb_version_operations smb30_operations = {
|
||||
.compare_fids = smb2_compare_fids,
|
||||
.setup_request = smb2_setup_request,
|
||||
@ -706,6 +1023,7 @@ struct smb_version_operations smb30_operations = {
|
||||
.unlink = smb2_unlink,
|
||||
.rename = smb2_rename_path,
|
||||
.create_hardlink = smb2_create_hardlink,
|
||||
.query_symlink = smb2_query_symlink,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
@ -729,6 +1047,10 @@ struct smb_version_operations smb30_operations = {
|
||||
.new_lease_key = smb2_new_lease_key,
|
||||
.generate_signingkey = generate_smb3signingkey,
|
||||
.calc_signature = smb3_calc_signature,
|
||||
.is_read_op = smb21_is_read_op,
|
||||
.set_oplock_level = smb3_set_oplock_level,
|
||||
.create_lease_buf = smb3_create_lease_buf,
|
||||
.parse_lease_buf = smb3_parse_lease_buf,
|
||||
};
|
||||
|
||||
struct smb_version_values smb20_values = {
|
||||
@ -746,9 +1068,9 @@ struct smb_version_values smb20_values = {
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
.cap_large_files = SMB2_LARGE_FILES,
|
||||
.oplock_read = SMB2_OPLOCK_LEVEL_II,
|
||||
.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.create_lease_size = sizeof(struct create_lease),
|
||||
};
|
||||
|
||||
struct smb_version_values smb21_values = {
|
||||
@ -766,9 +1088,9 @@ struct smb_version_values smb21_values = {
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
.cap_large_files = SMB2_LARGE_FILES,
|
||||
.oplock_read = SMB2_OPLOCK_LEVEL_II,
|
||||
.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.create_lease_size = sizeof(struct create_lease),
|
||||
};
|
||||
|
||||
struct smb_version_values smb30_values = {
|
||||
@ -786,9 +1108,9 @@ struct smb_version_values smb30_values = {
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
.cap_large_files = SMB2_LARGE_FILES,
|
||||
.oplock_read = SMB2_OPLOCK_LEVEL_II,
|
||||
.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.create_lease_size = sizeof(struct create_lease_v2),
|
||||
};
|
||||
|
||||
struct smb_version_values smb302_values = {
|
||||
@ -806,7 +1128,7 @@ struct smb_version_values smb302_values = {
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
.cap_large_files = SMB2_LARGE_FILES,
|
||||
.oplock_read = SMB2_OPLOCK_LEVEL_II,
|
||||
.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
|
||||
.create_lease_size = sizeof(struct create_lease_v2),
|
||||
};
|
||||
|
@ -477,6 +477,13 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are here due to reconnect, free per-smb session key
|
||||
* in case signing was required.
|
||||
*/
|
||||
kfree(ses->auth_key.response);
|
||||
ses->auth_key.response = NULL;
|
||||
|
||||
/*
|
||||
* If memory allocation is successful, caller of this function
|
||||
* frees it.
|
||||
@ -484,6 +491,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
|
||||
ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
|
||||
if (!ses->ntlmssp)
|
||||
return -ENOMEM;
|
||||
ses->ntlmssp->sesskey_per_smbsess = true;
|
||||
|
||||
/* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */
|
||||
ses->sectype = RawNTLMSSP;
|
||||
@ -628,6 +636,40 @@ ssetup_exit:
|
||||
/* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
|
||||
if ((phase == NtLmChallenge) && (rc == 0))
|
||||
goto ssetup_ntlmssp_authenticate;
|
||||
|
||||
if (!rc) {
|
||||
mutex_lock(&server->srv_mutex);
|
||||
if (server->sign && server->ops->generate_signingkey) {
|
||||
rc = server->ops->generate_signingkey(ses);
|
||||
kfree(ses->auth_key.response);
|
||||
ses->auth_key.response = NULL;
|
||||
if (rc) {
|
||||
cifs_dbg(FYI,
|
||||
"SMB3 session key generation failed\n");
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
goto keygen_exit;
|
||||
}
|
||||
}
|
||||
if (!server->session_estab) {
|
||||
server->sequence_number = 0x2;
|
||||
server->session_estab = true;
|
||||
}
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
|
||||
cifs_dbg(FYI, "SMB2/3 session established successfully\n");
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
ses->status = CifsGood;
|
||||
ses->need_reconnect = false;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
}
|
||||
|
||||
keygen_exit:
|
||||
if (!server->sign) {
|
||||
kfree(ses->auth_key.response);
|
||||
ses->auth_key.response = NULL;
|
||||
}
|
||||
kfree(ses->ntlmssp);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -813,39 +855,6 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct create_lease *
|
||||
create_lease_buf(u8 *lease_key, u8 oplock)
|
||||
{
|
||||
struct create_lease *buf;
|
||||
|
||||
buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
|
||||
buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
|
||||
if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
|
||||
buf->lcontext.LeaseState = SMB2_LEASE_WRITE_CACHING |
|
||||
SMB2_LEASE_READ_CACHING;
|
||||
else if (oplock == SMB2_OPLOCK_LEVEL_II)
|
||||
buf->lcontext.LeaseState = SMB2_LEASE_READ_CACHING;
|
||||
else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
|
||||
buf->lcontext.LeaseState = SMB2_LEASE_HANDLE_CACHING |
|
||||
SMB2_LEASE_READ_CACHING |
|
||||
SMB2_LEASE_WRITE_CACHING;
|
||||
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease, lcontext));
|
||||
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
|
||||
buf->ccontext.NameOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease, Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
buf->Name[0] = 'R';
|
||||
buf->Name[1] = 'q';
|
||||
buf->Name[2] = 'L';
|
||||
buf->Name[3] = 's';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static struct create_durable *
|
||||
create_durable_buf(void)
|
||||
@ -894,55 +903,49 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
|
||||
}
|
||||
|
||||
static __u8
|
||||
parse_lease_state(struct smb2_create_rsp *rsp)
|
||||
parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
|
||||
unsigned int *epoch)
|
||||
{
|
||||
char *data_offset;
|
||||
struct create_lease *lc;
|
||||
bool found = false;
|
||||
struct create_context *cc;
|
||||
unsigned int next = 0;
|
||||
char *name;
|
||||
|
||||
data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
|
||||
lc = (struct create_lease *)data_offset;
|
||||
cc = (struct create_context *)data_offset;
|
||||
do {
|
||||
lc = (struct create_lease *)((char *)lc + next);
|
||||
name = le16_to_cpu(lc->ccontext.NameOffset) + (char *)lc;
|
||||
if (le16_to_cpu(lc->ccontext.NameLength) != 4 ||
|
||||
cc = (struct create_context *)((char *)cc + next);
|
||||
name = le16_to_cpu(cc->NameOffset) + (char *)cc;
|
||||
if (le16_to_cpu(cc->NameLength) != 4 ||
|
||||
strncmp(name, "RqLs", 4)) {
|
||||
next = le32_to_cpu(lc->ccontext.Next);
|
||||
next = le32_to_cpu(cc->Next);
|
||||
continue;
|
||||
}
|
||||
if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
|
||||
return SMB2_OPLOCK_LEVEL_NOCHANGE;
|
||||
found = true;
|
||||
break;
|
||||
return server->ops->parse_lease_buf(cc, epoch);
|
||||
} while (next != 0);
|
||||
|
||||
if (!found)
|
||||
return 0;
|
||||
|
||||
return smb2_map_lease_to_oplock(lc->lcontext.LeaseState);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
add_lease_context(struct kvec *iov, unsigned int *num_iovec, __u8 *oplock)
|
||||
add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
unsigned int *num_iovec, __u8 *oplock)
|
||||
{
|
||||
struct smb2_create_req *req = iov[0].iov_base;
|
||||
unsigned int num = *num_iovec;
|
||||
|
||||
iov[num].iov_base = create_lease_buf(oplock+1, *oplock);
|
||||
iov[num].iov_base = server->ops->create_lease_buf(oplock+1, *oplock);
|
||||
if (iov[num].iov_base == NULL)
|
||||
return -ENOMEM;
|
||||
iov[num].iov_len = sizeof(struct create_lease);
|
||||
iov[num].iov_len = server->vals->create_lease_size;
|
||||
req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
|
||||
if (!req->CreateContextsOffset)
|
||||
req->CreateContextsOffset = cpu_to_le32(
|
||||
sizeof(struct smb2_create_req) - 4 +
|
||||
iov[num - 1].iov_len);
|
||||
req->CreateContextsLength = cpu_to_le32(
|
||||
le32_to_cpu(req->CreateContextsLength) +
|
||||
sizeof(struct create_lease));
|
||||
inc_rfc1001_len(&req->hdr, sizeof(struct create_lease));
|
||||
le32_add_cpu(&req->CreateContextsLength,
|
||||
server->vals->create_lease_size);
|
||||
inc_rfc1001_len(&req->hdr, server->vals->create_lease_size);
|
||||
*num_iovec = num + 1;
|
||||
return 0;
|
||||
}
|
||||
@ -967,9 +970,7 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
|
||||
req->CreateContextsOffset =
|
||||
cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
|
||||
iov[1].iov_len);
|
||||
req->CreateContextsLength =
|
||||
cpu_to_le32(le32_to_cpu(req->CreateContextsLength) +
|
||||
sizeof(struct create_durable));
|
||||
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable));
|
||||
inc_rfc1001_len(&req->hdr, sizeof(struct create_durable));
|
||||
*num_iovec = num + 1;
|
||||
return 0;
|
||||
@ -977,7 +978,8 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
|
||||
|
||||
int
|
||||
SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
__u8 *oplock, struct smb2_file_all_info *buf)
|
||||
__u8 *oplock, struct smb2_file_all_info *buf,
|
||||
struct smb2_err_rsp **err_buf)
|
||||
{
|
||||
struct smb2_create_req *req;
|
||||
struct smb2_create_rsp *rsp;
|
||||
@ -1048,11 +1050,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
if (!server->oplocks)
|
||||
*oplock = SMB2_OPLOCK_LEVEL_NONE;
|
||||
|
||||
if (!(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
|
||||
if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
|
||||
*oplock == SMB2_OPLOCK_LEVEL_NONE)
|
||||
req->RequestedOplockLevel = *oplock;
|
||||
else {
|
||||
rc = add_lease_context(iov, &num_iovecs, oplock);
|
||||
rc = add_lease_context(server, iov, &num_iovecs, oplock);
|
||||
if (rc) {
|
||||
cifs_small_buf_release(req);
|
||||
kfree(copy_path);
|
||||
@ -1062,11 +1064,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
|
||||
if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
|
||||
/* need to set Next field of lease context if we request it */
|
||||
if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
|
||||
if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
|
||||
struct create_context *ccontext =
|
||||
(struct create_context *)iov[num_iovecs-1].iov_base;
|
||||
ccontext->Next =
|
||||
cpu_to_le32(sizeof(struct create_lease));
|
||||
cpu_to_le32(server->vals->create_lease_size);
|
||||
}
|
||||
rc = add_durable_context(iov, &num_iovecs, oparms);
|
||||
if (rc) {
|
||||
@ -1082,6 +1084,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
|
||||
if (rc != 0) {
|
||||
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
|
||||
if (err_buf)
|
||||
*err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
|
||||
GFP_KERNEL);
|
||||
goto creat_exit;
|
||||
}
|
||||
|
||||
@ -1098,7 +1103,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
}
|
||||
|
||||
if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)
|
||||
*oplock = parse_lease_state(rsp);
|
||||
*oplock = parse_lease_state(server, rsp, &oparms->fid->epoch);
|
||||
else
|
||||
*oplock = rsp->OplockLevel;
|
||||
creat_exit:
|
||||
|
@ -150,6 +150,20 @@ struct smb2_err_rsp {
|
||||
__u8 ErrorData[1]; /* variable length */
|
||||
} __packed;
|
||||
|
||||
struct smb2_symlink_err_rsp {
|
||||
__le32 SymLinkLength;
|
||||
__le32 SymLinkErrorTag;
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__le16 UnparsedPathLength;
|
||||
__le16 SubstituteNameOffset;
|
||||
__le16 SubstituteNameLength;
|
||||
__le16 PrintNameOffset;
|
||||
__le16 PrintNameLength;
|
||||
__le32 Flags;
|
||||
__u8 PathBuffer[0];
|
||||
} __packed;
|
||||
|
||||
#define SMB2_CLIENT_GUID_SIZE 16
|
||||
|
||||
extern __u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
|
||||
@ -462,6 +476,10 @@ struct create_context {
|
||||
__u8 Buffer[0];
|
||||
} __packed;
|
||||
|
||||
#define SMB2_LEASE_READ_CACHING_HE 0x01
|
||||
#define SMB2_LEASE_HANDLE_CACHING_HE 0x02
|
||||
#define SMB2_LEASE_WRITE_CACHING_HE 0x04
|
||||
|
||||
#define SMB2_LEASE_NONE __constant_cpu_to_le32(0x00)
|
||||
#define SMB2_LEASE_READ_CACHING __constant_cpu_to_le32(0x01)
|
||||
#define SMB2_LEASE_HANDLE_CACHING __constant_cpu_to_le32(0x02)
|
||||
@ -479,12 +497,31 @@ struct lease_context {
|
||||
__le64 LeaseDuration;
|
||||
} __packed;
|
||||
|
||||
struct lease_context_v2 {
|
||||
__le64 LeaseKeyLow;
|
||||
__le64 LeaseKeyHigh;
|
||||
__le32 LeaseState;
|
||||
__le32 LeaseFlags;
|
||||
__le64 LeaseDuration;
|
||||
__le64 ParentLeaseKeyLow;
|
||||
__le64 ParentLeaseKeyHigh;
|
||||
__le16 Epoch;
|
||||
__le16 Reserved;
|
||||
} __packed;
|
||||
|
||||
struct create_lease {
|
||||
struct create_context ccontext;
|
||||
__u8 Name[8];
|
||||
struct lease_context lcontext;
|
||||
} __packed;
|
||||
|
||||
struct create_lease_v2 {
|
||||
struct create_context ccontext;
|
||||
__u8 Name[8];
|
||||
struct lease_context_v2 lcontext;
|
||||
__u8 Pad[4];
|
||||
} __packed;
|
||||
|
||||
struct create_durable {
|
||||
struct create_context ccontext;
|
||||
__u8 Name[8];
|
||||
|
@ -53,7 +53,6 @@ extern int smb3_calc_signature(struct smb_rqst *rqst,
|
||||
struct TCP_Server_Info *server);
|
||||
extern void smb2_echo_request(struct work_struct *work);
|
||||
extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode);
|
||||
extern __u8 smb2_map_lease_to_oplock(__le32 lease_state);
|
||||
extern bool smb2_is_valid_oplock_break(char *buffer,
|
||||
struct TCP_Server_Info *srv);
|
||||
|
||||
@ -87,7 +86,6 @@ extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
extern int smb2_open_file(const unsigned int xid,
|
||||
struct cifs_open_parms *oparms,
|
||||
__u32 *oplock, FILE_ALL_INFO *buf);
|
||||
extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
|
||||
extern int smb2_unlock_range(struct cifsFileInfo *cfile,
|
||||
struct file_lock *flock, const unsigned int xid);
|
||||
extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
|
||||
@ -106,7 +104,8 @@ extern int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses,
|
||||
extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
|
||||
extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
__le16 *path, __u8 *oplock,
|
||||
struct smb2_file_all_info *buf);
|
||||
struct smb2_file_all_info *buf,
|
||||
struct smb2_err_rsp **err_buf);
|
||||
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||
bool is_fsctl, char *in_data, u32 indatalen,
|
||||
|
@ -114,6 +114,23 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cifs_ses *
|
||||
smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
|
||||
{
|
||||
struct cifs_ses *ses;
|
||||
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
||||
if (ses->Suid != smb2hdr->SessionId)
|
||||
continue;
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
return ses;
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
@ -124,6 +141,13 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
struct kvec *iov = rqst->rq_iov;
|
||||
int n_vec = rqst->rq_nvec;
|
||||
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
|
||||
struct cifs_ses *ses;
|
||||
|
||||
ses = smb2_find_smb_ses(smb2_pdu, server);
|
||||
if (!ses) {
|
||||
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
|
||||
memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
|
||||
@ -135,7 +159,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
}
|
||||
|
||||
rc = crypto_shash_setkey(server->secmech.hmacsha256,
|
||||
server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
|
||||
ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
|
||||
return rc;
|
||||
@ -198,8 +222,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
generate_smb3signingkey(struct TCP_Server_Info *server)
|
||||
int
|
||||
generate_smb3signingkey(struct cifs_ses *ses)
|
||||
{
|
||||
unsigned char zero = 0x0;
|
||||
__u8 i[4] = {0, 0, 0, 1};
|
||||
@ -209,90 +233,99 @@ generate_smb3signingkey(struct TCP_Server_Info *server)
|
||||
unsigned char *hashptr = prfhash;
|
||||
|
||||
memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
|
||||
memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE);
|
||||
memset(ses->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE);
|
||||
|
||||
rc = smb3_crypto_shash_allocate(server);
|
||||
rc = smb3_crypto_shash_allocate(ses->server);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_setkey(server->secmech.hmacsha256,
|
||||
server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
|
||||
rc = crypto_shash_setkey(ses->server->secmech.hmacsha256,
|
||||
ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not set with session key\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
|
||||
i, 4);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not update with n\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
|
||||
"SMB2AESCMAC", 12);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not update with label\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
|
||||
&zero, 1);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not update with zero\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
|
||||
"SmbSign", 8);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not update with context\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash,
|
||||
L, 4);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not update with L\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash,
|
||||
hashptr);
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
|
||||
goto smb3signkey_ret;
|
||||
}
|
||||
|
||||
memcpy(server->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE);
|
||||
memcpy(ses->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE);
|
||||
|
||||
smb3signkey_ret:
|
||||
return;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
{
|
||||
int i, rc;
|
||||
int i;
|
||||
int rc = 0;
|
||||
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
|
||||
unsigned char *sigptr = smb3_signature;
|
||||
struct kvec *iov = rqst->rq_iov;
|
||||
int n_vec = rqst->rq_nvec;
|
||||
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
|
||||
struct cifs_ses *ses;
|
||||
|
||||
ses = smb2_find_smb_ses(smb2_pdu, server);
|
||||
if (!ses) {
|
||||
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
|
||||
memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
|
||||
|
||||
rc = crypto_shash_setkey(server->secmech.cmacaes,
|
||||
server->smb3signingkey, SMB2_CMACAES_SIZE);
|
||||
ses->smb3signingkey, SMB2_CMACAES_SIZE);
|
||||
|
||||
if (rc) {
|
||||
cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
|
||||
return rc;
|
||||
@ -389,6 +422,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
|
||||
|
||||
if ((smb2_pdu->Command == SMB2_NEGOTIATE) ||
|
||||
(smb2_pdu->Command == SMB2_SESSION_SETUP) ||
|
||||
(smb2_pdu->Command == SMB2_OPLOCK_BREAK) ||
|
||||
(!server->session_estab))
|
||||
return 0;
|
||||
|
663
fs/cifs/winucase.c
Normal file
663
fs/cifs/winucase.c
Normal file
@ -0,0 +1,663 @@
|
||||
/*
|
||||
* fs/cifs/winucase.c
|
||||
*
|
||||
* Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* The const tables in this file were converted from the following info
|
||||
* provided by Microsoft:
|
||||
*
|
||||
* 3.1.5.3 Mapping UTF-16 Strings to Upper Case:
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/hh877830.aspx
|
||||
* http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=10921
|
||||
*
|
||||
* In particular, the table in "Windows 8 Upper Case Mapping Table.txt" was
|
||||
* post-processed using the winucase_convert.pl script.
|
||||
*/
|
||||
|
||||
#include <linux/nls.h>
|
||||
|
||||
wchar_t cifs_toupper(wchar_t in); /* quiet sparse */
|
||||
|
||||
static const wchar_t t2_00[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0000,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178,
|
||||
};
|
||||
|
||||
static const wchar_t t2_01[256] = {
|
||||
0x0000, 0x0100, 0x0000, 0x0102, 0x0000, 0x0104, 0x0000, 0x0106,
|
||||
0x0000, 0x0108, 0x0000, 0x010a, 0x0000, 0x010c, 0x0000, 0x010e,
|
||||
0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0000, 0x0116,
|
||||
0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x011c, 0x0000, 0x011e,
|
||||
0x0000, 0x0120, 0x0000, 0x0122, 0x0000, 0x0124, 0x0000, 0x0126,
|
||||
0x0000, 0x0128, 0x0000, 0x012a, 0x0000, 0x012c, 0x0000, 0x012e,
|
||||
0x0000, 0x0000, 0x0000, 0x0132, 0x0000, 0x0134, 0x0000, 0x0136,
|
||||
0x0000, 0x0000, 0x0139, 0x0000, 0x013b, 0x0000, 0x013d, 0x0000,
|
||||
0x013f, 0x0000, 0x0141, 0x0000, 0x0143, 0x0000, 0x0145, 0x0000,
|
||||
0x0147, 0x0000, 0x0000, 0x014a, 0x0000, 0x014c, 0x0000, 0x014e,
|
||||
0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
|
||||
0x0000, 0x0158, 0x0000, 0x015a, 0x0000, 0x015c, 0x0000, 0x015e,
|
||||
0x0000, 0x0160, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166,
|
||||
0x0000, 0x0168, 0x0000, 0x016a, 0x0000, 0x016c, 0x0000, 0x016e,
|
||||
0x0000, 0x0170, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176,
|
||||
0x0000, 0x0000, 0x0179, 0x0000, 0x017b, 0x0000, 0x017d, 0x0000,
|
||||
0x0243, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0000, 0x0000,
|
||||
0x0187, 0x0000, 0x0000, 0x0000, 0x018b, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x01f6, 0x0000, 0x0000,
|
||||
0x0000, 0x0198, 0x023d, 0x0000, 0x0000, 0x0000, 0x0220, 0x0000,
|
||||
0x0000, 0x01a0, 0x0000, 0x01a2, 0x0000, 0x01a4, 0x0000, 0x0000,
|
||||
0x01a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x01ac, 0x0000, 0x0000,
|
||||
0x01af, 0x0000, 0x0000, 0x0000, 0x01b3, 0x0000, 0x01b5, 0x0000,
|
||||
0x0000, 0x01b8, 0x0000, 0x0000, 0x0000, 0x01bc, 0x0000, 0x01f7,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01c4, 0x0000,
|
||||
0x0000, 0x01c7, 0x0000, 0x0000, 0x01ca, 0x0000, 0x01cd, 0x0000,
|
||||
0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000,
|
||||
0x01d7, 0x0000, 0x01d9, 0x0000, 0x01db, 0x018e, 0x0000, 0x01de,
|
||||
0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
|
||||
0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
|
||||
0x0000, 0x0000, 0x0000, 0x01f1, 0x0000, 0x01f4, 0x0000, 0x0000,
|
||||
0x0000, 0x01f8, 0x0000, 0x01fa, 0x0000, 0x01fc, 0x0000, 0x01fe,
|
||||
};
|
||||
|
||||
static const wchar_t t2_02[256] = {
|
||||
0x0000, 0x0200, 0x0000, 0x0202, 0x0000, 0x0204, 0x0000, 0x0206,
|
||||
0x0000, 0x0208, 0x0000, 0x020a, 0x0000, 0x020c, 0x0000, 0x020e,
|
||||
0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0216,
|
||||
0x0000, 0x0218, 0x0000, 0x021a, 0x0000, 0x021c, 0x0000, 0x021e,
|
||||
0x0000, 0x0000, 0x0000, 0x0222, 0x0000, 0x0224, 0x0000, 0x0226,
|
||||
0x0000, 0x0228, 0x0000, 0x022a, 0x0000, 0x022c, 0x0000, 0x022e,
|
||||
0x0000, 0x0230, 0x0000, 0x0232, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x023b, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0246,
|
||||
0x0000, 0x0248, 0x0000, 0x024a, 0x0000, 0x024c, 0x0000, 0x024e,
|
||||
0x2c6f, 0x2c6d, 0x0000, 0x0181, 0x0186, 0x0000, 0x0189, 0x018a,
|
||||
0x0000, 0x018f, 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0193, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0197, 0x0196, 0x0000, 0x2c62, 0x0000, 0x0000, 0x0000, 0x019c,
|
||||
0x0000, 0x2c6e, 0x019d, 0x0000, 0x0000, 0x019f, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2c64, 0x0000, 0x0000,
|
||||
0x01a6, 0x0000, 0x0000, 0x01a9, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x01b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_03[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0370, 0x0000, 0x0372, 0x0000, 0x0000, 0x0000, 0x0376,
|
||||
0x0000, 0x0000, 0x0000, 0x03fd, 0x03fe, 0x03ff, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0386, 0x0388, 0x0389, 0x038a,
|
||||
0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
|
||||
0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
|
||||
0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
|
||||
0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03cf,
|
||||
0x0000, 0x03d8, 0x0000, 0x03da, 0x0000, 0x03dc, 0x0000, 0x03de,
|
||||
0x0000, 0x03e0, 0x0000, 0x03e2, 0x0000, 0x03e4, 0x0000, 0x03e6,
|
||||
0x0000, 0x03e8, 0x0000, 0x03ea, 0x0000, 0x03ec, 0x0000, 0x03ee,
|
||||
0x0000, 0x0000, 0x03f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x03f7, 0x0000, 0x0000, 0x03fa, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_04[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||
0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||
0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
|
||||
0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
|
||||
0x0000, 0x0460, 0x0000, 0x0462, 0x0000, 0x0464, 0x0000, 0x0466,
|
||||
0x0000, 0x0468, 0x0000, 0x046a, 0x0000, 0x046c, 0x0000, 0x046e,
|
||||
0x0000, 0x0470, 0x0000, 0x0472, 0x0000, 0x0474, 0x0000, 0x0476,
|
||||
0x0000, 0x0478, 0x0000, 0x047a, 0x0000, 0x047c, 0x0000, 0x047e,
|
||||
0x0000, 0x0480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x048a, 0x0000, 0x048c, 0x0000, 0x048e,
|
||||
0x0000, 0x0490, 0x0000, 0x0492, 0x0000, 0x0494, 0x0000, 0x0496,
|
||||
0x0000, 0x0498, 0x0000, 0x049a, 0x0000, 0x049c, 0x0000, 0x049e,
|
||||
0x0000, 0x04a0, 0x0000, 0x04a2, 0x0000, 0x04a4, 0x0000, 0x04a6,
|
||||
0x0000, 0x04a8, 0x0000, 0x04aa, 0x0000, 0x04ac, 0x0000, 0x04ae,
|
||||
0x0000, 0x04b0, 0x0000, 0x04b2, 0x0000, 0x04b4, 0x0000, 0x04b6,
|
||||
0x0000, 0x04b8, 0x0000, 0x04ba, 0x0000, 0x04bc, 0x0000, 0x04be,
|
||||
0x0000, 0x0000, 0x04c1, 0x0000, 0x04c3, 0x0000, 0x04c5, 0x0000,
|
||||
0x04c7, 0x0000, 0x04c9, 0x0000, 0x04cb, 0x0000, 0x04cd, 0x04c0,
|
||||
0x0000, 0x04d0, 0x0000, 0x04d2, 0x0000, 0x04d4, 0x0000, 0x04d6,
|
||||
0x0000, 0x04d8, 0x0000, 0x04da, 0x0000, 0x04dc, 0x0000, 0x04de,
|
||||
0x0000, 0x04e0, 0x0000, 0x04e2, 0x0000, 0x04e4, 0x0000, 0x04e6,
|
||||
0x0000, 0x04e8, 0x0000, 0x04ea, 0x0000, 0x04ec, 0x0000, 0x04ee,
|
||||
0x0000, 0x04f0, 0x0000, 0x04f2, 0x0000, 0x04f4, 0x0000, 0x04f6,
|
||||
0x0000, 0x04f8, 0x0000, 0x04fa, 0x0000, 0x04fc, 0x0000, 0x04fe,
|
||||
};
|
||||
|
||||
static const wchar_t t2_05[256] = {
|
||||
0x0000, 0x0500, 0x0000, 0x0502, 0x0000, 0x0504, 0x0000, 0x0506,
|
||||
0x0000, 0x0508, 0x0000, 0x050a, 0x0000, 0x050c, 0x0000, 0x050e,
|
||||
0x0000, 0x0510, 0x0000, 0x0512, 0x0000, 0x0514, 0x0000, 0x0516,
|
||||
0x0000, 0x0518, 0x0000, 0x051a, 0x0000, 0x051c, 0x0000, 0x051e,
|
||||
0x0000, 0x0520, 0x0000, 0x0522, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
|
||||
0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
|
||||
0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
|
||||
0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
|
||||
0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_1d[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xa77d, 0x0000, 0x0000, 0x0000, 0x2c63, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_1e[256] = {
|
||||
0x0000, 0x1e00, 0x0000, 0x1e02, 0x0000, 0x1e04, 0x0000, 0x1e06,
|
||||
0x0000, 0x1e08, 0x0000, 0x1e0a, 0x0000, 0x1e0c, 0x0000, 0x1e0e,
|
||||
0x0000, 0x1e10, 0x0000, 0x1e12, 0x0000, 0x1e14, 0x0000, 0x1e16,
|
||||
0x0000, 0x1e18, 0x0000, 0x1e1a, 0x0000, 0x1e1c, 0x0000, 0x1e1e,
|
||||
0x0000, 0x1e20, 0x0000, 0x1e22, 0x0000, 0x1e24, 0x0000, 0x1e26,
|
||||
0x0000, 0x1e28, 0x0000, 0x1e2a, 0x0000, 0x1e2c, 0x0000, 0x1e2e,
|
||||
0x0000, 0x1e30, 0x0000, 0x1e32, 0x0000, 0x1e34, 0x0000, 0x1e36,
|
||||
0x0000, 0x1e38, 0x0000, 0x1e3a, 0x0000, 0x1e3c, 0x0000, 0x1e3e,
|
||||
0x0000, 0x1e40, 0x0000, 0x1e42, 0x0000, 0x1e44, 0x0000, 0x1e46,
|
||||
0x0000, 0x1e48, 0x0000, 0x1e4a, 0x0000, 0x1e4c, 0x0000, 0x1e4e,
|
||||
0x0000, 0x1e50, 0x0000, 0x1e52, 0x0000, 0x1e54, 0x0000, 0x1e56,
|
||||
0x0000, 0x1e58, 0x0000, 0x1e5a, 0x0000, 0x1e5c, 0x0000, 0x1e5e,
|
||||
0x0000, 0x1e60, 0x0000, 0x1e62, 0x0000, 0x1e64, 0x0000, 0x1e66,
|
||||
0x0000, 0x1e68, 0x0000, 0x1e6a, 0x0000, 0x1e6c, 0x0000, 0x1e6e,
|
||||
0x0000, 0x1e70, 0x0000, 0x1e72, 0x0000, 0x1e74, 0x0000, 0x1e76,
|
||||
0x0000, 0x1e78, 0x0000, 0x1e7a, 0x0000, 0x1e7c, 0x0000, 0x1e7e,
|
||||
0x0000, 0x1e80, 0x0000, 0x1e82, 0x0000, 0x1e84, 0x0000, 0x1e86,
|
||||
0x0000, 0x1e88, 0x0000, 0x1e8a, 0x0000, 0x1e8c, 0x0000, 0x1e8e,
|
||||
0x0000, 0x1e90, 0x0000, 0x1e92, 0x0000, 0x1e94, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x1ea0, 0x0000, 0x1ea2, 0x0000, 0x1ea4, 0x0000, 0x1ea6,
|
||||
0x0000, 0x1ea8, 0x0000, 0x1eaa, 0x0000, 0x1eac, 0x0000, 0x1eae,
|
||||
0x0000, 0x1eb0, 0x0000, 0x1eb2, 0x0000, 0x1eb4, 0x0000, 0x1eb6,
|
||||
0x0000, 0x1eb8, 0x0000, 0x1eba, 0x0000, 0x1ebc, 0x0000, 0x1ebe,
|
||||
0x0000, 0x1ec0, 0x0000, 0x1ec2, 0x0000, 0x1ec4, 0x0000, 0x1ec6,
|
||||
0x0000, 0x1ec8, 0x0000, 0x1eca, 0x0000, 0x1ecc, 0x0000, 0x1ece,
|
||||
0x0000, 0x1ed0, 0x0000, 0x1ed2, 0x0000, 0x1ed4, 0x0000, 0x1ed6,
|
||||
0x0000, 0x1ed8, 0x0000, 0x1eda, 0x0000, 0x1edc, 0x0000, 0x1ede,
|
||||
0x0000, 0x1ee0, 0x0000, 0x1ee2, 0x0000, 0x1ee4, 0x0000, 0x1ee6,
|
||||
0x0000, 0x1ee8, 0x0000, 0x1eea, 0x0000, 0x1eec, 0x0000, 0x1eee,
|
||||
0x0000, 0x1ef0, 0x0000, 0x1ef2, 0x0000, 0x1ef4, 0x0000, 0x1ef6,
|
||||
0x0000, 0x1ef8, 0x0000, 0x1efa, 0x0000, 0x1efc, 0x0000, 0x1efe,
|
||||
};
|
||||
|
||||
static const wchar_t t2_1f[256] = {
|
||||
0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x1f59, 0x0000, 0x1f5b, 0x0000, 0x1f5d, 0x0000, 0x1f5f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb,
|
||||
0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0x0000, 0x0000,
|
||||
0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1fb8, 0x1fb9, 0x0000, 0x1fbc, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x1fcc, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1fd8, 0x1fd9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1fe8, 0x1fe9, 0x0000, 0x0000, 0x0000, 0x1fec, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x1ffc, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_21[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2132, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,
|
||||
0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x2183, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_24[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd,
|
||||
0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5,
|
||||
0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd,
|
||||
0x24ce, 0x24cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_2c[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x2c00, 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07,
|
||||
0x2c08, 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f,
|
||||
0x2c10, 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17,
|
||||
0x2c18, 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f,
|
||||
0x2c20, 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27,
|
||||
0x2c28, 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x0000,
|
||||
0x0000, 0x2c60, 0x0000, 0x0000, 0x0000, 0x023a, 0x023e, 0x0000,
|
||||
0x2c67, 0x0000, 0x2c69, 0x0000, 0x2c6b, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x2c72, 0x0000, 0x0000, 0x2c75, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2c80, 0x0000, 0x2c82, 0x0000, 0x2c84, 0x0000, 0x2c86,
|
||||
0x0000, 0x2c88, 0x0000, 0x2c8a, 0x0000, 0x2c8c, 0x0000, 0x2c8e,
|
||||
0x0000, 0x2c90, 0x0000, 0x2c92, 0x0000, 0x2c94, 0x0000, 0x2c96,
|
||||
0x0000, 0x2c98, 0x0000, 0x2c9a, 0x0000, 0x2c9c, 0x0000, 0x2c9e,
|
||||
0x0000, 0x2ca0, 0x0000, 0x2ca2, 0x0000, 0x2ca4, 0x0000, 0x2ca6,
|
||||
0x0000, 0x2ca8, 0x0000, 0x2caa, 0x0000, 0x2cac, 0x0000, 0x2cae,
|
||||
0x0000, 0x2cb0, 0x0000, 0x2cb2, 0x0000, 0x2cb4, 0x0000, 0x2cb6,
|
||||
0x0000, 0x2cb8, 0x0000, 0x2cba, 0x0000, 0x2cbc, 0x0000, 0x2cbe,
|
||||
0x0000, 0x2cc0, 0x0000, 0x2cc2, 0x0000, 0x2cc4, 0x0000, 0x2cc6,
|
||||
0x0000, 0x2cc8, 0x0000, 0x2cca, 0x0000, 0x2ccc, 0x0000, 0x2cce,
|
||||
0x0000, 0x2cd0, 0x0000, 0x2cd2, 0x0000, 0x2cd4, 0x0000, 0x2cd6,
|
||||
0x0000, 0x2cd8, 0x0000, 0x2cda, 0x0000, 0x2cdc, 0x0000, 0x2cde,
|
||||
0x0000, 0x2ce0, 0x0000, 0x2ce2, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_2d[256] = {
|
||||
0x10a0, 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7,
|
||||
0x10a8, 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af,
|
||||
0x10b0, 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7,
|
||||
0x10b8, 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf,
|
||||
0x10c0, 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_a6[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xa640, 0x0000, 0xa642, 0x0000, 0xa644, 0x0000, 0xa646,
|
||||
0x0000, 0xa648, 0x0000, 0xa64a, 0x0000, 0xa64c, 0x0000, 0xa64e,
|
||||
0x0000, 0xa650, 0x0000, 0xa652, 0x0000, 0xa654, 0x0000, 0xa656,
|
||||
0x0000, 0xa658, 0x0000, 0xa65a, 0x0000, 0xa65c, 0x0000, 0xa65e,
|
||||
0x0000, 0x0000, 0x0000, 0xa662, 0x0000, 0xa664, 0x0000, 0xa666,
|
||||
0x0000, 0xa668, 0x0000, 0xa66a, 0x0000, 0xa66c, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xa680, 0x0000, 0xa682, 0x0000, 0xa684, 0x0000, 0xa686,
|
||||
0x0000, 0xa688, 0x0000, 0xa68a, 0x0000, 0xa68c, 0x0000, 0xa68e,
|
||||
0x0000, 0xa690, 0x0000, 0xa692, 0x0000, 0xa694, 0x0000, 0xa696,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_a7[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xa722, 0x0000, 0xa724, 0x0000, 0xa726,
|
||||
0x0000, 0xa728, 0x0000, 0xa72a, 0x0000, 0xa72c, 0x0000, 0xa72e,
|
||||
0x0000, 0x0000, 0x0000, 0xa732, 0x0000, 0xa734, 0x0000, 0xa736,
|
||||
0x0000, 0xa738, 0x0000, 0xa73a, 0x0000, 0xa73c, 0x0000, 0xa73e,
|
||||
0x0000, 0xa740, 0x0000, 0xa742, 0x0000, 0xa744, 0x0000, 0xa746,
|
||||
0x0000, 0xa748, 0x0000, 0xa74a, 0x0000, 0xa74c, 0x0000, 0xa74e,
|
||||
0x0000, 0xa750, 0x0000, 0xa752, 0x0000, 0xa754, 0x0000, 0xa756,
|
||||
0x0000, 0xa758, 0x0000, 0xa75a, 0x0000, 0xa75c, 0x0000, 0xa75e,
|
||||
0x0000, 0xa760, 0x0000, 0xa762, 0x0000, 0xa764, 0x0000, 0xa766,
|
||||
0x0000, 0xa768, 0x0000, 0xa76a, 0x0000, 0xa76c, 0x0000, 0xa76e,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0xa779, 0x0000, 0xa77b, 0x0000, 0x0000, 0xa77e,
|
||||
0x0000, 0xa780, 0x0000, 0xa782, 0x0000, 0xa784, 0x0000, 0xa786,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xa78b, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t t2_ff[256] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27,
|
||||
0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f,
|
||||
0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37,
|
||||
0xff38, 0xff39, 0xff3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
};
|
||||
|
||||
static const wchar_t *const toplevel[256] = {
|
||||
t2_00, t2_01, t2_02, t2_03, t2_04, t2_05, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, t2_1d, t2_1e, t2_1f,
|
||||
NULL, t2_21, NULL, NULL, t2_24, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, t2_2c, t2_2d, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, t2_a6, t2_a7,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, t2_ff,
|
||||
};
|
||||
|
||||
/**
|
||||
* cifs_toupper - convert a wchar_t from lower to uppercase
|
||||
* @in: character to convert from lower to uppercase
|
||||
*
|
||||
* This function consults the static tables above to convert a wchar_t from
|
||||
* lower to uppercase. In the event that there is no mapping, the original
|
||||
* "in" character is returned.
|
||||
*/
|
||||
wchar_t
|
||||
cifs_toupper(wchar_t in)
|
||||
{
|
||||
unsigned char idx;
|
||||
const wchar_t *tbl;
|
||||
wchar_t out;
|
||||
|
||||
/* grab upper byte */
|
||||
idx = (in & 0xff00) >> 8;
|
||||
|
||||
/* find pointer to 2nd layer table */
|
||||
tbl = toplevel[idx];
|
||||
if (!tbl)
|
||||
return in;
|
||||
|
||||
/* grab lower byte */
|
||||
idx = in & 0xff;
|
||||
|
||||
/* look up character in table */
|
||||
out = tbl[idx];
|
||||
if (out)
|
||||
return out;
|
||||
|
||||
return in;
|
||||
}
|
27
include/uapi/linux/cifs/cifs_mount.h
Normal file
27
include/uapi/linux/cifs/cifs_mount.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* include/uapi/linux/cifs/cifs_mount.h
|
||||
*
|
||||
* Author(s): Scott Lovenberg (scott.lovenberg@gmail.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*/
|
||||
#ifndef _CIFS_MOUNT_H
|
||||
#define _CIFS_MOUNT_H
|
||||
|
||||
/* Max string lengths for cifs mounting options. */
|
||||
#define CIFS_MAX_DOMAINNAME_LEN 256 /* max fully qualified domain name */
|
||||
#define CIFS_MAX_USERNAME_LEN 256 /* reasonable max for current servers */
|
||||
#define CIFS_MAX_PASSWORD_LEN 512 /* Windows max seems to be 256 wide chars */
|
||||
#define CIFS_MAX_SHARE_LEN 256 /* reasonable max share name length */
|
||||
#define CIFS_NI_MAXHOST 1024 /* max host name length (256 * 4 bytes) */
|
||||
|
||||
|
||||
#endif /* _CIFS_MOUNT_H */
|
Loading…
Reference in New Issue
Block a user