This source file includes following definitions.
- sftpfs_blksize
- sftpfs_internal_waitsocket
- sftpfs_stat_init
- sftpfs_waitsocket
- sftpfs_is_sftp_error
- sftpfs_ssherror_to_gliberror
- sftpfs_fix_filename
- sftpfs_op_init
- sftpfs_attr_to_stat
- sftpfs_lstat
- sftpfs_stat
- sftpfs_readlink
- sftpfs_symlink
- sftpfs_utime
- sftpfs_chmod
- sftpfs_unlink
- sftpfs_rename
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <config.h>
28 #include <errno.h>
29
30 #ifdef HAVE_SYS_SELECT_H
31 #include <sys/select.h>
32 #else
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 #endif
37
38 #include "lib/global.h"
39 #include "lib/util.h"
40 #include "lib/vfs/utilvfs.h"
41
42 #include "internal.h"
43
44
45
46 GString *sftpfs_filename_buffer = NULL;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 static void
63 sftpfs_blksize (struct stat *s)
64 {
65 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
66 s->st_blksize = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
67 #endif
68 vfs_adjust_stat (s);
69 }
70
71
72
73
74
75
76
77
78
79
80 static int
81 sftpfs_internal_waitsocket (sftpfs_super_t *super, GError **mcerror)
82 {
83 struct timeval timeout = { 10, 0 };
84 fd_set fd;
85 fd_set *writefd = NULL;
86 fd_set *readfd = NULL;
87 int dir, ret;
88
89 mc_return_val_if_error (mcerror, -1);
90
91 FD_ZERO (&fd);
92 FD_SET (super->socket_handle, &fd);
93
94
95 dir = libssh2_session_block_directions (super->session);
96
97 if ((dir & LIBSSH2_SESSION_BLOCK_INBOUND) != 0)
98 readfd = &fd;
99
100 if ((dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) != 0)
101 writefd = &fd;
102
103 ret = select (super->socket_handle + 1, readfd, writefd, NULL, &timeout);
104 if (ret < 0)
105 {
106 int my_errno = errno;
107
108 mc_propagate_error (mcerror, my_errno, _("sftp: socket error: %s"),
109 unix_error_string (my_errno));
110 }
111
112 return ret;
113 }
114
115
116
117 static int
118 sftpfs_stat_init (sftpfs_super_t **super, const vfs_path_element_t **path_element,
119 const vfs_path_t *vpath, GError **mcerror, int stat_type,
120 LIBSSH2_SFTP_ATTRIBUTES *attrs)
121 {
122 const GString *fixfname;
123 int res;
124
125 if (!sftpfs_op_init (super, path_element, vpath, mcerror))
126 return -1;
127
128 fixfname = sftpfs_fix_filename ((*path_element)->path);
129
130 do
131 {
132 res = libssh2_sftp_stat_ex ((*super)->sftp_session, fixfname->str, fixfname->len,
133 stat_type, attrs);
134 if (res >= 0)
135 break;
136
137 if (sftpfs_is_sftp_error ((*super)->sftp_session, res, LIBSSH2_FX_PERMISSION_DENIED))
138 return -EACCES;
139
140 if (sftpfs_is_sftp_error ((*super)->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
141 return -ENOENT;
142
143 if (!sftpfs_waitsocket (*super, res, mcerror))
144 return -1;
145 }
146 while (res == LIBSSH2_ERROR_EAGAIN);
147
148 return res;
149 }
150
151
152
153
154
155 gboolean
156 sftpfs_waitsocket (sftpfs_super_t *super, int sftp_res, GError **mcerror)
157 {
158 if (sftp_res != LIBSSH2_ERROR_EAGAIN)
159 {
160 sftpfs_ssherror_to_gliberror (super, sftp_res, mcerror);
161 return FALSE;
162 }
163
164 sftpfs_internal_waitsocket (super, mcerror);
165
166 return (mcerror == NULL || *mcerror == NULL);
167 }
168
169
170
171 gboolean
172 sftpfs_is_sftp_error (LIBSSH2_SFTP *sftp_session, int sftp_res, int sftp_error)
173 {
174 return (sftp_res == LIBSSH2_ERROR_SFTP_PROTOCOL &&
175 libssh2_sftp_last_error (sftp_session) == (unsigned long) sftp_error);
176 }
177
178
179
180
181
182
183
184
185
186
187 void
188 sftpfs_ssherror_to_gliberror (sftpfs_super_t *super, int libssh_errno, GError **mcerror)
189 {
190 char *err = NULL;
191 int err_len;
192
193 mc_return_if_error (mcerror);
194
195 libssh2_session_last_error (super->session, &err, &err_len, 1);
196 if (libssh_errno == LIBSSH2_ERROR_SFTP_PROTOCOL && super->sftp_session != NULL)
197 mc_propagate_error (mcerror, libssh_errno, "%s %lu", err,
198 libssh2_sftp_last_error (super->sftp_session));
199 else
200 mc_propagate_error (mcerror, libssh_errno, "%s", err);
201 g_free (err);
202 }
203
204
205
206
207
208
209
210
211
212
213
214 const GString *
215 sftpfs_fix_filename (const char *file_name)
216 {
217 g_string_printf (sftpfs_filename_buffer, "%c%s", PATH_SEP, file_name);
218 return sftpfs_filename_buffer;
219 }
220
221
222
223 gboolean
224 sftpfs_op_init (sftpfs_super_t **super, const vfs_path_element_t **path_element,
225 const vfs_path_t *vpath, GError **mcerror)
226 {
227 struct vfs_s_super *lc_super = NULL;
228
229 mc_return_val_if_error (mcerror, FALSE);
230
231 if (vfs_s_get_path (vpath, &lc_super, 0) == NULL)
232 return FALSE;
233
234 if (lc_super == NULL)
235 return FALSE;
236
237 *super = SFTP_SUPER (lc_super);
238 if ((*super)->sftp_session == NULL)
239 return FALSE;
240
241 *path_element = vfs_path_get_by_index (vpath, -1);
242
243 return TRUE;
244 }
245
246
247
248 void
249 sftpfs_attr_to_stat (const LIBSSH2_SFTP_ATTRIBUTES *attrs, struct stat *s)
250 {
251 if ((attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
252 {
253 s->st_uid = attrs->uid;
254 s->st_gid = attrs->gid;
255 }
256
257 if ((attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
258 {
259 vfs_zero_stat_times (s);
260 s->st_atime = attrs->atime;
261 s->st_mtime = attrs->mtime;
262 s->st_ctime = attrs->mtime;
263 }
264
265 if ((attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
266 {
267 s->st_size = attrs->filesize;
268 sftpfs_blksize (s);
269 }
270
271 if ((attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0)
272 s->st_mode = attrs->permissions;
273 }
274
275
276
277
278
279
280
281
282
283
284
285 int
286 sftpfs_lstat (const vfs_path_t *vpath, struct stat *buf, GError **mcerror)
287 {
288 sftpfs_super_t *super = NULL;
289 const vfs_path_element_t *path_element = NULL;
290 LIBSSH2_SFTP_ATTRIBUTES attrs;
291 int res;
292
293 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
294 if (res >= 0)
295 {
296 sftpfs_attr_to_stat (&attrs, buf);
297 res = 0;
298 }
299
300 return res;
301 }
302
303
304
305
306
307
308
309
310
311
312
313 int
314 sftpfs_stat (const vfs_path_t *vpath, struct stat *buf, GError **mcerror)
315 {
316 sftpfs_super_t *super = NULL;
317 const vfs_path_element_t *path_element = NULL;
318 LIBSSH2_SFTP_ATTRIBUTES attrs;
319 int res;
320
321 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_STAT, &attrs);
322 if (res >= 0)
323 {
324 buf->st_nlink = 1;
325 sftpfs_attr_to_stat (&attrs, buf);
326 res = 0;
327 }
328
329 return res;
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343 int
344 sftpfs_readlink (const vfs_path_t *vpath, char *buf, size_t size, GError **mcerror)
345 {
346 sftpfs_super_t *super = NULL;
347 const vfs_path_element_t *path_element = NULL;
348 const GString *fixfname;
349 int res;
350
351 if (!sftpfs_op_init (&super, &path_element, vpath, mcerror))
352 return -1;
353
354 fixfname = sftpfs_fix_filename (path_element->path);
355
356 do
357 {
358 res =
359 libssh2_sftp_symlink_ex (super->sftp_session, fixfname->str, fixfname->len, buf, size,
360 LIBSSH2_SFTP_READLINK);
361 if (res >= 0)
362 break;
363
364 if (!sftpfs_waitsocket (super, res, mcerror))
365 return -1;
366 }
367 while (res == LIBSSH2_ERROR_EAGAIN);
368
369 return res;
370 }
371
372
373
374
375
376
377
378
379
380
381
382 int
383 sftpfs_symlink (const vfs_path_t *vpath1, const vfs_path_t *vpath2, GError **mcerror)
384 {
385 sftpfs_super_t *super = NULL;
386 const vfs_path_element_t *path_element2 = NULL;
387 const char *path1;
388 size_t path1_len;
389 const GString *ctmp_path;
390 char *tmp_path;
391 unsigned int tmp_path_len;
392 int res;
393
394 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
395 return -1;
396
397 ctmp_path = sftpfs_fix_filename (path_element2->path);
398 tmp_path = g_strndup (ctmp_path->str, ctmp_path->len);
399 tmp_path_len = ctmp_path->len;
400
401 path1 = vfs_path_get_last_path_str (vpath1);
402 path1_len = strlen (path1);
403
404 do
405 {
406 res =
407 libssh2_sftp_symlink_ex (super->sftp_session, path1, path1_len, tmp_path, tmp_path_len,
408 LIBSSH2_SFTP_SYMLINK);
409 if (res >= 0)
410 break;
411
412 if (!sftpfs_waitsocket (super, res, mcerror))
413 {
414 g_free (tmp_path);
415 return -1;
416 }
417 }
418 while (res == LIBSSH2_ERROR_EAGAIN);
419 g_free (tmp_path);
420
421 return 0;
422 }
423
424
425
426
427
428
429
430
431
432
433
434
435 int
436 sftpfs_utime (const vfs_path_t *vpath, time_t atime, time_t mtime, GError **mcerror)
437 {
438 sftpfs_super_t *super = NULL;
439 const vfs_path_element_t *path_element = NULL;
440 LIBSSH2_SFTP_ATTRIBUTES attrs;
441 const GString *fixfname;
442 int res;
443
444 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
445 if (res < 0)
446 return res;
447
448 attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
449 attrs.atime = atime;
450 attrs.mtime = mtime;
451
452 fixfname = sftpfs_fix_filename (path_element->path);
453
454 do
455 {
456 res =
457 libssh2_sftp_stat_ex (super->sftp_session, fixfname->str, fixfname->len,
458 LIBSSH2_SFTP_SETSTAT, &attrs);
459 if (res >= 0)
460 break;
461
462 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
463 return -ENOENT;
464
465 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
466 {
467 res = 0;
468 break;
469 }
470
471 if (!sftpfs_waitsocket (super, res, mcerror))
472 return -1;
473 }
474 while (res == LIBSSH2_ERROR_EAGAIN);
475
476 return res;
477 }
478
479
480
481
482
483
484
485
486
487
488
489 int
490 sftpfs_chmod (const vfs_path_t *vpath, mode_t mode, GError **mcerror)
491 {
492 sftpfs_super_t *super = NULL;
493 const vfs_path_element_t *path_element = NULL;
494 LIBSSH2_SFTP_ATTRIBUTES attrs;
495 const GString *fixfname;
496 int res;
497
498 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
499 if (res < 0)
500 return res;
501
502 attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
503 attrs.permissions = mode;
504
505 fixfname = sftpfs_fix_filename (path_element->path);
506
507 do
508 {
509 res =
510 libssh2_sftp_stat_ex (super->sftp_session, fixfname->str, fixfname->len,
511 LIBSSH2_SFTP_SETSTAT, &attrs);
512 if (res >= 0)
513 break;
514
515 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
516 return -ENOENT;
517
518 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
519 {
520 res = 0;
521 break;
522 }
523
524 if (!sftpfs_waitsocket (super, res, mcerror))
525 return -1;
526 }
527 while (res == LIBSSH2_ERROR_EAGAIN);
528
529 return res;
530 }
531
532
533
534
535
536
537
538
539
540
541 int
542 sftpfs_unlink (const vfs_path_t *vpath, GError **mcerror)
543 {
544 sftpfs_super_t *super = NULL;
545 const vfs_path_element_t *path_element = NULL;
546 const GString *fixfname;
547 int res;
548
549 if (!sftpfs_op_init (&super, &path_element, vpath, mcerror))
550 return -1;
551
552 fixfname = sftpfs_fix_filename (path_element->path);
553
554 do
555 {
556 res = libssh2_sftp_unlink_ex (super->sftp_session, fixfname->str, fixfname->len);
557 if (res >= 0)
558 break;
559
560 if (!sftpfs_waitsocket (super, res, mcerror))
561 return -1;
562 }
563 while (res == LIBSSH2_ERROR_EAGAIN);
564
565 return res;
566 }
567
568
569
570
571
572
573
574
575
576
577
578 int
579 sftpfs_rename (const vfs_path_t *vpath1, const vfs_path_t *vpath2, GError **mcerror)
580 {
581 sftpfs_super_t *super = NULL;
582 const char *path1;
583 const vfs_path_element_t *path_element2 = NULL;
584 const GString *ctmp_path;
585 char *tmp_path;
586 unsigned int tmp_path_len;
587 const GString *fixfname;
588 int res;
589
590 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
591 return -1;
592
593 ctmp_path = sftpfs_fix_filename (path_element2->path);
594 tmp_path = g_strndup (ctmp_path->str, ctmp_path->len);
595 tmp_path_len = ctmp_path->len;
596
597 path1 = vfs_path_get_last_path_str (vpath1);
598 fixfname = sftpfs_fix_filename (path1);
599
600 do
601 {
602 res =
603 libssh2_sftp_rename_ex (super->sftp_session, fixfname->str, fixfname->len, tmp_path,
604 tmp_path_len, LIBSSH2_SFTP_SYMLINK);
605 if (res >= 0)
606 break;
607
608 if (!sftpfs_waitsocket (super, res, mcerror))
609 {
610 g_free (tmp_path);
611 return -1;
612 }
613 }
614 while (res == LIBSSH2_ERROR_EAGAIN);
615 g_free (tmp_path);
616
617 return 0;
618 }
619
620