- * Set a named extended attribute on a file or directory * * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", * kernelspace string pointer "attrname", userspace buffer * pointer "data", buffer length "nbytes", thread "td". * Returns: 0 on success, an error number otherwise * Locks: none * References: vp must be a valid reference for the duration o
| 170 | * References: vp must be a valid reference for the duration of the call |
| 171 | */ |
| 172 | static int |
| 173 | extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, |
| 174 | void *data, size_t nbytes, struct thread *td) |
| 175 | { |
| 176 | struct mount *mp; |
| 177 | struct uio auio; |
| 178 | struct iovec aiov; |
| 179 | ssize_t cnt; |
| 180 | int error; |
| 181 | |
| 182 | if (nbytes > IOSIZE_MAX) |
| 183 | return (EINVAL); |
| 184 | |
| 185 | error = vn_start_write(vp, &mp, V_WAIT | PCATCH); |
| 186 | if (error) |
| 187 | return (error); |
| 188 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
| 189 | |
| 190 | aiov.iov_base = data; |
| 191 | aiov.iov_len = nbytes; |
| 192 | auio.uio_iov = &aiov; |
| 193 | auio.uio_iovcnt = 1; |
| 194 | auio.uio_offset = 0; |
| 195 | auio.uio_resid = nbytes; |
| 196 | auio.uio_rw = UIO_WRITE; |
| 197 | auio.uio_segflg = UIO_USERSPACE; |
| 198 | auio.uio_td = td; |
| 199 | cnt = nbytes; |
| 200 | |
| 201 | #ifdef MAC |
| 202 | error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace, |
| 203 | attrname); |
| 204 | if (error) |
| 205 | goto done; |
| 206 | #endif |
| 207 | |
| 208 | error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, |
| 209 | td->td_ucred, td); |
| 210 | cnt -= auio.uio_resid; |
| 211 | td->td_retval[0] = cnt; |
| 212 | |
| 213 | #ifdef MAC |
| 214 | done: |
| 215 | #endif |
| 216 | VOP_UNLOCK(vp); |
| 217 | vn_finished_write(mp); |
| 218 | return (error); |
| 219 | } |
| 220 | |
| 221 | #ifndef _SYS_SYSPROTO_H_ |
| 222 | struct extattr_set_fd_args { |
no test coverage detected