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, stat_type,
133 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 = libssh2_sftp_symlink_ex (super->sftp_session, fixfname->str, fixfname->len, buf, size,
359 LIBSSH2_SFTP_READLINK);
360 if (res >= 0)
361 break;
362
363 if (!sftpfs_waitsocket (super, res, mcerror))
364 return -1;
365 }
366 while (res == LIBSSH2_ERROR_EAGAIN);
367
368 return res;
369 }
370
371
372
373
374
375
376
377
378
379
380
381 int
382 sftpfs_symlink (const vfs_path_t *vpath1, const vfs_path_t *vpath2, GError **mcerror)
383 {
384 sftpfs_super_t *super = NULL;
385 const vfs_path_element_t *path_element2 = NULL;
386 const char *path1;
387 size_t path1_len;
388 const GString *ctmp_path;
389 char *tmp_path;
390 unsigned int tmp_path_len;
391 int res;
392
393 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
394 return -1;
395
396 ctmp_path = sftpfs_fix_filename (path_element2->path);
397 tmp_path = g_strndup (ctmp_path->str, ctmp_path->len);
398 tmp_path_len = ctmp_path->len;
399
400 path1 = vfs_path_get_last_path_str (vpath1);
401 path1_len = strlen (path1);
402
403 do
404 {
405 res = libssh2_sftp_symlink_ex (super->sftp_session, path1, path1_len, tmp_path,
406 tmp_path_len, LIBSSH2_SFTP_SYMLINK);
407 if (res >= 0)
408 break;
409
410 if (!sftpfs_waitsocket (super, res, mcerror))
411 {
412 g_free (tmp_path);
413 return -1;
414 }
415 }
416 while (res == LIBSSH2_ERROR_EAGAIN);
417 g_free (tmp_path);
418
419 return 0;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433 int
434 sftpfs_utime (const vfs_path_t *vpath, time_t atime, time_t mtime, GError **mcerror)
435 {
436 sftpfs_super_t *super = NULL;
437 const vfs_path_element_t *path_element = NULL;
438 LIBSSH2_SFTP_ATTRIBUTES attrs;
439 const GString *fixfname;
440 int res;
441
442 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
443 if (res < 0)
444 return res;
445
446 attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
447 attrs.atime = atime;
448 attrs.mtime = mtime;
449
450 fixfname = sftpfs_fix_filename (path_element->path);
451
452 do
453 {
454 res = libssh2_sftp_stat_ex (super->sftp_session, fixfname->str, fixfname->len,
455 LIBSSH2_SFTP_SETSTAT, &attrs);
456 if (res >= 0)
457 break;
458
459 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
460 return -ENOENT;
461
462 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
463 {
464 res = 0;
465 break;
466 }
467
468 if (!sftpfs_waitsocket (super, res, mcerror))
469 return -1;
470 }
471 while (res == LIBSSH2_ERROR_EAGAIN);
472
473 return res;
474 }
475
476
477
478
479
480
481
482
483
484
485
486 int
487 sftpfs_chmod (const vfs_path_t *vpath, mode_t mode, GError **mcerror)
488 {
489 sftpfs_super_t *super = NULL;
490 const vfs_path_element_t *path_element = NULL;
491 LIBSSH2_SFTP_ATTRIBUTES attrs;
492 const GString *fixfname;
493 int res;
494
495 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
496 if (res < 0)
497 return res;
498
499 attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
500 attrs.permissions = mode;
501
502 fixfname = sftpfs_fix_filename (path_element->path);
503
504 do
505 {
506 res = libssh2_sftp_stat_ex (super->sftp_session, fixfname->str, fixfname->len,
507 LIBSSH2_SFTP_SETSTAT, &attrs);
508 if (res >= 0)
509 break;
510
511 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
512 return -ENOENT;
513
514 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
515 {
516 res = 0;
517 break;
518 }
519
520 if (!sftpfs_waitsocket (super, res, mcerror))
521 return -1;
522 }
523 while (res == LIBSSH2_ERROR_EAGAIN);
524
525 return res;
526 }
527
528
529
530
531
532
533
534
535
536
537 int
538 sftpfs_unlink (const vfs_path_t *vpath, GError **mcerror)
539 {
540 sftpfs_super_t *super = NULL;
541 const vfs_path_element_t *path_element = NULL;
542 const GString *fixfname;
543 int res;
544
545 if (!sftpfs_op_init (&super, &path_element, vpath, mcerror))
546 return -1;
547
548 fixfname = sftpfs_fix_filename (path_element->path);
549
550 do
551 {
552 res = libssh2_sftp_unlink_ex (super->sftp_session, fixfname->str, fixfname->len);
553 if (res >= 0)
554 break;
555
556 if (!sftpfs_waitsocket (super, res, mcerror))
557 return -1;
558 }
559 while (res == LIBSSH2_ERROR_EAGAIN);
560
561 return res;
562 }
563
564
565
566
567
568
569
570
571
572
573
574 int
575 sftpfs_rename (const vfs_path_t *vpath1, const vfs_path_t *vpath2, GError **mcerror)
576 {
577 sftpfs_super_t *super = NULL;
578 const char *path1;
579 const vfs_path_element_t *path_element2 = NULL;
580 const GString *ctmp_path;
581 char *tmp_path;
582 unsigned int tmp_path_len;
583 const GString *fixfname;
584 int res;
585
586 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
587 return -1;
588
589 ctmp_path = sftpfs_fix_filename (path_element2->path);
590 tmp_path = g_strndup (ctmp_path->str, ctmp_path->len);
591 tmp_path_len = ctmp_path->len;
592
593 path1 = vfs_path_get_last_path_str (vpath1);
594 fixfname = sftpfs_fix_filename (path1);
595
596 do
597 {
598 res = libssh2_sftp_rename_ex (super->sftp_session, fixfname->str, fixfname->len, tmp_path,
599 tmp_path_len, LIBSSH2_SFTP_SYMLINK);
600 if (res >= 0)
601 break;
602
603 if (!sftpfs_waitsocket (super, res, mcerror))
604 {
605 g_free (tmp_path);
606 return -1;
607 }
608 }
609 while (res == LIBSSH2_ERROR_EAGAIN);
610 g_free (tmp_path);
611
612 return 0;
613 }
614
615