|
Lines 47-58
void
Link Here
|
| 47 |
attrib_clear(Attrib *a) |
47 |
attrib_clear(Attrib *a) |
| 48 |
{ |
48 |
{ |
| 49 |
a->flags = 0; |
49 |
a->flags = 0; |
|
|
50 |
a->ext_flags = 0; |
| 51 |
a->dev = 0; |
| 52 |
a->ino = 0; |
| 53 |
a->rdev = 0; |
| 50 |
a->size = 0; |
54 |
a->size = 0; |
|
|
55 |
a->blocks = 0; |
| 56 |
a->blksize = 0; |
| 51 |
a->uid = 0; |
57 |
a->uid = 0; |
| 52 |
a->gid = 0; |
58 |
a->gid = 0; |
| 53 |
a->perm = 0; |
59 |
a->perm = 0; |
|
|
60 |
a->nlink = 0; |
| 54 |
a->atime = 0; |
61 |
a->atime = 0; |
| 55 |
a->mtime = 0; |
62 |
a->mtime = 0; |
|
|
63 |
a->ctime = 0; |
| 64 |
a->atimensec = 0; |
| 65 |
a->mtimensec = 0; |
| 66 |
a->ctimensec = 0; |
| 56 |
} |
67 |
} |
| 57 |
|
68 |
|
| 58 |
/* Convert from struct stat to filexfer attribs */ |
69 |
/* Convert from struct stat to filexfer attribs */ |
|
Lines 61-66
stat_to_attrib(const struct stat *st, At
Link Here
|
| 61 |
{ |
72 |
{ |
| 62 |
attrib_clear(a); |
73 |
attrib_clear(a); |
| 63 |
a->flags = 0; |
74 |
a->flags = 0; |
|
|
75 |
a->ext_flags = 0; |
| 64 |
a->flags |= SSH2_FILEXFER_ATTR_SIZE; |
76 |
a->flags |= SSH2_FILEXFER_ATTR_SIZE; |
| 65 |
a->size = st->st_size; |
77 |
a->size = st->st_size; |
| 66 |
a->flags |= SSH2_FILEXFER_ATTR_UIDGID; |
78 |
a->flags |= SSH2_FILEXFER_ATTR_UIDGID; |
|
Lines 69-76
stat_to_attrib(const struct stat *st, At
Link Here
|
| 69 |
a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; |
81 |
a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; |
| 70 |
a->perm = st->st_mode; |
82 |
a->perm = st->st_mode; |
| 71 |
a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME; |
83 |
a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME; |
|
|
84 |
a->ext_flags |= SSH2_FXE_EXTATTR_ATIME; |
| 85 |
a->ext_flags |= SSH2_FXE_EXTATTR_MTIME; |
| 72 |
a->atime = st->st_atime; |
86 |
a->atime = st->st_atime; |
| 73 |
a->mtime = st->st_mtime; |
87 |
a->mtime = st->st_mtime; |
|
|
88 |
a->ext_flags |= SSH2_FXE_EXTATTR_CTIME; |
| 89 |
a->ctime = st->st_ctime; |
| 90 |
a->ext_flags |= SSH2_FXE_EXTATTR_ATIMENSEC; |
| 91 |
a->atimensec = st->st_atimensec; |
| 92 |
a->ext_flags |= SSH2_FXE_EXTATTR_MTIMENSEC; |
| 93 |
a->mtimensec = st->st_mtimensec; |
| 94 |
a->ext_flags |= SSH2_FXE_EXTATTR_CTIMENSEC; |
| 95 |
a->ctimensec = st->st_ctimensec; |
| 96 |
a->ext_flags |= SSH2_FXE_EXTATTR_DEV; |
| 97 |
a->dev = st->st_dev; |
| 98 |
a->ext_flags |= SSH2_FXE_EXTATTR_INO; |
| 99 |
a->ino = st->st_ino; |
| 100 |
a->ext_flags |= SSH2_FXE_EXTATTR_NLINK; |
| 101 |
a->nlink = st->st_nlink; |
| 102 |
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { |
| 103 |
a->ext_flags |= SSH2_FXE_EXTATTR_RDEV; |
| 104 |
a->rdev = st->st_rdev; |
| 105 |
} |
| 106 |
a->ext_flags |= SSH2_FXE_EXTATTR_BLKSIZE; |
| 107 |
a->blksize = st->st_blksize; |
| 108 |
a->ext_flags |= SSH2_FXE_EXTATTR_BLOCKS; |
| 109 |
a->blocks = st->st_blocks; |
| 74 |
} |
110 |
} |
| 75 |
|
111 |
|
| 76 |
/* Convert from filexfer attribs to struct stat */ |
112 |
/* Convert from filexfer attribs to struct stat */ |
|
Lines 87-96
attrib_to_stat(const Attrib *a, struct s
Link Here
|
| 87 |
} |
123 |
} |
| 88 |
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) |
124 |
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) |
| 89 |
st->st_mode = a->perm; |
125 |
st->st_mode = a->perm; |
| 90 |
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
126 |
if ((a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) || |
|
|
127 |
(a->ext_flags & SSH2_FXE_EXTATTR_ATIME)) |
| 91 |
st->st_atime = a->atime; |
128 |
st->st_atime = a->atime; |
|
|
129 |
if ((a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) || |
| 130 |
(a->ext_flags & SSH2_FXE_EXTATTR_MTIME)) |
| 92 |
st->st_mtime = a->mtime; |
131 |
st->st_mtime = a->mtime; |
| 93 |
} |
132 |
if (a->ext_flags & SSH2_FXE_EXTATTR_CTIME) |
|
|
133 |
st->st_ctime = a->ctime; |
| 134 |
if (a->ext_flags & SSH2_FXE_EXTATTR_ATIMENSEC) |
| 135 |
st->st_atimensec = a->atimensec; |
| 136 |
if (a->ext_flags & SSH2_FXE_EXTATTR_MTIMENSEC) |
| 137 |
st->st_mtimensec = a->mtimensec; |
| 138 |
if (a->ext_flags & SSH2_FXE_EXTATTR_CTIMENSEC) |
| 139 |
st->st_ctimensec = a->ctimensec; |
| 140 |
if (a->ext_flags & SSH2_FXE_EXTATTR_DEV) |
| 141 |
st->st_dev = a->dev; |
| 142 |
if (a->ext_flags & SSH2_FXE_EXTATTR_INO) |
| 143 |
st->st_ino = a->ino; |
| 144 |
if (a->ext_flags & SSH2_FXE_EXTATTR_NLINK) |
| 145 |
st->st_nlink = a->nlink; |
| 146 |
if (a->ext_flags & SSH2_FXE_EXTATTR_RDEV) |
| 147 |
st->st_rdev = a->rdev; |
| 148 |
if (a->ext_flags & SSH2_FXE_EXTATTR_BLKSIZE) |
| 149 |
st->st_blksize = a->blksize; |
| 150 |
if (a->ext_flags & SSH2_FXE_EXTATTR_BLOCKS) |
| 151 |
st->st_blocks = a->blocks; |
| 152 |
} |
| 153 |
|
| 154 |
static void |
| 155 |
decode_extra_attrib(Buffer *b, Attrib *a) |
| 156 |
{ |
| 157 |
a->ext_flags = buffer_get_int(b); |
| 158 |
if (a->ext_flags & SSH2_FXE_EXTATTR_DEV) |
| 159 |
a->dev = buffer_get_int64(b); |
| 160 |
if (a->ext_flags & SSH2_FXE_EXTATTR_INO) |
| 161 |
a->ino = buffer_get_int64(b); |
| 162 |
if (a->ext_flags & SSH2_FXE_EXTATTR_NLINK) |
| 163 |
a->nlink = buffer_get_int(b); |
| 164 |
if (a->ext_flags & SSH2_FXE_EXTATTR_RDEV) |
| 165 |
a->rdev = buffer_get_int64(b); |
| 166 |
if (a->ext_flags & SSH2_FXE_EXTATTR_BLKSIZE) |
| 167 |
a->blksize = buffer_get_int(b); |
| 168 |
if (a->ext_flags & SSH2_FXE_EXTATTR_BLOCKS) |
| 169 |
a->blocks = buffer_get_int64(b); |
| 170 |
if (a->ext_flags & SSH2_FXE_EXTATTR_ATIME) |
| 171 |
a->atime = buffer_get_int64(b); |
| 172 |
if (a->ext_flags & SSH2_FXE_EXTATTR_ATIMENSEC) |
| 173 |
a->atimensec = buffer_get_int(b); |
| 174 |
if (a->ext_flags & SSH2_FXE_EXTATTR_MTIME) |
| 175 |
a->mtime = buffer_get_int64(b); |
| 176 |
if (a->ext_flags & SSH2_FXE_EXTATTR_MTIMENSEC) |
| 177 |
a->mtimensec = buffer_get_int(b); |
| 178 |
if (a->ext_flags & SSH2_FXE_EXTATTR_CTIME) |
| 179 |
a->ctime = buffer_get_int64(b); |
| 180 |
if (a->ext_flags & SSH2_FXE_EXTATTR_CTIMENSEC) |
| 181 |
a->ctimensec = buffer_get_int(b); |
| 94 |
} |
182 |
} |
| 95 |
|
183 |
|
| 96 |
/* Decode attributes in buffer */ |
184 |
/* Decode attributes in buffer */ |
|
Lines 115-140
decode_attrib(Buffer *b)
Link Here
|
| 115 |
} |
203 |
} |
| 116 |
/* vendor-specific extensions */ |
204 |
/* vendor-specific extensions */ |
| 117 |
if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { |
205 |
if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { |
| 118 |
char *type, *data; |
206 |
char *type; |
|
|
207 |
void *data; |
| 119 |
int i, count; |
208 |
int i, count; |
|
|
209 |
u_int datalen; |
| 120 |
|
210 |
|
| 121 |
count = buffer_get_int(b); |
211 |
count = buffer_get_int(b); |
| 122 |
for (i = 0; i < count; i++) { |
212 |
for (i = 0; i < count; i++) { |
| 123 |
type = buffer_get_string(b, NULL); |
213 |
type = buffer_get_string(b, NULL); |
| 124 |
data = buffer_get_string(b, NULL); |
214 |
data = buffer_get_string_ptr(b, &datalen); |
| 125 |
debug3("Got file attribute \"%s\"", type); |
215 |
debug3("Got file attribute \"%s\"", type); |
|
|
216 |
if (strcmp(type, "extattr@openssh.com") == 0) { |
| 217 |
Buffer ext; |
| 218 |
|
| 219 |
buffer_init(&ext); |
| 220 |
buffer_append(&ext, data, datalen); |
| 221 |
decode_extra_attrib(&ext, &a); |
| 222 |
buffer_free(&ext); |
| 223 |
} |
| 126 |
xfree(type); |
224 |
xfree(type); |
| 127 |
xfree(data); |
|
|
| 128 |
} |
225 |
} |
| 129 |
} |
226 |
} |
| 130 |
return &a; |
227 |
return &a; |
| 131 |
} |
228 |
} |
| 132 |
|
229 |
|
|
|
230 |
static void |
| 231 |
encode_extra_attrib(Buffer *b, const Attrib *a) |
| 232 |
{ |
| 233 |
buffer_put_int(b, a->ext_flags); |
| 234 |
if (a->ext_flags & SSH2_FXE_EXTATTR_DEV) |
| 235 |
buffer_put_int64(b, a->dev); |
| 236 |
if (a->ext_flags & SSH2_FXE_EXTATTR_INO) |
| 237 |
buffer_put_int64(b, a->ino); |
| 238 |
if (a->ext_flags & SSH2_FXE_EXTATTR_NLINK) |
| 239 |
buffer_put_int(b, a->nlink); |
| 240 |
if (a->ext_flags & SSH2_FXE_EXTATTR_RDEV) |
| 241 |
buffer_put_int64(b, a->rdev); |
| 242 |
if (a->ext_flags & SSH2_FXE_EXTATTR_BLKSIZE) |
| 243 |
buffer_put_int(b, a->blksize); |
| 244 |
if (a->ext_flags & SSH2_FXE_EXTATTR_BLOCKS) |
| 245 |
buffer_put_int64(b, a->blocks); |
| 246 |
if (a->ext_flags & SSH2_FXE_EXTATTR_ATIME) |
| 247 |
buffer_put_int64(b, a->atime); |
| 248 |
if (a->ext_flags & SSH2_FXE_EXTATTR_ATIMENSEC) |
| 249 |
buffer_put_int(b, a->atimensec); |
| 250 |
if (a->ext_flags & SSH2_FXE_EXTATTR_MTIME) |
| 251 |
buffer_put_int64(b, a->mtime); |
| 252 |
if (a->ext_flags & SSH2_FXE_EXTATTR_MTIMENSEC) |
| 253 |
buffer_put_int(b, a->mtimensec); |
| 254 |
if (a->ext_flags & SSH2_FXE_EXTATTR_CTIME) |
| 255 |
buffer_put_int64(b, a->ctime); |
| 256 |
if (a->ext_flags & SSH2_FXE_EXTATTR_CTIMENSEC) |
| 257 |
buffer_put_int(b, a->ctimensec); |
| 258 |
} |
| 259 |
|
| 133 |
/* Encode attributes to buffer */ |
260 |
/* Encode attributes to buffer */ |
| 134 |
void |
261 |
void |
| 135 |
encode_attrib(Buffer *b, const Attrib *a) |
262 |
encode_attrib(Buffer *b, const Attrib *a) |
| 136 |
{ |
263 |
{ |
| 137 |
buffer_put_int(b, a->flags); |
264 |
int flags = a->flags; |
|
|
265 |
|
| 266 |
if (a->ext_flags != 0) |
| 267 |
flags |= SSH2_FILEXFER_ATTR_EXTENDED; |
| 268 |
|
| 269 |
buffer_put_int(b, flags); |
| 138 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) |
270 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) |
| 139 |
buffer_put_int64(b, a->size); |
271 |
buffer_put_int64(b, a->size); |
| 140 |
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
272 |
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
|
Lines 147-152
encode_attrib(Buffer *b, const Attrib *a
Link Here
|
| 147 |
buffer_put_int(b, a->atime); |
279 |
buffer_put_int(b, a->atime); |
| 148 |
buffer_put_int(b, a->mtime); |
280 |
buffer_put_int(b, a->mtime); |
| 149 |
} |
281 |
} |
|
|
282 |
|
| 283 |
if (flags & SSH2_FILEXFER_ATTR_EXTENDED) { |
| 284 |
u_int ext_count = 1; |
| 285 |
Buffer ext; |
| 286 |
|
| 287 |
buffer_put_int(b, ext_count); |
| 288 |
buffer_put_cstring(b, "extattr@openssh.com"); |
| 289 |
|
| 290 |
buffer_init(&ext); |
| 291 |
encode_extra_attrib(&ext, a); |
| 292 |
buffer_put_string(b, buffer_ptr(&ext), buffer_len(&ext)); |
| 293 |
buffer_free(&ext); |
| 294 |
} |
| 150 |
} |
295 |
} |
| 151 |
|
296 |
|
| 152 |
/* Convert from SSH2_FX_ status to text error message */ |
297 |
/* Convert from SSH2_FX_ status to text error message */ |