665 |
665 |
&statp->n_muid);
|
666 |
666 |
break;
|
667 |
667 |
}
|
|
668 |
case 'I': {
|
|
669 |
V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
|
|
670 |
offset += pdu_unmarshal(pdu, offset, "ddddqqqqq",
|
|
671 |
&iattr->valid, &iattr->mode,
|
|
672 |
&iattr->uid, &iattr->gid, &iattr->size,
|
|
673 |
&iattr->atime_sec, &iattr->atime_nsec,
|
|
674 |
&iattr->mtime_sec, &iattr->mtime_nsec);
|
|
675 |
break;
|
|
676 |
}
|
668 |
677 |
default:
|
669 |
678 |
break;
|
670 |
679 |
}
|
... | ... | |
1240 |
1249 |
qemu_free(vs);
|
1241 |
1250 |
}
|
1242 |
1251 |
|
|
1252 |
/* From Linux kernel code */
|
|
1253 |
#define ATTR_MODE (1 << 0)
|
|
1254 |
#define ATTR_UID (1 << 1)
|
|
1255 |
#define ATTR_GID (1 << 2)
|
|
1256 |
#define ATTR_SIZE (1 << 3)
|
|
1257 |
#define ATTR_ATIME (1 << 4)
|
|
1258 |
#define ATTR_MTIME (1 << 5)
|
|
1259 |
#define ATTR_CTIME (1 << 6)
|
|
1260 |
#define ATTR_MASK 127
|
|
1261 |
#define ATTR_ATIME_SET (1 << 7)
|
|
1262 |
#define ATTR_MTIME_SET (1 << 8)
|
|
1263 |
|
|
1264 |
static void v9fs_setattr_post_truncate(V9fsState *s, V9fsSetattrState *vs,
|
|
1265 |
int err)
|
|
1266 |
{
|
|
1267 |
if (err == -1) {
|
|
1268 |
err = -errno;
|
|
1269 |
goto out;
|
|
1270 |
}
|
|
1271 |
err = vs->offset;
|
|
1272 |
|
|
1273 |
out:
|
|
1274 |
complete_pdu(s, vs->pdu, err);
|
|
1275 |
qemu_free(vs);
|
|
1276 |
}
|
|
1277 |
|
|
1278 |
static void v9fs_setattr_post_chown(V9fsState *s, V9fsSetattrState *vs, int err)
|
|
1279 |
{
|
|
1280 |
if (err == -1) {
|
|
1281 |
err = -errno;
|
|
1282 |
goto out;
|
|
1283 |
}
|
|
1284 |
|
|
1285 |
if (vs->v9iattr.valid & (ATTR_SIZE)) {
|
|
1286 |
err = v9fs_do_truncate(s, &vs->fidp->path, vs->v9iattr.size);
|
|
1287 |
}
|
|
1288 |
v9fs_setattr_post_truncate(s, vs, err);
|
|
1289 |
return;
|
|
1290 |
|
|
1291 |
out:
|
|
1292 |
complete_pdu(s, vs->pdu, err);
|
|
1293 |
qemu_free(vs);
|
|
1294 |
}
|
|
1295 |
|
|
1296 |
static void v9fs_setattr_post_utimensat(V9fsState *s, V9fsSetattrState *vs,
|
|
1297 |
int err)
|
|
1298 |
{
|
|
1299 |
if (err == -1) {
|
|
1300 |
err = -errno;
|
|
1301 |
goto out;
|
|
1302 |
}
|
|
1303 |
|
|
1304 |
/* If the only valid entry in iattr is ctime we can call
|
|
1305 |
* chown(-1,-1) to update the ctime of the file
|
|
1306 |
*/
|
|
1307 |
if ((vs->v9iattr.valid & (ATTR_UID | ATTR_GID)) ||
|
|
1308 |
((vs->v9iattr.valid & ATTR_CTIME)
|
|
1309 |
&& !((vs->v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
|
|
1310 |
if (!(vs->v9iattr.valid & ATTR_UID)) {
|
|
1311 |
vs->v9iattr.uid = -1;
|
|
1312 |
}
|
|
1313 |
if (!(vs->v9iattr.valid & ATTR_GID)) {
|
|
1314 |
vs->v9iattr.gid = -1;
|
|
1315 |
}
|
|
1316 |
err = v9fs_do_chown(s, &vs->fidp->path, vs->v9iattr.uid,
|
|
1317 |
vs->v9iattr.gid);
|
|
1318 |
}
|
|
1319 |
v9fs_setattr_post_chown(s, vs, err);
|
|
1320 |
return;
|
|
1321 |
|
|
1322 |
out:
|
|
1323 |
complete_pdu(s, vs->pdu, err);
|
|
1324 |
qemu_free(vs);
|
|
1325 |
}
|
|
1326 |
|
|
1327 |
static void v9fs_setattr_post_chmod(V9fsState *s, V9fsSetattrState *vs, int err)
|
|
1328 |
{
|
|
1329 |
if (err == -1) {
|
|
1330 |
err = -errno;
|
|
1331 |
goto out;
|
|
1332 |
}
|
|
1333 |
|
|
1334 |
if (vs->v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) {
|
|
1335 |
struct timespec times[2];
|
|
1336 |
if (vs->v9iattr.valid & ATTR_ATIME) {
|
|
1337 |
if (vs->v9iattr.valid & ATTR_ATIME_SET) {
|
|
1338 |
times[0].tv_sec = vs->v9iattr.atime_sec;
|
|
1339 |
times[0].tv_nsec = vs->v9iattr.atime_nsec;
|
|
1340 |
} else {
|
|
1341 |
times[0].tv_nsec = UTIME_NOW;
|
|
1342 |
}
|
|
1343 |
} else {
|
|
1344 |
times[0].tv_nsec = UTIME_OMIT;
|
|
1345 |
}
|
|
1346 |
|
|
1347 |
if (vs->v9iattr.valid & ATTR_MTIME) {
|
|
1348 |
if (vs->v9iattr.valid & ATTR_MTIME_SET) {
|
|
1349 |
times[1].tv_sec = vs->v9iattr.mtime_sec;
|
|
1350 |
times[1].tv_nsec = vs->v9iattr.mtime_nsec;
|
|
1351 |
} else {
|
|
1352 |
times[1].tv_nsec = UTIME_NOW;
|
|
1353 |
}
|
|
1354 |
} else {
|
|
1355 |
times[1].tv_nsec = UTIME_OMIT;
|
|
1356 |
}
|
|
1357 |
err = v9fs_do_utimensat(s, &vs->fidp->path, times);
|
|
1358 |
}
|
|
1359 |
v9fs_setattr_post_utimensat(s, vs, err);
|
|
1360 |
return;
|
|
1361 |
|
|
1362 |
out:
|
|
1363 |
complete_pdu(s, vs->pdu, err);
|
|
1364 |
qemu_free(vs);
|
|
1365 |
}
|
|
1366 |
|
|
1367 |
static void v9fs_setattr(V9fsState *s, V9fsPDU *pdu)
|
|
1368 |
{
|
|
1369 |
int32_t fid;
|
|
1370 |
V9fsSetattrState *vs;
|
|
1371 |
int err = 0;
|
|
1372 |
|
|
1373 |
vs = qemu_malloc(sizeof(*vs));
|
|
1374 |
vs->pdu = pdu;
|
|
1375 |
vs->offset = 7;
|
|
1376 |
|
|
1377 |
pdu_unmarshal(pdu, vs->offset, "dI", &fid, &vs->v9iattr);
|
|
1378 |
|
|
1379 |
vs->fidp = lookup_fid(s, fid);
|
|
1380 |
if (vs->fidp == NULL) {
|
|
1381 |
err = -EINVAL;
|
|
1382 |
goto out;
|
|
1383 |
}
|
|
1384 |
|
|
1385 |
if (vs->v9iattr.valid & ATTR_MODE) {
|
|
1386 |
err = v9fs_do_chmod(s, &vs->fidp->path, vs->v9iattr.mode);
|
|
1387 |
}
|
|
1388 |
|
|
1389 |
v9fs_setattr_post_chmod(s, vs, err);
|
|
1390 |
return;
|
|
1391 |
|
|
1392 |
out:
|
|
1393 |
complete_pdu(s, vs->pdu, err);
|
|
1394 |
qemu_free(vs);
|
|
1395 |
}
|
|
1396 |
|
1243 |
1397 |
static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
|
1244 |
1398 |
{
|
1245 |
1399 |
complete_pdu(s, vs->pdu, err);
|
... | ... | |
2514 |
2668 |
[P9_TREADDIR] = v9fs_readdir,
|
2515 |
2669 |
[P9_TSTATFS] = v9fs_statfs,
|
2516 |
2670 |
[P9_TGETATTR] = v9fs_getattr,
|
|
2671 |
[P9_TSETATTR] = v9fs_setattr,
|
2517 |
2672 |
[P9_TVERSION] = v9fs_version,
|
2518 |
2673 |
[P9_TATTACH] = v9fs_attach,
|
2519 |
2674 |
[P9_TSTAT] = v9fs_stat,
|