nfsd: nfsd should drop CAP_MKNOD for non-root
[safe/jmp/linux-2.6] / fs / cifs / link.c
index 8e25996..63f6440 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
@@ -50,47 +50,49 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
 
        fromName = build_path_from_dentry(old_file);
        toName = build_path_from_dentry(direntry);
-       if((fromName == NULL) || (toName == NULL)) {
+       if ((fromName == NULL) || (toName == NULL)) {
                rc = -ENOMEM;
                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->local_nls,
                                            cifs_sb_target->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
        else {
                rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
-                                       cifs_sb_target->local_nls, 
+                                       cifs_sb_target->local_nls,
                                        cifs_sb_target->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
-               if((rc == -EIO) || (rc == -EINVAL))
-                       rc = -EOPNOTSUPP;  
+               if ((rc == -EIO) || (rc == -EINVAL))
+                       rc = -EOPNOTSUPP;
        }
 
        d_drop(direntry);       /* force new lookup from server of target */
 
        /* if source file is cached (oplocked) revalidate will not go to server
           until the file is closed or oplock broken so update nlinks locally */
-       if(old_file->d_inode) {
+       if (old_file->d_inode) {
                cifsInode = CIFS_I(old_file->d_inode);
-               if(rc == 0) {
+               if (rc == 0) {
                        old_file->d_inode->i_nlink++;
-                       old_file->d_inode->i_ctime = CURRENT_TIME;
+/* BB should we make this contingent on superblock flag NOATIME? */
+/*                     old_file->d_inode->i_ctime = CURRENT_TIME;*/
                        /* parent dir timestamps will update from srv
                        within a second, would it really be worth it
                        to set the parent dir cifs inode time to zero
                        to force revalidate (faster) for it too? */
                }
-               /* if not oplocked will force revalidate to get info 
+               /* if not oplocked will force revalidate to get info
                   on source file from srv */
                cifsInode->time = 0;
 
-                /* Will update parent dir timestamps from srv within a second.
+               /* Will update parent dir timestamps from srv within a second.
                   Would it really be worth it to set the parent dir (cifs
                   inode) time field to zero to force revalidate on parent
-                  directory faster ie 
+                  directory faster ie
                        CIFS_I(inode)->time = 0;  */
        }
 
@@ -108,7 +110,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
        int rc = -EACCES;
        int xid;
        char *full_path = NULL;
-       char * target_path = ERR_PTR(-ENOMEM);
+       char *target_path = ERR_PTR(-ENOMEM);
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *pTcon;
 
@@ -128,13 +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 */
@@ -175,7 +183,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 
        full_path = build_path_from_dentry(direntry);
 
-       if(full_path == NULL) {
+       if (full_path == NULL) {
                FreeXid(xid);
                return -ENOMEM;
        }
@@ -184,19 +192,20 @@ 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
-          rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
+          rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
+                                       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);
+                                                     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",
@@ -221,14 +230,11 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
        struct inode *inode = direntry->d_inode;
        int rc = -EACCES;
        int xid;
-       int oplock = FALSE;
+       int oplock = 0;
        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;
+       char *tmpbuffer;
        int len;
        __u16 fid;
 
@@ -236,13 +242,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
 
-/* BB would it be safe against deadlock to grab this sem 
+/* 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) {
+       if (full_path == NULL) {
                FreeXid(xid);
                return -ENOMEM;
        }
@@ -250,71 +256,47 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
        cFYI(1,
             ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
              full_path, inode, pBuffer, buflen));
-       if(buflen > PATH_MAX)
+       if (buflen > PATH_MAX)
                len = PATH_MAX;
        else
                len = buflen;
-       tmpbuffer = kmalloc(len,GFP_KERNEL);   
-       if(tmpbuffer == NULL) {
+       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 */
+/* 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,
                                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"));
+               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 & 
+                               OPEN_REPARSE_POINT, &fid, &oplock, NULL,
+                               cifs_sb->local_nls,
+                               cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-               if(!rc) {
+               if (!rc) {
                        rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
                                tmpbuffer,
-                               len - 1, 
+                               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 */
+                       if (CIFSSMBClose(xid, pTcon, fid)) {
+                               cFYI(1, ("Error closing junction point "
+                                        "(open for ioctl)"));
                        }
+                       /* If it is a DFS junction earlier we would have gotten
+                          PATH_NOT_COVERED returned from server so we do
+                          not need to request the DFS info here */
                }
        }
        /* BB Anything else to do to handle recursive links? */