Exemplo n.º 1
0
int
cifs_dir_open(struct inode *inode, struct file *file)
{				/* NB: currently unused since searches are opened in readdir */
	int rc = 0;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	if(file->f_dentry) {
		down(&file->f_dentry->d_sb->s_vfs_rename_sem);
		full_path = build_wildcard_path_from_dentry(file->f_dentry);
		up(&file->f_dentry->d_sb->s_vfs_rename_sem);
	} else {
		FreeXid(xid);
		return -EIO;
	}

	cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));

	if (full_path)
		kfree(full_path);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 2
0
int
cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
{
	int rc = -EOPNOTSUPP;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;
	struct inode *newinode = NULL;

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	full_path = build_path_from_dentry(direntry);

	if (full_path == NULL) {
		rc = -ENOMEM;
		FreeXid(xid);
		return rc;
	}

	cFYI(1, "Full path: %s", full_path);
	cFYI(1, "symname is %s", symname);

	/* BB what if DFS and this volume is on different share? BB */
	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); */

	if (rc == 0) {
		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, NULL);

		if (rc != 0) {
			cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d",
			      rc);
		} else {
			if (pTcon->nocase)
				direntry->d_op = &cifs_ci_dentry_ops;
			else
				direntry->d_op = &cifs_dentry_ops;
			d_instantiate(direntry, newinode);
		}
	}

	kfree(full_path);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 3
0
/* Retrieve an ACL from the server */
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
				       const char *path, const __u16 *pfid)
{
	struct cifsFileInfo *open_file = NULL;
	bool unlock_file = false;
	int xid;
	int rc = -EIO;
	__u16 fid;
	struct super_block *sb;
	struct cifs_sb_info *cifs_sb;
	struct cifs_ntsd *pntsd = NULL;

	cFYI(1, ("get mode from ACL for %s", path));

	if (inode == NULL)
		return NULL;

	xid = GetXid();
	if (pfid == NULL)
		open_file = find_readable_file(CIFS_I(inode));
	else
		fid = *pfid;

	sb = inode->i_sb;
	if (sb == NULL) {
		FreeXid(xid);
		return NULL;
	}
	cifs_sb = CIFS_SB(sb);

	if (open_file) {
		unlock_file = true;
		fid = open_file->netfid;
	} else if (pfid == NULL) {
		int oplock = 0;
		/* open file */
		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
				READ_CONTROL, 0, &fid, &oplock, NULL,
				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc != 0) {
			cERROR(1, ("Unable to open file to get ACL"));
			FreeXid(xid);
			return NULL;
		}
	}

	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
	if (unlock_file == true) /* find_readable_file increments ref count */
		atomic_dec(&open_file->wrtPending);
	else if (pfid == NULL) /* if opened above we have to close the handle */
		CIFSSMBClose(xid, cifs_sb->tcon, fid);
	/* else handle was passed in by caller */

	FreeXid(xid);
	return pntsd;
}
Exemplo n.º 4
0
int
cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
{
	int rc = -EOPNOTSUPP;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;
	struct inode *newinode = NULL;

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	down(&inode->i_sb->s_vfs_rename_sem);
	full_path = build_path_from_dentry(direntry);
	up(&inode->i_sb->s_vfs_rename_sem);

	if(full_path == NULL) {
		FreeXid(xid);
		return -ENOMEM;
	}

	cFYI(1, ("Full path: %s ", full_path));
	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)
		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
					   cifs_sb->local_nls);
	/* else
	   rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */

	if (rc == 0) {
		if (pTcon->ses->capabilities & CAP_UNIX)
			rc = cifs_get_inode_info_unix(&newinode, full_path,
						      inode->i_sb);
		else
			rc = cifs_get_inode_info(&newinode, full_path, NULL,
						 inode->i_sb);

		if (rc != 0) {
			cFYI(1,
			     ("Create symlink worked but get_inode_info failed with rc = %d ",
			      rc));
		} else {
			direntry->d_op = &cifs_dentry_ops;
			d_instantiate(direntry, newinode);
		}
	}

	if (full_path)
		kfree(full_path);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 5
0
int cifs_removexattr(struct dentry *direntry, const char *ea_name)
{
	int rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	struct super_block *sb;
	char *full_path;

	if (direntry == NULL)
		return -EIO;
	if (direntry->d_inode == NULL)
		return -EIO;
	sb = direntry->d_inode->i_sb;
	if (sb == NULL)
		return -EIO;
	xid = GetXid();

	cifs_sb = CIFS_SB(sb);
	pTcon = cifs_sb->tcon;

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		FreeXid(xid);
		return rc;
	}
	if (ea_name == NULL) {
		cFYI(1, "Null xattr names not supported");
	} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
		&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
		cFYI(1,
		     "illegal xattr request %s (only user namespace supported)",
		     ea_name);
		/* BB what if no namespace prefix? */
		/* Should we just pass them to server, except for
		system and perhaps security prefixes? */
	} else {
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
			goto remove_ea_exit;

		ea_name += 5; /* skip past user. prefix */
		rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
			(__u16)0, cifs_sb->local_nls,
			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	}
remove_ea_exit:
	kfree(full_path);
	FreeXid(xid);
#endif
	return rc;
}
Exemplo n.º 6
0
/* Set an ACL on the server */
static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
				struct inode *inode, const char *path)
{
	struct cifsFileInfo *open_file;
	bool unlock_file = false;
	int xid;
	int rc = -EIO;
	__u16 fid;
	struct super_block *sb;
	struct cifs_sb_info *cifs_sb;

	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));

	if (!inode)
		return rc;

	sb = inode->i_sb;
	if (sb == NULL)
		return rc;

	cifs_sb = CIFS_SB(sb);
	xid = GetXid();

	open_file = find_readable_file(CIFS_I(inode));
	if (open_file) {
		unlock_file = true;
		fid = open_file->netfid;
	} else {
		int oplock = 0;
		/* open file */
		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
				WRITE_DAC, 0, &fid, &oplock, NULL,
				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc != 0) {
			cERROR(1, ("Unable to open file to set ACL"));
			FreeXid(xid);
			return rc;
		}
	}

	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
	if (unlock_file)
		atomic_dec(&open_file->wrtPending);
	else
		CIFSSMBClose(xid, cifs_sb->tcon, fid);

	FreeXid(xid);

	return rc;
}
Exemplo n.º 7
0
ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
{
	ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	struct super_block *sb;
	char *full_path;

	if (direntry == NULL)
		return -EIO;
	if (direntry->d_inode == NULL)
		return -EIO;
	sb = direntry->d_inode->i_sb;
	if (sb == NULL)
		return -EIO;

	cifs_sb = CIFS_SB(sb);
	pTcon = cifs_sb->tcon;

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
		return -EOPNOTSUPP;

	xid = GetXid();

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		FreeXid(xid);
		return rc;
	}
	/* return dos attributes as pseudo xattr */
	/* return alt name if available as pseudo attr */

	/* if proc/fs/cifs/streamstoxattr is set then
		search server for EAs or streams to
		returns as xattrs */
	rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
				buf_size, cifs_sb->local_nls,
				cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);

	kfree(full_path);
	FreeXid(xid);
#endif
	return rc;
}
Exemplo n.º 8
0
static int
cifs_statfs(struct super_block *sb, struct kstatfs *buf)
{
	int xid, rc;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;

	xid = GetXid();

	cifs_sb = CIFS_SB(sb);
	pTcon = cifs_sb->tcon;

	buf->f_type = CIFS_MAGIC_NUMBER;

	/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
	buf->f_namelen = PATH_MAX;	/* PATH_MAX may be too long - it would presumably
					   be length of total path, note that some servers may be 
					   able to support more than this, but best to be safe
					   since Win2k and others can not handle very long filenames */
	buf->f_files = 0;	/* undefined */
	buf->f_ffree = 0;	/* unlimited */

	rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);

	/*     
	   int f_type;
	   __fsid_t f_fsid;
	   int f_namelen;  */
	/* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
	FreeXid(xid);
	return 0;		/* always return success? what if volume is no longer available? */
}
Exemplo n.º 9
0
static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
		struct cifs_ntsd *pnntsd, u32 acllen)
{
	int oplock = 0;
	int xid, rc;
	__u16 fid;

	xid = GetXid();

	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
			 &fid, &oplock, NULL, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cERROR(1, "Unable to open file to set ACL");
		goto out;
	}

	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
	cFYI(DBG2, "SetCIFSACL rc = %d", rc);

	CIFSSMBClose(xid, cifs_sb->tcon, fid);
 out:
	FreeXid(xid);
	return rc;
}
Exemplo n.º 10
0
static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
		const char *path, u32 *pacllen)
{
	struct cifs_ntsd *pntsd = NULL;
	int oplock = 0;
	int xid, rc, create_options = 0;
	__u16 fid;
	struct cifs_tcon *tcon;
	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

	if (IS_ERR(tlink))
		return ERR_CAST(tlink);

	tcon = tlink_tcon(tlink);
	xid = GetXid();

	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
			create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (!rc) {
		rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
		CIFSSMBClose(xid, tcon, fid);
	}

	cifs_put_tlink(tlink);
	FreeXid(xid);

	cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
	if (rc)
		return ERR_PTR(rc);
	return pntsd;
}
Exemplo n.º 11
0
static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
		const char *path, u32 *pacllen)
{
	struct cifs_ntsd *pntsd = NULL;
	int oplock = 0;
	int xid, rc;
	__u16 fid;

	xid = GetXid();

	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
			 &fid, &oplock, NULL, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cERROR(1, "Unable to open file to get ACL");
		goto out;
	}

	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
	cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);

	CIFSSMBClose(xid, cifs_sb->tcon, fid);
 out:
	FreeXid(xid);
	return pntsd;
}
Exemplo n.º 12
0
int cifs_dir_notify(struct file *file, unsigned long arg)
{
	int xid;
	int rc = -EINVAL;
	int oplock = FALSE;
	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;

	if (experimEnabled == 0)
		return 0;

	xid = GetXid();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
	pTcon = cifs_sb->tcon;

	full_path = build_path_from_dentry(file->f_dentry);
#else
	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
	pTcon = cifs_sb->tcon;

	full_path = build_path_from_dentry(file->f_path.dentry);
#endif

	if (full_path == NULL) {
		rc = -ENOMEM;
	} else {
		cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
			GENERIC_READ | SYNCHRONIZE, FILE_SHARE_ALL, 0 /* create options */,
			&netfid, &oplock, NULL, cifs_sb->local_nls,
			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
		/* BB fixme - add this handle to a notify handle list */
		if (rc) {
			cFYI(1, ("Could not open directory for notify"));
		} else {
			filter = convert_to_cifs_notify_flags(arg);
			if (filter != 0) {
				rc = CIFSSMBNotify(xid, pTcon,
					0 /* no subdirs */, netfid,
					filter, file, arg & DN_MULTISHOT,
					cifs_sb->local_nls);
			} 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 */
			cFYI(1, ("notify rc %d", rc));
		}
	}

	FreeXid(xid);
	return rc;
}
Exemplo n.º 13
0
int
cifs_hardlink(struct dentry *old_file, struct inode *inode,
	      struct dentry *direntry)
{
	int rc = -EACCES;
	int xid;
	char *fromName = NULL;
	char *toName = NULL;
	struct cifs_sb_info *cifs_sb_target;
	struct cifsTconInfo *pTcon;
	struct cifsInodeInfo *cifsInode;

	xid = GetXid();

	cifs_sb_target = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb_target->tcon;

/* No need to check for cross device links since server will do that
   BB note DFS case in future though (when we may have to check) */

	fromName = build_path_from_dentry(old_file);
	toName = build_path_from_dentry(direntry);
	if((fromName == NULL) || (toName == NULL)) {
		rc = -ENOMEM;
		goto cifs_hl_exit;
	}

	if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
					    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->mnt_cifs_flags &
						CIFS_MOUNT_MAP_SPECIAL_CHR);
		if((rc == -EIO) || (rc == -EINVAL))
			rc = -EOPNOTSUPP;  
	}

/* if (!rc)     */
	{
		/*   renew_parental_timestamps(old_file);
		   inode->i_nlink++;
		   mark_inode_dirty(inode);
		   d_instantiate(direntry, inode); */
		/* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
	}
	d_drop(direntry);	/* force new lookup from server */
	cifsInode = CIFS_I(old_file->d_inode);
	cifsInode->time = 0;	/* will force revalidate to go get info when needed */

cifs_hl_exit:
	kfree(fromName);
	kfree(toName);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 14
0
void *
cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
{
	struct inode *inode = direntry->d_inode;
	int rc = -EACCES;
	int xid;
	char *full_path = NULL;
	char * target_path = ERR_PTR(-ENOMEM);
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;

	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);
		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) {

/* BB Add special case check for Samba DFS symlinks */

		target_path[PATH_MAX-1] = 0;
	} else {
		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 */
}
Exemplo n.º 15
0
int cifs_rmdir(struct inode *inode, struct dentry *direntry)
{
	int rc = 0;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;
	struct cifsInodeInfo *cifsInode;

	cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		FreeXid(xid);
		return -ENOMEM;
	}

	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);

	if (!rc) {
		drop_nlink(inode);
		spin_lock(&direntry->d_inode->i_lock);
		i_size_write(direntry->d_inode, 0);
		clear_nlink(direntry->d_inode);
		spin_unlock(&direntry->d_inode->i_lock);
	}

	cifsInode = CIFS_I(direntry->d_inode);
	cifsInode->time = 0;	/* force revalidate to go get info when
				   needed */
	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
		current_fs_time(inode->i_sb);

	kfree(full_path);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 16
0
int
cifs_rmdir(struct inode *inode, struct dentry *direntry)
{
	int rc = 0;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;
	struct cifsInodeInfo *cifsInode;

	cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	down(&inode->i_sb->s_vfs_rename_sem);
	full_path = build_path_from_dentry(direntry);
	up(&inode->i_sb->s_vfs_rename_sem);
	if(full_path == NULL) {
		FreeXid(xid);
		return -ENOMEM;
	}

	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);

	if (!rc) {
		inode->i_nlink--;
		i_size_write(direntry->d_inode,0);
		direntry->d_inode->i_nlink = 0;
	}

	cifsInode = CIFS_I(direntry->d_inode);
	cifsInode->time = 0;	/* force revalidate to go get info when needed */
	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
	    CURRENT_TIME;

	if (full_path)
		kfree(full_path);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 17
0
static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
		struct cifs_ntsd *pnntsd, u32 acllen)
{
	int xid, rc;

	xid = GetXid();
	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
	FreeXid(xid);

	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
	return rc;
}
Exemplo n.º 18
0
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number) 
{
	int rc = -EPERM;
	int xid;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;
	char *full_path = NULL;
	struct inode * newinode = NULL;

	if (!old_valid_dev(device_number))
		return -EINVAL;

	xid = GetXid();

	cifs_sb = CIFS_SB(inode->i_sb);
	pTcon = cifs_sb->tcon;

	down(&direntry->d_sb->s_vfs_rename_sem);
	full_path = build_path_from_dentry(direntry);
	up(&direntry->d_sb->s_vfs_rename_sem);
	if(full_path == NULL)
		rc = -ENOMEM;
	
	if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
				mode,(__u64)current->euid,(__u64)current->egid,
				device_number, cifs_sb->local_nls,
				cifs_sb->mnt_cifs_flags & 
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		} else {
			rc = CIFSSMBUnixSetPerms(xid, pTcon,
				full_path, mode, (__u64)-1, (__u64)-1,
				device_number, cifs_sb->local_nls,
				cifs_sb->mnt_cifs_flags & 
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		}

		if(!rc) {
			rc = cifs_get_inode_info_unix(&newinode, full_path,
						inode->i_sb,xid);
			direntry->d_op = &cifs_dentry_ops;
			if(rc == 0)
				d_instantiate(direntry, newinode);
		}
	}

	kfree(full_path);
	FreeXid(xid);
	return rc;
}
Exemplo n.º 19
0
static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
		__u16 fid, u32 *pacllen)
{
	struct cifs_ntsd *pntsd = NULL;
	int xid, rc;

	xid = GetXid();
	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
	FreeXid(xid);


	cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
	return pntsd;
}
Exemplo n.º 20
0
void *
cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
{
	struct inode *inode = direntry->d_inode;
	int rc = -ENOMEM;
	int xid;
	char *full_path = NULL;
	char *target_path = NULL;
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifsTconInfo *tcon = cifs_sb->tcon;

	xid = GetXid();

	/*
	 * 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;
	}

	full_path = build_path_from_dentry(direntry);
	if (!full_path)
		goto out;

	cFYI(1, "Full path: %s inode = 0x%p", full_path, inode);

	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);
	}

	FreeXid(xid);
	nd_set_link(nd, target_path);
	return NULL;
}
Exemplo n.º 21
0
static int
cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
	struct super_block *sb = dentry->d_sb;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
	int rc = -EOPNOTSUPP;
	int xid;

	xid = GetXid();

	buf->f_type = CIFS_MAGIC_NUMBER;

	/*
	 * PATH_MAX may be too long - it would presumably be total path,
	 * but note that some servers (includinng Samba 3) have a shorter
	 * maximum path.
	 *
	 * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
	 */
	buf->f_namelen = PATH_MAX;
	buf->f_files = 0;	/* undefined */
	buf->f_ffree = 0;	/* unlimited */

	/*
	 * We could add a second check for a QFS Unix capability bit
	 */
	if ((tcon->ses->capabilities & CAP_UNIX) &&
	    (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
		rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);

	/*
	 * Only need to call the old QFSInfo if failed on newer one,
	 * e.g. by OS/2.
	 **/
	if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
		rc = CIFSSMBQFSInfo(xid, tcon, buf);

	/*
	 * Some old Windows servers also do not support level 103, retry with
	 * older level one if old server failed the previous call or we
	 * bypassed it because we detected that this was an older LANMAN sess
	 */
	if (rc)
		rc = SMBOldQFSInfo(xid, tcon, buf);

	FreeXid(xid);
	return 0;
}
Exemplo n.º 22
0
int cifs_dir_notify(struct file * file, unsigned long arg)
{
	int xid;
	int rc = -EINVAL;
	int oplock = FALSE;
	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;

	xid = GetXid();
	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
	pTcon = cifs_sb->tcon;

	down(&file->f_dentry->d_sb->s_vfs_rename_sem);
	full_path = build_path_from_dentry(file->f_dentry);
	up(&file->f_dentry->d_sb->s_vfs_rename_sem);

	if(full_path == NULL) {
		rc = -ENOMEM;
	} else {
		cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 
			GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
			&netfid, &oplock,NULL, cifs_sb->local_nls);
		/* BB fixme - add this handle to a notify handle list */
		if(rc) {
			cERROR(1,("Could not open directory for notify"));  /* BB remove BB */
		} else {
			filter = convert_to_cifs_notify_flags(arg);
			if(filter != 0) {
				rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, 
					filter, cifs_sb->local_nls);
			} 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 */
            cERROR(1,("notify rc %d",rc));
		}
	}
	
	FreeXid(xid);
	return rc;
}
Exemplo n.º 23
0
static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
		struct cifs_ntsd *pnntsd, u32 acllen)
{
	int xid, rc;
	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

	if (IS_ERR(tlink))
		return PTR_ERR(tlink);

	xid = GetXid();
	rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
	FreeXid(xid);
	cifs_put_tlink(tlink);

	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
	return rc;
}
Exemplo n.º 24
0
static int
cifs_statfs(struct super_block *sb, struct kstatfs *buf)
{
	int xid; 
	int rc = -EOPNOTSUPP;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;

	xid = GetXid();

	cifs_sb = CIFS_SB(sb);
	pTcon = cifs_sb->tcon;

	buf->f_type = CIFS_MAGIC_NUMBER;

	/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
	buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would 
				      presumably be total path, but note
				      that some servers (includinng Samba 3)
				      have a shorter maximum path */
	buf->f_files = 0;	/* undefined */
	buf->f_ffree = 0;	/* unlimited */

#ifdef CONFIG_CIFS_EXPERIMENTAL
/* BB we could add a second check for a QFS Unix capability bit */
/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
    if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
			le64_to_cpu(pTcon->fsUnixInfo.Capability)))
	    rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf);

    /* Only need to call the old QFSInfo if failed
    on newer one */
    if(rc)
#endif /* CIFS_EXPERIMENTAL */
	rc = CIFSSMBQFSInfo(xid, pTcon, buf);

	/*     
	   int f_type;
	   __fsid_t f_fsid;
	   int f_namelen;  */
	/* BB get from info in tcon struct at mount time call to QFSAttrInfo */
	FreeXid(xid);
	return 0;		/* always return success? what if volume is no
				   longer available? */
}
Exemplo n.º 25
0
static int
cifs_statfs(struct super_block *sb, struct kstatfs *buf)
{
	int xid, rc = -EOPNOTSUPP;
	struct cifs_sb_info *cifs_sb;
	struct cifsTconInfo *pTcon;

	xid = GetXid();

	cifs_sb = CIFS_SB(sb);
	pTcon = cifs_sb->tcon;

	buf->f_type = CIFS_MAGIC_NUMBER;

	/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
	buf->f_namelen = PATH_MAX;	/* PATH_MAX may be too long - it would presumably
					   be length of total path, note that some servers may be 
					   able to support more than this, but best to be safe
					   since Win2k and others can not handle very long filenames */
	buf->f_files = 0;	/* undefined */
	buf->f_ffree = 0;	/* unlimited */

#ifdef CONFIG_CIFS_EXPERIMENTAL
/* BB we could add a second check for a QFS Unix capability bit */
    if (pTcon->ses->capabilities & CAP_UNIX)
	    rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls);

    /* Only need to call the old QFSInfo if failed
    on newer one */
    if(rc)
#endif /* CIFS_EXPERIMENTAL */
	rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);

	/*     
	   int f_type;
	   __fsid_t f_fsid;
	   int f_namelen;  */
	/* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
	FreeXid(xid);
	return 0;		/* always return success? what if volume is no longer available? */
}
Exemplo n.º 26
0
int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
			struct inode *inode, const char *path, int aclflag)
{
	int oplock = 0;
	int xid, rc, access_flags, create_options = 0;
	__u16 fid;
	struct cifs_tcon *tcon;
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

	if (IS_ERR(tlink))
		return PTR_ERR(tlink);

	tcon = tlink_tcon(tlink);
	xid = GetXid();

	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

	if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
		access_flags = WRITE_OWNER;
	else
		access_flags = WRITE_DAC;

	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
			create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
		cERROR(1, "Unable to open file to set ACL");
		goto out;
	}

	rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
	cFYI(DBG2, "SetCIFSACL rc = %d", rc);

	CIFSSMBClose(xid, tcon, fid);
out:
	FreeXid(xid);
	cifs_put_tlink(tlink);
	return rc;
}
Exemplo n.º 27
0
int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
{
	int xid;
	int rc = 0;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifsTconInfo *pTcon;

	if (cifs_sb)
		pTcon = cifs_sb->tcon;
	else
		return -EIO;

	xid = GetXid();
	if (pTcon) {
		cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
	} else
		rc = -EIO;

	FreeXid(xid);
	return rc;
}
Exemplo n.º 28
0
int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
{
	int xid;
	int rc = 0;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifsTconInfo *pTcon;

	if (cifs_sb)
		pTcon = cifs_sb->tcon;
	else
		return -EIO;

	xid = GetXid();
	if (pTcon) {
		cFYI(1, ("pqstats %p", qstats));
	} else
		rc = -EIO;

	FreeXid(xid);
	return rc;
}
Exemplo n.º 29
0
static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
		__u16 fid, u32 *pacllen)
{
	struct cifs_ntsd *pntsd = NULL;
	int xid, rc;
	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);

	if (IS_ERR(tlink))
		return ERR_CAST(tlink);

	xid = GetXid();
	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
	FreeXid(xid);

	cifs_put_tlink(tlink);

	cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
	if (rc)
		return ERR_PTR(rc);
	return pntsd;
}
Exemplo n.º 30
0
int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
		    struct fs_disk_quota *pdquota)
{
	int xid;
	int rc = 0;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifsTconInfo *pTcon;

	if (cifs_sb)
		pTcon = cifs_sb->tcon;
	else
		return -EIO;

	xid = GetXid();
	if (pTcon) {
		cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
	} else
		rc = -EIO;

	FreeXid(xid);
	return rc;
}