Re: [PATCH] cifs: Add support of Alternate Data Streams

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon,  3 Sep 2012 18:06:06 -0500
shirishpargaonkar@xxxxxxxxx wrote:

> From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> 
> 
> Add support of Alternate Data Streams (ads).
> For the support, we need to add additional (desired) access flags
> to the generic ones that cifs client does currently.
> The ads files have a : in the name, so that is used to differentiate
> and add additional desired access.
> One operations that does not work is Rename (0x7).
> 
> 
> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> ---
>  fs/cifs/dir.c   |   12 ++++++++++--
>  fs/cifs/file.c  |   45 ++++++++++++++++++++++++++++++++++-----------
>  fs/cifs/inode.c |   14 ++++++++++++++
>  3 files changed, 58 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index cbe709a..8f8d546 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -245,10 +245,18 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
>  	}
>  
>  	desiredAccess = 0;
> -	if (OPEN_FMODE(oflags) & FMODE_READ)
> +	if (OPEN_FMODE(oflags) & FMODE_READ) {
>  		desiredAccess |= GENERIC_READ; /* is this too little? */
> -	if (OPEN_FMODE(oflags) & FMODE_WRITE)
> +		if (strstr(full_path, ":"))
> +			desiredAccess |= FILE_READ_DATA | FILE_READ_EA |
> +				FILE_READ_ATTRIBUTES | READ_CONTROL;
> +	}
> +	if (OPEN_FMODE(oflags) & FMODE_WRITE) {
>  		desiredAccess |= GENERIC_WRITE;
> +		if (strstr(full_path, ":"))
> +			desiredAccess |= FILE_WRITE_DATA | FILE_APPEND_DATA |
> +					FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
> +	}
>  
>  	disposition = FILE_OVERWRITE_IF;
>  	if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 9154192..80f35f8 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -43,22 +43,41 @@
>  #include "cifs_fs_sb.h"
>  #include "fscache.h"
>  
> -static inline int cifs_convert_flags(unsigned int flags)
> -{
> -	if ((flags & O_ACCMODE) == O_RDONLY)
> -		return GENERIC_READ;
> -	else if ((flags & O_ACCMODE) == O_WRONLY)
> -		return GENERIC_WRITE;
> -	else if ((flags & O_ACCMODE) == O_RDWR) {
> +static inline int cifs_convert_flags(char *full_path, unsigned int flags)
> +{
> +	int daccess = 0;
> +
> +	if ((flags & O_ACCMODE) == O_RDONLY) {
> +		daccess = GENERIC_READ;
> +		if (strstr(full_path, ":"))
> +			daccess |= FILE_READ_DATA | FILE_READ_EA |
> +				FILE_READ_ATTRIBUTES | READ_CONTROL;
> +		return daccess;
> +	} else if ((flags & O_ACCMODE) == O_WRONLY) {
> +		daccess = GENERIC_WRITE;
> +		if (strstr(full_path, ":"))
> +			daccess |= FILE_WRITE_DATA | FILE_APPEND_DATA |
> +				FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
> +		return daccess;
> +	} else if ((flags & O_ACCMODE) == O_RDWR) {
>  		/* GENERIC_ALL is too much permission to request
>  		   can cause unnecessary access denied on create */
>  		/* return GENERIC_ALL; */
> -		return (GENERIC_READ | GENERIC_WRITE);
> +		daccess = GENERIC_READ | GENERIC_WRITE;
> +		if (strstr(full_path, ":"))
> +			daccess |= FILE_READ_DATA | FILE_WRITE_DATA |
> +				FILE_APPEND_DATA | FILE_READ_EA |
> +				FILE_WRITE_EA | FILE_READ_ATTRIBUTES |
> +				FILE_WRITE_ATTRIBUTES | READ_CONTROL;
> +		return daccess;


So if any component in the pathname happens to have a ':' in it, then
we'll open the file with a different set of access flags? ':' is a
perfectly legitimate character in posix pathnames. That sounds like a
very bad heuristic.

>  	}
>  
> -	return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
> +	daccess = READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
>  		FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
> -		FILE_READ_DATA);
> +		FILE_READ_DATA;
> +
> +	return daccess;
> +
>  }
>  
>  static u32 cifs_posix_convert_flags(unsigned int flags)
> @@ -149,6 +168,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
>  		goto posix_open_ret; /* caller does not need info */
>  
>  	cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
> +	if (strstr(full_path, ":"))
> +		fattr.cf_flags |= S_PRIVATE;
>  
>  	/* get new inode and set it up */
>  	if (*pinode == NULL) {
> @@ -158,6 +179,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
>  			rc = -ENOMEM;
>  			goto posix_open_ret;
>  		}
> +		if (strstr(full_path, ":"))
> +			(*pinode)->i_flags |= S_PRIVATE;
>  	} else {
>  		cifs_fattr_to_inode(*pinode, &fattr);
>  	}
> @@ -178,7 +201,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
>  	int create_options = CREATE_NOT_DIR;
>  	FILE_ALL_INFO *buf;
>  
> -	desiredAccess = cifs_convert_flags(f_flags);
> +	desiredAccess = cifs_convert_flags(full_path, f_flags);
>  
>  /*********************************************************************
>   *  open flag mapping table:
> @@ -538,7 +561,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
>  		   in the reconnect path it is important to retry hard */
>  	}
>  
> -	desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
> +	desiredAccess = cifs_convert_flags(full_path, pCifsFile->f_flags);
>  
>  	if (backup_cred(cifs_sb))
>  		create_options |= CREATE_OPEN_BACKUP_INTENT;
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index 7354877..0bde128 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -351,12 +351,17 @@ int cifs_get_inode_info_unix(struct inode **pinode,
>  			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
>  	}
>  
> +	if (strstr(full_path, ":"))
> +		fattr.cf_flags |= S_PRIVATE;
> +
>  	if (*pinode == NULL) {
>  		/* get new inode */
>  		cifs_fill_uniqueid(sb, &fattr);
>  		*pinode = cifs_iget(sb, &fattr);
>  		if (!*pinode)
>  			rc = -ENOMEM;
> +		if (strstr(full_path, ":"))
> +			(*pinode)->i_flags |= S_PRIVATE;
>  	} else {
>  		/* we already have inode, update it */
>  		cifs_fattr_to_inode(*pinode, &fattr);
> @@ -713,10 +718,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
>  			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
>  	}
>  
> +	if (strstr(full_path, ":"))
> +		fattr.cf_flags |= S_PRIVATE;
> +
>  	if (!*inode) {
>  		*inode = cifs_iget(sb, &fattr);
>  		if (!*inode)
>  			rc = -ENOMEM;
> +		if (strstr(full_path, ":"))
> +			(*inode)->i_flags |= S_PRIVATE;
>  	} else {
>  		cifs_fattr_to_inode(*inode, &fattr);
>  	}
> @@ -748,6 +758,10 @@ cifs_find_inode(struct inode *inode, void *opaque)
>  	if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
>  		return 0;
>  
> +	/* don't match inode with different flags */
> +	if ((inode->i_flags & S_PRIVATE) != (fattr->cf_flags & S_PRIVATE))
> +		return 0;
> +
>  	/* if it's not a directory or has no dentries, then flag it */
>  	if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
>  		fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;


-- 
Jeff Layton <jlayton@xxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux