Revision 65c05f9a hw/9pfs/virtio-9p.c
b/hw/9pfs/virtio-9p.c | ||
---|---|---|
1329 | 1329 |
#define ATTR_ATIME_SET (1 << 7) |
1330 | 1330 |
#define ATTR_MTIME_SET (1 << 8) |
1331 | 1331 |
|
1332 |
static void v9fs_setattr_post_truncate(V9fsState *s, V9fsSetattrState *vs, |
|
1333 |
int err) |
|
1334 |
{ |
|
1335 |
if (err == -1) { |
|
1336 |
err = -errno; |
|
1337 |
goto out; |
|
1338 |
} |
|
1339 |
err = vs->offset; |
|
1340 |
|
|
1341 |
out: |
|
1342 |
complete_pdu(s, vs->pdu, err); |
|
1343 |
qemu_free(vs); |
|
1344 |
} |
|
1345 |
|
|
1346 |
static void v9fs_setattr_post_chown(V9fsState *s, V9fsSetattrState *vs, int err) |
|
1332 |
static void v9fs_setattr(void *opaque) |
|
1347 | 1333 |
{ |
1348 |
if (err == -1) { |
|
1349 |
err = -errno; |
|
1350 |
goto out; |
|
1351 |
} |
|
1334 |
int err = 0; |
|
1335 |
int32_t fid; |
|
1336 |
V9fsFidState *fidp; |
|
1337 |
size_t offset = 7; |
|
1338 |
V9fsIattr v9iattr; |
|
1339 |
V9fsPDU *pdu = opaque; |
|
1340 |
V9fsState *s = pdu->s; |
|
1352 | 1341 |
|
1353 |
if (vs->v9iattr.valid & (ATTR_SIZE)) { |
|
1354 |
err = v9fs_do_truncate(s, &vs->fidp->path, vs->v9iattr.size); |
|
1355 |
} |
|
1356 |
v9fs_setattr_post_truncate(s, vs, err); |
|
1357 |
return; |
|
1342 |
pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr); |
|
1358 | 1343 |
|
1359 |
out: |
|
1360 |
complete_pdu(s, vs->pdu, err); |
|
1361 |
qemu_free(vs); |
|
1362 |
} |
|
1363 |
|
|
1364 |
static void v9fs_setattr_post_utimensat(V9fsState *s, V9fsSetattrState *vs, |
|
1365 |
int err) |
|
1366 |
{ |
|
1367 |
if (err == -1) { |
|
1368 |
err = -errno; |
|
1344 |
fidp = lookup_fid(s, fid); |
|
1345 |
if (fidp == NULL) { |
|
1346 |
err = -EINVAL; |
|
1369 | 1347 |
goto out; |
1370 | 1348 |
} |
1371 |
|
|
1372 |
/* If the only valid entry in iattr is ctime we can call |
|
1373 |
* chown(-1,-1) to update the ctime of the file |
|
1374 |
*/ |
|
1375 |
if ((vs->v9iattr.valid & (ATTR_UID | ATTR_GID)) || |
|
1376 |
((vs->v9iattr.valid & ATTR_CTIME) |
|
1377 |
&& !((vs->v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) { |
|
1378 |
if (!(vs->v9iattr.valid & ATTR_UID)) { |
|
1379 |
vs->v9iattr.uid = -1; |
|
1380 |
} |
|
1381 |
if (!(vs->v9iattr.valid & ATTR_GID)) { |
|
1382 |
vs->v9iattr.gid = -1; |
|
1349 |
if (v9iattr.valid & ATTR_MODE) { |
|
1350 |
err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode); |
|
1351 |
if (err < 0) { |
|
1352 |
goto out; |
|
1383 | 1353 |
} |
1384 |
err = v9fs_do_chown(s, &vs->fidp->path, vs->v9iattr.uid, |
|
1385 |
vs->v9iattr.gid); |
|
1386 | 1354 |
} |
1387 |
v9fs_setattr_post_chown(s, vs, err); |
|
1388 |
return; |
|
1389 |
|
|
1390 |
out: |
|
1391 |
complete_pdu(s, vs->pdu, err); |
|
1392 |
qemu_free(vs); |
|
1393 |
} |
|
1394 |
|
|
1395 |
static void v9fs_setattr_post_chmod(V9fsState *s, V9fsSetattrState *vs, int err) |
|
1396 |
{ |
|
1397 |
if (err == -1) { |
|
1398 |
err = -errno; |
|
1399 |
goto out; |
|
1400 |
} |
|
1401 |
|
|
1402 |
if (vs->v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) { |
|
1355 |
if (v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) { |
|
1403 | 1356 |
struct timespec times[2]; |
1404 |
if (vs->v9iattr.valid & ATTR_ATIME) {
|
|
1405 |
if (vs->v9iattr.valid & ATTR_ATIME_SET) {
|
|
1406 |
times[0].tv_sec = vs->v9iattr.atime_sec;
|
|
1407 |
times[0].tv_nsec = vs->v9iattr.atime_nsec;
|
|
1357 |
if (v9iattr.valid & ATTR_ATIME) { |
|
1358 |
if (v9iattr.valid & ATTR_ATIME_SET) { |
|
1359 |
times[0].tv_sec = v9iattr.atime_sec; |
|
1360 |
times[0].tv_nsec = v9iattr.atime_nsec; |
|
1408 | 1361 |
} else { |
1409 | 1362 |
times[0].tv_nsec = UTIME_NOW; |
1410 | 1363 |
} |
1411 | 1364 |
} else { |
1412 | 1365 |
times[0].tv_nsec = UTIME_OMIT; |
1413 | 1366 |
} |
1414 |
|
|
1415 |
if (vs->v9iattr.valid & ATTR_MTIME) { |
|
1416 |
if (vs->v9iattr.valid & ATTR_MTIME_SET) { |
|
1417 |
times[1].tv_sec = vs->v9iattr.mtime_sec; |
|
1418 |
times[1].tv_nsec = vs->v9iattr.mtime_nsec; |
|
1367 |
if (v9iattr.valid & ATTR_MTIME) { |
|
1368 |
if (v9iattr.valid & ATTR_MTIME_SET) { |
|
1369 |
times[1].tv_sec = v9iattr.mtime_sec; |
|
1370 |
times[1].tv_nsec = v9iattr.mtime_nsec; |
|
1419 | 1371 |
} else { |
1420 | 1372 |
times[1].tv_nsec = UTIME_NOW; |
1421 | 1373 |
} |
1422 | 1374 |
} else { |
1423 | 1375 |
times[1].tv_nsec = UTIME_OMIT; |
1424 | 1376 |
} |
1425 |
err = v9fs_do_utimensat(s, &vs->fidp->path, times); |
|
1377 |
err = v9fs_co_utimensat(s, &fidp->path, times); |
|
1378 |
if (err < 0) { |
|
1379 |
goto out; |
|
1380 |
} |
|
1426 | 1381 |
} |
1427 |
v9fs_setattr_post_utimensat(s, vs, err); |
|
1428 |
return; |
|
1429 |
|
|
1430 |
out: |
|
1431 |
complete_pdu(s, vs->pdu, err); |
|
1432 |
qemu_free(vs); |
|
1433 |
} |
|
1434 |
|
|
1435 |
static void v9fs_setattr(void *opaque) |
|
1436 |
{ |
|
1437 |
V9fsPDU *pdu = opaque; |
|
1438 |
V9fsState *s = pdu->s; |
|
1439 |
int32_t fid; |
|
1440 |
V9fsSetattrState *vs; |
|
1441 |
int err = 0; |
|
1442 |
|
|
1443 |
vs = qemu_malloc(sizeof(*vs)); |
|
1444 |
vs->pdu = pdu; |
|
1445 |
vs->offset = 7; |
|
1446 |
|
|
1447 |
pdu_unmarshal(pdu, vs->offset, "dI", &fid, &vs->v9iattr); |
|
1448 |
|
|
1449 |
vs->fidp = lookup_fid(s, fid); |
|
1450 |
if (vs->fidp == NULL) { |
|
1451 |
err = -EINVAL; |
|
1452 |
goto out; |
|
1382 |
/* |
|
1383 |
* If the only valid entry in iattr is ctime we can call |
|
1384 |
* chown(-1,-1) to update the ctime of the file |
|
1385 |
*/ |
|
1386 |
if ((v9iattr.valid & (ATTR_UID | ATTR_GID)) || |
|
1387 |
((v9iattr.valid & ATTR_CTIME) |
|
1388 |
&& !((v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) { |
|
1389 |
if (!(v9iattr.valid & ATTR_UID)) { |
|
1390 |
v9iattr.uid = -1; |
|
1391 |
} |
|
1392 |
if (!(v9iattr.valid & ATTR_GID)) { |
|
1393 |
v9iattr.gid = -1; |
|
1394 |
} |
|
1395 |
err = v9fs_co_chown(s, &fidp->path, v9iattr.uid, |
|
1396 |
v9iattr.gid); |
|
1397 |
if (err < 0) { |
|
1398 |
goto out; |
|
1399 |
} |
|
1453 | 1400 |
} |
1454 |
|
|
1455 |
if (vs->v9iattr.valid & ATTR_MODE) { |
|
1456 |
err = v9fs_do_chmod(s, &vs->fidp->path, vs->v9iattr.mode); |
|
1401 |
if (v9iattr.valid & (ATTR_SIZE)) { |
|
1402 |
err = v9fs_co_truncate(s, &fidp->path, v9iattr.size); |
|
1403 |
if (err < 0) { |
|
1404 |
goto out; |
|
1405 |
} |
|
1457 | 1406 |
} |
1458 |
|
|
1459 |
v9fs_setattr_post_chmod(s, vs, err); |
|
1460 |
return; |
|
1461 |
|
|
1407 |
err = offset; |
|
1462 | 1408 |
out: |
1463 |
complete_pdu(s, vs->pdu, err); |
|
1464 |
qemu_free(vs); |
|
1409 |
complete_pdu(s, pdu, err); |
|
1465 | 1410 |
} |
1466 | 1411 |
|
1467 | 1412 |
static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err) |
Also available in: Unified diff