FreeBSD/sys/ufs/ffs/ffs_vnops.c
/*
 * Vnode operation to set a named attribute.
 */
Vnode operation to set a named attribute.
Vnode operation to set a named attribute .
static int
ffs_setextattr(struct vop_setextattr_args *ap)
{
	struct inode *ip;
	struct fs *fs;
	uint32_t ealength, ul;
	ssize_t ealen;
	int olen, eapad1, eapad2, error, i, easize;
	u_char *eae, *p;
	ip = VTOI(ap->a_vp);
	fs = ip->i_fs;
	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
		return (EOPNOTSUPP);
	if (strlen(ap->a_name) == 0)
		return (EINVAL);
	if (ap->a_uio == NULL)
		return (EOPNOTSUPP);
	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
		return (EROFS);
	ealen = ap->a_uio->uio_resid;
	if (ealen < 0 || ealen > lblktosize(fs, NXADDR))
		return (EINVAL);
	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
	    ap->a_cred, ap->a_td, VWRITE);
	if (error) {
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = error;
		return (error);
	}
	error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
	if (error)
		return (error);
	ealength = sizeof(uint32_t) + 3 + strlen(ap->a_name);
	eapad1 = 8 - (ealength % 8);
	if (eapad1 == 8)
		eapad1 = 0;
	eapad2 = 8 - (ealen % 8);
	if (eapad2 == 8)
		eapad2 = 0;
	ealength += eapad1 + ealen + eapad2;
	eae = malloc(ip->i_ea_len + ealength, M_TEMP, M_WAITOK);
	bcopy(ip->i_ea_area, eae, ip->i_ea_len);
	easize = ip->i_ea_len;
	olen = ffs_findextattr(eae, easize,
	    ap->a_attrnamespace, ap->a_name, &p, NULL);
        if (olen == -1) {
		p = eae + easize;
		easize += ealength;
	} else {
		bcopy(p, &ul, sizeof ul);
		i = p - eae + ul;
		if (ul != ealength) {
			bcopy(p + ul, p + ealength, easize - i);
			easize += (ealength - ul);
		}
	}
	if (easize > lblktosize(fs, NXADDR)) {
		free(eae, M_TEMP);
		ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = ENOSPC;
		return(ENOSPC);
	}
	bcopy(&ealength, p, sizeof(ealength));
	p += sizeof(ealength);
	*p++ = ap->a_attrnamespace;
	*p++ = eapad2;
	*p++ = strlen(ap->a_name);
	strcpy(p, ap->a_name);
	p += strlen(ap->a_name);
	bzero(p, eapad1);
	p += eapad1;
	error = uiomove(p, ealen, ap->a_uio);
	if (error) {
		free(eae, M_TEMP);
		ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
			ip->i_ea_error = error;
		return(error);
	}
	p += ealen;
	bzero(p, eapad2);
	p = ip->i_ea_area;
	ip->i_ea_area = eae;
	ip->i_ea_len = easize;
	free(p, M_TEMP);
	error = ffs_close_ea(ap->a_vp, 1, ap->a_cred, ap->a_td);
	return(error);
}
static int ffs_setextattr ( struct vop_setextattr_args * ap ) { struct inode * ip ; struct fs * fs ; uint32_t ealength , ul ; ssize_t ealen ; int olen , eapad1 , eapad2 , error , i , easize ; u_char * eae , * p ; ip = VTOI ( ap -> a_vp ) ; fs = ip -> i_fs ; if ( ap -> a_vp -> v_type == VCHR || ap -> a_vp -> v_type == VBLK ) return ( EOPNOTSUPP ) ; if ( strlen ( ap -> a_name ) == 0 ) return ( EINVAL ) ; if ( ap -> a_uio == NULL ) return ( EOPNOTSUPP ) ; if ( ap -> a_vp -> v_mount -> mnt_flag & MNT_RDONLY ) return ( EROFS ) ; ealen = ap -> a_uio -> uio_resid ; if ( ealen < 0 || ealen > lblktosize ( fs , NXADDR ) ) return ( EINVAL ) ; error = extattr_check_cred ( ap -> a_vp , ap -> a_attrnamespace , ap -> a_cred , ap -> a_td , VWRITE ) ; if ( error ) { if ( ip -> i_ea_area != NULL && ip -> i_ea_error == 0 ) ip -> i_ea_error = error ; return ( error ) ; } error = ffs_open_ea ( ap -> a_vp , ap -> a_cred , ap -> a_td ) ; if ( error ) return ( error ) ; ealength = sizeof ( uint32_t ) + 3 + strlen ( ap -> a_name ) ; eapad1 = 8 - ( ealength % 8 ) ; if ( eapad1 == 8 ) eapad1 = 0 ; eapad2 = 8 - ( ealen % 8 ) ; if ( eapad2 == 8 ) eapad2 = 0 ; ealength += eapad1 + ealen + eapad2 ; eae = malloc ( ip -> i_ea_len + ealength , M_TEMP , M_WAITOK ) ; bcopy ( ip -> i_ea_area , eae , ip -> i_ea_len ) ; easize = ip -> i_ea_len ; olen = ffs_findextattr ( eae , easize , ap -> a_attrnamespace , ap -> a_name , & p , NULL ) ; if ( olen == -1 ) { p = eae + easize ; easize += ealength ; } else { bcopy ( p , & ul , sizeof ul ) ; i = p - eae + ul ; if ( ul != ealength ) { bcopy ( p + ul , p + ealength , easize - i ) ; easize += ( ealength - ul ) ; } } if ( easize > lblktosize ( fs , NXADDR ) ) { free ( eae , M_TEMP ) ; ffs_close_ea ( ap -> a_vp , 0 , ap -> a_cred , ap -> a_td ) ; if ( ip -> i_ea_area != NULL && ip -> i_ea_error == 0 ) ip -> i_ea_error = ENOSPC ; return ( ENOSPC ) ; } bcopy ( & ealength , p , sizeof ( ealength ) ) ; p += sizeof ( ealength ) ; * p ++ = ap -> a_attrnamespace ; * p ++ = eapad2 ; * p ++ = strlen ( ap -> a_name ) ; strcpy ( p , ap -> a_name ) ; p += strlen ( ap -> a_name ) ; bzero ( p , eapad1 ) ; p += eapad1 ; error = uiomove ( p , ealen , ap -> a_uio ) ; if ( error ) { free ( eae , M_TEMP ) ; ffs_close_ea ( ap -> a_vp , 0 , ap -> a_cred , ap -> a_td ) ; if ( ip -> i_ea_area != NULL && ip -> i_ea_error == 0 ) ip -> i_ea_error = error ; return ( error ) ; } p += ealen ; bzero ( p , eapad2 ) ; p = ip -> i_ea_area ; ip -> i_ea_area = eae ; ip -> i_ea_len = easize ; free ( p , M_TEMP ) ; error = ffs_close_ea ( ap -> a_vp , 1 , ap -> a_cred , ap -> a_td ) ; return ( error ) ; }
Vnode operation to set a named attribute.
Vnode operation to set a named attribute .
/*
vop_setextattr {
	IN struct vnode *a_vp;
	IN int a_attrnamespace;
	IN const char *a_name;
	INOUT struct uio *a_uio;
	IN struct ucred *a_cred;
	IN struct thread *a_td;
};
*/ /* XXX Now unsupported API to delete EAs using NULL uio. */ /*
		 * ffs_lock_ea is not needed there, because the vnode
		 * must be exclusively locked.
		 */ /* new, append at end */