2005-04-17 02:20:36 +04:00
/*
* fs / cifs / fcntl . c
*
* vfs operations that deal with the file control API
2007-06-05 22:30:44 +04:00
*
2005-04-17 02:20:36 +04:00
* Copyright ( C ) International Business Machines Corp . , 2003 , 2004
* Author ( s ) : Steve French ( sfrench @ us . ibm . com )
*
* This library is free software ; you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation ; either version 2.1 of the License , or
* ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See
* the GNU Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/fs.h>
# include <linux/stat.h>
# include <linux/fcntl.h>
# include "cifsglob.h"
# include "cifsproto.h"
# include "cifs_unicode.h"
# include "cifs_debug.h"
# include "cifsfs.h"
static __u32 convert_to_cifs_notify_flags ( unsigned long fcntl_notify_flags )
{
__u32 cifs_ntfy_flags = 0 ;
/* No way on Linux VFS to ask to monitor xattr
changes ( and no stream support either */
2008-02-08 02:25:02 +03:00
if ( fcntl_notify_flags & DN_ACCESS )
2005-04-17 02:20:36 +04:00
cifs_ntfy_flags | = FILE_NOTIFY_CHANGE_LAST_ACCESS ;
2007-06-05 22:30:44 +04:00
if ( fcntl_notify_flags & DN_MODIFY ) {
2005-04-17 02:20:36 +04:00
/* What does this mean on directories? */
cifs_ntfy_flags | = FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_SIZE ;
}
2007-06-05 22:30:44 +04:00
if ( fcntl_notify_flags & DN_CREATE ) {
cifs_ntfy_flags | = FILE_NOTIFY_CHANGE_CREATION |
2005-04-17 02:20:36 +04:00
FILE_NOTIFY_CHANGE_LAST_WRITE ;
}
2008-02-08 02:25:02 +03:00
if ( fcntl_notify_flags & DN_DELETE )
2005-04-17 02:20:36 +04:00
cifs_ntfy_flags | = FILE_NOTIFY_CHANGE_LAST_WRITE ;
2007-06-05 22:30:44 +04:00
if ( fcntl_notify_flags & DN_RENAME ) {
2005-04-17 02:20:36 +04:00
/* BB review this - checking various server behaviors */
2007-06-05 22:30:44 +04:00
cifs_ntfy_flags | = FILE_NOTIFY_CHANGE_DIR_NAME |
2005-04-17 02:20:36 +04:00
FILE_NOTIFY_CHANGE_FILE_NAME ;
}
2007-06-05 22:30:44 +04:00
if ( fcntl_notify_flags & DN_ATTRIB ) {
cifs_ntfy_flags | = FILE_NOTIFY_CHANGE_SECURITY |
2005-04-17 02:20:36 +04:00
FILE_NOTIFY_CHANGE_ATTRIBUTES ;
}
2007-06-05 22:30:44 +04:00
/* if (fcntl_notify_flags & DN_MULTISHOT) {
2005-04-17 02:20:36 +04:00
cifs_ntfy_flags | = ;
} */ /* BB fixme - not sure how to handle this with CIFS yet */
return cifs_ntfy_flags ;
}
2007-07-10 05:16:18 +04:00
int cifs_dir_notify ( struct file * file , unsigned long arg )
2005-04-17 02:20:36 +04:00
{
int xid ;
int rc = - EINVAL ;
2008-04-29 04:06:05 +04:00
int oplock = 0 ;
2005-04-17 02:20:36 +04:00
struct cifs_sb_info * cifs_sb ;
struct cifsTconInfo * pTcon ;
char * full_path = NULL ;
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES ;
__u16 netfid ;
2007-06-05 22:30:44 +04:00
if ( experimEnabled = = 0 )
2005-10-11 06:52:13 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
xid = GetXid ( ) ;
2006-12-08 13:36:48 +03:00
cifs_sb = CIFS_SB ( file - > f_path . dentry - > d_sb ) ;
2005-04-17 02:20:36 +04:00
pTcon = cifs_sb - > tcon ;
2006-12-08 13:36:48 +03:00
full_path = build_path_from_dentry ( file - > f_path . dentry ) ;
2005-04-17 02:20:36 +04:00
2007-06-05 22:30:44 +04:00
if ( full_path = = NULL ) {
2005-04-17 02:20:36 +04:00
rc = - ENOMEM ;
} else {
2007-06-05 22:30:44 +04:00
cFYI ( 1 , ( " dir notify on file %s Arg 0x%lx " , full_path , arg ) ) ;
rc = CIFSSMBOpen ( xid , pTcon , full_path , FILE_OPEN ,
2005-04-17 02:20:36 +04:00
GENERIC_READ | SYNCHRONIZE , 0 /* create options */ ,
2007-06-05 22:30:44 +04:00
& netfid , & oplock , NULL , cifs_sb - > local_nls ,
2005-04-29 09:41:06 +04:00
cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR ) ;
2005-04-17 02:20:36 +04:00
/* BB fixme - add this handle to a notify handle list */
2007-06-05 22:30:44 +04:00
if ( rc ) {
cFYI ( 1 , ( " Could not open directory for notify " ) ) ;
2005-04-17 02:20:36 +04:00
} else {
filter = convert_to_cifs_notify_flags ( arg ) ;
2007-06-05 22:30:44 +04:00
if ( filter ! = 0 ) {
rc = CIFSSMBNotify ( xid , pTcon ,
2005-08-25 07:03:11 +04:00
0 /* no subdirs */ , netfid ,
filter , file , arg & DN_MULTISHOT ,
cifs_sb - > local_nls ) ;
2005-04-17 02:20:36 +04:00
} else {
rc = - EINVAL ;
}
/* BB add code to close file eventually (at unmount
it would close automatically but may be a way
to do it easily when inode freed or when
notify info is cleared / changed */
2007-06-05 22:30:44 +04:00
cFYI ( 1 , ( " notify rc %d " , rc ) ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-06-05 22:30:44 +04:00
2005-04-17 02:20:36 +04:00
FreeXid ( xid ) ;
return rc ;
}