diff options
author | Jonathan Corbet <corbet@lwn.net> | 2008-07-15 01:29:34 +0400 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2008-07-15 01:29:34 +0400 |
commit | 2fceef397f9880b212a74c418290ce69e7ac00eb (patch) | |
tree | d9cc09ab992825ef7fede4a688103503e3caf655 /fs/cifs/dir.c | |
parent | feae1ef116ed381625d3731c5ae4f4ebcb3fa302 (diff) | |
parent | bce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff) | |
download | linux-2fceef397f9880b212a74c418290ce69e7ac00eb.tar.xz |
Merge commit 'v2.6.26' into bkl-removal
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) struct dentry *temp; int namelen; int pplen; + int dfsplen; char *full_path; char dirsep; + struct cifs_sb_info *cifs_sb; if (direntry == NULL) return NULL; /* not much we can do if dentry is freed and we need to reopen the file after it was closed implicitly when the server crashed */ - dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); - pplen = CIFS_SB(direntry->d_sb)->prepathlen; + cifs_sb = CIFS_SB(direntry->d_sb); + dirsep = CIFS_DIR_SEP(cifs_sb); + pplen = cifs_sb->prepathlen; + if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) + dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); + else + dfsplen = 0; cifs_bp_rename_retry: - namelen = pplen; + namelen = pplen + dfsplen; for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; @@ -91,7 +98,7 @@ cifs_bp_rename_retry: return NULL; } } - if (namelen != pplen) { + if (namelen != pplen + dfsplen) { cERROR(1, ("did not end path lookup where expected namelen is %d", namelen)); @@ -107,7 +114,18 @@ cifs_bp_rename_retry: since the '\' is a valid posix character so we can not switch those safely to '/' if any are found in the middle of the prepath */ /* BB test paths to Windows with '/' in the midst of prepath */ - strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); + + if (dfsplen) { + strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { + int i; + for (i = 0; i < dfsplen; i++) { + if (full_path[i] == '\\') + full_path[i] = '/'; + } + } + } + strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen); return full_path; } @@ -242,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, buf, inode->i_sb, xid, &fileHandle); if (newinode) { - newinode->i_mode = mode; + if (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_DYNPERM) + newinode->i_mode = mode; if ((oplock & CIFS_CREATE_ACTION) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { @@ -590,7 +610,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, * case take precedence. If a is not a negative dentry, this * should have no side effects */ - memcpy(a->name, b->name, a->len); + memcpy((void *)a->name, b->name, a->len); return 0; } return 1; |