示例#1
0
/*
 * CATIA translation of a pathname component after returning from lookuppnvp
 */
static char *
smb_pathname_catia_v4tov5(smb_request_t *sr, char *name,
    char *namebuf, int buflen)
{
	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
		smb_vop_catia_v4tov5(name, namebuf, buflen);
		return (namebuf);
	}

	return (name);
}
示例#2
0
/*
 * smb_vop_lookup
 *
 * dvp:		directory vnode (in)
 * name:	name of file to be looked up (in)
 * vpp:		looked-up vnode (out)
 * od_name:	on-disk name of file (out).
 *		This parameter is optional.  If a pointer is passed in, it
 * 		must be allocated with MAXNAMELEN bytes
 * rootvp:	vnode of the tree root (in)
 *		This parameter is always passed in non-NULL except at the time
 *		of share set up.
 * direntflags:	dirent flags returned from VOP_LOOKUP
 */
int
smb_vop_lookup(
    vnode_t		*dvp,
    char		*name,
    vnode_t		**vpp,
    char		*od_name,
    int			flags,
    int			*direntflags,
    vnode_t		*rootvp,
    cred_t		*cr)
{
	int error = 0;
	int option_flags = 0;
	pathname_t rpn;
	char *np = name;
	char namebuf[MAXNAMELEN];

	if (*name == '\0')
		return (EINVAL);

	ASSERT(vpp);
	*vpp = NULL;
	*direntflags = 0;

	if ((name[0] == '.') && (name[1] == '.') && (name[2] == 0)) {
		if (rootvp && (dvp == rootvp)) {
			VN_HOLD(dvp);
			*vpp = dvp;
			return (0);
		}

		if (dvp->v_flag & VROOT) {
			vfs_t *vfsp;
			vnode_t *cvp = dvp;

			/*
			 * Set dvp and check for races with forced unmount
			 * (see lookuppnvp())
			 */

			vfsp = cvp->v_vfsp;
			vfs_rlock_wait(vfsp);
			if (((dvp = cvp->v_vfsp->vfs_vnodecovered) == NULL) ||
			    (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) {
				vfs_unlock(vfsp);
				return (EIO);
			}
			vfs_unlock(vfsp);
		}
	}

	if (flags & SMB_IGNORE_CASE)
		option_flags = FIGNORECASE;

	if (flags & SMB_CATIA)
		np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf));

	pn_alloc(&rpn);

	error = VOP_LOOKUP(dvp, np, vpp, NULL, option_flags, NULL, cr,
	    &smb_ct, direntflags, &rpn);

	if ((error == 0) && od_name) {
		bzero(od_name, MAXNAMELEN);
		np = (option_flags == FIGNORECASE) ? rpn.pn_buf : name;

		if (flags & SMB_CATIA)
			smb_vop_catia_v4tov5(np, od_name, MAXNAMELEN);
		else
			(void) strlcpy(od_name, np, MAXNAMELEN);
	}

	pn_free(&rpn);
	return (error);
}
示例#3
0
/*
 * smb_odir_next_odirent
 *
 * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer
 * is empty or we've reached the end of it), read the next set of
 * entries from the file system (vop_readdir).
 *
 * File systems which support VFSFT_EDIRENT_FLAGS will return the
 * directory entries as a buffer of edirent_t structure. Others will
 * return a buffer of dirent64_t structures.  For simplicity translate
 * the data into an smb_odirent_t structure.
 * The ed_name/d_name in d_buf is NULL terminated by the file system.
 *
 * Some file systems can have directories larger than SMB_MAXDIRSIZE.
 * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT and set d_eof
 * to true to stop subsequent calls to smb_vop_readdir.
 *
 * Returns:
 *      0 - success. odirent is populated with the next directory entry
 * ENOENT - no more directory entries
 *  errno - error
 */
static int
smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
{
	int		rc;
	int		reclen;
	int		eof;
	dirent64_t	*dp;
	edirent_t	*edp;
	char		*np;
	uint32_t	abe_flag = 0;

	ASSERT(MUTEX_HELD(&od->d_mutex));

	bzero(odirent, sizeof (smb_odirent_t));

	if (od->d_bufptr != NULL) {
		if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
			reclen = od->d_edp->ed_reclen;
		else
			reclen = od->d_dp->d_reclen;

		if (reclen == 0) {
			od->d_bufptr = NULL;
		} else {
			od->d_bufptr += reclen;
			if (od->d_bufptr >= od->d_buf + od->d_bufsize)
				od->d_bufptr = NULL;
		}
	}

	if (od->d_bufptr == NULL) {
		if (od->d_eof)
			return (ENOENT);

		od->d_bufsize = sizeof (od->d_buf);

		if (od->d_flags & SMB_ODIR_FLAG_ABE)
			abe_flag = SMB_ABE;

		rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset,
		    od->d_buf, &od->d_bufsize, &eof, abe_flag, od->d_cred);

		if ((rc == 0) && (od->d_bufsize == 0))
			rc = ENOENT;

		if (rc != 0) {
			od->d_bufptr = NULL;
			od->d_bufsize = 0;
			return (rc);
		}

		od->d_eof = (eof != 0);
		od->d_bufptr = od->d_buf;
	}

	if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
		od->d_offset = od->d_edp->ed_off;
	else
		od->d_offset = od->d_dp->d_off;

	if (od->d_offset >= SMB_MAXDIRSIZE) {
		od->d_bufptr = NULL;
		od->d_bufsize = 0;
		od->d_eof = B_TRUE;
		return (ENOENT);
	}

	if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) {
		edp = od->d_edp;
		odirent->od_ino = edp->ed_ino;
		odirent->od_eflags = edp->ed_eflags;
		np = edp->ed_name;
	} else {
		dp = od->d_dp;
		odirent->od_ino = dp->d_ino;
		odirent->od_eflags = 0;
		np =  dp->d_name;
	}

	if ((od->d_flags & SMB_ODIR_FLAG_CATIA) &&
	    ((od->d_flags & SMB_ODIR_FLAG_XATTR) == 0)) {
		smb_vop_catia_v4tov5(np, odirent->od_name,
		    sizeof (odirent->od_name));
	} else {
		(void) strlcpy(odirent->od_name, np,
		    sizeof (odirent->od_name));
	}

	return (0);
}