278 |
278 |
value, size);
|
279 |
279 |
}
|
280 |
280 |
|
|
281 |
static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path,
|
|
282 |
V9fsString *xattr_name,
|
|
283 |
void *value, size_t size, int flags)
|
|
284 |
{
|
|
285 |
return s->ops->lsetxattr(&s->ctx, path->data,
|
|
286 |
xattr_name->data, value, size, flags);
|
|
287 |
}
|
|
288 |
|
281 |
289 |
static void v9fs_string_init(V9fsString *str)
|
282 |
290 |
{
|
283 |
291 |
str->data = NULL;
|
... | ... | |
431 |
439 |
return f;
|
432 |
440 |
}
|
433 |
441 |
|
|
442 |
static int v9fs_xattr_fid_clunk(V9fsState *s, V9fsFidState *fidp)
|
|
443 |
{
|
|
444 |
int retval = 0;
|
|
445 |
|
|
446 |
if (fidp->fs.xattr.copied_len == -1) {
|
|
447 |
/* getxattr/listxattr fid */
|
|
448 |
goto free_value;
|
|
449 |
}
|
|
450 |
/*
|
|
451 |
* if this is fid for setxattr. clunk should
|
|
452 |
* result in setxattr localcall
|
|
453 |
*/
|
|
454 |
if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) {
|
|
455 |
/* clunk after partial write */
|
|
456 |
retval = -EINVAL;
|
|
457 |
goto free_out;
|
|
458 |
}
|
|
459 |
retval = v9fs_do_lsetxattr(s, &fidp->path, &fidp->fs.xattr.name,
|
|
460 |
fidp->fs.xattr.value,
|
|
461 |
fidp->fs.xattr.len,
|
|
462 |
fidp->fs.xattr.flags);
|
|
463 |
free_out:
|
|
464 |
v9fs_string_free(&fidp->fs.xattr.name);
|
|
465 |
free_value:
|
|
466 |
if (fidp->fs.xattr.value) {
|
|
467 |
qemu_free(fidp->fs.xattr.value);
|
|
468 |
}
|
|
469 |
return retval;
|
|
470 |
}
|
|
471 |
|
434 |
472 |
static int free_fid(V9fsState *s, int32_t fid)
|
435 |
473 |
{
|
|
474 |
int retval = 0;
|
436 |
475 |
V9fsFidState **fidpp, *fidp;
|
437 |
476 |
|
438 |
477 |
for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
|
... | ... | |
453 |
492 |
} else if (fidp->fid_type == P9_FID_DIR) {
|
454 |
493 |
v9fs_do_closedir(s, fidp->fs.dir);
|
455 |
494 |
} else if (fidp->fid_type == P9_FID_XATTR) {
|
456 |
|
if (fidp->fs.xattr.value) {
|
457 |
|
qemu_free(fidp->fs.xattr.value);
|
458 |
|
}
|
|
495 |
retval = v9fs_xattr_fid_clunk(s, fidp);
|
459 |
496 |
}
|
460 |
497 |
v9fs_string_free(&fidp->path);
|
461 |
498 |
qemu_free(fidp);
|
462 |
499 |
|
463 |
|
return 0;
|
|
500 |
return retval;
|
464 |
501 |
}
|
465 |
502 |
|
466 |
503 |
#define P9_QID_TYPE_DIR 0x80
|
... | ... | |
2211 |
2248 |
qemu_free(vs);
|
2212 |
2249 |
}
|
2213 |
2250 |
|
|
2251 |
static void v9fs_xattr_write(V9fsState *s, V9fsWriteState *vs)
|
|
2252 |
{
|
|
2253 |
int i, to_copy;
|
|
2254 |
ssize_t err = 0;
|
|
2255 |
int write_count;
|
|
2256 |
int64_t xattr_len;
|
|
2257 |
|
|
2258 |
xattr_len = vs->fidp->fs.xattr.len;
|
|
2259 |
write_count = xattr_len - vs->off;
|
|
2260 |
if (write_count > vs->count) {
|
|
2261 |
write_count = vs->count;
|
|
2262 |
} else if (write_count < 0) {
|
|
2263 |
/*
|
|
2264 |
* write beyond XATTR value len specified in
|
|
2265 |
* xattrcreate
|
|
2266 |
*/
|
|
2267 |
err = -ENOSPC;
|
|
2268 |
goto out;
|
|
2269 |
}
|
|
2270 |
vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", write_count);
|
|
2271 |
err = vs->offset;
|
|
2272 |
vs->fidp->fs.xattr.copied_len += write_count;
|
|
2273 |
/*
|
|
2274 |
* Now copy the content from sg list
|
|
2275 |
*/
|
|
2276 |
for (i = 0; i < vs->cnt; i++) {
|
|
2277 |
if (write_count > vs->sg[i].iov_len) {
|
|
2278 |
to_copy = vs->sg[i].iov_len;
|
|
2279 |
} else {
|
|
2280 |
to_copy = write_count;
|
|
2281 |
}
|
|
2282 |
memcpy((char *)vs->fidp->fs.xattr.value + vs->off,
|
|
2283 |
vs->sg[i].iov_base, to_copy);
|
|
2284 |
/* updating vs->off since we are not using below */
|
|
2285 |
vs->off += to_copy;
|
|
2286 |
write_count -= to_copy;
|
|
2287 |
}
|
|
2288 |
out:
|
|
2289 |
complete_pdu(s, vs->pdu, err);
|
|
2290 |
qemu_free(vs);
|
|
2291 |
}
|
|
2292 |
|
2214 |
2293 |
static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
|
2215 |
2294 |
{
|
2216 |
2295 |
int32_t fid;
|
... | ... | |
2226 |
2305 |
vs->len = 0;
|
2227 |
2306 |
|
2228 |
2307 |
pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count,
|
2229 |
|
vs->sg, &vs->cnt);
|
|
2308 |
vs->sg, &vs->cnt);
|
2230 |
2309 |
|
2231 |
2310 |
vs->fidp = lookup_fid(s, fid);
|
2232 |
2311 |
if (vs->fidp == NULL) {
|
... | ... | |
2234 |
2313 |
goto out;
|
2235 |
2314 |
}
|
2236 |
2315 |
|
2237 |
|
if (vs->fidp->fs.fd == -1) {
|
|
2316 |
if (vs->fidp->fid_type == P9_FID_FILE) {
|
|
2317 |
if (vs->fidp->fs.fd == -1) {
|
|
2318 |
err = -EINVAL;
|
|
2319 |
goto out;
|
|
2320 |
}
|
|
2321 |
} else if (vs->fidp->fid_type == P9_FID_XATTR) {
|
|
2322 |
/*
|
|
2323 |
* setxattr operation
|
|
2324 |
*/
|
|
2325 |
v9fs_xattr_write(s, vs);
|
|
2326 |
return;
|
|
2327 |
} else {
|
2238 |
2328 |
err = -EINVAL;
|
2239 |
2329 |
goto out;
|
2240 |
2330 |
}
|
2241 |
|
|
2242 |
2331 |
err = v9fs_do_lseek(s, vs->fidp->fs.fd, vs->off, SEEK_SET);
|
2243 |
2332 |
|
2244 |
2333 |
v9fs_write_post_lseek(s, vs, err);
|
... | ... | |
3276 |
3365 |
qemu_free(vs);
|
3277 |
3366 |
}
|
3278 |
3367 |
|
|
3368 |
static void v9fs_xattrcreate(V9fsState *s, V9fsPDU *pdu)
|
|
3369 |
{
|
|
3370 |
int flags;
|
|
3371 |
int32_t fid;
|
|
3372 |
ssize_t err = 0;
|
|
3373 |
V9fsXattrState *vs;
|
|
3374 |
|
|
3375 |
vs = qemu_malloc(sizeof(*vs));
|
|
3376 |
vs->pdu = pdu;
|
|
3377 |
vs->offset = 7;
|
|
3378 |
|
|
3379 |
pdu_unmarshal(vs->pdu, vs->offset, "dsqd",
|
|
3380 |
&fid, &vs->name, &vs->size, &flags);
|
|
3381 |
|
|
3382 |
vs->file_fidp = lookup_fid(s, fid);
|
|
3383 |
if (vs->file_fidp == NULL) {
|
|
3384 |
err = -EINVAL;
|
|
3385 |
goto out;
|
|
3386 |
}
|
|
3387 |
|
|
3388 |
/* Make the file fid point to xattr */
|
|
3389 |
vs->xattr_fidp = vs->file_fidp;
|
|
3390 |
vs->xattr_fidp->fid_type = P9_FID_XATTR;
|
|
3391 |
vs->xattr_fidp->fs.xattr.copied_len = 0;
|
|
3392 |
vs->xattr_fidp->fs.xattr.len = vs->size;
|
|
3393 |
vs->xattr_fidp->fs.xattr.flags = flags;
|
|
3394 |
v9fs_string_init(&vs->xattr_fidp->fs.xattr.name);
|
|
3395 |
v9fs_string_copy(&vs->xattr_fidp->fs.xattr.name, &vs->name);
|
|
3396 |
vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size);
|
|
3397 |
|
|
3398 |
out:
|
|
3399 |
complete_pdu(s, vs->pdu, err);
|
|
3400 |
v9fs_string_free(&vs->name);
|
|
3401 |
qemu_free(vs);
|
|
3402 |
}
|
3279 |
3403 |
|
3280 |
3404 |
typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
|
3281 |
3405 |
|
... | ... | |
3285 |
3409 |
[P9_TGETATTR] = v9fs_getattr,
|
3286 |
3410 |
[P9_TSETATTR] = v9fs_setattr,
|
3287 |
3411 |
[P9_TXATTRWALK] = v9fs_xattrwalk,
|
|
3412 |
[P9_TXATTRCREATE] = v9fs_xattrcreate,
|
3288 |
3413 |
[P9_TMKNOD] = v9fs_mknod,
|
3289 |
3414 |
[P9_TRENAME] = v9fs_rename,
|
3290 |
3415 |
[P9_TMKDIR] = v9fs_mkdir,
|