Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / fs / cifs / link.c
index 41f657c..cd83c53 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 &
@@ -106,58 +107,51 @@ void *
 cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 {
        struct inode *inode = direntry->d_inode;
-       int rc = -EACCES;
+       int rc = -ENOMEM;
        int xid;
        char *full_path = NULL;
-       char *target_path = ERR_PTR(-ENOMEM);
-       struct cifs_sb_info *cifs_sb;
-       struct cifsTconInfo *pTcon;
+       char *target_path = NULL;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifsTconInfo *tcon = cifs_sb->tcon;
 
        xid = GetXid();
 
-       full_path = build_path_from_dentry(direntry);
-
-       if (!full_path)
-               goto out_no_free;
-
-       cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
-       cifs_sb = CIFS_SB(inode->i_sb);
-       pTcon = cifs_sb->tcon;
-       target_path = kmalloc(PATH_MAX, GFP_KERNEL);
-       if (!target_path) {
-               target_path = ERR_PTR(-ENOMEM);
+       /*
+        * For now, we just handle symlinks with unix extensions enabled.
+        * Eventually we should handle NTFS reparse points, and MacOS
+        * symlink support. For instance...
+        *
+        * rc = CIFSSMBQueryReparseLinkInfo(...)
+        *
+        * For now, just return -EACCES when the server doesn't support posix
+        * extensions. Note that we still allow querying symlinks when posix
+        * extensions are manually disabled. We could disable these as well
+        * but there doesn't seem to be any harm in allowing the client to
+        * read them.
+        */
+       if (!(tcon->ses->capabilities & CAP_UNIX)) {
+               rc = -EACCES;
                goto out;
        }
 
-       /* BB add read reparse point symlink code and Unix extensions
-          symlink code here BB */
-       if (pTcon->ses->capabilities & CAP_UNIX)
-               rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
-                                            target_path,
-                                            PATH_MAX-1,
-                                            cifs_sb->local_nls);
-       else {
-               /* rc = CIFSSMBQueryReparseLinkInfo */
-               /* BB Add code to Query ReparsePoint info */
-               /* BB Add MAC style xsymlink check here if enabled */
-       }
-
-       if (rc == 0) {
+       full_path = build_path_from_dentry(direntry);
+       if (!full_path)
+               goto out;
 
-/* BB Add special case check for Samba DFS symlinks */
+       cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
 
-               target_path[PATH_MAX-1] = 0;
-       } else {
+       rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
+                                    cifs_sb->local_nls);
+       kfree(full_path);
+out:
+       if (rc != 0) {
                kfree(target_path);
                target_path = ERR_PTR(rc);
        }
 
-out:
-       kfree(full_path);
-out_no_free:
        FreeXid(xid);
        nd_set_link(nd, target_path);
-       return NULL;    /* No cookie */
+       return NULL;
 }
 
 int
@@ -186,7 +180,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,12 +188,12 @@ 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
                        rc = cifs_get_inode_info(&newinode, full_path, NULL,
-                                                inode->i_sb, xid);
+                                                inode->i_sb, xid, NULL);
 
                if (rc != 0) {
                        cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
@@ -218,132 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
        return rc;
 }
 
-int
-cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
-{
-       struct inode *inode = direntry->d_inode;
-       int rc = -EACCES;
-       int xid;
-       int oplock = FALSE;
-       struct cifs_sb_info *cifs_sb;
-       struct cifsTconInfo *pTcon;
-       char *full_path = NULL;
-       char *tmp_path = NULL;
-       char *tmpbuffer;
-       unsigned char *referrals = NULL;
-       int num_referrals = 0;
-       int len;
-       __u16 fid;
-
-       xid = GetXid();
-       cifs_sb = CIFS_SB(inode->i_sb);
-       pTcon = cifs_sb->tcon;
-
-/* BB would it be safe against deadlock to grab this sem
-      even though rename itself grabs the sem and calls lookup? */
-/*       mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
-       full_path = build_path_from_dentry(direntry);
-/*       mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
-
-       if (full_path == NULL) {
-               FreeXid(xid);
-               return -ENOMEM;
-       }
-
-       cFYI(1,
-            ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
-             full_path, inode, pBuffer, buflen));
-       if (buflen > PATH_MAX)
-               len = PATH_MAX;
-       else
-               len = buflen;
-       tmpbuffer = kmalloc(len, GFP_KERNEL);
-       if (tmpbuffer == NULL) {
-               kfree(full_path);
-               FreeXid(xid);
-               return -ENOMEM;
-       }
-
-/* BB add read reparse point symlink code and
-       Unix extensions symlink code here BB */
-       if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
-               rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
-                               tmpbuffer,
-                               len - 1,
-                               cifs_sb->local_nls);
-       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,
-                               cifs_sb->local_nls,
-                               cifs_sb->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
-               if (!rc) {
-                       rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
-                               tmpbuffer,
-                               len - 1,
-                               fid,
-                               cifs_sb->local_nls);
-                       if (CIFSSMBClose(xid, pTcon, fid)) {
-                               cFYI(1,("Error closing junction point (open for ioctl)"));
-                       }
-                       if (rc == -EIO) {
-                               /* Query if DFS Junction */
-                               tmp_path =
-                                       kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
-                                               GFP_KERNEL);
-                               if (tmp_path) {
-                                       strncpy(tmp_path, pTcon->treeName,
-                                               MAX_TREE_SIZE);
-                                       strncat(tmp_path, full_path,
-                                               MAX_PATHCONF);
-                                       rc = get_dfs_path(xid, pTcon->ses,
-                                               tmp_path,
-                                               cifs_sb->local_nls,
-                                               &num_referrals, &referrals,
-                                               cifs_sb->mnt_cifs_flags &
-                                                   CIFS_MOUNT_MAP_SPECIAL_CHR);
-                                       cFYI(1, ("Get DFS for %s rc = %d ",
-                                               tmp_path, rc));
-                                       if ((num_referrals == 0) && (rc == 0))
-                                               rc = -EACCES;
-                                       else {
-                                               cFYI(1, ("num referral: %d",
-                                                       num_referrals));
-                                               if (referrals) {
-                                                       cFYI(1,("referral string: %s", referrals));
-                                                       strncpy(tmpbuffer, referrals, len-1);
-                                               }
-                                       }
-                                       kfree(referrals);
-                                       kfree(tmp_path);
-}
-                               /* BB add code like else decode referrals
-                               then memcpy to tmpbuffer and free referrals
-                               string array BB */
-                       }
-               }
-       }
-       /* BB Anything else to do to handle recursive links? */
-       /* BB Should we be using page ops here? */
-
-       /* BB null terminate returned string in pBuffer? BB */
-       if (rc == 0) {
-               rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
-               cFYI(1,
-                    ("vfs_readlink called from cifs_readlink returned %d",
-                     rc));
-       }
-
-       kfree(tmpbuffer);
-       kfree(full_path);
-       FreeXid(xid);
-       return rc;
-}
-
 void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
 {
        char *p = nd_get_link(nd);