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