diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e4e0078a0526..f0b5b5f3dd2e 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 | ||
@@ -590,7 +608,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, | |||
590 | * case take precedence. If a is not a negative dentry, this | 608 | * case take precedence. If a is not a negative dentry, this |
591 | * should have no side effects | 609 | * should have no side effects |
592 | */ | 610 | */ |
593 | memcpy(a->name, b->name, a->len); | 611 | memcpy((void *)a->name, b->name, a->len); |
594 | return 0; | 612 | return 0; |
595 | } | 613 | } |
596 | return 1; | 614 | return 1; |