diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/AUTHORS | 1 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 10 | ||||
-rw-r--r-- | fs/cifs/README | 5 | ||||
-rw-r--r-- | fs/cifs/TODO | 15 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 14 | ||||
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 49 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifs_spnego.c | 3 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 65 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 48 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 13 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 339 | ||||
-rw-r--r-- | fs/cifs/connect.c | 73 | ||||
-rw-r--r-- | fs/cifs/dir.c | 34 | ||||
-rw-r--r-- | fs/cifs/dns_resolve.c | 9 | ||||
-rw-r--r-- | fs/cifs/file.c | 13 | ||||
-rw-r--r-- | fs/cifs/inode.c | 567 | ||||
-rw-r--r-- | fs/cifs/ioctl.c | 4 | ||||
-rw-r--r-- | fs/cifs/link.c | 43 | ||||
-rw-r--r-- | fs/cifs/misc.c | 3 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 6 | ||||
-rw-r--r-- | fs/cifs/ntlmssp.h | 4 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 84 |
25 files changed, 765 insertions, 645 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index 8848e4dfa026..9c136d7803d9 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS | |||
@@ -36,6 +36,7 @@ Miklos Szeredi | |||
36 | Kazeon team for various fixes especially for 2.4 version. | 36 | Kazeon team for various fixes especially for 2.4 version. |
37 | Asser Ferno (Change Notify support) | 37 | Asser Ferno (Change Notify support) |
38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup | 38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup |
39 | Igor Mammedov (DFS support) | ||
39 | 40 | ||
40 | Test case and Bug Report contributors | 41 | Test case and Bug Report contributors |
41 | ------------------------------------- | 42 | ------------------------------------- |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 8355e918fddf..1f3465201fdf 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,5 +1,12 @@ | |||
1 | Version 1.53 | 1 | Version 1.53 |
2 | ------------ | 2 | ------------ |
3 | DFS support added (Microsoft Distributed File System client support needed | ||
4 | for referrals which enable a hierarchical name space among servers). | ||
5 | Disable temporary caching of mode bits to servers which do not support | ||
6 | storing of mode (e.g. Windows servers, when client mounts without cifsacl | ||
7 | mount option) and add new "dynperm" mount option to enable temporary caching | ||
8 | of mode (enable old behavior). Fix hang on mount caused when server crashes | ||
9 | tcp session during negotiate protocol. | ||
3 | 10 | ||
4 | Version 1.52 | 11 | Version 1.52 |
5 | ------------ | 12 | ------------ |
@@ -12,7 +19,8 @@ Add ability to modify cifs acls for handling chmod (when mounted with | |||
12 | cifsacl flag). Fix prefixpath path separator so we can handle mounts | 19 | cifsacl flag). Fix prefixpath path separator so we can handle mounts |
13 | with prefixpaths longer than one directory (one path component) when | 20 | with prefixpaths longer than one directory (one path component) when |
14 | mounted to Windows servers. Fix slow file open when cifsacl | 21 | mounted to Windows servers. Fix slow file open when cifsacl |
15 | enabled. | 22 | enabled. Fix memory leak in FindNext when the SMB call returns -EBADF. |
23 | |||
16 | 24 | ||
17 | Version 1.51 | 25 | Version 1.51 |
18 | ------------ | 26 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index 621aa1a85971..2bd6fe556f88 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -483,6 +483,11 @@ A partial list of the supported mount options follows: | |||
483 | sign Must use packet signing (helps avoid unwanted data modification | 483 | sign Must use packet signing (helps avoid unwanted data modification |
484 | by intermediate systems in the route). Note that signing | 484 | by intermediate systems in the route). Note that signing |
485 | does not work with lanman or plaintext authentication. | 485 | does not work with lanman or plaintext authentication. |
486 | seal Must seal (encrypt) all data on this mounted share before | ||
487 | sending on the network. Requires support for Unix Extensions. | ||
488 | Note that this differs from the sign mount option in that it | ||
489 | causes encryption of data sent over this mounted share but other | ||
490 | shares mounted to the same server are unaffected. | ||
486 | sec Security mode. Allowed values are: | 491 | sec Security mode. Allowed values are: |
487 | none attempt to connection as a null user (no name) | 492 | none attempt to connection as a null user (no name) |
488 | krb5 Use Kerberos version 5 authentication | 493 | krb5 Use Kerberos version 5 authentication |
diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 92c9feac440f..5aff46c61e52 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO | |||
@@ -1,4 +1,4 @@ | |||
1 | Version 1.52 January 3, 2008 | 1 | Version 1.53 May 20, 2008 |
2 | 2 | ||
3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
4 | ================================== | 4 | ================================== |
@@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in | |||
20 | fs/cifs/connect.c and add back in NTLMSSP code if any servers | 20 | fs/cifs/connect.c and add back in NTLMSSP code if any servers |
21 | need it | 21 | need it |
22 | 22 | ||
23 | e) ms-dfs and ms-dfs host name resolution cleanup | 23 | e) fix NTLMv2 signing when two mounts with different users to same |
24 | |||
25 | f) fix NTLMv2 signing when two mounts with different users to same | ||
26 | server. | 24 | server. |
27 | 25 | ||
28 | g) Directory entry caching relies on a 1 second timer, rather than | 26 | f) Directory entry caching relies on a 1 second timer, rather than |
29 | using FindNotify or equivalent. - (started) | 27 | using FindNotify or equivalent. - (started) |
30 | 28 | ||
31 | h) quota support (needs minor kernel change since quota calls | 29 | g) quota support (needs minor kernel change since quota calls |
32 | to make it to network filesystems or deviceless filesystems) | 30 | to make it to network filesystems or deviceless filesystems) |
33 | 31 | ||
34 | i) investigate sync behavior (including syncpage) and check | 32 | h) investigate sync behavior (including syncpage) and check |
35 | for proper behavior of intr/nointr | 33 | for proper behavior of intr/nointr |
36 | 34 | ||
35 | i) improve support for very old servers (OS/2 and Win9x for example) | ||
36 | Including support for changing the time remotely (utimes command). | ||
37 | |||
37 | j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the | 38 | j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the |
38 | extra copy in/out of the socket buffers in some cases. | 39 | extra copy in/out of the socket buffers in some cases. |
39 | 40 | ||
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index cb52cbbe45ff..f58e41d3ba48 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
@@ -186,6 +186,11 @@ asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len) | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | } | 188 | } |
189 | |||
190 | /* don't trust len bigger than ctx buffer */ | ||
191 | if (*len > ctx->end - ctx->pointer) | ||
192 | return 0; | ||
193 | |||
189 | return 1; | 194 | return 1; |
190 | } | 195 | } |
191 | 196 | ||
@@ -203,6 +208,10 @@ asn1_header_decode(struct asn1_ctx *ctx, | |||
203 | if (!asn1_length_decode(ctx, &def, &len)) | 208 | if (!asn1_length_decode(ctx, &def, &len)) |
204 | return 0; | 209 | return 0; |
205 | 210 | ||
211 | /* primitive shall be definite, indefinite shall be constructed */ | ||
212 | if (*con == ASN1_PRI && !def) | ||
213 | return 0; | ||
214 | |||
206 | if (def) | 215 | if (def) |
207 | *eoc = ctx->pointer + len; | 216 | *eoc = ctx->pointer + len; |
208 | else | 217 | else |
@@ -389,6 +398,11 @@ asn1_oid_decode(struct asn1_ctx *ctx, | |||
389 | unsigned long *optr; | 398 | unsigned long *optr; |
390 | 399 | ||
391 | size = eoc - ctx->pointer + 1; | 400 | size = eoc - ctx->pointer + 1; |
401 | |||
402 | /* first subid actually encodes first two subids */ | ||
403 | if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) | ||
404 | return 0; | ||
405 | |||
392 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); | 406 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); |
393 | if (*oid == NULL) | 407 | if (*oid == NULL) |
394 | return 0; | 408 | return 0; |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index f6fdecf6598c..d82374c9e329 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -219,53 +219,6 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, | |||
219 | 219 | ||
220 | } | 220 | } |
221 | 221 | ||
222 | static char *build_full_dfs_path_from_dentry(struct dentry *dentry) | ||
223 | { | ||
224 | char *full_path = NULL; | ||
225 | char *search_path; | ||
226 | char *tmp_path; | ||
227 | size_t l_max_len; | ||
228 | struct cifs_sb_info *cifs_sb; | ||
229 | |||
230 | if (dentry->d_inode == NULL) | ||
231 | return NULL; | ||
232 | |||
233 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); | ||
234 | |||
235 | if (cifs_sb->tcon == NULL) | ||
236 | return NULL; | ||
237 | |||
238 | search_path = build_path_from_dentry(dentry); | ||
239 | if (search_path == NULL) | ||
240 | return NULL; | ||
241 | |||
242 | if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) { | ||
243 | int i; | ||
244 | /* we should use full path name for correct working with DFS */ | ||
245 | l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) + | ||
246 | strnlen(search_path, MAX_PATHCONF) + 1; | ||
247 | tmp_path = kmalloc(l_max_len, GFP_KERNEL); | ||
248 | if (tmp_path == NULL) { | ||
249 | kfree(search_path); | ||
250 | return NULL; | ||
251 | } | ||
252 | strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len); | ||
253 | tmp_path[l_max_len-1] = 0; | ||
254 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | ||
255 | for (i = 0; i < l_max_len; i++) { | ||
256 | if (tmp_path[i] == '\\') | ||
257 | tmp_path[i] = '/'; | ||
258 | } | ||
259 | strncat(tmp_path, search_path, l_max_len - strlen(tmp_path)); | ||
260 | |||
261 | full_path = tmp_path; | ||
262 | kfree(search_path); | ||
263 | } else { | ||
264 | full_path = search_path; | ||
265 | } | ||
266 | return full_path; | ||
267 | } | ||
268 | |||
269 | static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, | 222 | static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, |
270 | struct list_head *mntlist) | 223 | struct list_head *mntlist) |
271 | { | 224 | { |
@@ -333,7 +286,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
333 | goto out_err; | 286 | goto out_err; |
334 | } | 287 | } |
335 | 288 | ||
336 | full_path = build_full_dfs_path_from_dentry(dentry); | 289 | full_path = build_path_from_dentry(dentry); |
337 | if (full_path == NULL) { | 290 | if (full_path == NULL) { |
338 | rc = -ENOMEM; | 291 | rc = -ENOMEM; |
339 | goto out_err; | 292 | goto out_err; |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 8ad2330ba061..877c85409f1f 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ | 30 | #define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ |
31 | #define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ | 31 | #define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ |
32 | #define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ | 32 | #define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ |
33 | #define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ | ||
33 | 34 | ||
34 | struct cifs_sb_info { | 35 | struct cifs_sb_info { |
35 | struct cifsTconInfo *tcon; /* primary mount */ | 36 | struct cifsTconInfo *tcon; /* primary mount */ |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 6653e29637a7..7013aaff6aed 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -119,6 +119,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
119 | dp = description + strlen(description); | 119 | dp = description + strlen(description); |
120 | sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); | 120 | sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); |
121 | 121 | ||
122 | dp = description + strlen(description); | ||
123 | sprintf(dp, ";user=%s", sesInfo->userName); | ||
124 | |||
122 | cFYI(1, ("key description = %s", description)); | 125 | cFYI(1, ("key description = %s", description)); |
123 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); | 126 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); |
124 | 127 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 427a7c695896..86b4d5f405ae 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifsfs.c | 2 | * fs/cifs/cifsfs.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2002,2007 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * Common Internet FileSystem (CIFS) client | 7 | * Common Internet FileSystem (CIFS) client |
@@ -97,9 +97,6 @@ cifs_read_super(struct super_block *sb, void *data, | |||
97 | { | 97 | { |
98 | struct inode *inode; | 98 | struct inode *inode; |
99 | struct cifs_sb_info *cifs_sb; | 99 | struct cifs_sb_info *cifs_sb; |
100 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
101 | int len; | ||
102 | #endif | ||
103 | int rc = 0; | 100 | int rc = 0; |
104 | 101 | ||
105 | /* BB should we make this contingent on mount parm? */ | 102 | /* BB should we make this contingent on mount parm? */ |
@@ -117,15 +114,17 @@ cifs_read_super(struct super_block *sb, void *data, | |||
117 | * complex operation (mount), and in case of fail | 114 | * complex operation (mount), and in case of fail |
118 | * just exit instead of doing mount and attempting | 115 | * just exit instead of doing mount and attempting |
119 | * undo it if this copy fails?*/ | 116 | * undo it if this copy fails?*/ |
120 | len = strlen(data); | 117 | if (data) { |
121 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | 118 | int len = strlen(data); |
122 | if (cifs_sb->mountdata == NULL) { | 119 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); |
123 | kfree(sb->s_fs_info); | 120 | if (cifs_sb->mountdata == NULL) { |
124 | sb->s_fs_info = NULL; | 121 | kfree(sb->s_fs_info); |
125 | return -ENOMEM; | 122 | sb->s_fs_info = NULL; |
123 | return -ENOMEM; | ||
124 | } | ||
125 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
126 | cifs_sb->mountdata[len] = '\0'; | ||
126 | } | 127 | } |
127 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
128 | cifs_sb->mountdata[len] = '\0'; | ||
129 | #endif | 128 | #endif |
130 | 129 | ||
131 | rc = cifs_mount(sb, cifs_sb, data, devname); | 130 | rc = cifs_mount(sb, cifs_sb, data, devname); |
@@ -353,9 +352,41 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
353 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || | 352 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || |
354 | !(cifs_sb->tcon->unix_ext)) | 353 | !(cifs_sb->tcon->unix_ext)) |
355 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | 354 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); |
355 | if (!cifs_sb->tcon->unix_ext) { | ||
356 | seq_printf(s, ",file_mode=0%o,dir_mode=0%o", | ||
357 | cifs_sb->mnt_file_mode, | ||
358 | cifs_sb->mnt_dir_mode); | ||
359 | } | ||
360 | if (cifs_sb->tcon->seal) | ||
361 | seq_printf(s, ",seal"); | ||
362 | if (cifs_sb->tcon->nocase) | ||
363 | seq_printf(s, ",nocase"); | ||
364 | if (cifs_sb->tcon->retry) | ||
365 | seq_printf(s, ",hard"); | ||
356 | } | 366 | } |
357 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 367 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) |
358 | seq_printf(s, ",posixpaths"); | 368 | seq_printf(s, ",posixpaths"); |
369 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) | ||
370 | seq_printf(s, ",setuids"); | ||
371 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | ||
372 | seq_printf(s, ",serverino"); | ||
373 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | ||
374 | seq_printf(s, ",directio"); | ||
375 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | ||
376 | seq_printf(s, ",nouser_xattr"); | ||
377 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | ||
378 | seq_printf(s, ",mapchars"); | ||
379 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | ||
380 | seq_printf(s, ",sfu"); | ||
381 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
382 | seq_printf(s, ",nobrl"); | ||
383 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | ||
384 | seq_printf(s, ",cifsacl"); | ||
385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | ||
386 | seq_printf(s, ",dynperm"); | ||
387 | if (m->mnt_sb->s_flags & MS_POSIXACL) | ||
388 | seq_printf(s, ",acl"); | ||
389 | |||
359 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 390 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
360 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 391 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); |
361 | } | 392 | } |
@@ -657,7 +688,7 @@ const struct file_operations cifs_file_ops = { | |||
657 | .splice_read = generic_file_splice_read, | 688 | .splice_read = generic_file_splice_read, |
658 | .llseek = cifs_llseek, | 689 | .llseek = cifs_llseek, |
659 | #ifdef CONFIG_CIFS_POSIX | 690 | #ifdef CONFIG_CIFS_POSIX |
660 | .ioctl = cifs_ioctl, | 691 | .unlocked_ioctl = cifs_ioctl, |
661 | #endif /* CONFIG_CIFS_POSIX */ | 692 | #endif /* CONFIG_CIFS_POSIX */ |
662 | 693 | ||
663 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 694 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
@@ -677,7 +708,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
677 | .flush = cifs_flush, | 708 | .flush = cifs_flush, |
678 | .splice_read = generic_file_splice_read, | 709 | .splice_read = generic_file_splice_read, |
679 | #ifdef CONFIG_CIFS_POSIX | 710 | #ifdef CONFIG_CIFS_POSIX |
680 | .ioctl = cifs_ioctl, | 711 | .unlocked_ioctl = cifs_ioctl, |
681 | #endif /* CONFIG_CIFS_POSIX */ | 712 | #endif /* CONFIG_CIFS_POSIX */ |
682 | .llseek = cifs_llseek, | 713 | .llseek = cifs_llseek, |
683 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 714 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
@@ -697,7 +728,7 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
697 | .splice_read = generic_file_splice_read, | 728 | .splice_read = generic_file_splice_read, |
698 | .llseek = cifs_llseek, | 729 | .llseek = cifs_llseek, |
699 | #ifdef CONFIG_CIFS_POSIX | 730 | #ifdef CONFIG_CIFS_POSIX |
700 | .ioctl = cifs_ioctl, | 731 | .unlocked_ioctl = cifs_ioctl, |
701 | #endif /* CONFIG_CIFS_POSIX */ | 732 | #endif /* CONFIG_CIFS_POSIX */ |
702 | 733 | ||
703 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 734 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
@@ -716,7 +747,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
716 | .flush = cifs_flush, | 747 | .flush = cifs_flush, |
717 | .splice_read = generic_file_splice_read, | 748 | .splice_read = generic_file_splice_read, |
718 | #ifdef CONFIG_CIFS_POSIX | 749 | #ifdef CONFIG_CIFS_POSIX |
719 | .ioctl = cifs_ioctl, | 750 | .unlocked_ioctl = cifs_ioctl, |
720 | #endif /* CONFIG_CIFS_POSIX */ | 751 | #endif /* CONFIG_CIFS_POSIX */ |
721 | .llseek = cifs_llseek, | 752 | .llseek = cifs_llseek, |
722 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 753 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
@@ -731,7 +762,7 @@ const struct file_operations cifs_dir_ops = { | |||
731 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 762 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
732 | .dir_notify = cifs_dir_notify, | 763 | .dir_notify = cifs_dir_notify, |
733 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 764 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
734 | .ioctl = cifs_ioctl, | 765 | .unlocked_ioctl = cifs_ioctl, |
735 | }; | 766 | }; |
736 | 767 | ||
737 | static void | 768 | static void |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index cd1301a09b3b..25a6cbd15529 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -95,8 +95,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, | |||
95 | size_t, int); | 95 | size_t, int); |
96 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | 96 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); |
97 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 97 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
98 | extern int cifs_ioctl(struct inode *inode, struct file *filep, | 98 | extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); |
99 | unsigned int command, unsigned long arg); | ||
100 | 99 | ||
101 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 100 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
102 | extern const struct export_operations cifs_export_ops; | 101 | extern const struct export_operations cifs_export_ops; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b7d9f698e63e..9cfcf326ead3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -281,6 +281,7 @@ struct cifsTconInfo { | |||
281 | bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ | 281 | bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ |
282 | bool retry:1; | 282 | bool retry:1; |
283 | bool nocase:1; | 283 | bool nocase:1; |
284 | bool seal:1; /* transport encryption for this mounted share */ | ||
284 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol | 285 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol |
285 | for this mount even if server would support */ | 286 | for this mount even if server would support */ |
286 | /* BB add field for back pointer to sb struct(s)? */ | 287 | /* BB add field for back pointer to sb struct(s)? */ |
@@ -332,7 +333,6 @@ struct cifsFileInfo { | |||
332 | bool messageMode:1; /* for pipes: message vs byte mode */ | 333 | bool messageMode:1; /* for pipes: message vs byte mode */ |
333 | atomic_t wrtPending; /* handle in use - defer close */ | 334 | atomic_t wrtPending; /* handle in use - defer close */ |
334 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ | 335 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ |
335 | char *search_resume_name; /* BB removeme BB */ | ||
336 | struct cifs_search_info srch_inf; | 336 | struct cifs_search_info srch_inf; |
337 | }; | 337 | }; |
338 | 338 | ||
@@ -625,7 +625,7 @@ GLOBAL_EXTERN atomic_t tcpSesAllocCount; | |||
625 | GLOBAL_EXTERN atomic_t tcpSesReconnectCount; | 625 | GLOBAL_EXTERN atomic_t tcpSesReconnectCount; |
626 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; | 626 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; |
627 | 627 | ||
628 | /* Various Debug counters to remove someday (BB) */ | 628 | /* Various Debug counters */ |
629 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ | 629 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ |
630 | #ifdef CONFIG_CIFS_STATS2 | 630 | #ifdef CONFIG_CIFS_STATS2 |
631 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ | 631 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index c43bf4b7a556..0f327c224da3 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -79,6 +79,19 @@ | |||
79 | #define TRANS2_GET_DFS_REFERRAL 0x10 | 79 | #define TRANS2_GET_DFS_REFERRAL 0x10 |
80 | #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 | 80 | #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 |
81 | 81 | ||
82 | /* SMB Transact (Named Pipe) subcommand codes */ | ||
83 | #define TRANS_SET_NMPIPE_STATE 0x0001 | ||
84 | #define TRANS_RAW_READ_NMPIPE 0x0011 | ||
85 | #define TRANS_QUERY_NMPIPE_STATE 0x0021 | ||
86 | #define TRANS_QUERY_NMPIPE_INFO 0x0022 | ||
87 | #define TRANS_PEEK_NMPIPE 0x0023 | ||
88 | #define TRANS_TRANSACT_NMPIPE 0x0026 | ||
89 | #define TRANS_RAW_WRITE_NMPIPE 0x0031 | ||
90 | #define TRANS_READ_NMPIPE 0x0036 | ||
91 | #define TRANS_WRITE_NMPIPE 0x0037 | ||
92 | #define TRANS_WAIT_NMPIPE 0x0053 | ||
93 | #define TRANS_CALL_NMPIPE 0x0054 | ||
94 | |||
82 | /* NT Transact subcommand codes */ | 95 | /* NT Transact subcommand codes */ |
83 | #define NT_TRANSACT_CREATE 0x01 | 96 | #define NT_TRANSACT_CREATE 0x01 |
84 | #define NT_TRANSACT_IOCTL 0x02 | 97 | #define NT_TRANSACT_IOCTL 0x02 |
@@ -328,12 +341,13 @@ | |||
328 | #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ | 341 | #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ |
329 | #define CREATE_NO_EA_KNOWLEDGE 0x00000200 | 342 | #define CREATE_NO_EA_KNOWLEDGE 0x00000200 |
330 | #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete | 343 | #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete |
331 | open for recovery flag - should | 344 | "open for recovery" flag - should |
332 | be zero */ | 345 | be zero in any case */ |
346 | #define CREATE_OPEN_FOR_RECOVERY 0x00000400 | ||
333 | #define CREATE_RANDOM_ACCESS 0x00000800 | 347 | #define CREATE_RANDOM_ACCESS 0x00000800 |
334 | #define CREATE_DELETE_ON_CLOSE 0x00001000 | 348 | #define CREATE_DELETE_ON_CLOSE 0x00001000 |
335 | #define CREATE_OPEN_BY_ID 0x00002000 | 349 | #define CREATE_OPEN_BY_ID 0x00002000 |
336 | #define CREATE_OPEN_BACKUP_INTN 0x00004000 | 350 | #define CREATE_OPEN_BACKUP_INTENT 0x00004000 |
337 | #define CREATE_NO_COMPRESSION 0x00008000 | 351 | #define CREATE_NO_COMPRESSION 0x00008000 |
338 | #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ | 352 | #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ |
339 | #define OPEN_REPARSE_POINT 0x00200000 | 353 | #define OPEN_REPARSE_POINT 0x00200000 |
@@ -722,7 +736,6 @@ typedef struct smb_com_tconx_rsp_ext { | |||
722 | #define SMB_CSC_CACHE_AUTO_REINT 0x0004 | 736 | #define SMB_CSC_CACHE_AUTO_REINT 0x0004 |
723 | #define SMB_CSC_CACHE_VDO 0x0008 | 737 | #define SMB_CSC_CACHE_VDO 0x0008 |
724 | #define SMB_CSC_NO_CACHING 0x000C | 738 | #define SMB_CSC_NO_CACHING 0x000C |
725 | |||
726 | #define SMB_UNIQUE_FILE_NAME 0x0010 | 739 | #define SMB_UNIQUE_FILE_NAME 0x0010 |
727 | #define SMB_EXTENDED_SIGNATURES 0x0020 | 740 | #define SMB_EXTENDED_SIGNATURES 0x0020 |
728 | 741 | ||
@@ -806,7 +819,7 @@ typedef struct smb_com_findclose_req { | |||
806 | #define ICOUNT_MASK 0x00FF | 819 | #define ICOUNT_MASK 0x00FF |
807 | #define PIPE_READ_MODE 0x0100 | 820 | #define PIPE_READ_MODE 0x0100 |
808 | #define NAMED_PIPE_TYPE 0x0400 | 821 | #define NAMED_PIPE_TYPE 0x0400 |
809 | #define PIPE_END_POINT 0x0800 | 822 | #define PIPE_END_POINT 0x4000 |
810 | #define BLOCKING_NAMED_PIPE 0x8000 | 823 | #define BLOCKING_NAMED_PIPE 0x8000 |
811 | 824 | ||
812 | typedef struct smb_com_open_req { /* also handles create */ | 825 | typedef struct smb_com_open_req { /* also handles create */ |
@@ -1904,19 +1917,26 @@ typedef struct smb_com_transaction2_get_dfs_refer_req { | |||
1904 | char RequestFileName[1]; | 1917 | char RequestFileName[1]; |
1905 | } __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ; | 1918 | } __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ; |
1906 | 1919 | ||
1920 | #define DFS_VERSION cpu_to_le16(0x0003) | ||
1921 | |||
1922 | /* DFS server target type */ | ||
1923 | #define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */ | ||
1924 | #define DFS_TYPE_ROOT 0x0001 | ||
1925 | |||
1926 | /* Referral Entry Flags */ | ||
1927 | #define DFS_NAME_LIST_REF 0x0200 | ||
1928 | |||
1907 | typedef struct dfs_referral_level_3 { | 1929 | typedef struct dfs_referral_level_3 { |
1908 | __le16 VersionNumber; | 1930 | __le16 VersionNumber; |
1909 | __le16 ReferralSize; | 1931 | __le16 Size; |
1910 | __le16 ServerType; /* 0x0001 = CIFS server */ | 1932 | __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */ |
1911 | __le16 ReferralFlags; /* or proximity - not clear which since it is | 1933 | __le16 ReferralEntryFlags; /* 0x0200 bit set only for domain |
1912 | always set to zero - SNIA spec says 0x01 | 1934 | or DC referral responce */ |
1913 | means strip off PathConsumed chars before | 1935 | __le32 TimeToLive; |
1914 | submitting RequestFileName to remote node */ | ||
1915 | __le16 TimeToLive; | ||
1916 | __le16 Proximity; | ||
1917 | __le16 DfsPathOffset; | 1936 | __le16 DfsPathOffset; |
1918 | __le16 DfsAlternatePathOffset; | 1937 | __le16 DfsAlternatePathOffset; |
1919 | __le16 NetworkAddressOffset; | 1938 | __le16 NetworkAddressOffset; /* offset of the link target */ |
1939 | __le16 ServiceSiteGuid; | ||
1920 | } __attribute__((packed)) REFERRAL3; | 1940 | } __attribute__((packed)) REFERRAL3; |
1921 | 1941 | ||
1922 | typedef struct smb_com_transaction_get_dfs_refer_rsp { | 1942 | typedef struct smb_com_transaction_get_dfs_refer_rsp { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d481f6c5a2be..b9f5e935f821 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -93,7 +93,7 @@ extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); | |||
93 | 93 | ||
94 | extern int cifs_get_inode_info(struct inode **pinode, | 94 | extern int cifs_get_inode_info(struct inode **pinode, |
95 | const unsigned char *search_path, | 95 | const unsigned char *search_path, |
96 | FILE_ALL_INFO * pfile_info, | 96 | FILE_ALL_INFO *pfile_info, |
97 | struct super_block *sb, int xid, const __u16 *pfid); | 97 | struct super_block *sb, int xid, const __u16 *pfid); |
98 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 98 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
99 | const unsigned char *search_path, | 99 | const unsigned char *search_path, |
@@ -130,7 +130,7 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, | |||
130 | 130 | ||
131 | extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 131 | extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |
132 | const unsigned char *searchName, | 132 | const unsigned char *searchName, |
133 | FILE_ALL_INFO * findData, | 133 | FILE_ALL_INFO *findData, |
134 | int legacy /* whether to use old info level */, | 134 | int legacy /* whether to use old info level */, |
135 | const struct nls_table *nls_codepage, int remap); | 135 | const struct nls_table *nls_codepage, int remap); |
136 | extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 136 | extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, |
@@ -141,18 +141,15 @@ extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | |||
141 | extern int CIFSSMBUnixQPathInfo(const int xid, | 141 | extern int CIFSSMBUnixQPathInfo(const int xid, |
142 | struct cifsTconInfo *tcon, | 142 | struct cifsTconInfo *tcon, |
143 | const unsigned char *searchName, | 143 | const unsigned char *searchName, |
144 | FILE_UNIX_BASIC_INFO * pFindData, | 144 | FILE_UNIX_BASIC_INFO *pFindData, |
145 | const struct nls_table *nls_codepage, int remap); | 145 | const struct nls_table *nls_codepage, int remap); |
146 | 146 | ||
147 | extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 147 | extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, |
148 | const unsigned char *searchName, | 148 | const unsigned char *searchName, |
149 | unsigned char **targetUNCs, | 149 | struct dfs_info3_param **target_nodes, |
150 | unsigned int *number_of_UNC_in_array, | 150 | unsigned int *number_of_nodes_in_array, |
151 | const struct nls_table *nls_codepage, int remap); | 151 | const struct nls_table *nls_codepage, int remap); |
152 | 152 | ||
153 | extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | ||
154 | const char *old_path, | ||
155 | const struct nls_table *nls_codepage, int remap); | ||
156 | extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 153 | extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, |
157 | const char *old_path, | 154 | const char *old_path, |
158 | const struct nls_table *nls_codepage, | 155 | const struct nls_table *nls_codepage, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 95fbba4ea7d4..4511b708f0f3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -81,6 +81,40 @@ static struct { | |||
81 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ | 81 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ |
82 | #endif /* CIFS_POSIX */ | 82 | #endif /* CIFS_POSIX */ |
83 | 83 | ||
84 | /* Allocates buffer into dst and copies smb string from src to it. | ||
85 | * caller is responsible for freeing dst if function returned 0. | ||
86 | * returns: | ||
87 | * on success - 0 | ||
88 | * on failure - errno | ||
89 | */ | ||
90 | static int | ||
91 | cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, | ||
92 | const bool is_unicode, const struct nls_table *nls_codepage) | ||
93 | { | ||
94 | int plen; | ||
95 | |||
96 | if (is_unicode) { | ||
97 | plen = UniStrnlen((wchar_t *)src, maxlen); | ||
98 | *dst = kmalloc(plen + 2, GFP_KERNEL); | ||
99 | if (!*dst) | ||
100 | goto cifs_strncpy_to_host_ErrExit; | ||
101 | cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); | ||
102 | } else { | ||
103 | plen = strnlen(src, maxlen); | ||
104 | *dst = kmalloc(plen + 2, GFP_KERNEL); | ||
105 | if (!*dst) | ||
106 | goto cifs_strncpy_to_host_ErrExit; | ||
107 | strncpy(*dst, src, plen); | ||
108 | } | ||
109 | (*dst)[plen] = 0; | ||
110 | (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */ | ||
111 | return 0; | ||
112 | |||
113 | cifs_strncpy_to_host_ErrExit: | ||
114 | cERROR(1, ("Failed to allocate buffer for string\n")); | ||
115 | return -ENOMEM; | ||
116 | } | ||
117 | |||
84 | 118 | ||
85 | /* Mark as invalid, all open files on tree connections since they | 119 | /* Mark as invalid, all open files on tree connections since they |
86 | were closed when session to server was lost */ | 120 | were closed when session to server was lost */ |
@@ -1166,6 +1200,20 @@ static __u16 convert_disposition(int disposition) | |||
1166 | return ofun; | 1200 | return ofun; |
1167 | } | 1201 | } |
1168 | 1202 | ||
1203 | static int | ||
1204 | access_flags_to_smbopen_mode(const int access_flags) | ||
1205 | { | ||
1206 | int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); | ||
1207 | |||
1208 | if (masked_flags == GENERIC_READ) | ||
1209 | return SMBOPEN_READ; | ||
1210 | else if (masked_flags == GENERIC_WRITE) | ||
1211 | return SMBOPEN_WRITE; | ||
1212 | |||
1213 | /* just go for read/write */ | ||
1214 | return SMBOPEN_READWRITE; | ||
1215 | } | ||
1216 | |||
1169 | int | 1217 | int |
1170 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | 1218 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, |
1171 | const char *fileName, const int openDisposition, | 1219 | const char *fileName, const int openDisposition, |
@@ -1207,13 +1255,7 @@ OldOpenRetry: | |||
1207 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); | 1255 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); |
1208 | 1256 | ||
1209 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); | 1257 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); |
1210 | /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ | 1258 | pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags)); |
1211 | /* 0 = read | ||
1212 | 1 = write | ||
1213 | 2 = rw | ||
1214 | 3 = execute | ||
1215 | */ | ||
1216 | pSMB->Mode = cpu_to_le16(2); | ||
1217 | pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ | 1259 | pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ |
1218 | /* set file as system file if special file such | 1260 | /* set file as system file if special file such |
1219 | as fifo and server expecting SFU style and | 1261 | as fifo and server expecting SFU style and |
@@ -1247,7 +1289,7 @@ OldOpenRetry: | |||
1247 | } else { | 1289 | } else { |
1248 | /* BB verify if wct == 15 */ | 1290 | /* BB verify if wct == 15 */ |
1249 | 1291 | ||
1250 | /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */ | 1292 | /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/ |
1251 | 1293 | ||
1252 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | 1294 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ |
1253 | /* Let caller know file was created so we can set the mode. */ | 1295 | /* Let caller know file was created so we can set the mode. */ |
@@ -1686,7 +1728,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1686 | { | 1728 | { |
1687 | int rc = 0; | 1729 | int rc = 0; |
1688 | LOCK_REQ *pSMB = NULL; | 1730 | LOCK_REQ *pSMB = NULL; |
1689 | LOCK_RSP *pSMBr = NULL; | 1731 | /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ |
1690 | int bytes_returned; | 1732 | int bytes_returned; |
1691 | int timeout = 0; | 1733 | int timeout = 0; |
1692 | __u16 count; | 1734 | __u16 count; |
@@ -1697,8 +1739,6 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1697 | if (rc) | 1739 | if (rc) |
1698 | return rc; | 1740 | return rc; |
1699 | 1741 | ||
1700 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | ||
1701 | |||
1702 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1742 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1703 | timeout = CIFS_ASYNC_OP; /* no response expected */ | 1743 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1704 | pSMB->Timeout = 0; | 1744 | pSMB->Timeout = 0; |
@@ -1732,7 +1772,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1732 | 1772 | ||
1733 | if (waitFlag) { | 1773 | if (waitFlag) { |
1734 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1774 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1735 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1775 | (struct smb_hdr *) pSMB, &bytes_returned); |
1736 | cifs_small_buf_release(pSMB); | 1776 | cifs_small_buf_release(pSMB); |
1737 | } else { | 1777 | } else { |
1738 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, | 1778 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
@@ -1767,7 +1807,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1767 | cFYI(1, ("Posix Lock")); | 1807 | cFYI(1, ("Posix Lock")); |
1768 | 1808 | ||
1769 | if (pLockData == NULL) | 1809 | if (pLockData == NULL) |
1770 | return EINVAL; | 1810 | return -EINVAL; |
1771 | 1811 | ||
1772 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | 1812 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); |
1773 | 1813 | ||
@@ -1944,7 +1984,7 @@ renameRetry: | |||
1944 | /* protocol requires ASCII signature byte on Unicode string */ | 1984 | /* protocol requires ASCII signature byte on Unicode string */ |
1945 | pSMB->OldFileName[name_len + 1] = 0x00; | 1985 | pSMB->OldFileName[name_len + 1] = 0x00; |
1946 | name_len2 = | 1986 | name_len2 = |
1947 | cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2], | 1987 | cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], |
1948 | toName, PATH_MAX, nls_codepage, remap); | 1988 | toName, PATH_MAX, nls_codepage, remap); |
1949 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; | 1989 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
1950 | name_len2 *= 2; /* convert to bytes */ | 1990 | name_len2 *= 2; /* convert to bytes */ |
@@ -2117,8 +2157,7 @@ copyRetry: | |||
2117 | cFYI(1, ("Send error in copy = %d with %d files copied", | 2157 | cFYI(1, ("Send error in copy = %d with %d files copied", |
2118 | rc, le16_to_cpu(pSMBr->CopyCount))); | 2158 | rc, le16_to_cpu(pSMBr->CopyCount))); |
2119 | } | 2159 | } |
2120 | if (pSMB) | 2160 | cifs_buf_release(pSMB); |
2121 | cifs_buf_release(pSMB); | ||
2122 | 2161 | ||
2123 | if (rc == -EAGAIN) | 2162 | if (rc == -EAGAIN) |
2124 | goto copyRetry; | 2163 | goto copyRetry; |
@@ -2207,8 +2246,7 @@ createSymLinkRetry: | |||
2207 | if (rc) | 2246 | if (rc) |
2208 | cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); | 2247 | cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); |
2209 | 2248 | ||
2210 | if (pSMB) | 2249 | cifs_buf_release(pSMB); |
2211 | cifs_buf_release(pSMB); | ||
2212 | 2250 | ||
2213 | if (rc == -EAGAIN) | 2251 | if (rc == -EAGAIN) |
2214 | goto createSymLinkRetry; | 2252 | goto createSymLinkRetry; |
@@ -2925,7 +2963,8 @@ setAclRetry: | |||
2925 | } | 2963 | } |
2926 | params = 6 + name_len; | 2964 | params = 6 + name_len; |
2927 | pSMB->MaxParameterCount = cpu_to_le16(2); | 2965 | pSMB->MaxParameterCount = cpu_to_le16(2); |
2928 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ | 2966 | /* BB find max SMB size from sess */ |
2967 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
2929 | pSMB->MaxSetupCount = 0; | 2968 | pSMB->MaxSetupCount = 0; |
2930 | pSMB->Reserved = 0; | 2969 | pSMB->Reserved = 0; |
2931 | pSMB->Flags = 0; | 2970 | pSMB->Flags = 0; |
@@ -3322,7 +3361,8 @@ QPathInfoRetry: | |||
3322 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 3361 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
3323 | pSMB->TotalDataCount = 0; | 3362 | pSMB->TotalDataCount = 0; |
3324 | pSMB->MaxParameterCount = cpu_to_le16(2); | 3363 | pSMB->MaxParameterCount = cpu_to_le16(2); |
3325 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 3364 | /* BB find exact max SMB PDU from sess structure BB */ |
3365 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
3326 | pSMB->MaxSetupCount = 0; | 3366 | pSMB->MaxSetupCount = 0; |
3327 | pSMB->Reserved = 0; | 3367 | pSMB->Reserved = 0; |
3328 | pSMB->Flags = 0; | 3368 | pSMB->Flags = 0; |
@@ -3388,7 +3428,7 @@ QPathInfoRetry: | |||
3388 | int | 3428 | int |
3389 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, | 3429 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, |
3390 | const unsigned char *searchName, | 3430 | const unsigned char *searchName, |
3391 | FILE_UNIX_BASIC_INFO * pFindData, | 3431 | FILE_UNIX_BASIC_INFO *pFindData, |
3392 | const struct nls_table *nls_codepage, int remap) | 3432 | const struct nls_table *nls_codepage, int remap) |
3393 | { | 3433 | { |
3394 | /* SMB_QUERY_FILE_UNIX_BASIC */ | 3434 | /* SMB_QUERY_FILE_UNIX_BASIC */ |
@@ -3679,6 +3719,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3679 | if (rc) { | 3719 | if (rc) { |
3680 | if (rc == -EBADF) { | 3720 | if (rc == -EBADF) { |
3681 | psrch_inf->endOfSearch = true; | 3721 | psrch_inf->endOfSearch = true; |
3722 | cifs_buf_release(pSMB); | ||
3682 | rc = 0; /* search probably was closed at end of search*/ | 3723 | rc = 0; /* search probably was closed at end of search*/ |
3683 | } else | 3724 | } else |
3684 | cFYI(1, ("FindNext returned = %d", rc)); | 3725 | cFYI(1, ("FindNext returned = %d", rc)); |
@@ -3856,25 +3897,112 @@ GetInodeNumOut: | |||
3856 | return rc; | 3897 | return rc; |
3857 | } | 3898 | } |
3858 | 3899 | ||
3900 | /* parses DFS refferal V3 structure | ||
3901 | * caller is responsible for freeing target_nodes | ||
3902 | * returns: | ||
3903 | * on success - 0 | ||
3904 | * on failure - errno | ||
3905 | */ | ||
3906 | static int | ||
3907 | parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | ||
3908 | unsigned int *num_of_nodes, | ||
3909 | struct dfs_info3_param **target_nodes, | ||
3910 | const struct nls_table *nls_codepage) | ||
3911 | { | ||
3912 | int i, rc = 0; | ||
3913 | char *data_end; | ||
3914 | bool is_unicode; | ||
3915 | struct dfs_referral_level_3 *ref; | ||
3916 | |||
3917 | is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE; | ||
3918 | *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); | ||
3919 | |||
3920 | if (*num_of_nodes < 1) { | ||
3921 | cERROR(1, ("num_referrals: must be at least > 0," | ||
3922 | "but we get num_referrals = %d\n", *num_of_nodes)); | ||
3923 | rc = -EINVAL; | ||
3924 | goto parse_DFS_referrals_exit; | ||
3925 | } | ||
3926 | |||
3927 | ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); | ||
3928 | if (ref->VersionNumber != cpu_to_le16(3)) { | ||
3929 | cERROR(1, ("Referrals of V%d version are not supported," | ||
3930 | "should be V3", le16_to_cpu(ref->VersionNumber))); | ||
3931 | rc = -EINVAL; | ||
3932 | goto parse_DFS_referrals_exit; | ||
3933 | } | ||
3934 | |||
3935 | /* get the upper boundary of the resp buffer */ | ||
3936 | data_end = (char *)(&(pSMBr->PathConsumed)) + | ||
3937 | le16_to_cpu(pSMBr->t2.DataCount); | ||
3938 | |||
3939 | cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", | ||
3940 | *num_of_nodes, | ||
3941 | le16_to_cpu(pSMBr->DFSFlags))); | ||
3942 | |||
3943 | *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * | ||
3944 | *num_of_nodes, GFP_KERNEL); | ||
3945 | if (*target_nodes == NULL) { | ||
3946 | cERROR(1, ("Failed to allocate buffer for target_nodes\n")); | ||
3947 | rc = -ENOMEM; | ||
3948 | goto parse_DFS_referrals_exit; | ||
3949 | } | ||
3950 | |||
3951 | /* collect neccessary data from referrals */ | ||
3952 | for (i = 0; i < *num_of_nodes; i++) { | ||
3953 | char *temp; | ||
3954 | int max_len; | ||
3955 | struct dfs_info3_param *node = (*target_nodes)+i; | ||
3956 | |||
3957 | node->flags = le16_to_cpu(pSMBr->DFSFlags); | ||
3958 | node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); | ||
3959 | node->server_type = le16_to_cpu(ref->ServerType); | ||
3960 | node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); | ||
3961 | |||
3962 | /* copy DfsPath */ | ||
3963 | temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); | ||
3964 | max_len = data_end - temp; | ||
3965 | rc = cifs_strncpy_to_host(&(node->path_name), temp, | ||
3966 | max_len, is_unicode, nls_codepage); | ||
3967 | if (rc) | ||
3968 | goto parse_DFS_referrals_exit; | ||
3969 | |||
3970 | /* copy link target UNC */ | ||
3971 | temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); | ||
3972 | max_len = data_end - temp; | ||
3973 | rc = cifs_strncpy_to_host(&(node->node_name), temp, | ||
3974 | max_len, is_unicode, nls_codepage); | ||
3975 | if (rc) | ||
3976 | goto parse_DFS_referrals_exit; | ||
3977 | |||
3978 | ref += le16_to_cpu(ref->Size); | ||
3979 | } | ||
3980 | |||
3981 | parse_DFS_referrals_exit: | ||
3982 | if (rc) { | ||
3983 | free_dfs_info_array(*target_nodes, *num_of_nodes); | ||
3984 | *target_nodes = NULL; | ||
3985 | *num_of_nodes = 0; | ||
3986 | } | ||
3987 | return rc; | ||
3988 | } | ||
3989 | |||
3859 | int | 3990 | int |
3860 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 3991 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, |
3861 | const unsigned char *searchName, | 3992 | const unsigned char *searchName, |
3862 | unsigned char **targetUNCs, | 3993 | struct dfs_info3_param **target_nodes, |
3863 | unsigned int *number_of_UNC_in_array, | 3994 | unsigned int *num_of_nodes, |
3864 | const struct nls_table *nls_codepage, int remap) | 3995 | const struct nls_table *nls_codepage, int remap) |
3865 | { | 3996 | { |
3866 | /* TRANS2_GET_DFS_REFERRAL */ | 3997 | /* TRANS2_GET_DFS_REFERRAL */ |
3867 | TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; | 3998 | TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; |
3868 | TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; | 3999 | TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; |
3869 | struct dfs_referral_level_3 *referrals = NULL; | ||
3870 | int rc = 0; | 4000 | int rc = 0; |
3871 | int bytes_returned; | 4001 | int bytes_returned; |
3872 | int name_len; | 4002 | int name_len; |
3873 | unsigned int i; | ||
3874 | char *temp; | ||
3875 | __u16 params, byte_count; | 4003 | __u16 params, byte_count; |
3876 | *number_of_UNC_in_array = 0; | 4004 | *num_of_nodes = 0; |
3877 | *targetUNCs = NULL; | 4005 | *target_nodes = NULL; |
3878 | 4006 | ||
3879 | cFYI(1, ("In GetDFSRefer the path %s", searchName)); | 4007 | cFYI(1, ("In GetDFSRefer the path %s", searchName)); |
3880 | if (ses == NULL) | 4008 | if (ses == NULL) |
@@ -3921,7 +4049,8 @@ getDFSRetry: | |||
3921 | pSMB->DataCount = 0; | 4049 | pSMB->DataCount = 0; |
3922 | pSMB->DataOffset = 0; | 4050 | pSMB->DataOffset = 0; |
3923 | pSMB->MaxParameterCount = 0; | 4051 | pSMB->MaxParameterCount = 0; |
3924 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 4052 | /* BB find exact max SMB PDU from sess structure BB */ |
4053 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
3925 | pSMB->MaxSetupCount = 0; | 4054 | pSMB->MaxSetupCount = 0; |
3926 | pSMB->Reserved = 0; | 4055 | pSMB->Reserved = 0; |
3927 | pSMB->Flags = 0; | 4056 | pSMB->Flags = 0; |
@@ -3943,103 +4072,26 @@ getDFSRetry: | |||
3943 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4072 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
3944 | if (rc) { | 4073 | if (rc) { |
3945 | cFYI(1, ("Send error in GetDFSRefer = %d", rc)); | 4074 | cFYI(1, ("Send error in GetDFSRefer = %d", rc)); |
3946 | } else { /* decode response */ | 4075 | goto GetDFSRefExit; |
3947 | /* BB Add logic to parse referrals here */ | 4076 | } |
3948 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4077 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3949 | 4078 | ||
3950 | /* BB Also check if enough total bytes returned? */ | 4079 | /* BB Also check if enough total bytes returned? */ |
3951 | if (rc || (pSMBr->ByteCount < 17)) | 4080 | if (rc || (pSMBr->ByteCount < 17)) { |
3952 | rc = -EIO; /* bad smb */ | 4081 | rc = -EIO; /* bad smb */ |
3953 | else { | 4082 | goto GetDFSRefExit; |
3954 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4083 | } |
3955 | __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); | ||
3956 | 4084 | ||
3957 | cFYI(1, | 4085 | cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", |
3958 | ("Decoding GetDFSRefer response BCC: %d Offset %d", | 4086 | pSMBr->ByteCount, |
3959 | pSMBr->ByteCount, data_offset)); | 4087 | le16_to_cpu(pSMBr->t2.DataOffset))); |
3960 | referrals = | ||
3961 | (struct dfs_referral_level_3 *) | ||
3962 | (8 /* sizeof start of data block */ + | ||
3963 | data_offset + | ||
3964 | (char *) &pSMBr->hdr.Protocol); | ||
3965 | cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n" | ||
3966 | "for referral one refer size: 0x%x srv " | ||
3967 | "type: 0x%x refer flags: 0x%x ttl: 0x%x", | ||
3968 | le16_to_cpu(pSMBr->NumberOfReferrals), | ||
3969 | le16_to_cpu(pSMBr->DFSFlags), | ||
3970 | le16_to_cpu(referrals->ReferralSize), | ||
3971 | le16_to_cpu(referrals->ServerType), | ||
3972 | le16_to_cpu(referrals->ReferralFlags), | ||
3973 | le16_to_cpu(referrals->TimeToLive))); | ||
3974 | /* BB This field is actually two bytes in from start of | ||
3975 | data block so we could do safety check that DataBlock | ||
3976 | begins at address of pSMBr->NumberOfReferrals */ | ||
3977 | *number_of_UNC_in_array = | ||
3978 | le16_to_cpu(pSMBr->NumberOfReferrals); | ||
3979 | |||
3980 | /* BB Fix below so can return more than one referral */ | ||
3981 | if (*number_of_UNC_in_array > 1) | ||
3982 | *number_of_UNC_in_array = 1; | ||
3983 | |||
3984 | /* get the length of the strings describing refs */ | ||
3985 | name_len = 0; | ||
3986 | for (i = 0; i < *number_of_UNC_in_array; i++) { | ||
3987 | /* make sure that DfsPathOffset not past end */ | ||
3988 | __u16 offset = | ||
3989 | le16_to_cpu(referrals->DfsPathOffset); | ||
3990 | if (offset > data_count) { | ||
3991 | /* if invalid referral, stop here and do | ||
3992 | not try to copy any more */ | ||
3993 | *number_of_UNC_in_array = i; | ||
3994 | break; | ||
3995 | } | ||
3996 | temp = ((char *)referrals) + offset; | ||
3997 | 4088 | ||
3998 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { | 4089 | /* parse returned result into more usable form */ |
3999 | name_len += UniStrnlen((wchar_t *)temp, | 4090 | rc = parse_DFS_referrals(pSMBr, num_of_nodes, |
4000 | data_count); | 4091 | target_nodes, nls_codepage); |
4001 | } else { | ||
4002 | name_len += strnlen(temp, data_count); | ||
4003 | } | ||
4004 | referrals++; | ||
4005 | /* BB add check that referral pointer does | ||
4006 | not fall off end PDU */ | ||
4007 | } | ||
4008 | /* BB add check for name_len bigger than bcc */ | ||
4009 | *targetUNCs = | ||
4010 | kmalloc(name_len+1+(*number_of_UNC_in_array), | ||
4011 | GFP_KERNEL); | ||
4012 | if (*targetUNCs == NULL) { | ||
4013 | rc = -ENOMEM; | ||
4014 | goto GetDFSRefExit; | ||
4015 | } | ||
4016 | /* copy the ref strings */ | ||
4017 | referrals = (struct dfs_referral_level_3 *) | ||
4018 | (8 /* sizeof data hdr */ + data_offset + | ||
4019 | (char *) &pSMBr->hdr.Protocol); | ||
4020 | |||
4021 | for (i = 0; i < *number_of_UNC_in_array; i++) { | ||
4022 | temp = ((char *)referrals) + | ||
4023 | le16_to_cpu(referrals->DfsPathOffset); | ||
4024 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
4025 | cifs_strfromUCS_le(*targetUNCs, | ||
4026 | (__le16 *) temp, | ||
4027 | name_len, | ||
4028 | nls_codepage); | ||
4029 | } else { | ||
4030 | strncpy(*targetUNCs, temp, name_len); | ||
4031 | } | ||
4032 | /* BB update target_uncs pointers */ | ||
4033 | referrals++; | ||
4034 | } | ||
4035 | temp = *targetUNCs; | ||
4036 | temp[name_len] = 0; | ||
4037 | } | ||
4038 | 4092 | ||
4039 | } | ||
4040 | GetDFSRefExit: | 4093 | GetDFSRefExit: |
4041 | if (pSMB) | 4094 | cifs_buf_release(pSMB); |
4042 | cifs_buf_release(pSMB); | ||
4043 | 4095 | ||
4044 | if (rc == -EAGAIN) | 4096 | if (rc == -EAGAIN) |
4045 | goto getDFSRetry; | 4097 | goto getDFSRetry; |
@@ -4229,7 +4281,8 @@ QFSAttributeRetry: | |||
4229 | params = 2; /* level */ | 4281 | params = 2; /* level */ |
4230 | pSMB->TotalDataCount = 0; | 4282 | pSMB->TotalDataCount = 0; |
4231 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4283 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4232 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4284 | /* BB find exact max SMB PDU from sess structure BB */ |
4285 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4233 | pSMB->MaxSetupCount = 0; | 4286 | pSMB->MaxSetupCount = 0; |
4234 | pSMB->Reserved = 0; | 4287 | pSMB->Reserved = 0; |
4235 | pSMB->Flags = 0; | 4288 | pSMB->Flags = 0; |
@@ -4298,7 +4351,8 @@ QFSDeviceRetry: | |||
4298 | params = 2; /* level */ | 4351 | params = 2; /* level */ |
4299 | pSMB->TotalDataCount = 0; | 4352 | pSMB->TotalDataCount = 0; |
4300 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4353 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4301 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4354 | /* BB find exact max SMB PDU from sess structure BB */ |
4355 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4302 | pSMB->MaxSetupCount = 0; | 4356 | pSMB->MaxSetupCount = 0; |
4303 | pSMB->Reserved = 0; | 4357 | pSMB->Reserved = 0; |
4304 | pSMB->Flags = 0; | 4358 | pSMB->Flags = 0; |
@@ -4369,7 +4423,8 @@ QFSUnixRetry: | |||
4369 | pSMB->DataCount = 0; | 4423 | pSMB->DataCount = 0; |
4370 | pSMB->DataOffset = 0; | 4424 | pSMB->DataOffset = 0; |
4371 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4425 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4372 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | 4426 | /* BB find exact max SMB PDU from sess structure BB */ |
4427 | pSMB->MaxDataCount = cpu_to_le16(100); | ||
4373 | pSMB->MaxSetupCount = 0; | 4428 | pSMB->MaxSetupCount = 0; |
4374 | pSMB->Reserved = 0; | 4429 | pSMB->Reserved = 0; |
4375 | pSMB->Flags = 0; | 4430 | pSMB->Flags = 0; |
@@ -4444,7 +4499,8 @@ SETFSUnixRetry: | |||
4444 | offset = param_offset + params; | 4499 | offset = param_offset + params; |
4445 | 4500 | ||
4446 | pSMB->MaxParameterCount = cpu_to_le16(4); | 4501 | pSMB->MaxParameterCount = cpu_to_le16(4); |
4447 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | 4502 | /* BB find exact max SMB PDU from sess structure BB */ |
4503 | pSMB->MaxDataCount = cpu_to_le16(100); | ||
4448 | pSMB->SetupCount = 1; | 4504 | pSMB->SetupCount = 1; |
4449 | pSMB->Reserved3 = 0; | 4505 | pSMB->Reserved3 = 0; |
4450 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); | 4506 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); |
@@ -4512,7 +4568,8 @@ QFSPosixRetry: | |||
4512 | pSMB->DataCount = 0; | 4568 | pSMB->DataCount = 0; |
4513 | pSMB->DataOffset = 0; | 4569 | pSMB->DataOffset = 0; |
4514 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4570 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4515 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | 4571 | /* BB find exact max SMB PDU from sess structure BB */ |
4572 | pSMB->MaxDataCount = cpu_to_le16(100); | ||
4516 | pSMB->MaxSetupCount = 0; | 4573 | pSMB->MaxSetupCount = 0; |
4517 | pSMB->Reserved = 0; | 4574 | pSMB->Reserved = 0; |
4518 | pSMB->Flags = 0; | 4575 | pSMB->Flags = 0; |
@@ -4702,7 +4759,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4702 | 4759 | ||
4703 | count = sizeof(struct file_end_of_file_info); | 4760 | count = sizeof(struct file_end_of_file_info); |
4704 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4761 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4705 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ | 4762 | /* BB find exact max SMB PDU from sess structure BB */ |
4763 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4706 | pSMB->SetupCount = 1; | 4764 | pSMB->SetupCount = 1; |
4707 | pSMB->Reserved3 = 0; | 4765 | pSMB->Reserved3 = 0; |
4708 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | 4766 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); |
@@ -4789,7 +4847,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4789 | 4847 | ||
4790 | count = sizeof(FILE_BASIC_INFO); | 4848 | count = sizeof(FILE_BASIC_INFO); |
4791 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4849 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4792 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ | 4850 | /* BB find max SMB PDU from sess */ |
4851 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4793 | pSMB->SetupCount = 1; | 4852 | pSMB->SetupCount = 1; |
4794 | pSMB->Reserved3 = 0; | 4853 | pSMB->Reserved3 = 0; |
4795 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | 4854 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); |
@@ -4856,7 +4915,8 @@ SetTimesRetry: | |||
4856 | params = 6 + name_len; | 4915 | params = 6 + name_len; |
4857 | count = sizeof(FILE_BASIC_INFO); | 4916 | count = sizeof(FILE_BASIC_INFO); |
4858 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4917 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4859 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4918 | /* BB find max SMB PDU from sess structure BB */ |
4919 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4860 | pSMB->MaxSetupCount = 0; | 4920 | pSMB->MaxSetupCount = 0; |
4861 | pSMB->Reserved = 0; | 4921 | pSMB->Reserved = 0; |
4862 | pSMB->Flags = 0; | 4922 | pSMB->Flags = 0; |
@@ -4986,7 +5046,8 @@ setPermsRetry: | |||
4986 | params = 6 + name_len; | 5046 | params = 6 + name_len; |
4987 | count = sizeof(FILE_UNIX_BASIC_INFO); | 5047 | count = sizeof(FILE_UNIX_BASIC_INFO); |
4988 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5048 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4989 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 5049 | /* BB find max SMB PDU from sess structure BB */ |
5050 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4990 | pSMB->MaxSetupCount = 0; | 5051 | pSMB->MaxSetupCount = 0; |
4991 | pSMB->Reserved = 0; | 5052 | pSMB->Reserved = 0; |
4992 | pSMB->Flags = 0; | 5053 | pSMB->Flags = 0; |
@@ -5051,8 +5112,7 @@ setPermsRetry: | |||
5051 | if (rc) | 5112 | if (rc) |
5052 | cFYI(1, ("SetPathInfo (perms) returned %d", rc)); | 5113 | cFYI(1, ("SetPathInfo (perms) returned %d", rc)); |
5053 | 5114 | ||
5054 | if (pSMB) | 5115 | cifs_buf_release(pSMB); |
5055 | cifs_buf_release(pSMB); | ||
5056 | if (rc == -EAGAIN) | 5116 | if (rc == -EAGAIN) |
5057 | goto setPermsRetry; | 5117 | goto setPermsRetry; |
5058 | return rc; | 5118 | return rc; |
@@ -5169,7 +5229,8 @@ QAllEAsRetry: | |||
5169 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 5229 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
5170 | pSMB->TotalDataCount = 0; | 5230 | pSMB->TotalDataCount = 0; |
5171 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5231 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5172 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 5232 | /* BB find exact max SMB PDU from sess structure BB */ |
5233 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
5173 | pSMB->MaxSetupCount = 0; | 5234 | pSMB->MaxSetupCount = 0; |
5174 | pSMB->Reserved = 0; | 5235 | pSMB->Reserved = 0; |
5175 | pSMB->Flags = 0; | 5236 | pSMB->Flags = 0; |
@@ -5273,8 +5334,7 @@ QAllEAsRetry: | |||
5273 | } | 5334 | } |
5274 | } | 5335 | } |
5275 | } | 5336 | } |
5276 | if (pSMB) | 5337 | cifs_buf_release(pSMB); |
5277 | cifs_buf_release(pSMB); | ||
5278 | if (rc == -EAGAIN) | 5338 | if (rc == -EAGAIN) |
5279 | goto QAllEAsRetry; | 5339 | goto QAllEAsRetry; |
5280 | 5340 | ||
@@ -5317,7 +5377,8 @@ QEARetry: | |||
5317 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 5377 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
5318 | pSMB->TotalDataCount = 0; | 5378 | pSMB->TotalDataCount = 0; |
5319 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5379 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5320 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 5380 | /* BB find exact max SMB PDU from sess structure BB */ |
5381 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
5321 | pSMB->MaxSetupCount = 0; | 5382 | pSMB->MaxSetupCount = 0; |
5322 | pSMB->Reserved = 0; | 5383 | pSMB->Reserved = 0; |
5323 | pSMB->Flags = 0; | 5384 | pSMB->Flags = 0; |
@@ -5422,8 +5483,7 @@ QEARetry: | |||
5422 | } | 5483 | } |
5423 | } | 5484 | } |
5424 | } | 5485 | } |
5425 | if (pSMB) | 5486 | cifs_buf_release(pSMB); |
5426 | cifs_buf_release(pSMB); | ||
5427 | if (rc == -EAGAIN) | 5487 | if (rc == -EAGAIN) |
5428 | goto QEARetry; | 5488 | goto QEARetry; |
5429 | 5489 | ||
@@ -5475,7 +5535,8 @@ SetEARetry: | |||
5475 | 5535 | ||
5476 | count = sizeof(*parm_data) + ea_value_len + name_len; | 5536 | count = sizeof(*parm_data) + ea_value_len + name_len; |
5477 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5537 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5478 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ | 5538 | /* BB find max SMB PDU from sess */ |
5539 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
5479 | pSMB->MaxSetupCount = 0; | 5540 | pSMB->MaxSetupCount = 0; |
5480 | pSMB->Reserved = 0; | 5541 | pSMB->Reserved = 0; |
5481 | pSMB->Flags = 0; | 5542 | pSMB->Flags = 0; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f428bf3bf1a9..e8fa46c7cff2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -60,7 +60,7 @@ struct smb_vol { | |||
60 | char *domainname; | 60 | char *domainname; |
61 | char *UNC; | 61 | char *UNC; |
62 | char *UNCip; | 62 | char *UNCip; |
63 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ | 63 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ |
64 | char *iocharset; /* local code page for mapping to and from Unicode */ | 64 | char *iocharset; /* local code page for mapping to and from Unicode */ |
65 | char source_rfc1001_name[16]; /* netbios name of client */ | 65 | char source_rfc1001_name[16]; /* netbios name of client */ |
66 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ | 66 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ |
@@ -75,19 +75,21 @@ struct smb_vol { | |||
75 | bool setuids:1; | 75 | bool setuids:1; |
76 | bool override_uid:1; | 76 | bool override_uid:1; |
77 | bool override_gid:1; | 77 | bool override_gid:1; |
78 | bool dynperm:1; | ||
78 | bool noperm:1; | 79 | bool noperm:1; |
79 | bool no_psx_acl:1; /* set if posix acl support should be disabled */ | 80 | bool no_psx_acl:1; /* set if posix acl support should be disabled */ |
80 | bool cifs_acl:1; | 81 | bool cifs_acl:1; |
81 | bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 82 | bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
82 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ | 83 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ |
83 | bool direct_io:1; | 84 | bool direct_io:1; |
84 | bool remap:1; /* set to remap seven reserved chars in filenames */ | 85 | bool remap:1; /* set to remap seven reserved chars in filenames */ |
85 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ | 86 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ |
86 | bool no_linux_ext:1; | 87 | bool no_linux_ext:1; |
87 | bool sfu_emul:1; | 88 | bool sfu_emul:1; |
88 | bool nullauth:1; /* attempt to authenticate with null user */ | 89 | bool nullauth:1; /* attempt to authenticate with null user */ |
89 | unsigned nocase; /* request case insensitive filenames */ | 90 | bool nocase:1; /* request case insensitive filenames */ |
90 | unsigned nobrl; /* disable sending byte range locks to srv */ | 91 | bool nobrl:1; /* disable sending byte range locks to srv */ |
92 | bool seal:1; /* request transport encryption on share */ | ||
91 | unsigned int rsize; | 93 | unsigned int rsize; |
92 | unsigned int wsize; | 94 | unsigned int wsize; |
93 | unsigned int sockopt; | 95 | unsigned int sockopt; |
@@ -651,6 +653,7 @@ multi_t2_fnd: | |||
651 | spin_lock(&GlobalMid_Lock); | 653 | spin_lock(&GlobalMid_Lock); |
652 | server->tcpStatus = CifsExiting; | 654 | server->tcpStatus = CifsExiting; |
653 | spin_unlock(&GlobalMid_Lock); | 655 | spin_unlock(&GlobalMid_Lock); |
656 | wake_up_all(&server->response_q); | ||
654 | 657 | ||
655 | /* don't exit until kthread_stop is called */ | 658 | /* don't exit until kthread_stop is called */ |
656 | set_current_state(TASK_UNINTERRUPTIBLE); | 659 | set_current_state(TASK_UNINTERRUPTIBLE); |
@@ -1246,6 +1249,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1246 | vol->setuids = 1; | 1249 | vol->setuids = 1; |
1247 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 1250 | } else if (strnicmp(data, "nosetuids", 9) == 0) { |
1248 | vol->setuids = 0; | 1251 | vol->setuids = 0; |
1252 | } else if (strnicmp(data, "dynperm", 7) == 0) { | ||
1253 | vol->dynperm = true; | ||
1254 | } else if (strnicmp(data, "nodynperm", 9) == 0) { | ||
1255 | vol->dynperm = false; | ||
1249 | } else if (strnicmp(data, "nohard", 6) == 0) { | 1256 | } else if (strnicmp(data, "nohard", 6) == 0) { |
1250 | vol->retry = 0; | 1257 | vol->retry = 0; |
1251 | } else if (strnicmp(data, "nosoft", 6) == 0) { | 1258 | } else if (strnicmp(data, "nosoft", 6) == 0) { |
@@ -1268,8 +1275,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1268 | vol->no_psx_acl = 1; | 1275 | vol->no_psx_acl = 1; |
1269 | } else if (strnicmp(data, "sign", 4) == 0) { | 1276 | } else if (strnicmp(data, "sign", 4) == 0) { |
1270 | vol->secFlg |= CIFSSEC_MUST_SIGN; | 1277 | vol->secFlg |= CIFSSEC_MUST_SIGN; |
1271 | /* } else if (strnicmp(data, "seal",4) == 0) { | 1278 | } else if (strnicmp(data, "seal", 4) == 0) { |
1272 | vol->secFlg |= CIFSSEC_MUST_SEAL; */ | 1279 | /* we do not do the following in secFlags because seal |
1280 | is a per tree connection (mount) not a per socket | ||
1281 | or per-smb connection option in the protocol */ | ||
1282 | /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ | ||
1283 | vol->seal = 1; | ||
1273 | } else if (strnicmp(data, "direct", 6) == 0) { | 1284 | } else if (strnicmp(data, "direct", 6) == 0) { |
1274 | vol->direct_io = 1; | 1285 | vol->direct_io = 1; |
1275 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { | 1286 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { |
@@ -1414,34 +1425,12 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) | |||
1414 | } | 1425 | } |
1415 | 1426 | ||
1416 | int | 1427 | int |
1417 | connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | ||
1418 | const char *old_path, const struct nls_table *nls_codepage, | ||
1419 | int remap) | ||
1420 | { | ||
1421 | struct dfs_info3_param *referrals = NULL; | ||
1422 | unsigned int num_referrals; | ||
1423 | int rc = 0; | ||
1424 | |||
1425 | rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage, | ||
1426 | &num_referrals, &referrals, remap); | ||
1427 | |||
1428 | /* BB Add in code to: if valid refrl, if not ip address contact | ||
1429 | the helper that resolves tcp names, mount to it, try to | ||
1430 | tcon to it unmount it if fail */ | ||
1431 | |||
1432 | kfree(referrals); | ||
1433 | |||
1434 | return rc; | ||
1435 | } | ||
1436 | |||
1437 | int | ||
1438 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, | 1428 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, |
1439 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, | 1429 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, |
1440 | struct dfs_info3_param **preferrals, int remap) | 1430 | struct dfs_info3_param **preferrals, int remap) |
1441 | { | 1431 | { |
1442 | char *temp_unc; | 1432 | char *temp_unc; |
1443 | int rc = 0; | 1433 | int rc = 0; |
1444 | unsigned char *targetUNCs; | ||
1445 | 1434 | ||
1446 | *pnum_referrals = 0; | 1435 | *pnum_referrals = 0; |
1447 | *preferrals = NULL; | 1436 | *preferrals = NULL; |
@@ -1464,7 +1453,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, | |||
1464 | kfree(temp_unc); | 1453 | kfree(temp_unc); |
1465 | } | 1454 | } |
1466 | if (rc == 0) | 1455 | if (rc == 0) |
1467 | rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &targetUNCs, | 1456 | rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, |
1468 | pnum_referrals, nls_codepage, remap); | 1457 | pnum_referrals, nls_codepage, remap); |
1469 | /* BB map targetUNCs to dfs_info3 structures, here or | 1458 | /* BB map targetUNCs to dfs_info3 structures, here or |
1470 | in CIFSGetDFSRefer BB */ | 1459 | in CIFSGetDFSRefer BB */ |
@@ -1815,7 +1804,7 @@ convert_delimiter(char *path, char delim) | |||
1815 | if (path == NULL) | 1804 | if (path == NULL) |
1816 | return; | 1805 | return; |
1817 | 1806 | ||
1818 | if (delim == '/') | 1807 | if (delim == '/') |
1819 | old_delim = '\\'; | 1808 | old_delim = '\\'; |
1820 | else | 1809 | else |
1821 | old_delim = '/'; | 1810 | old_delim = '/'; |
@@ -2125,11 +2114,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2125 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; | 2114 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; |
2126 | if (volume_info.override_gid) | 2115 | if (volume_info.override_gid) |
2127 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; | 2116 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; |
2117 | if (volume_info.dynperm) | ||
2118 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; | ||
2128 | if (volume_info.direct_io) { | 2119 | if (volume_info.direct_io) { |
2129 | cFYI(1, ("mounting share using direct i/o")); | 2120 | cFYI(1, ("mounting share using direct i/o")); |
2130 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 2121 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
2131 | } | 2122 | } |
2132 | 2123 | ||
2124 | if ((volume_info.cifs_acl) && (volume_info.dynperm)) | ||
2125 | cERROR(1, ("mount option dynperm ignored if cifsacl " | ||
2126 | "mount option supported")); | ||
2127 | |||
2133 | tcon = | 2128 | tcon = |
2134 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, | 2129 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, |
2135 | volume_info.username); | 2130 | volume_info.username); |
@@ -2141,6 +2136,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2141 | for the retry flag is used */ | 2136 | for the retry flag is used */ |
2142 | tcon->retry = volume_info.retry; | 2137 | tcon->retry = volume_info.retry; |
2143 | tcon->nocase = volume_info.nocase; | 2138 | tcon->nocase = volume_info.nocase; |
2139 | if (tcon->seal != volume_info.seal) | ||
2140 | cERROR(1, ("transport encryption setting " | ||
2141 | "conflicts with existing tid")); | ||
2144 | } else { | 2142 | } else { |
2145 | tcon = tconInfoAlloc(); | 2143 | tcon = tconInfoAlloc(); |
2146 | if (tcon == NULL) | 2144 | if (tcon == NULL) |
@@ -2154,10 +2152,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2154 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) | 2152 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) |
2155 | && (strchr(volume_info.UNC + 3, '/') == | 2153 | && (strchr(volume_info.UNC + 3, '/') == |
2156 | NULL)) { | 2154 | NULL)) { |
2157 | rc = connect_to_dfs_path(xid, pSesInfo, | 2155 | /* rc = connect_to_dfs_path(xid, pSesInfo, |
2158 | "", cifs_sb->local_nls, | 2156 | "", cifs_sb->local_nls, |
2159 | cifs_sb->mnt_cifs_flags & | 2157 | cifs_sb->mnt_cifs_flags & |
2160 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2158 | CIFS_MOUNT_MAP_SPECIAL_CHR);*/ |
2159 | cFYI(1, ("DFS root not supported")); | ||
2161 | rc = -ENODEV; | 2160 | rc = -ENODEV; |
2162 | goto out; | 2161 | goto out; |
2163 | } else { | 2162 | } else { |
@@ -2173,6 +2172,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2173 | atomic_inc(&pSesInfo->inUse); | 2172 | atomic_inc(&pSesInfo->inUse); |
2174 | tcon->retry = volume_info.retry; | 2173 | tcon->retry = volume_info.retry; |
2175 | tcon->nocase = volume_info.nocase; | 2174 | tcon->nocase = volume_info.nocase; |
2175 | tcon->seal = volume_info.seal; | ||
2176 | } | 2176 | } |
2177 | } | 2177 | } |
2178 | } | 2178 | } |
@@ -2314,9 +2314,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2314 | user = ses->userName; | 2314 | user = ses->userName; |
2315 | domain = ses->domainName; | 2315 | domain = ses->domainName; |
2316 | smb_buffer = cifs_buf_get(); | 2316 | smb_buffer = cifs_buf_get(); |
2317 | if (smb_buffer == NULL) { | 2317 | |
2318 | if (smb_buffer == NULL) | ||
2318 | return -ENOMEM; | 2319 | return -ENOMEM; |
2319 | } | 2320 | |
2320 | smb_buffer_response = smb_buffer; | 2321 | smb_buffer_response = smb_buffer; |
2321 | pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; | 2322 | pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; |
2322 | 2323 | ||
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e4e0078a0526..fb69c1fa85c9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -49,18 +49,25 @@ build_path_from_dentry(struct dentry *direntry) | |||
49 | struct dentry *temp; | 49 | struct dentry *temp; |
50 | int namelen; | 50 | int namelen; |
51 | int pplen; | 51 | int pplen; |
52 | int dfsplen; | ||
52 | char *full_path; | 53 | char *full_path; |
53 | char dirsep; | 54 | char dirsep; |
55 | struct cifs_sb_info *cifs_sb; | ||
54 | 56 | ||
55 | if (direntry == NULL) | 57 | if (direntry == NULL) |
56 | return NULL; /* not much we can do if dentry is freed and | 58 | return NULL; /* not much we can do if dentry is freed and |
57 | we need to reopen the file after it was closed implicitly | 59 | we need to reopen the file after it was closed implicitly |
58 | when the server crashed */ | 60 | when the server crashed */ |
59 | 61 | ||
60 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | 62 | cifs_sb = CIFS_SB(direntry->d_sb); |
61 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; | 63 | dirsep = CIFS_DIR_SEP(cifs_sb); |
64 | pplen = cifs_sb->prepathlen; | ||
65 | if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) | ||
66 | dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); | ||
67 | else | ||
68 | dfsplen = 0; | ||
62 | cifs_bp_rename_retry: | 69 | cifs_bp_rename_retry: |
63 | namelen = pplen; | 70 | namelen = pplen + dfsplen; |
64 | for (temp = direntry; !IS_ROOT(temp);) { | 71 | for (temp = direntry; !IS_ROOT(temp);) { |
65 | namelen += (1 + temp->d_name.len); | 72 | namelen += (1 + temp->d_name.len); |
66 | temp = temp->d_parent; | 73 | temp = temp->d_parent; |
@@ -91,7 +98,7 @@ cifs_bp_rename_retry: | |||
91 | return NULL; | 98 | return NULL; |
92 | } | 99 | } |
93 | } | 100 | } |
94 | if (namelen != pplen) { | 101 | if (namelen != pplen + dfsplen) { |
95 | cERROR(1, | 102 | cERROR(1, |
96 | ("did not end path lookup where expected namelen is %d", | 103 | ("did not end path lookup where expected namelen is %d", |
97 | namelen)); | 104 | namelen)); |
@@ -107,7 +114,18 @@ cifs_bp_rename_retry: | |||
107 | since the '\' is a valid posix character so we can not switch | 114 | since the '\' is a valid posix character so we can not switch |
108 | those safely to '/' if any are found in the middle of the prepath */ | 115 | those safely to '/' if any are found in the middle of the prepath */ |
109 | /* BB test paths to Windows with '/' in the midst of prepath */ | 116 | /* BB test paths to Windows with '/' in the midst of prepath */ |
110 | strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); | 117 | |
118 | if (dfsplen) { | ||
119 | strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); | ||
120 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { | ||
121 | int i; | ||
122 | for (i = 0; i < dfsplen; i++) { | ||
123 | if (full_path[i] == '\\') | ||
124 | full_path[i] = '/'; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen); | ||
111 | return full_path; | 129 | return full_path; |
112 | } | 130 | } |
113 | 131 | ||
@@ -242,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
242 | buf, inode->i_sb, xid, | 260 | buf, inode->i_sb, xid, |
243 | &fileHandle); | 261 | &fileHandle); |
244 | if (newinode) { | 262 | if (newinode) { |
245 | newinode->i_mode = mode; | 263 | if (cifs_sb->mnt_cifs_flags & |
264 | CIFS_MOUNT_DYNPERM) | ||
265 | newinode->i_mode = mode; | ||
246 | if ((oplock & CIFS_CREATE_ACTION) && | 266 | if ((oplock & CIFS_CREATE_ACTION) && |
247 | (cifs_sb->mnt_cifs_flags & | 267 | (cifs_sb->mnt_cifs_flags & |
248 | CIFS_MOUNT_SET_UID)) { | 268 | CIFS_MOUNT_SET_UID)) { |
@@ -590,7 +610,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, | |||
590 | * case take precedence. If a is not a negative dentry, this | 610 | * case take precedence. If a is not a negative dentry, this |
591 | * should have no side effects | 611 | * should have no side effects |
592 | */ | 612 | */ |
593 | memcpy(a->name, b->name, a->len); | 613 | memcpy((void *)a->name, b->name, a->len); |
594 | return 0; | 614 | return 0; |
595 | } | 615 | } |
596 | return 1; | 616 | return 1; |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 939e256f8497..f730ef35499e 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
@@ -134,10 +134,6 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
134 | rkey = request_key(&key_type_dns_resolver, name, ""); | 134 | rkey = request_key(&key_type_dns_resolver, name, ""); |
135 | if (!IS_ERR(rkey)) { | 135 | if (!IS_ERR(rkey)) { |
136 | data = rkey->payload.data; | 136 | data = rkey->payload.data; |
137 | cFYI(1, ("%s: resolved: %s to %s", __func__, | ||
138 | rkey->description, | ||
139 | *ip_addr | ||
140 | )); | ||
141 | } else { | 137 | } else { |
142 | cERROR(1, ("%s: unable to resolve: %s", __func__, name)); | 138 | cERROR(1, ("%s: unable to resolve: %s", __func__, name)); |
143 | goto out; | 139 | goto out; |
@@ -150,6 +146,11 @@ skip_upcall: | |||
150 | if (*ip_addr) { | 146 | if (*ip_addr) { |
151 | memcpy(*ip_addr, data, len); | 147 | memcpy(*ip_addr, data, len); |
152 | (*ip_addr)[len] = '\0'; | 148 | (*ip_addr)[len] = '\0'; |
149 | if (!IS_ERR(rkey)) | ||
150 | cFYI(1, ("%s: resolved: %s to %s", __func__, | ||
151 | name, | ||
152 | *ip_addr | ||
153 | )); | ||
153 | rc = 0; | 154 | rc = 0; |
154 | } else { | 155 | } else { |
155 | rc = -ENOMEM; | 156 | rc = -ENOMEM; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 31a0a33b9d95..0aac824371a5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -75,7 +75,11 @@ static inline int cifs_convert_flags(unsigned int flags) | |||
75 | return (GENERIC_READ | GENERIC_WRITE); | 75 | return (GENERIC_READ | GENERIC_WRITE); |
76 | } | 76 | } |
77 | 77 | ||
78 | return 0x20197; | 78 | return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | |
79 | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | | ||
80 | FILE_READ_DATA); | ||
81 | |||
82 | |||
79 | } | 83 | } |
80 | 84 | ||
81 | static inline int cifs_get_disposition(unsigned int flags) | 85 | static inline int cifs_get_disposition(unsigned int flags) |
@@ -542,7 +546,6 @@ int cifs_close(struct inode *inode, struct file *file) | |||
542 | msleep(timeout); | 546 | msleep(timeout); |
543 | timeout *= 8; | 547 | timeout *= 8; |
544 | } | 548 | } |
545 | kfree(pSMBFile->search_resume_name); | ||
546 | kfree(file->private_data); | 549 | kfree(file->private_data); |
547 | file->private_data = NULL; | 550 | file->private_data = NULL; |
548 | } else | 551 | } else |
@@ -601,12 +604,6 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
601 | else | 604 | else |
602 | cifs_buf_release(ptmp); | 605 | cifs_buf_release(ptmp); |
603 | } | 606 | } |
604 | ptmp = pCFileStruct->search_resume_name; | ||
605 | if (ptmp) { | ||
606 | cFYI(1, ("closedir free resume name")); | ||
607 | pCFileStruct->search_resume_name = NULL; | ||
608 | kfree(ptmp); | ||
609 | } | ||
610 | kfree(file->private_data); | 607 | kfree(file->private_data); |
611 | file->private_data = NULL; | 608 | file->private_data = NULL; |
612 | } | 609 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fcbdbb6ad7bf..722be543ceec 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -161,118 +161,115 @@ static void cifs_unix_info_to_inode(struct inode *inode, | |||
161 | spin_unlock(&inode->i_lock); | 161 | spin_unlock(&inode->i_lock); |
162 | } | 162 | } |
163 | 163 | ||
164 | static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb, | ||
165 | const char *search_path) | ||
166 | { | ||
167 | int tree_len; | ||
168 | int path_len; | ||
169 | int i; | ||
170 | char *tmp_path; | ||
171 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
172 | |||
173 | if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) | ||
174 | return search_path; | ||
175 | |||
176 | /* use full path name for working with DFS */ | ||
177 | tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); | ||
178 | path_len = strnlen(search_path, MAX_PATHCONF); | ||
179 | 164 | ||
180 | tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); | 165 | /* |
181 | if (tmp_path == NULL) | 166 | * Needed to setup inode data for the directory which is the |
182 | return search_path; | 167 | * junction to the new submount (ie to setup the fake directory |
168 | * which represents a DFS referral) | ||
169 | */ | ||
170 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | ||
171 | struct super_block *sb) | ||
172 | { | ||
173 | struct inode *pinode = NULL; | ||
174 | |||
175 | memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); | ||
176 | |||
177 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | ||
178 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | ||
179 | __u64 UniqueId = 0; */ | ||
180 | pfnd_dat->LastStatusChange = | ||
181 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
182 | pfnd_dat->LastAccessTime = | ||
183 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
184 | pfnd_dat->LastModificationTime = | ||
185 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
186 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | ||
187 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | ||
188 | pfnd_dat->Nlinks = cpu_to_le64(2); | ||
189 | if (sb->s_root) | ||
190 | pinode = sb->s_root->d_inode; | ||
191 | if (pinode == NULL) | ||
192 | return; | ||
183 | 193 | ||
184 | strncpy(tmp_path, pTcon->treeName, tree_len); | 194 | /* fill in default values for the remaining based on root |
185 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 195 | inode since we can not query the server for this inode info */ |
186 | for (i = 0; i < tree_len; i++) { | 196 | pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); |
187 | if (tmp_path[i] == '\\') | 197 | pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); |
188 | tmp_path[i] = '/'; | 198 | pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); |
189 | } | 199 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); |
190 | strncpy(tmp_path+tree_len, search_path, path_len); | ||
191 | tmp_path[tree_len+path_len] = 0; | ||
192 | return tmp_path; | ||
193 | } | 200 | } |
194 | 201 | ||
195 | int cifs_get_inode_info_unix(struct inode **pinode, | 202 | int cifs_get_inode_info_unix(struct inode **pinode, |
196 | const unsigned char *search_path, struct super_block *sb, int xid) | 203 | const unsigned char *full_path, struct super_block *sb, int xid) |
197 | { | 204 | { |
198 | int rc = 0; | 205 | int rc = 0; |
199 | FILE_UNIX_BASIC_INFO findData; | 206 | FILE_UNIX_BASIC_INFO find_data; |
200 | struct cifsTconInfo *pTcon; | 207 | struct cifsTconInfo *pTcon; |
201 | struct inode *inode; | 208 | struct inode *inode; |
202 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 209 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
203 | const unsigned char *full_path; | ||
204 | bool is_dfs_referral = false; | 210 | bool is_dfs_referral = false; |
211 | struct cifsInodeInfo *cifsInfo; | ||
212 | __u64 num_of_bytes; | ||
213 | __u64 end_of_file; | ||
205 | 214 | ||
206 | pTcon = cifs_sb->tcon; | 215 | pTcon = cifs_sb->tcon; |
207 | cFYI(1, ("Getting info on %s", search_path)); | 216 | cFYI(1, ("Getting info on %s", full_path)); |
208 | |||
209 | full_path = cifs_get_search_path(cifs_sb, search_path); | ||
210 | 217 | ||
211 | try_again_CIFSSMBUnixQPathInfo: | ||
212 | /* could have done a find first instead but this returns more info */ | 218 | /* could have done a find first instead but this returns more info */ |
213 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, | 219 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, |
214 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 220 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
215 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 221 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
216 | /* dump_mem("\nUnixQPathInfo return data", &findData, | ||
217 | sizeof(findData)); */ | ||
218 | if (rc) { | 222 | if (rc) { |
219 | if (rc == -EREMOTE && !is_dfs_referral) { | 223 | if (rc == -EREMOTE && !is_dfs_referral) { |
220 | is_dfs_referral = true; | 224 | is_dfs_referral = true; |
221 | if (full_path != search_path) { | 225 | cFYI(DBG2, ("DFS ref")); |
222 | kfree(full_path); | 226 | /* for DFS, server does not give us real inode data */ |
223 | full_path = search_path; | 227 | fill_fake_finddataunix(&find_data, sb); |
224 | } | 228 | rc = 0; |
225 | goto try_again_CIFSSMBUnixQPathInfo; | ||
226 | } | 229 | } |
227 | goto cgiiu_exit; | 230 | } |
228 | } else { | 231 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); |
229 | struct cifsInodeInfo *cifsInfo; | 232 | end_of_file = le64_to_cpu(find_data.EndOfFile); |
230 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); | ||
231 | __u64 end_of_file = le64_to_cpu(findData.EndOfFile); | ||
232 | 233 | ||
233 | /* get new inode */ | 234 | /* get new inode */ |
235 | if (*pinode == NULL) { | ||
236 | *pinode = new_inode(sb); | ||
234 | if (*pinode == NULL) { | 237 | if (*pinode == NULL) { |
235 | *pinode = new_inode(sb); | 238 | rc = -ENOMEM; |
236 | if (*pinode == NULL) { | 239 | goto cgiiu_exit; |
237 | rc = -ENOMEM; | ||
238 | goto cgiiu_exit; | ||
239 | } | ||
240 | /* Is an i_ino of zero legal? */ | ||
241 | /* Are there sanity checks we can use to ensure that | ||
242 | the server is really filling in that field? */ | ||
243 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | ||
244 | (*pinode)->i_ino = | ||
245 | (unsigned long)findData.UniqueId; | ||
246 | } /* note ino incremented to unique num in new_inode */ | ||
247 | if (sb->s_flags & MS_NOATIME) | ||
248 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
249 | |||
250 | insert_inode_hash(*pinode); | ||
251 | } | 240 | } |
241 | /* Is an i_ino of zero legal? */ | ||
242 | /* note ino incremented to unique num in new_inode */ | ||
243 | /* Are there sanity checks we can use to ensure that | ||
244 | the server is really filling in that field? */ | ||
245 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | ||
246 | (*pinode)->i_ino = (unsigned long)find_data.UniqueId; | ||
252 | 247 | ||
253 | inode = *pinode; | 248 | if (sb->s_flags & MS_NOATIME) |
254 | cifsInfo = CIFS_I(inode); | 249 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; |
255 | 250 | ||
256 | cFYI(1, ("Old time %ld", cifsInfo->time)); | 251 | insert_inode_hash(*pinode); |
257 | cifsInfo->time = jiffies; | 252 | } |
258 | cFYI(1, ("New time %ld", cifsInfo->time)); | 253 | |
259 | /* this is ok to set on every inode revalidate */ | 254 | inode = *pinode; |
260 | atomic_set(&cifsInfo->inUse, 1); | 255 | cifsInfo = CIFS_I(inode); |
261 | 256 | ||
262 | cifs_unix_info_to_inode(inode, &findData, 0); | 257 | cFYI(1, ("Old time %ld", cifsInfo->time)); |
258 | cifsInfo->time = jiffies; | ||
259 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
260 | /* this is ok to set on every inode revalidate */ | ||
261 | atomic_set(&cifsInfo->inUse, 1); | ||
263 | 262 | ||
263 | cifs_unix_info_to_inode(inode, &find_data, 0); | ||
264 | 264 | ||
265 | if (num_of_bytes < end_of_file) | 265 | if (num_of_bytes < end_of_file) |
266 | cFYI(1, ("allocation size less than end of file")); | 266 | cFYI(1, ("allocation size less than end of file")); |
267 | cFYI(1, ("Size %ld and blocks %llu", | 267 | cFYI(1, ("Size %ld and blocks %llu", |
268 | (unsigned long) inode->i_size, | 268 | (unsigned long) inode->i_size, |
269 | (unsigned long long)inode->i_blocks)); | 269 | (unsigned long long)inode->i_blocks)); |
270 | 270 | ||
271 | cifs_set_ops(inode, is_dfs_referral); | 271 | cifs_set_ops(inode, is_dfs_referral); |
272 | } | ||
273 | cgiiu_exit: | 272 | cgiiu_exit: |
274 | if (full_path != search_path) | ||
275 | kfree(full_path); | ||
276 | return rc; | 273 | return rc; |
277 | } | 274 | } |
278 | 275 | ||
@@ -379,21 +376,52 @@ static int get_sfu_mode(struct inode *inode, | |||
379 | #endif | 376 | #endif |
380 | } | 377 | } |
381 | 378 | ||
379 | /* | ||
380 | * Needed to setup inode data for the directory which is the | ||
381 | * junction to the new submount (ie to setup the fake directory | ||
382 | * which represents a DFS referral) | ||
383 | */ | ||
384 | static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, | ||
385 | struct super_block *sb) | ||
386 | { | ||
387 | memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); | ||
388 | |||
389 | /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); | ||
390 | __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | ||
391 | __u8 pfnd_dat->DeletePending = 0; | ||
392 | __u8 pfnd_data->Directory = 0; | ||
393 | __le32 pfnd_dat->EASize = 0; | ||
394 | __u64 pfnd_dat->IndexNumber = 0; | ||
395 | __u64 pfnd_dat->IndexNumber1 = 0; */ | ||
396 | pfnd_dat->CreationTime = | ||
397 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
398 | pfnd_dat->LastAccessTime = | ||
399 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
400 | pfnd_dat->LastWriteTime = | ||
401 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
402 | pfnd_dat->ChangeTime = | ||
403 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
404 | pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); | ||
405 | pfnd_dat->NumberOfLinks = cpu_to_le32(2); | ||
406 | } | ||
407 | |||
382 | int cifs_get_inode_info(struct inode **pinode, | 408 | int cifs_get_inode_info(struct inode **pinode, |
383 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, | 409 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
384 | struct super_block *sb, int xid, const __u16 *pfid) | 410 | struct super_block *sb, int xid, const __u16 *pfid) |
385 | { | 411 | { |
386 | int rc = 0; | 412 | int rc = 0; |
413 | __u32 attr; | ||
414 | struct cifsInodeInfo *cifsInfo; | ||
387 | struct cifsTconInfo *pTcon; | 415 | struct cifsTconInfo *pTcon; |
388 | struct inode *inode; | 416 | struct inode *inode; |
389 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 417 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
390 | const unsigned char *full_path = NULL; | ||
391 | char *buf = NULL; | 418 | char *buf = NULL; |
392 | bool adjustTZ = false; | 419 | bool adjustTZ = false; |
393 | bool is_dfs_referral = false; | 420 | bool is_dfs_referral = false; |
421 | umode_t default_mode; | ||
394 | 422 | ||
395 | pTcon = cifs_sb->tcon; | 423 | pTcon = cifs_sb->tcon; |
396 | cFYI(1, ("Getting info on %s", search_path)); | 424 | cFYI(1, ("Getting info on %s", full_path)); |
397 | 425 | ||
398 | if ((pfindData == NULL) && (*pinode != NULL)) { | 426 | if ((pfindData == NULL) && (*pinode != NULL)) { |
399 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 427 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
@@ -409,9 +437,6 @@ int cifs_get_inode_info(struct inode **pinode, | |||
409 | return -ENOMEM; | 437 | return -ENOMEM; |
410 | pfindData = (FILE_ALL_INFO *)buf; | 438 | pfindData = (FILE_ALL_INFO *)buf; |
411 | 439 | ||
412 | full_path = cifs_get_search_path(cifs_sb, search_path); | ||
413 | |||
414 | try_again_CIFSSMBQPathInfo: | ||
415 | /* could do find first instead but this returns more info */ | 440 | /* could do find first instead but this returns more info */ |
416 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, | 441 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, |
417 | 0 /* not legacy */, | 442 | 0 /* not legacy */, |
@@ -429,178 +454,163 @@ try_again_CIFSSMBQPathInfo: | |||
429 | } | 454 | } |
430 | } | 455 | } |
431 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 456 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ |
432 | if (rc) { | 457 | if (rc == -EREMOTE) { |
433 | if (rc == -EREMOTE && !is_dfs_referral) { | 458 | is_dfs_referral = true; |
434 | is_dfs_referral = true; | 459 | fill_fake_finddata(pfindData, sb); |
435 | if (full_path != search_path) { | 460 | rc = 0; |
436 | kfree(full_path); | 461 | } else if (rc) |
437 | full_path = search_path; | ||
438 | } | ||
439 | goto try_again_CIFSSMBQPathInfo; | ||
440 | } | ||
441 | goto cgii_exit; | 462 | goto cgii_exit; |
442 | } else { | ||
443 | struct cifsInodeInfo *cifsInfo; | ||
444 | __u32 attr = le32_to_cpu(pfindData->Attributes); | ||
445 | |||
446 | /* get new inode */ | ||
447 | if (*pinode == NULL) { | ||
448 | *pinode = new_inode(sb); | ||
449 | if (*pinode == NULL) { | ||
450 | rc = -ENOMEM; | ||
451 | goto cgii_exit; | ||
452 | } | ||
453 | /* Is an i_ino of zero legal? Can we use that to check | ||
454 | if the server supports returning inode numbers? Are | ||
455 | there other sanity checks we can use to ensure that | ||
456 | the server is really filling in that field? */ | ||
457 | |||
458 | /* We can not use the IndexNumber field by default from | ||
459 | Windows or Samba (in ALL_INFO buf) but we can request | ||
460 | it explicitly. It may not be unique presumably if | ||
461 | the server has multiple devices mounted under one | ||
462 | share */ | ||
463 | 463 | ||
464 | /* There may be higher info levels that work but are | 464 | attr = le32_to_cpu(pfindData->Attributes); |
465 | there Windows server or network appliances for which | ||
466 | IndexNumber field is not guaranteed unique? */ | ||
467 | 465 | ||
468 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 466 | /* get new inode */ |
469 | int rc1 = 0; | 467 | if (*pinode == NULL) { |
470 | __u64 inode_num; | 468 | *pinode = new_inode(sb); |
471 | 469 | if (*pinode == NULL) { | |
472 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 470 | rc = -ENOMEM; |
473 | search_path, &inode_num, | 471 | goto cgii_exit; |
472 | } | ||
473 | /* Is an i_ino of zero legal? Can we use that to check | ||
474 | if the server supports returning inode numbers? Are | ||
475 | there other sanity checks we can use to ensure that | ||
476 | the server is really filling in that field? */ | ||
477 | |||
478 | /* We can not use the IndexNumber field by default from | ||
479 | Windows or Samba (in ALL_INFO buf) but we can request | ||
480 | it explicitly. It may not be unique presumably if | ||
481 | the server has multiple devices mounted under one share */ | ||
482 | |||
483 | /* There may be higher info levels that work but are | ||
484 | there Windows server or network appliances for which | ||
485 | IndexNumber field is not guaranteed unique? */ | ||
486 | |||
487 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | ||
488 | int rc1 = 0; | ||
489 | __u64 inode_num; | ||
490 | |||
491 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | ||
492 | full_path, &inode_num, | ||
474 | cifs_sb->local_nls, | 493 | cifs_sb->local_nls, |
475 | cifs_sb->mnt_cifs_flags & | 494 | cifs_sb->mnt_cifs_flags & |
476 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 495 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
477 | if (rc1) { | 496 | if (rc1) { |
478 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | 497 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); |
479 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 498 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
480 | } else /* do we need cast or hash to ino? */ | 499 | } else /* do we need cast or hash to ino? */ |
481 | (*pinode)->i_ino = inode_num; | 500 | (*pinode)->i_ino = inode_num; |
482 | } /* else ino incremented to unique num in new_inode*/ | 501 | } /* else ino incremented to unique num in new_inode*/ |
483 | if (sb->s_flags & MS_NOATIME) | 502 | if (sb->s_flags & MS_NOATIME) |
484 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | 503 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; |
485 | insert_inode_hash(*pinode); | 504 | insert_inode_hash(*pinode); |
486 | } | 505 | } |
487 | inode = *pinode; | 506 | inode = *pinode; |
488 | cifsInfo = CIFS_I(inode); | 507 | cifsInfo = CIFS_I(inode); |
489 | cifsInfo->cifsAttrs = attr; | 508 | cifsInfo->cifsAttrs = attr; |
490 | cFYI(1, ("Old time %ld", cifsInfo->time)); | 509 | cFYI(1, ("Old time %ld", cifsInfo->time)); |
491 | cifsInfo->time = jiffies; | 510 | cifsInfo->time = jiffies; |
492 | cFYI(1, ("New time %ld", cifsInfo->time)); | 511 | cFYI(1, ("New time %ld", cifsInfo->time)); |
493 | 512 | ||
494 | /* blksize needs to be multiple of two. So safer to default to | 513 | /* blksize needs to be multiple of two. So safer to default to |
495 | blksize and blkbits set in superblock so 2**blkbits and blksize | 514 | blksize and blkbits set in superblock so 2**blkbits and blksize |
496 | will match rather than setting to: | 515 | will match rather than setting to: |
497 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | 516 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ |
498 | 517 | ||
499 | /* Linux can not store file creation time so ignore it */ | 518 | /* Linux can not store file creation time so ignore it */ |
500 | if (pfindData->LastAccessTime) | 519 | if (pfindData->LastAccessTime) |
501 | inode->i_atime = cifs_NTtimeToUnix | 520 | inode->i_atime = cifs_NTtimeToUnix |
502 | (le64_to_cpu(pfindData->LastAccessTime)); | 521 | (le64_to_cpu(pfindData->LastAccessTime)); |
503 | else /* do not need to use current_fs_time - time not stored */ | 522 | else /* do not need to use current_fs_time - time not stored */ |
504 | inode->i_atime = CURRENT_TIME; | 523 | inode->i_atime = CURRENT_TIME; |
505 | inode->i_mtime = | 524 | inode->i_mtime = |
506 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); | 525 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); |
507 | inode->i_ctime = | 526 | inode->i_ctime = |
508 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); | 527 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); |
509 | cFYI(0, ("Attributes came in as 0x%x", attr)); | 528 | cFYI(DBG2, ("Attributes came in as 0x%x", attr)); |
510 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { | 529 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { |
511 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; | 530 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; |
512 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | 531 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; |
513 | } | 532 | } |
514 | 533 | ||
515 | /* set default mode. will override for dirs below */ | 534 | /* get default inode mode */ |
516 | if (atomic_read(&cifsInfo->inUse) == 0) | 535 | if (attr & ATTR_DIRECTORY) |
517 | /* new inode, can safely set these fields */ | 536 | default_mode = cifs_sb->mnt_dir_mode; |
518 | inode->i_mode = cifs_sb->mnt_file_mode; | 537 | else |
519 | else /* since we set the inode type below we need to mask off | 538 | default_mode = cifs_sb->mnt_file_mode; |
520 | to avoid strange results if type changes and both | 539 | |
521 | get orred in */ | 540 | /* set permission bits */ |
541 | if (atomic_read(&cifsInfo->inUse) == 0 || | ||
542 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
543 | inode->i_mode = default_mode; | ||
544 | else { | ||
545 | /* just reenable write bits if !ATTR_READONLY */ | ||
546 | if ((inode->i_mode & S_IWUGO) == 0 && | ||
547 | (attr & ATTR_READONLY) == 0) | ||
548 | inode->i_mode |= (S_IWUGO & default_mode); | ||
522 | inode->i_mode &= ~S_IFMT; | 549 | inode->i_mode &= ~S_IFMT; |
523 | /* if (attr & ATTR_REPARSE) */ | 550 | } |
524 | /* We no longer handle these as symlinks because we could not | 551 | /* clear write bits if ATTR_READONLY is set */ |
525 | follow them due to the absolute path with drive letter */ | 552 | if (attr & ATTR_READONLY) |
526 | if (attr & ATTR_DIRECTORY) { | 553 | inode->i_mode &= ~S_IWUGO; |
527 | /* override default perms since we do not do byte range locking | 554 | |
528 | on dirs */ | 555 | /* set inode type */ |
529 | inode->i_mode = cifs_sb->mnt_dir_mode; | 556 | if ((attr & ATTR_SYSTEM) && |
530 | inode->i_mode |= S_IFDIR; | 557 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { |
531 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 558 | /* no need to fix endianness on 0 */ |
532 | (cifsInfo->cifsAttrs & ATTR_SYSTEM) && | 559 | if (pfindData->EndOfFile == 0) |
533 | /* No need to le64 convert size of zero */ | ||
534 | (pfindData->EndOfFile == 0)) { | ||
535 | inode->i_mode = cifs_sb->mnt_file_mode; | ||
536 | inode->i_mode |= S_IFIFO; | 560 | inode->i_mode |= S_IFIFO; |
537 | /* BB Finish for SFU style symlinks and devices */ | 561 | else if (decode_sfu_inode(inode, |
538 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 562 | le64_to_cpu(pfindData->EndOfFile), |
539 | (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { | 563 | full_path, cifs_sb, xid)) |
540 | if (decode_sfu_inode(inode, | 564 | cFYI(1, ("unknown SFU file type\n")); |
541 | le64_to_cpu(pfindData->EndOfFile), | 565 | } else { |
542 | search_path, | 566 | if (attr & ATTR_DIRECTORY) |
543 | cifs_sb, xid)) | 567 | inode->i_mode |= S_IFDIR; |
544 | cFYI(1, ("Unrecognized sfu inode type")); | 568 | else |
545 | |||
546 | cFYI(1, ("sfu mode 0%o", inode->i_mode)); | ||
547 | } else { | ||
548 | inode->i_mode |= S_IFREG; | 569 | inode->i_mode |= S_IFREG; |
549 | /* treat the dos attribute of read-only as read-only | 570 | } |
550 | mode e.g. 555 */ | ||
551 | if (cifsInfo->cifsAttrs & ATTR_READONLY) | ||
552 | inode->i_mode &= ~(S_IWUGO); | ||
553 | else if ((inode->i_mode & S_IWUGO) == 0) | ||
554 | /* the ATTR_READONLY flag may have been */ | ||
555 | /* changed on server -- set any w bits */ | ||
556 | /* allowed by mnt_file_mode */ | ||
557 | inode->i_mode |= (S_IWUGO & | ||
558 | cifs_sb->mnt_file_mode); | ||
559 | /* BB add code here - | ||
560 | validate if device or weird share or device type? */ | ||
561 | } | ||
562 | 571 | ||
563 | spin_lock(&inode->i_lock); | 572 | spin_lock(&inode->i_lock); |
564 | if (is_size_safe_to_change(cifsInfo, | 573 | if (is_size_safe_to_change(cifsInfo, |
565 | le64_to_cpu(pfindData->EndOfFile))) { | 574 | le64_to_cpu(pfindData->EndOfFile))) { |
566 | /* can not safely shrink the file size here if the | 575 | /* can not safely shrink the file size here if the |
567 | client is writing to it due to potential races */ | 576 | client is writing to it due to potential races */ |
568 | i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); | 577 | i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); |
569 | 578 | ||
570 | /* 512 bytes (2**9) is the fake blocksize that must be | 579 | /* 512 bytes (2**9) is the fake blocksize that must be |
571 | used for this calculation */ | 580 | used for this calculation */ |
572 | inode->i_blocks = (512 - 1 + le64_to_cpu( | 581 | inode->i_blocks = (512 - 1 + le64_to_cpu( |
573 | pfindData->AllocationSize)) >> 9; | 582 | pfindData->AllocationSize)) >> 9; |
574 | } | 583 | } |
575 | spin_unlock(&inode->i_lock); | 584 | spin_unlock(&inode->i_lock); |
576 | 585 | ||
577 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); | 586 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); |
578 | 587 | ||
579 | /* BB fill in uid and gid here? with help from winbind? | 588 | /* BB fill in uid and gid here? with help from winbind? |
580 | or retrieve from NTFS stream extended attribute */ | 589 | or retrieve from NTFS stream extended attribute */ |
581 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 590 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
582 | /* fill in 0777 bits from ACL */ | 591 | /* fill in 0777 bits from ACL */ |
583 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 592 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
584 | cFYI(1, ("Getting mode bits from ACL")); | 593 | cFYI(1, ("Getting mode bits from ACL")); |
585 | acl_to_uid_mode(inode, search_path, pfid); | 594 | acl_to_uid_mode(inode, full_path, pfid); |
586 | } | 595 | } |
587 | #endif | 596 | #endif |
588 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 597 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
589 | /* fill in remaining high mode bits e.g. SUID, VTX */ | 598 | /* fill in remaining high mode bits e.g. SUID, VTX */ |
590 | get_sfu_mode(inode, search_path, cifs_sb, xid); | 599 | get_sfu_mode(inode, full_path, cifs_sb, xid); |
591 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | 600 | } else if (atomic_read(&cifsInfo->inUse) == 0) { |
592 | inode->i_uid = cifs_sb->mnt_uid; | 601 | inode->i_uid = cifs_sb->mnt_uid; |
593 | inode->i_gid = cifs_sb->mnt_gid; | 602 | inode->i_gid = cifs_sb->mnt_gid; |
594 | /* set so we do not keep refreshing these fields with | 603 | /* set so we do not keep refreshing these fields with |
595 | bad data after user has changed them in memory */ | 604 | bad data after user has changed them in memory */ |
596 | atomic_set(&cifsInfo->inUse, 1); | 605 | atomic_set(&cifsInfo->inUse, 1); |
597 | } | ||
598 | |||
599 | cifs_set_ops(inode, is_dfs_referral); | ||
600 | } | 606 | } |
607 | |||
608 | cifs_set_ops(inode, is_dfs_referral); | ||
609 | |||
610 | |||
611 | |||
612 | |||
601 | cgii_exit: | 613 | cgii_exit: |
602 | if (full_path != search_path) | ||
603 | kfree(full_path); | ||
604 | kfree(buf); | 614 | kfree(buf); |
605 | return rc; | 615 | return rc; |
606 | } | 616 | } |
@@ -1005,8 +1015,11 @@ mkdir_get_info: | |||
1005 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1015 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1006 | } | 1016 | } |
1007 | if (direntry->d_inode) { | 1017 | if (direntry->d_inode) { |
1008 | direntry->d_inode->i_mode = mode; | 1018 | if (cifs_sb->mnt_cifs_flags & |
1009 | direntry->d_inode->i_mode |= S_IFDIR; | 1019 | CIFS_MOUNT_DYNPERM) |
1020 | direntry->d_inode->i_mode = | ||
1021 | (mode | S_IFDIR); | ||
1022 | |||
1010 | if (cifs_sb->mnt_cifs_flags & | 1023 | if (cifs_sb->mnt_cifs_flags & |
1011 | CIFS_MOUNT_SET_UID) { | 1024 | CIFS_MOUNT_SET_UID) { |
1012 | direntry->d_inode->i_uid = | 1025 | direntry->d_inode->i_uid = |
@@ -1502,8 +1515,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1502 | int oplock = 0; | 1515 | int oplock = 0; |
1503 | 1516 | ||
1504 | rc = SMBLegacyOpen(xid, pTcon, full_path, | 1517 | rc = SMBLegacyOpen(xid, pTcon, full_path, |
1505 | FILE_OPEN, | 1518 | FILE_OPEN, GENERIC_WRITE, |
1506 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | ||
1507 | CREATE_NOT_DIR, &netfid, &oplock, | 1519 | CREATE_NOT_DIR, &netfid, &oplock, |
1508 | NULL, cifs_sb->local_nls, | 1520 | NULL, cifs_sb->local_nls, |
1509 | cifs_sb->mnt_cifs_flags & | 1521 | cifs_sb->mnt_cifs_flags & |
@@ -1534,13 +1546,26 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1534 | } else | 1546 | } else |
1535 | goto cifs_setattr_exit; | 1547 | goto cifs_setattr_exit; |
1536 | } | 1548 | } |
1537 | if (attrs->ia_valid & ATTR_UID) { | 1549 | |
1538 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | 1550 | /* |
1539 | uid = attrs->ia_uid; | 1551 | * Without unix extensions we can't send ownership changes to the |
1540 | } | 1552 | * server, so silently ignore them. This is consistent with how |
1541 | if (attrs->ia_valid & ATTR_GID) { | 1553 | * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With |
1542 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | 1554 | * CIFSACL support + proper Windows to Unix idmapping, we may be |
1543 | gid = attrs->ia_gid; | 1555 | * able to support this in the future. |
1556 | */ | ||
1557 | if (!pTcon->unix_ext && | ||
1558 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { | ||
1559 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); | ||
1560 | } else { | ||
1561 | if (attrs->ia_valid & ATTR_UID) { | ||
1562 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | ||
1563 | uid = attrs->ia_uid; | ||
1564 | } | ||
1565 | if (attrs->ia_valid & ATTR_GID) { | ||
1566 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | ||
1567 | gid = attrs->ia_gid; | ||
1568 | } | ||
1544 | } | 1569 | } |
1545 | 1570 | ||
1546 | time_buf.Attributes = 0; | 1571 | time_buf.Attributes = 0; |
@@ -1550,7 +1575,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1550 | attrs->ia_valid &= ~ATTR_MODE; | 1575 | attrs->ia_valid &= ~ATTR_MODE; |
1551 | 1576 | ||
1552 | if (attrs->ia_valid & ATTR_MODE) { | 1577 | if (attrs->ia_valid & ATTR_MODE) { |
1553 | cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); | 1578 | cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); |
1554 | mode = attrs->ia_mode; | 1579 | mode = attrs->ia_mode; |
1555 | } | 1580 | } |
1556 | 1581 | ||
@@ -1565,18 +1590,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1565 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1590 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
1566 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 1591 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
1567 | rc = mode_to_acl(inode, full_path, mode); | 1592 | rc = mode_to_acl(inode, full_path, mode); |
1568 | else if ((mode & S_IWUGO) == 0) { | 1593 | else |
1569 | #else | ||
1570 | if ((mode & S_IWUGO) == 0) { | ||
1571 | #endif | 1594 | #endif |
1572 | /* not writeable */ | 1595 | if (((mode & S_IWUGO) == 0) && |
1573 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 1596 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1574 | set_dosattr = true; | 1597 | set_dosattr = true; |
1575 | time_buf.Attributes = | 1598 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | |
1576 | cpu_to_le32(cifsInode->cifsAttrs | | 1599 | ATTR_READONLY); |
1577 | ATTR_READONLY); | 1600 | /* fix up mode if we're not using dynperm */ |
1578 | } | 1601 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
1579 | } else if (cifsInode->cifsAttrs & ATTR_READONLY) { | 1602 | attrs->ia_mode = inode->i_mode & ~S_IWUGO; |
1603 | } else if ((mode & S_IWUGO) && | ||
1604 | (cifsInode->cifsAttrs & ATTR_READONLY)) { | ||
1580 | /* If file is readonly on server, we would | 1605 | /* If file is readonly on server, we would |
1581 | not be able to write to it - so if any write | 1606 | not be able to write to it - so if any write |
1582 | bit is enabled for user or group or other we | 1607 | bit is enabled for user or group or other we |
@@ -1587,6 +1612,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1587 | /* Windows ignores set to zero */ | 1612 | /* Windows ignores set to zero */ |
1588 | if (time_buf.Attributes == 0) | 1613 | if (time_buf.Attributes == 0) |
1589 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); | 1614 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); |
1615 | |||
1616 | /* reset local inode permissions to normal */ | ||
1617 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1618 | attrs->ia_mode &= ~(S_IALLUGO); | ||
1619 | if (S_ISDIR(inode->i_mode)) | ||
1620 | attrs->ia_mode |= | ||
1621 | cifs_sb->mnt_dir_mode; | ||
1622 | else | ||
1623 | attrs->ia_mode |= | ||
1624 | cifs_sb->mnt_file_mode; | ||
1625 | } | ||
1626 | } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1627 | /* ignore mode change - ATTR_READONLY hasn't changed */ | ||
1628 | attrs->ia_valid &= ~ATTR_MODE; | ||
1590 | } | 1629 | } |
1591 | } | 1630 | } |
1592 | 1631 | ||
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 5c792df13d62..0088a5b52564 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c | |||
@@ -30,9 +30,9 @@ | |||
30 | 30 | ||
31 | #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) | 31 | #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) |
32 | 32 | ||
33 | int cifs_ioctl(struct inode *inode, struct file *filep, | 33 | long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) |
34 | unsigned int command, unsigned long arg) | ||
35 | { | 34 | { |
35 | struct inode *inode = filep->f_dentry->d_inode; | ||
36 | int rc = -ENOTTY; /* strange error - but the precedent */ | 36 | int rc = -ENOTTY; /* strange error - but the precedent */ |
37 | int xid; | 37 | int xid; |
38 | struct cifs_sb_info *cifs_sb; | 38 | struct cifs_sb_info *cifs_sb; |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1c2c3ce5020b..63f644000ce5 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -234,7 +234,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) | |||
234 | struct cifs_sb_info *cifs_sb; | 234 | struct cifs_sb_info *cifs_sb; |
235 | struct cifsTconInfo *pTcon; | 235 | struct cifsTconInfo *pTcon; |
236 | char *full_path = NULL; | 236 | char *full_path = NULL; |
237 | char *tmp_path = NULL; | ||
238 | char *tmpbuffer; | 237 | char *tmpbuffer; |
239 | int len; | 238 | int len; |
240 | __u16 fid; | 239 | __u16 fid; |
@@ -295,45 +294,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) | |||
295 | cFYI(1, ("Error closing junction point " | 294 | cFYI(1, ("Error closing junction point " |
296 | "(open for ioctl)")); | 295 | "(open for ioctl)")); |
297 | } | 296 | } |
298 | /* BB unwind this long, nested function, or remove BB */ | 297 | /* If it is a DFS junction earlier we would have gotten |
299 | if (rc == -EIO) { | 298 | PATH_NOT_COVERED returned from server so we do |
300 | /* Query if DFS Junction */ | 299 | not need to request the DFS info here */ |
301 | unsigned int num_referrals = 0; | ||
302 | struct dfs_info3_param *refs = NULL; | ||
303 | tmp_path = | ||
304 | kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, | ||
305 | GFP_KERNEL); | ||
306 | if (tmp_path) { | ||
307 | strncpy(tmp_path, pTcon->treeName, | ||
308 | MAX_TREE_SIZE); | ||
309 | strncat(tmp_path, full_path, | ||
310 | MAX_PATHCONF); | ||
311 | rc = get_dfs_path(xid, pTcon->ses, | ||
312 | tmp_path, | ||
313 | cifs_sb->local_nls, | ||
314 | &num_referrals, &refs, | ||
315 | cifs_sb->mnt_cifs_flags & | ||
316 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
317 | cFYI(1, ("Get DFS for %s rc = %d ", | ||
318 | tmp_path, rc)); | ||
319 | if ((num_referrals == 0) && (rc == 0)) | ||
320 | rc = -EACCES; | ||
321 | else { | ||
322 | cFYI(1, ("num referral: %d", | ||
323 | num_referrals)); | ||
324 | if (refs && refs->path_name) { | ||
325 | strncpy(tmpbuffer, | ||
326 | refs->path_name, | ||
327 | len-1); | ||
328 | } | ||
329 | } | ||
330 | kfree(refs); | ||
331 | kfree(tmp_path); | ||
332 | } | ||
333 | /* BB add code like else decode referrals | ||
334 | then memcpy to tmpbuffer and free referrals | ||
335 | string array BB */ | ||
336 | } | ||
337 | } | 300 | } |
338 | } | 301 | } |
339 | /* BB Anything else to do to handle recursive links? */ | 302 | /* BB Anything else to do to handle recursive links? */ |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1d69b8014e0b..4b17f8fe3157 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -519,8 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
519 | pnotify = (struct file_notify_information *) | 519 | pnotify = (struct file_notify_information *) |
520 | ((char *)&pSMBr->hdr.Protocol + data_offset); | 520 | ((char *)&pSMBr->hdr.Protocol + data_offset); |
521 | cFYI(1, ("dnotify on %s Action: 0x%x", | 521 | cFYI(1, ("dnotify on %s Action: 0x%x", |
522 | pnotify->FileName, | 522 | pnotify->FileName, pnotify->Action)); |
523 | pnotify->Action)); /* BB removeme BB */ | ||
524 | /* cifs_dump_mem("Rcvd notify Data: ",buf, | 523 | /* cifs_dump_mem("Rcvd notify Data: ",buf, |
525 | sizeof(struct smb_hdr)+60); */ | 524 | sizeof(struct smb_hdr)+60); */ |
526 | return true; | 525 | return true; |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 00f4cff400b3..8703d68f5b20 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -141,11 +141,11 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) | |||
141 | int ret = 0; | 141 | int ret = 0; |
142 | 142 | ||
143 | /* calculate length by finding first slash or NULL */ | 143 | /* calculate length by finding first slash or NULL */ |
144 | if (address_family == AF_INET) { | 144 | if (address_family == AF_INET) |
145 | ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); | 145 | ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); |
146 | } else if (address_family == AF_INET6) { | 146 | else if (address_family == AF_INET6) |
147 | ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); | 147 | ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); |
148 | } | 148 | |
149 | cFYI(DBG2, ("address conversion returned %d for %s", ret, cp)); | 149 | cFYI(DBG2, ("address conversion returned %d for %s", ret, cp)); |
150 | if (ret > 0) | 150 | if (ret > 0) |
151 | ret = 1; | 151 | ret = 1; |
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 7170a9b70f1e..c377d8065d99 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h | |||
@@ -64,7 +64,7 @@ typedef struct _SECURITY_BUFFER { | |||
64 | } __attribute__((packed)) SECURITY_BUFFER; | 64 | } __attribute__((packed)) SECURITY_BUFFER; |
65 | 65 | ||
66 | typedef struct _NEGOTIATE_MESSAGE { | 66 | typedef struct _NEGOTIATE_MESSAGE { |
67 | __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; | 67 | __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; |
68 | __le32 MessageType; /* 1 */ | 68 | __le32 MessageType; /* 1 */ |
69 | __le32 NegotiateFlags; | 69 | __le32 NegotiateFlags; |
70 | SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ | 70 | SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ |
@@ -74,7 +74,7 @@ typedef struct _NEGOTIATE_MESSAGE { | |||
74 | } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; | 74 | } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; |
75 | 75 | ||
76 | typedef struct _CHALLENGE_MESSAGE { | 76 | typedef struct _CHALLENGE_MESSAGE { |
77 | __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; | 77 | __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; |
78 | __le32 MessageType; /* 2 */ | 78 | __le32 MessageType; /* 2 */ |
79 | SECURITY_BUFFER TargetName; | 79 | SECURITY_BUFFER TargetName; |
80 | __le32 NegotiateFlags; | 80 | __le32 NegotiateFlags; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 34ec32100c72..83f306954883 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
132 | __u32 attr; | 132 | __u32 attr; |
133 | __u64 allocation_size; | 133 | __u64 allocation_size; |
134 | __u64 end_of_file; | 134 | __u64 end_of_file; |
135 | umode_t default_mode; | ||
135 | 136 | ||
136 | /* save mtime and size */ | 137 | /* save mtime and size */ |
137 | local_mtime = tmp_inode->i_mtime; | 138 | local_mtime = tmp_inode->i_mtime; |
@@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
187 | if (atomic_read(&cifsInfo->inUse) == 0) { | 188 | if (atomic_read(&cifsInfo->inUse) == 0) { |
188 | tmp_inode->i_uid = cifs_sb->mnt_uid; | 189 | tmp_inode->i_uid = cifs_sb->mnt_uid; |
189 | tmp_inode->i_gid = cifs_sb->mnt_gid; | 190 | tmp_inode->i_gid = cifs_sb->mnt_gid; |
190 | /* set default mode. will override for dirs below */ | 191 | } |
191 | tmp_inode->i_mode = cifs_sb->mnt_file_mode; | 192 | |
192 | } else { | 193 | if (attr & ATTR_DIRECTORY) |
193 | /* mask off the type bits since it gets set | 194 | default_mode = cifs_sb->mnt_dir_mode; |
194 | below and we do not want to get two type | 195 | else |
195 | bits set */ | 196 | default_mode = cifs_sb->mnt_file_mode; |
197 | |||
198 | /* set initial permissions */ | ||
199 | if ((atomic_read(&cifsInfo->inUse) == 0) || | ||
200 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
201 | tmp_inode->i_mode = default_mode; | ||
202 | else { | ||
203 | /* just reenable write bits if !ATTR_READONLY */ | ||
204 | if ((tmp_inode->i_mode & S_IWUGO) == 0 && | ||
205 | (attr & ATTR_READONLY) == 0) | ||
206 | tmp_inode->i_mode |= (S_IWUGO & default_mode); | ||
207 | |||
196 | tmp_inode->i_mode &= ~S_IFMT; | 208 | tmp_inode->i_mode &= ~S_IFMT; |
197 | } | 209 | } |
198 | 210 | ||
199 | if (attr & ATTR_DIRECTORY) { | 211 | /* clear write bits if ATTR_READONLY is set */ |
200 | *pobject_type = DT_DIR; | 212 | if (attr & ATTR_READONLY) |
201 | /* override default perms since we do not lock dirs */ | 213 | tmp_inode->i_mode &= ~S_IWUGO; |
202 | if (atomic_read(&cifsInfo->inUse) == 0) | 214 | |
203 | tmp_inode->i_mode = cifs_sb->mnt_dir_mode; | 215 | /* set inode type */ |
204 | tmp_inode->i_mode |= S_IFDIR; | 216 | if ((attr & ATTR_SYSTEM) && |
205 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 217 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { |
206 | (attr & ATTR_SYSTEM)) { | ||
207 | if (end_of_file == 0) { | 218 | if (end_of_file == 0) { |
208 | *pobject_type = DT_FIFO; | ||
209 | tmp_inode->i_mode |= S_IFIFO; | 219 | tmp_inode->i_mode |= S_IFIFO; |
220 | *pobject_type = DT_FIFO; | ||
210 | } else { | 221 | } else { |
211 | /* rather than get the type here, we mark the | 222 | /* |
212 | inode as needing revalidate and get the real type | 223 | * trying to get the type can be slow, so just call |
213 | (blk vs chr vs. symlink) later ie in lookup */ | 224 | * this a regular file for now, and mark for reval |
214 | *pobject_type = DT_REG; | 225 | */ |
215 | tmp_inode->i_mode |= S_IFREG; | 226 | tmp_inode->i_mode |= S_IFREG; |
227 | *pobject_type = DT_REG; | ||
216 | cifsInfo->time = 0; | 228 | cifsInfo->time = 0; |
217 | } | 229 | } |
218 | /* we no longer mark these because we could not follow them */ | ||
219 | /* } else if (attr & ATTR_REPARSE) { | ||
220 | *pobject_type = DT_LNK; | ||
221 | tmp_inode->i_mode |= S_IFLNK; */ | ||
222 | } else { | 230 | } else { |
223 | *pobject_type = DT_REG; | 231 | if (attr & ATTR_DIRECTORY) { |
224 | tmp_inode->i_mode |= S_IFREG; | 232 | tmp_inode->i_mode |= S_IFDIR; |
225 | if (attr & ATTR_READONLY) | 233 | *pobject_type = DT_DIR; |
226 | tmp_inode->i_mode &= ~(S_IWUGO); | 234 | } else { |
227 | else if ((tmp_inode->i_mode & S_IWUGO) == 0) | 235 | tmp_inode->i_mode |= S_IFREG; |
228 | /* the ATTR_READONLY flag may have been changed on */ | 236 | *pobject_type = DT_REG; |
229 | /* server -- set any w bits allowed by mnt_file_mode */ | 237 | } |
230 | tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); | 238 | } |
231 | } /* could add code here - to validate if device or weird share type? */ | ||
232 | 239 | ||
233 | /* can not fill in nlink here as in qpathinfo version and Unx search */ | 240 | /* can not fill in nlink here as in qpathinfo version and Unx search */ |
234 | if (atomic_read(&cifsInfo->inUse) == 0) | 241 | if (atomic_read(&cifsInfo->inUse) == 0) |
@@ -670,10 +677,11 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
670 | (index_to_find < first_entry_in_buffer)) { | 677 | (index_to_find < first_entry_in_buffer)) { |
671 | /* close and restart search */ | 678 | /* close and restart search */ |
672 | cFYI(1, ("search backing up - close and restart search")); | 679 | cFYI(1, ("search backing up - close and restart search")); |
673 | cifsFile->invalidHandle = true; | 680 | if (!cifsFile->srch_inf.endOfSearch && |
674 | CIFSFindClose(xid, pTcon, cifsFile->netfid); | 681 | !cifsFile->invalidHandle) { |
675 | kfree(cifsFile->search_resume_name); | 682 | cifsFile->invalidHandle = true; |
676 | cifsFile->search_resume_name = NULL; | 683 | CIFSFindClose(xid, pTcon, cifsFile->netfid); |
684 | } | ||
677 | if (cifsFile->srch_inf.ntwrk_buf_start) { | 685 | if (cifsFile->srch_inf.ntwrk_buf_start) { |
678 | cFYI(1, ("freeing SMB ff cache buf on search rewind")); | 686 | cFYI(1, ("freeing SMB ff cache buf on search rewind")); |
679 | if (cifsFile->srch_inf.smallBuf) | 687 | if (cifsFile->srch_inf.smallBuf) |
@@ -1040,9 +1048,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1040 | } /* else { | 1048 | } /* else { |
1041 | cifsFile->invalidHandle = true; | 1049 | cifsFile->invalidHandle = true; |
1042 | CIFSFindClose(xid, pTcon, cifsFile->netfid); | 1050 | CIFSFindClose(xid, pTcon, cifsFile->netfid); |
1043 | } | 1051 | } */ |
1044 | kfree(cifsFile->search_resume_name); | ||
1045 | cifsFile->search_resume_name = NULL; */ | ||
1046 | 1052 | ||
1047 | rc = find_cifs_entry(xid, pTcon, file, | 1053 | rc = find_cifs_entry(xid, pTcon, file, |
1048 | ¤t_entry, &num_to_fill); | 1054 | ¤t_entry, &num_to_fill); |