|
Lines 99-104
static void process_extended_statvfs(u_int32_t id);
Link Here
|
| 99 |
static void process_extended_fstatvfs(u_int32_t id); |
99 |
static void process_extended_fstatvfs(u_int32_t id); |
| 100 |
static void process_extended_hardlink(u_int32_t id); |
100 |
static void process_extended_hardlink(u_int32_t id); |
| 101 |
static void process_extended_fsync(u_int32_t id); |
101 |
static void process_extended_fsync(u_int32_t id); |
|
|
102 |
static void process_extended_lsetstat(u_int32_t id); |
| 102 |
static void process_extended(u_int32_t id); |
103 |
static void process_extended(u_int32_t id); |
| 103 |
|
104 |
|
| 104 |
struct sftp_handler { |
105 |
struct sftp_handler { |
|
Lines 140-145
static const struct sftp_handler extended_handlers[] = {
Link Here
|
| 140 |
{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 }, |
141 |
{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 }, |
| 141 |
{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 }, |
142 |
{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 }, |
| 142 |
{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 }, |
143 |
{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 }, |
|
|
144 |
{ "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 }, |
| 143 |
{ NULL, NULL, 0, NULL, 0 } |
145 |
{ NULL, NULL, 0, NULL, 0 } |
| 144 |
}; |
146 |
}; |
| 145 |
|
147 |
|
|
Lines 658-663
process_init(void)
Link Here
|
| 658 |
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ |
660 |
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ |
| 659 |
/* fsync extension */ |
661 |
/* fsync extension */ |
| 660 |
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || |
662 |
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || |
|
|
663 |
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ |
| 664 |
(r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || |
| 661 |
(r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ |
665 |
(r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ |
| 662 |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
666 |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
| 663 |
send_msg(msg); |
667 |
send_msg(msg); |
|
Lines 881-886
attrib_to_tv(const Attrib *a)
Link Here
|
| 881 |
return tv; |
885 |
return tv; |
| 882 |
} |
886 |
} |
| 883 |
|
887 |
|
|
|
888 |
static struct timespec * |
| 889 |
attrib_to_ts(const Attrib *a) |
| 890 |
{ |
| 891 |
static struct timespec ts[2]; |
| 892 |
|
| 893 |
ts[0].tv_sec = a->atime; |
| 894 |
ts[0].tv_nsec = 0; |
| 895 |
ts[1].tv_sec = a->mtime; |
| 896 |
ts[1].tv_nsec = 0; |
| 897 |
return ts; |
| 898 |
} |
| 899 |
|
| 884 |
static void |
900 |
static void |
| 885 |
process_setstat(u_int32_t id) |
901 |
process_setstat(u_int32_t id) |
| 886 |
{ |
902 |
{ |
|
Lines 1342-1347
process_extended_fsync(u_int32_t id)
Link Here
|
| 1342 |
send_status(id, status); |
1358 |
send_status(id, status); |
| 1343 |
} |
1359 |
} |
| 1344 |
|
1360 |
|
|
|
1361 |
static void |
| 1362 |
process_extended_lsetstat(u_int32_t id) |
| 1363 |
{ |
| 1364 |
Attrib a; |
| 1365 |
char *name; |
| 1366 |
int r, status = SSH2_FX_OK; |
| 1367 |
|
| 1368 |
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || |
| 1369 |
(r = decode_attrib(iqueue, &a)) != 0) |
| 1370 |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
| 1371 |
|
| 1372 |
debug("request %u: lsetstat name \"%s\"", id, name); |
| 1373 |
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { |
| 1374 |
/* nonsensical for links */ |
| 1375 |
status = SSH2_FX_BAD_MESSAGE; |
| 1376 |
goto out; |
| 1377 |
} |
| 1378 |
if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
| 1379 |
logit("set \"%s\" mode %04o", name, a.perm); |
| 1380 |
r = fchmodat(AT_FDCWD, name, |
| 1381 |
a.perm & 07777, AT_SYMLINK_NOFOLLOW); |
| 1382 |
if (r == -1) |
| 1383 |
status = errno_to_portable(errno); |
| 1384 |
} |
| 1385 |
if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
| 1386 |
char buf[64]; |
| 1387 |
time_t t = a.mtime; |
| 1388 |
|
| 1389 |
strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", |
| 1390 |
localtime(&t)); |
| 1391 |
logit("set \"%s\" modtime %s", name, buf); |
| 1392 |
r = utimensat(AT_FDCWD, name, |
| 1393 |
attrib_to_ts(&a), AT_SYMLINK_NOFOLLOW); |
| 1394 |
if (r == -1) |
| 1395 |
status = errno_to_portable(errno); |
| 1396 |
} |
| 1397 |
if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { |
| 1398 |
logit("set \"%s\" owner %lu group %lu", name, |
| 1399 |
(u_long)a.uid, (u_long)a.gid); |
| 1400 |
r = fchownat(AT_FDCWD, name, a.uid, a.gid, |
| 1401 |
AT_SYMLINK_NOFOLLOW); |
| 1402 |
if (r == -1) |
| 1403 |
status = errno_to_portable(errno); |
| 1404 |
} |
| 1405 |
out: |
| 1406 |
send_status(id, status); |
| 1407 |
free(name); |
| 1408 |
} |
| 1409 |
|
| 1345 |
static void |
1410 |
static void |
| 1346 |
process_extended(u_int32_t id) |
1411 |
process_extended(u_int32_t id) |
| 1347 |
{ |
1412 |
{ |