|
Lines 30-35
Link Here
|
| 30 |
#include <sys/statvfs.h> |
30 |
#include <sys/statvfs.h> |
| 31 |
#endif |
31 |
#endif |
| 32 |
|
32 |
|
|
|
33 |
#include <sys/xattr.h> |
| 34 |
#ifndef ENOATTR |
| 35 |
#define ENOATTR ENODATA |
| 36 |
#endif |
| 37 |
|
| 33 |
#include <dirent.h> |
38 |
#include <dirent.h> |
| 34 |
#include <errno.h> |
39 |
#include <errno.h> |
| 35 |
#include <fcntl.h> |
40 |
#include <fcntl.h> |
|
Lines 51-56
Link Here
|
| 51 |
#include "sftp.h" |
56 |
#include "sftp.h" |
| 52 |
#include "sftp-common.h" |
57 |
#include "sftp-common.h" |
| 53 |
|
58 |
|
|
|
59 |
#define MAX_XATTR_DATA_LEN 100000 |
| 60 |
|
| 54 |
/* helper */ |
61 |
/* helper */ |
| 55 |
#define get_int64() buffer_get_int64(&iqueue); |
62 |
#define get_int64() buffer_get_int64(&iqueue); |
| 56 |
#define get_int() buffer_get_int(&iqueue); |
63 |
#define get_int() buffer_get_int(&iqueue); |
|
Lines 73-78
u_int version;
Link Here
|
| 73 |
/* Disable writes */ |
80 |
/* Disable writes */ |
| 74 |
int readonly; |
81 |
int readonly; |
| 75 |
|
82 |
|
|
|
83 |
/* xattr extension */ |
| 84 |
int xattr_caching; |
| 85 |
|
| 86 |
typedef struct Xattrib Xattrib; |
| 87 |
|
| 88 |
struct Xattrib { |
| 89 |
char *name; |
| 90 |
void *value; |
| 91 |
size_t size; |
| 92 |
}; |
| 93 |
|
| 76 |
/* portable attributes, etc. */ |
94 |
/* portable attributes, etc. */ |
| 77 |
|
95 |
|
| 78 |
typedef struct Stat Stat; |
96 |
typedef struct Stat Stat; |
|
Lines 81-86
struct Stat {
Link Here
|
| 81 |
char *name; |
99 |
char *name; |
| 82 |
char *long_name; |
100 |
char *long_name; |
| 83 |
Attrib attrib; |
101 |
Attrib attrib; |
|
|
102 |
Xattrib *xattrib; |
| 103 |
size_t xa_size; |
| 84 |
}; |
104 |
}; |
| 85 |
|
105 |
|
| 86 |
static int |
106 |
static int |
|
Lines 110-115
errno_to_portable(int unixerrno)
Link Here
|
| 110 |
case ENOSYS: |
130 |
case ENOSYS: |
| 111 |
ret = SSH2_FX_OP_UNSUPPORTED; |
131 |
ret = SSH2_FX_OP_UNSUPPORTED; |
| 112 |
break; |
132 |
break; |
|
|
133 |
case ENOATTR: |
| 134 |
ret = SSH2_FX_ENOATTR; |
| 135 |
break; |
| 136 |
case ENOSPC: |
| 137 |
case EDQUOT: |
| 138 |
ret = SSH2_FX_ENOSPC; |
| 139 |
break; |
| 140 |
case ENOTSUP: |
| 141 |
ret = SSH2_FX_ENOTSUP; |
| 142 |
break; |
| 143 |
case ERANGE: |
| 144 |
ret = SSH2_FX_ERANGE; |
| 145 |
break; |
| 146 |
case EMSGSIZE: |
| 147 |
ret = SSH2_FX_EMSGSIZE; |
| 148 |
break; |
| 113 |
default: |
149 |
default: |
| 114 |
ret = SSH2_FX_FAILURE; |
150 |
ret = SSH2_FX_FAILURE; |
| 115 |
break; |
151 |
break; |
|
Lines 396-401
status_to_message(u_int32_t status)
Link Here
|
| 396 |
"No connection", /* SSH_FX_NO_CONNECTION */ |
432 |
"No connection", /* SSH_FX_NO_CONNECTION */ |
| 397 |
"Connection lost", /* SSH_FX_CONNECTION_LOST */ |
433 |
"Connection lost", /* SSH_FX_CONNECTION_LOST */ |
| 398 |
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ |
434 |
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ |
|
|
435 |
"No such attribute", /* SSH2_FX_ENOATTR */ |
| 436 |
"No space", /* SSH2_FX_ENOSPC */ |
| 437 |
"Not supported", /* SSH2_FX_ENOTSUP */ |
| 438 |
"Range error", /* SSH2_FX_ERANGE */ |
| 439 |
"Message size error", /* SSH2_FX_EMSGSIZE */ |
| 399 |
"Unknown error" /* Others */ |
440 |
"Unknown error" /* Others */ |
| 400 |
}; |
441 |
}; |
| 401 |
return (status_messages[MIN(status,SSH2_FX_MAX)]); |
442 |
return (status_messages[MIN(status,SSH2_FX_MAX)]); |
|
Lines 454-476
send_handle(u_int32_t id, int handle)
Link Here
|
| 454 |
} |
495 |
} |
| 455 |
|
496 |
|
| 456 |
static void |
497 |
static void |
|
|
498 |
write_allxattr_data(Buffer *msg, Xattrib *xa, size_t xa_size) { |
| 499 |
buffer_put_int(msg, xa_size); |
| 500 |
if (xa_size == (size_t)-1) |
| 501 |
buffer_put_int(msg, *(int*)xa); |
| 502 |
else if (xa_size != 0) { |
| 503 |
size_t j; |
| 504 |
for (j=0; j<xa_size; ++j) { |
| 505 |
buffer_put_cstring(msg, xa[j].name); |
| 506 |
buffer_put_int(msg, xa[j].size); |
| 507 |
if (xa[j].size == (size_t)-1) |
| 508 |
buffer_put_int(msg, *(int*)xa[j].value); |
| 509 |
else if (xa[j].size != 0) |
| 510 |
buffer_append(msg, xa[j].value, xa[j].size); |
| 511 |
} |
| 512 |
} |
| 513 |
} |
| 514 |
|
| 515 |
static void |
| 516 |
send_names_start(Buffer *msg, u_int32_t id) |
| 517 |
{ |
| 518 |
debug("send_names_start %u", id); |
| 519 |
buffer_init(msg); |
| 520 |
buffer_put_char(msg, SSH2_FXP_NAME); |
| 521 |
buffer_put_int(msg, id); |
| 522 |
buffer_put_int(msg, 0); |
| 523 |
} |
| 524 |
|
| 525 |
static void |
| 526 |
send_names_next(Buffer *msg, u_int32_t id, const Stat *stats) |
| 527 |
{ |
| 528 |
buffer_put_cstring(msg, stats->name); |
| 529 |
buffer_put_cstring(msg, stats->long_name); |
| 530 |
encode_attrib(msg, &stats->attrib); |
| 531 |
if (xattr_caching) |
| 532 |
write_allxattr_data(msg, stats->xattrib, stats->xa_size); |
| 533 |
} |
| 534 |
|
| 535 |
static void |
| 536 |
send_names_end(Buffer *msg, int count) |
| 537 |
{ |
| 538 |
char buf[4]; |
| 539 |
put_u32(buf, count); |
| 540 |
memcpy((char*)buffer_ptr(msg) + 5, buf, 4); |
| 541 |
send_msg(msg); |
| 542 |
buffer_free(msg); |
| 543 |
} |
| 544 |
|
| 545 |
static void |
| 457 |
send_names(u_int32_t id, int count, const Stat *stats) |
546 |
send_names(u_int32_t id, int count, const Stat *stats) |
| 458 |
{ |
547 |
{ |
| 459 |
Buffer msg; |
548 |
Buffer msg; |
| 460 |
int i; |
549 |
int i; |
| 461 |
|
550 |
|
| 462 |
buffer_init(&msg); |
551 |
send_names_start(&msg, id); |
| 463 |
buffer_put_char(&msg, SSH2_FXP_NAME); |
|
|
| 464 |
buffer_put_int(&msg, id); |
| 465 |
buffer_put_int(&msg, count); |
| 466 |
debug("request %u: sent names count %d", id, count); |
552 |
debug("request %u: sent names count %d", id, count); |
| 467 |
for (i = 0; i < count; i++) { |
553 |
for (i = 0; i < count; i++) { |
| 468 |
buffer_put_cstring(&msg, stats[i].name); |
554 |
send_names_next(&msg, id, stats + i); |
| 469 |
buffer_put_cstring(&msg, stats[i].long_name); |
|
|
| 470 |
encode_attrib(&msg, &stats[i].attrib); |
| 471 |
} |
555 |
} |
| 472 |
send_msg(&msg); |
556 |
send_names_end(&msg, count); |
| 473 |
buffer_free(&msg); |
|
|
| 474 |
} |
557 |
} |
| 475 |
|
558 |
|
| 476 |
static void |
559 |
static void |
|
Lines 538-543
process_init(void)
Link Here
|
| 538 |
/* hardlink extension */ |
621 |
/* hardlink extension */ |
| 539 |
buffer_put_cstring(&msg, "hardlink@openssh.com"); |
622 |
buffer_put_cstring(&msg, "hardlink@openssh.com"); |
| 540 |
buffer_put_cstring(&msg, "1"); /* version */ |
623 |
buffer_put_cstring(&msg, "1"); /* version */ |
|
|
624 |
/* xattr extensions */ |
| 625 |
buffer_put_cstring(&msg, "setxattr@openssh.com"); |
| 626 |
buffer_put_cstring(&msg, "1"); /* version */ |
| 627 |
buffer_put_cstring(&msg, "getxattr@openssh.com"); |
| 628 |
buffer_put_cstring(&msg, "1"); /* version */ |
| 629 |
buffer_put_cstring(&msg, "listxattr@openssh.com"); |
| 630 |
buffer_put_cstring(&msg, "1"); /* version */ |
| 631 |
buffer_put_cstring(&msg, "removexattr@openssh.com"); |
| 632 |
buffer_put_cstring(&msg, "1"); /* version */ |
| 633 |
buffer_put_cstring(&msg, "cachexattr@openssh.com"); |
| 634 |
buffer_put_cstring(&msg, "1"); /* version */ |
| 635 |
buffer_put_cstring(&msg, "getallxattr@openssh.com"); |
| 636 |
buffer_put_cstring(&msg, "1"); /* version */ |
| 541 |
send_msg(&msg); |
637 |
send_msg(&msg); |
| 542 |
buffer_free(&msg); |
638 |
buffer_free(&msg); |
| 543 |
} |
639 |
} |
|
Lines 907-912
process_opendir(void)
Link Here
|
| 907 |
xfree(path); |
1003 |
xfree(path); |
| 908 |
} |
1004 |
} |
| 909 |
|
1005 |
|
|
|
1006 |
static void delete_xattr(Xattrib *xattr, size_t xa_size) |
| 1007 |
{ |
| 1008 |
if (xa_size != 0) { |
| 1009 |
if (xa_size != (size_t)-1) { |
| 1010 |
size_t i; |
| 1011 |
for (i=0; i<xa_size; ++i) { |
| 1012 |
xfree(xattr[i].name); |
| 1013 |
if (xattr[i].size != 0) { |
| 1014 |
xfree(xattr[i].value); |
| 1015 |
} |
| 1016 |
} |
| 1017 |
} |
| 1018 |
xfree(xattr); |
| 1019 |
} |
| 1020 |
} |
| 1021 |
|
| 1022 |
static size_t get_xattr(const char *path, Xattrib **xattrib) |
| 1023 |
{ |
| 1024 |
size_t lsize = 1024; |
| 1025 |
char *list = xmalloc(lsize); |
| 1026 |
size_t lret; |
| 1027 |
Xattrib *xattr = NULL; |
| 1028 |
do { |
| 1029 |
lret = llistxattr(path, list, lsize); |
| 1030 |
if (lret == (size_t)-1) { |
| 1031 |
if (errno == ERANGE) { |
| 1032 |
lret = llistxattr(path, list, 0); |
| 1033 |
if (lret != (size_t)-1) { |
| 1034 |
if (lret > MAX_XATTR_DATA_LEN) { |
| 1035 |
lret = (size_t)-1; |
| 1036 |
errno = EMSGSIZE; |
| 1037 |
} |
| 1038 |
else { |
| 1039 |
lsize = lret; |
| 1040 |
list = xrealloc(list, lsize, 1); |
| 1041 |
continue; |
| 1042 |
} |
| 1043 |
} |
| 1044 |
} |
| 1045 |
} |
| 1046 |
break; |
| 1047 |
} while (1); |
| 1048 |
debug3("get_xattr: lret=%ld", lret); |
| 1049 |
|
| 1050 |
if (lret == (size_t)-1) { |
| 1051 |
xattr = xmalloc(sizeof(int)); |
| 1052 |
*(int*)xattr = errno_to_portable(errno); |
| 1053 |
} else if (lret != 0) { |
| 1054 |
char *p; |
| 1055 |
char *list_end = list + lret; |
| 1056 |
int cnt = 0; |
| 1057 |
for (p=list; p<list_end; ++p) |
| 1058 |
if (!*p) |
| 1059 |
++cnt; |
| 1060 |
debug3("get_xattr: cnt=%d", cnt); |
| 1061 |
xattr = xcalloc(cnt, sizeof(Xattrib)); |
| 1062 |
size_t vsize = 1024; |
| 1063 |
void *value = xmalloc(vsize); |
| 1064 |
char *name = list; |
| 1065 |
int i; |
| 1066 |
size_t tot_siz = 0; |
| 1067 |
for (i=0; i<cnt; ++i) { |
| 1068 |
size_t nlen = strlen(name); |
| 1069 |
size_t gret; |
| 1070 |
do { |
| 1071 |
gret = lgetxattr(path, name, value, vsize); |
| 1072 |
//debug3("get_xattr: gret=%d, errno=%d(%d), name=%s, size=%ld, value=%s\n", gret, errno, ERANGE, name, vsize, value); |
| 1073 |
if (gret == (size_t)-1) { |
| 1074 |
if (errno == ERANGE) { |
| 1075 |
gret = lgetxattr(path, name, value, 0); |
| 1076 |
//debug3("get_xattr: gret=%d, errno=%d(%d), name=%s\n", gret, errno, ERANGE, name); |
| 1077 |
if (gret != (size_t)-1) { |
| 1078 |
if (gret > MAX_XATTR_DATA_LEN) { |
| 1079 |
gret = (size_t)-1; |
| 1080 |
errno = EMSGSIZE; |
| 1081 |
} |
| 1082 |
else { |
| 1083 |
vsize = gret; |
| 1084 |
value = xrealloc(value, vsize, 1); |
| 1085 |
continue; |
| 1086 |
} |
| 1087 |
} |
| 1088 |
} |
| 1089 |
} |
| 1090 |
break; |
| 1091 |
} while (1); |
| 1092 |
tot_siz += gret; |
| 1093 |
if (tot_siz > MAX_XATTR_DATA_LEN) |
| 1094 |
break; |
| 1095 |
xattr[i].name = xstrdup(name); |
| 1096 |
xattr[i].size = gret; |
| 1097 |
if (gret == (size_t)-1) { |
| 1098 |
xattr[i].value = xmalloc(sizeof(int)); |
| 1099 |
*(int*)xattr[i].value = errno_to_portable(errno); |
| 1100 |
} else if (gret != 0) { |
| 1101 |
xattr[i].value = xmalloc(gret); |
| 1102 |
memcpy(xattr[i].value, value, gret); |
| 1103 |
} |
| 1104 |
//debug3("get_xattr: name=%s, size=%ld, value=%s\n", xattr[i].name, xattr[i].size, xattr[i].value); |
| 1105 |
name += nlen+1; |
| 1106 |
} |
| 1107 |
if (i<cnt) { |
| 1108 |
delete_xattr(xattr, i); |
| 1109 |
xattr = xmalloc(sizeof(int)); |
| 1110 |
*(int*)xattr = errno_to_portable(EMSGSIZE); |
| 1111 |
} |
| 1112 |
xfree(value); |
| 1113 |
lret = cnt; |
| 1114 |
} |
| 1115 |
xfree(list); |
| 1116 |
*xattrib = xattr; |
| 1117 |
return lret; |
| 1118 |
} |
| 1119 |
|
| 910 |
static void |
1120 |
static void |
| 911 |
process_readdir(void) |
1121 |
process_readdir(void) |
| 912 |
{ |
1122 |
{ |
|
Lines 927-965
process_readdir(void)
Link Here
|
| 927 |
} else { |
1137 |
} else { |
| 928 |
struct stat st; |
1138 |
struct stat st; |
| 929 |
char pathname[MAXPATHLEN]; |
1139 |
char pathname[MAXPATHLEN]; |
| 930 |
Stat *stats; |
1140 |
Stat stats; |
| 931 |
int nstats = 10, count = 0, i; |
1141 |
int count = 0; |
|
|
1142 |
Buffer msg; |
| 1143 |
int max_entrysize = 256 + MAXPATHLEN + 32 + 1024; |
| 1144 |
debug3("readdir: xattr_caching=%d", xattr_caching); |
| 1145 |
if (xattr_caching) |
| 1146 |
max_entrysize += MAX_XATTR_DATA_LEN; |
| 1147 |
send_names_start(&msg, id); |
| 932 |
|
1148 |
|
| 933 |
stats = xcalloc(nstats, sizeof(Stat)); |
|
|
| 934 |
while ((dp = readdir(dirp)) != NULL) { |
1149 |
while ((dp = readdir(dirp)) != NULL) { |
| 935 |
if (count >= nstats) { |
|
|
| 936 |
nstats *= 2; |
| 937 |
stats = xrealloc(stats, nstats, sizeof(Stat)); |
| 938 |
} |
| 939 |
/* XXX OVERFLOW ? */ |
| 940 |
snprintf(pathname, sizeof pathname, "%s%s%s", path, |
1150 |
snprintf(pathname, sizeof pathname, "%s%s%s", path, |
| 941 |
strcmp(path, "/") ? "/" : "", dp->d_name); |
1151 |
strcmp(path, "/") ? "/" : "", dp->d_name); |
| 942 |
if (lstat(pathname, &st) < 0) |
1152 |
if (lstat(pathname, &st) < 0) |
| 943 |
continue; |
1153 |
continue; |
| 944 |
stat_to_attrib(&st, &(stats[count].attrib)); |
1154 |
stat_to_attrib(&st, &stats.attrib); |
| 945 |
stats[count].name = xstrdup(dp->d_name); |
1155 |
stats.name = xstrdup(dp->d_name); |
| 946 |
stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); |
1156 |
stats.long_name = ls_file(dp->d_name, &st, 0, 0); |
|
|
1157 |
stats.xa_size = 0; |
| 1158 |
if (xattr_caching) |
| 1159 |
stats.xa_size = get_xattr(pathname, &stats.xattrib); |
| 1160 |
debug3("readdir: stats.xa_size=%ld", stats.xa_size); |
| 1161 |
send_names_next(&msg, id, &stats); |
| 1162 |
xfree(stats.name); |
| 1163 |
xfree(stats.long_name); |
| 1164 |
delete_xattr(stats.xattrib, stats.xa_size); |
| 947 |
count++; |
1165 |
count++; |
| 948 |
/* send up to 100 entries in one message */ |
1166 |
if (buffer_len(&msg) + max_entrysize > SFTP_MAX_MSG_LENGTH) |
| 949 |
/* XXX check packet size instead */ |
|
|
| 950 |
if (count == 100) |
| 951 |
break; |
1167 |
break; |
| 952 |
} |
1168 |
} |
| 953 |
if (count > 0) { |
1169 |
if (count > 0) { |
| 954 |
send_names(id, count, stats); |
1170 |
debug3("readdir: count=%d", count); |
| 955 |
for (i = 0; i < count; i++) { |
1171 |
send_names_end(&msg, count); |
| 956 |
xfree(stats[i].name); |
|
|
| 957 |
xfree(stats[i].long_name); |
| 958 |
} |
| 959 |
} else { |
1172 |
} else { |
|
|
1173 |
buffer_free(&msg); |
| 960 |
send_status(id, SSH2_FX_EOF); |
1174 |
send_status(id, SSH2_FX_EOF); |
| 961 |
} |
1175 |
} |
| 962 |
xfree(stats); |
|
|
| 963 |
} |
1176 |
} |
| 964 |
} |
1177 |
} |
| 965 |
|
1178 |
|
|
Lines 1051-1056
process_realpath(void)
Link Here
|
| 1051 |
} else { |
1264 |
} else { |
| 1052 |
Stat s; |
1265 |
Stat s; |
| 1053 |
attrib_clear(&s.attrib); |
1266 |
attrib_clear(&s.attrib); |
|
|
1267 |
s.xa_size = 0; |
| 1054 |
s.name = s.long_name = resolvedname; |
1268 |
s.name = s.long_name = resolvedname; |
| 1055 |
send_names(id, 1, &s); |
1269 |
send_names(id, 1, &s); |
| 1056 |
} |
1270 |
} |
|
Lines 1138-1143
process_readlink(void)
Link Here
|
| 1138 |
|
1352 |
|
| 1139 |
buf[len] = '\0'; |
1353 |
buf[len] = '\0'; |
| 1140 |
attrib_clear(&s.attrib); |
1354 |
attrib_clear(&s.attrib); |
|
|
1355 |
s.xa_size = 0; |
| 1141 |
s.name = s.long_name = buf; |
1356 |
s.name = s.long_name = buf; |
| 1142 |
send_names(id, 1, &s); |
1357 |
send_names(id, 1, &s); |
| 1143 |
} |
1358 |
} |
|
Lines 1247-1252
process_extended_hardlink(u_int32_t id)
Link Here
|
| 1247 |
} |
1462 |
} |
| 1248 |
|
1463 |
|
| 1249 |
static void |
1464 |
static void |
|
|
1465 |
process_extended_setxattr(u_int32_t id) |
| 1466 |
{ |
| 1467 |
char *path, *name; |
| 1468 |
void *value = NULL; |
| 1469 |
u_int size; |
| 1470 |
int pflags, ret, status; |
| 1471 |
|
| 1472 |
path = get_string(NULL); |
| 1473 |
name = get_string(NULL); |
| 1474 |
value = get_string(&size); |
| 1475 |
pflags = get_int(); |
| 1476 |
debug3("request %u: setxattr", id); |
| 1477 |
if (readonly) { |
| 1478 |
status = SSH2_FX_PERMISSION_DENIED; |
| 1479 |
errno = EACCES; |
| 1480 |
} else { |
| 1481 |
int flags; |
| 1482 |
flags = (pflags & SSH2_FXE_XATTR_CREATE ) ? XATTR_CREATE : 0; |
| 1483 |
flags |= (pflags & SSH2_FXE_XATTR_REPLACE) ? XATTR_REPLACE : 0; |
| 1484 |
logit("setxattr path \"%s\" name \"%s\" size=%d flags=%d", path, name, size, flags); |
| 1485 |
ret = lsetxattr(path, name, value, size, flags); |
| 1486 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 1487 |
} |
| 1488 |
send_status(id, status); |
| 1489 |
xfree(path); |
| 1490 |
xfree(name); |
| 1491 |
xfree(value); |
| 1492 |
} |
| 1493 |
|
| 1494 |
void send_xattr_data (u_int32_t id, const char *data, size_t ret, size_t size) { |
| 1495 |
if ((ret != (size_t)-1) && (ret > MAX_XATTR_DATA_LEN) && (size != 0)) { |
| 1496 |
debug3("send_xattr_data EMSGSIZE: ret=%ld size=%ld ", ret, size); |
| 1497 |
errno = EMSGSIZE; |
| 1498 |
ret = (size_t)-1; |
| 1499 |
} |
| 1500 |
Buffer msg; |
| 1501 |
buffer_init(&msg); |
| 1502 |
buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY); |
| 1503 |
buffer_put_int(&msg, id); |
| 1504 |
int err_no_p = errno_to_portable(errno); |
| 1505 |
debug3("send_xattr_data ret=%ld errno=%d err_no_p=%d", ret, errno, err_no_p); |
| 1506 |
buffer_put_int(&msg, ret); |
| 1507 |
if (ret == (size_t)-1) { |
| 1508 |
buffer_put_int(&msg, err_no_p); |
| 1509 |
} else if (size != 0) { |
| 1510 |
buffer_append(&msg, data, ret); |
| 1511 |
} |
| 1512 |
send_msg(&msg); |
| 1513 |
buffer_free(&msg); |
| 1514 |
} |
| 1515 |
|
| 1516 |
static void |
| 1517 |
process_extended_getxattr(u_int32_t id) |
| 1518 |
{ |
| 1519 |
char *path, *name; |
| 1520 |
size_t size; |
| 1521 |
size_t ret; |
| 1522 |
|
| 1523 |
path = get_string(NULL); |
| 1524 |
name = get_string(NULL); |
| 1525 |
size = get_int(); |
| 1526 |
void *value = xmalloc(size+1); |
| 1527 |
|
| 1528 |
debug3("request %u: getxattr", id); |
| 1529 |
logit("getxattr path \"%s\" name \"%s\" size=%ld", path, name, size); |
| 1530 |
ret = lgetxattr(path, name, value, size); |
| 1531 |
send_xattr_data(id, value, ret, size); |
| 1532 |
xfree(path); |
| 1533 |
xfree(name); |
| 1534 |
xfree(value); |
| 1535 |
} |
| 1536 |
|
| 1537 |
static void |
| 1538 |
process_extended_listxattr(u_int32_t id) |
| 1539 |
{ |
| 1540 |
char *path; |
| 1541 |
size_t size; |
| 1542 |
size_t ret; |
| 1543 |
|
| 1544 |
path = get_string(NULL); |
| 1545 |
size = get_int(); |
| 1546 |
void *list = xmalloc(size+1); |
| 1547 |
|
| 1548 |
debug3("request %u: listxattr", id); |
| 1549 |
logit("listxattr path \"%s\" size=%ld", path, size); |
| 1550 |
ret = llistxattr(path, list, size); |
| 1551 |
send_xattr_data(id, list, ret, size); |
| 1552 |
xfree(path); |
| 1553 |
xfree(list); |
| 1554 |
} |
| 1555 |
|
| 1556 |
static void |
| 1557 |
process_extended_removexattr(u_int32_t id) |
| 1558 |
{ |
| 1559 |
char *path, *name; |
| 1560 |
int ret, status; |
| 1561 |
|
| 1562 |
path = get_string(NULL); |
| 1563 |
name = get_string(NULL); |
| 1564 |
debug3("request %u: removexattr", id); |
| 1565 |
logit("removexattr path \"%s\" name \"%s\"", path, name); |
| 1566 |
if (readonly) { |
| 1567 |
status = SSH2_FX_PERMISSION_DENIED; |
| 1568 |
errno = EACCES; |
| 1569 |
} else { |
| 1570 |
ret = lremovexattr(path, name); |
| 1571 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 1572 |
} |
| 1573 |
send_status(id, status); |
| 1574 |
xfree(path); |
| 1575 |
xfree(name); |
| 1576 |
} |
| 1577 |
|
| 1578 |
static void |
| 1579 |
process_extended_cachexattr(u_int32_t id) |
| 1580 |
{ |
| 1581 |
debug3("request %u: cachexattr", id); |
| 1582 |
xattr_caching = 1; |
| 1583 |
send_status(id, SSH2_FX_OK); |
| 1584 |
} |
| 1585 |
|
| 1586 |
static void |
| 1587 |
process_extended_getallxattr(u_int32_t id) |
| 1588 |
{ |
| 1589 |
char *path; |
| 1590 |
Xattrib *xattrib; |
| 1591 |
size_t xa_size; |
| 1592 |
|
| 1593 |
path = get_string(NULL); |
| 1594 |
debug3("request %u: getallxattr", id); |
| 1595 |
logit("getallxattr path \"%s\"", path); |
| 1596 |
xa_size = get_xattr(path, &xattrib); |
| 1597 |
debug3("getallxattr: xa_size=%ld", xa_size); |
| 1598 |
|
| 1599 |
Buffer msg; |
| 1600 |
buffer_init(&msg); |
| 1601 |
buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY); |
| 1602 |
buffer_put_int(&msg, id); |
| 1603 |
write_allxattr_data(&msg, xattrib, xa_size); |
| 1604 |
send_msg(&msg); |
| 1605 |
buffer_free(&msg); |
| 1606 |
xfree(path); |
| 1607 |
delete_xattr(xattrib, xa_size); |
| 1608 |
} |
| 1609 |
|
| 1610 |
static void |
| 1250 |
process_extended(void) |
1611 |
process_extended(void) |
| 1251 |
{ |
1612 |
{ |
| 1252 |
u_int32_t id; |
1613 |
u_int32_t id; |
|
Lines 1262-1267
process_extended(void)
Link Here
|
| 1262 |
process_extended_fstatvfs(id); |
1623 |
process_extended_fstatvfs(id); |
| 1263 |
else if (strcmp(request, "hardlink@openssh.com") == 0) |
1624 |
else if (strcmp(request, "hardlink@openssh.com") == 0) |
| 1264 |
process_extended_hardlink(id); |
1625 |
process_extended_hardlink(id); |
|
|
1626 |
else if (strcmp(request, "setxattr@openssh.com") == 0) |
| 1627 |
process_extended_setxattr(id); |
| 1628 |
else if (strcmp(request, "getxattr@openssh.com") == 0) |
| 1629 |
process_extended_getxattr(id); |
| 1630 |
else if (strcmp(request, "listxattr@openssh.com") == 0) |
| 1631 |
process_extended_listxattr(id); |
| 1632 |
else if (strcmp(request, "removexattr@openssh.com") == 0) |
| 1633 |
process_extended_removexattr(id); |
| 1634 |
else if (strcmp(request, "cachexattr@openssh.com") == 0) |
| 1635 |
process_extended_cachexattr(id); |
| 1636 |
else if (strcmp(request, "getallxattr@openssh.com") == 0) |
| 1637 |
process_extended_getallxattr(id); |
| 1265 |
else |
1638 |
else |
| 1266 |
send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ |
1639 |
send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ |
| 1267 |
xfree(request); |
1640 |
xfree(request); |
|
Lines 1293-1298
process(void)
Link Here
|
| 1293 |
buffer_consume(&iqueue, 4); |
1666 |
buffer_consume(&iqueue, 4); |
| 1294 |
buf_len -= 4; |
1667 |
buf_len -= 4; |
| 1295 |
type = buffer_get_char(&iqueue); |
1668 |
type = buffer_get_char(&iqueue); |
|
|
1669 |
debug3("request type: %d", type); |
| 1296 |
switch (type) { |
1670 |
switch (type) { |
| 1297 |
case SSH2_FXP_INIT: |
1671 |
case SSH2_FXP_INIT: |
| 1298 |
process_init(); |
1672 |
process_init(); |