Merge branch 'linux-2.6'
[powerpc.git] / fs / cifs / link.c
index 41f657c..1d6fb01 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/link.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Copyright (C) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -55,7 +55,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
                goto cifs_hl_exit;
        }
 
-       if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
+/*     if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
+       if (pTcon->unix_ext)
                rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
                                            cifs_sb_target->local_nls,
                                            cifs_sb_target->mnt_cifs_flags &
@@ -129,14 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
                goto out;
        }
 
-       /* BB add read reparse point symlink code and Unix extensions
-          symlink code here BB */
+       /* We could change this to:
+               if (pTcon->unix_ext)
+          but there does not seem any point in refusing to
+          get symlink info if we can, even if unix extensions
+          turned off for this mount */
+
        if (pTcon->ses->capabilities & CAP_UNIX)
                rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
                                             target_path,
                                             PATH_MAX-1,
                                             cifs_sb->local_nls);
        else {
+               /* BB add read reparse point symlink code here */
                /* rc = CIFSSMBQueryReparseLinkInfo */
                /* BB Add code to Query ReparsePoint info */
                /* BB Add MAC style xsymlink check here if enabled */
@@ -186,7 +192,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
        cFYI(1, ("symname is %s", symname));
 
        /* BB what if DFS and this volume is on different share? BB */
-       if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+       if (pTcon->unix_ext)
                rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
                                           cifs_sb->local_nls);
        /* else
@@ -194,7 +200,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
                                        cifs_sb_target->local_nls); */
 
        if (rc == 0) {
-               if (pTcon->ses->capabilities & CAP_UNIX)
+               if (pTcon->unix_ext)
                        rc = cifs_get_inode_info_unix(&newinode, full_path,
                                                      inode->i_sb, xid);
                else
@@ -230,8 +236,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
        char *full_path = NULL;
        char *tmp_path = NULL;
        char *tmpbuffer;
-       unsigned char *referrals = NULL;
-       int num_referrals = 0;
        int len;
        __u16 fid;
 
@@ -266,6 +270,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
 
 /* BB add read reparse point symlink code and
        Unix extensions symlink code here BB */
+/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
        if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
                rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
                                tmpbuffer,
@@ -274,7 +279,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
        else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
                cERROR(1, ("SFU style symlinks not implemented yet"));
                /* add open and read as in fs/cifs/inode.c */
-       
        } else {
                rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
                                OPEN_REPARSE_POINT, &fid, &oplock, NULL,
@@ -288,10 +292,14 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
                                fid,
                                cifs_sb->local_nls);
                        if (CIFSSMBClose(xid, pTcon, fid)) {
-                               cFYI(1,("Error closing junction point (open for ioctl)"));
+                               cFYI(1, ("Error closing junction point "
+                                        "(open for ioctl)"));
                        }
+                       /* BB unwind this long, nested function, or remove BB */
                        if (rc == -EIO) {
                                /* Query if DFS Junction */
+                               unsigned int num_referrals = 0;
+                               struct dfs_info3_param *refs = NULL;
                                tmp_path =
                                        kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
                                                GFP_KERNEL);
@@ -303,7 +311,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
                                        rc = get_dfs_path(xid, pTcon->ses,
                                                tmp_path,
                                                cifs_sb->local_nls,
-                                               &num_referrals, &referrals,
+                                               &num_referrals, &refs,
                                                cifs_sb->mnt_cifs_flags &
                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
                                        cFYI(1, ("Get DFS for %s rc = %d ",
@@ -313,12 +321,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
                                        else {
                                                cFYI(1, ("num referral: %d",
                                                        num_referrals));
-                                               if (referrals) {
-                                                       cFYI(1,("referral string: %s", referrals));
-                                                       strncpy(tmpbuffer, referrals, len-1);
+                                               if (refs && refs->path_name) {
+                                                       strncpy(tmpbuffer,
+                                                               refs->path_name,
+                                                               len-1);
                                                }
                                        }
-                                       kfree(referrals);
+                                       kfree(refs);
                                        kfree(tmp_path);
 }
                                /* BB add code like else decode referrals