diff options
Diffstat (limited to 'fs/cifs/dir.c')
| -rw-r--r-- | fs/cifs/dir.c | 34 |
1 files changed, 27 insertions, 7 deletions
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; |
