This source file includes following definitions.
- sftpfs_blksize
- sftpfs_internal_waitsocket
- sftpfs_op_init
- sftpfs_stat_init
- sftpfs_waitsocket
- sftpfs_is_sftp_error
- sftpfs_ssherror_to_gliberror
- sftpfs_fix_filename
- 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 static void
60 sftpfs_blksize (struct stat *s)
61 {
62 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
63 s->st_blksize = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
64 #endif
65 vfs_adjust_stat (s);
66 }
67
68
69
70
71
72
73
74
75
76
77 static int
78 sftpfs_internal_waitsocket (sftpfs_super_t * super, GError ** mcerror)
79 {
80 struct timeval timeout = { 10, 0 };
81 fd_set fd;
82 fd_set *writefd = NULL;
83 fd_set *readfd = NULL;
84 int dir, ret;
85
86 mc_return_val_if_error (mcerror, -1);
87
88 FD_ZERO (&fd);
89 FD_SET (super->socket_handle, &fd);
90
91
92 dir = libssh2_session_block_directions (super->session);
93
94 if ((dir & LIBSSH2_SESSION_BLOCK_INBOUND) != 0)
95 readfd = &fd;
96
97 if ((dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) != 0)
98 writefd = &fd;
99
100 ret = select (super->socket_handle + 1, readfd, writefd, NULL, &timeout);
101 if (ret < 0)
102 {
103 int my_errno = errno;
104
105 mc_propagate_error (mcerror, my_errno, _("sftp: socket error: %s"),
106 unix_error_string (my_errno));
107 }
108
109 return ret;
110 }
111
112
113
114 static gboolean
115 sftpfs_op_init (sftpfs_super_t ** super, const vfs_path_element_t ** path_element,
116 const vfs_path_t * vpath, GError ** mcerror)
117 {
118 struct vfs_s_super *lc_super = NULL;
119
120 mc_return_val_if_error (mcerror, FALSE);
121
122 if (vfs_s_get_path (vpath, &lc_super, 0) == NULL)
123 return FALSE;
124
125 if (lc_super == NULL)
126 return FALSE;
127
128 *super = SFTP_SUPER (lc_super);
129
130 if ((*super)->sftp_session == NULL)
131 return FALSE;
132
133 *path_element = vfs_path_get_by_index (vpath, -1);
134
135 return TRUE;
136 }
137
138
139
140 static int
141 sftpfs_stat_init (sftpfs_super_t ** super, const vfs_path_element_t ** path_element,
142 const vfs_path_t * vpath, GError ** mcerror, int stat_type,
143 LIBSSH2_SFTP_ATTRIBUTES * attrs)
144 {
145 const GString *fixfname;
146 int res;
147
148 if (!sftpfs_op_init (super, path_element, vpath, mcerror))
149 return -1;
150
151 fixfname = sftpfs_fix_filename ((*path_element)->path);
152
153 do
154 {
155 res = libssh2_sftp_stat_ex ((*super)->sftp_session, fixfname->str, fixfname->len,
156 stat_type, attrs);
157 if (res >= 0)
158 break;
159
160 if (sftpfs_is_sftp_error ((*super)->sftp_session, res, LIBSSH2_FX_PERMISSION_DENIED))
161 return -EACCES;
162
163 if (sftpfs_is_sftp_error ((*super)->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
164 return -ENOENT;
165
166 if (!sftpfs_waitsocket (*super, res, mcerror))
167 return -1;
168 }
169 while (res == LIBSSH2_ERROR_EAGAIN);
170
171 return res;
172 }
173
174
175
176
177
178 gboolean
179 sftpfs_waitsocket (sftpfs_super_t * super, int sftp_res, GError ** mcerror)
180 {
181 if (sftp_res != LIBSSH2_ERROR_EAGAIN)
182 {
183 sftpfs_ssherror_to_gliberror (super, sftp_res, mcerror);
184 return FALSE;
185 }
186
187 sftpfs_internal_waitsocket (super, mcerror);
188
189 return (mcerror == NULL || *mcerror == NULL);
190 }
191
192
193
194 gboolean
195 sftpfs_is_sftp_error (LIBSSH2_SFTP * sftp_session, int sftp_res, int sftp_error)
196 {
197 return (sftp_res == LIBSSH2_ERROR_SFTP_PROTOCOL &&
198 libssh2_sftp_last_error (sftp_session) == (unsigned long) sftp_error);
199 }
200
201
202
203
204
205
206
207
208
209
210 void
211 sftpfs_ssherror_to_gliberror (sftpfs_super_t * super, int libssh_errno, GError ** mcerror)
212 {
213 char *err = NULL;
214 int err_len;
215
216 mc_return_if_error (mcerror);
217
218 libssh2_session_last_error (super->session, &err, &err_len, 1);
219 if (libssh_errno == LIBSSH2_ERROR_SFTP_PROTOCOL && super->sftp_session != NULL)
220 mc_propagate_error (mcerror, libssh_errno, "%s %lu", err,
221 libssh2_sftp_last_error (super->sftp_session));
222 else
223 mc_propagate_error (mcerror, libssh_errno, "%s", err);
224 g_free (err);
225 }
226
227
228
229
230
231
232
233
234
235
236
237 const GString *
238 sftpfs_fix_filename (const char *file_name)
239 {
240 g_string_printf (sftpfs_filename_buffer, "%c%s", PATH_SEP, file_name);
241 return sftpfs_filename_buffer;
242 }
243
244
245
246 void
247 sftpfs_attr_to_stat (const LIBSSH2_SFTP_ATTRIBUTES * attrs, struct stat *s)
248 {
249 if ((attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
250 {
251 s->st_uid = attrs->uid;
252 s->st_gid = attrs->gid;
253 }
254
255 if ((attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
256 {
257 s->st_atime = attrs->atime;
258 s->st_mtime = attrs->mtime;
259 s->st_ctime = attrs->mtime;
260 #ifdef HAVE_STRUCT_STAT_ST_MTIM
261 s->st_atim.tv_nsec = s->st_mtim.tv_nsec = s->st_ctim.tv_nsec = 0;
262 #endif
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_element1;
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 path_element1 = vfs_path_get_by_index (vpath1, -1);
403 path1 = path_element1->path;
404 path1_len = strlen (path1);
405
406 do
407 {
408 res =
409 libssh2_sftp_symlink_ex (super->sftp_session, path1, path1_len, tmp_path, tmp_path_len,
410 LIBSSH2_SFTP_SYMLINK);
411 if (res >= 0)
412 break;
413
414 if (!sftpfs_waitsocket (super, res, mcerror))
415 {
416 g_free (tmp_path);
417 return -1;
418 }
419 }
420 while (res == LIBSSH2_ERROR_EAGAIN);
421 g_free (tmp_path);
422
423 return 0;
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437 int
438 sftpfs_utime (const vfs_path_t * vpath, time_t atime, time_t mtime, GError ** mcerror)
439 {
440 sftpfs_super_t *super = NULL;
441 const vfs_path_element_t *path_element = NULL;
442 LIBSSH2_SFTP_ATTRIBUTES attrs;
443 const GString *fixfname;
444 int res;
445
446 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
447 if (res < 0)
448 return res;
449
450 attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
451 attrs.atime = atime;
452 attrs.mtime = mtime;
453
454 fixfname = sftpfs_fix_filename (path_element->path);
455
456 do
457 {
458 res =
459 libssh2_sftp_stat_ex (super->sftp_session, fixfname->str, fixfname->len,
460 LIBSSH2_SFTP_SETSTAT, &attrs);
461 if (res >= 0)
462 break;
463
464 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
465 return -ENOENT;
466
467 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
468 {
469 res = 0;
470 break;
471 }
472
473 if (!sftpfs_waitsocket (super, res, mcerror))
474 return -1;
475 }
476 while (res == LIBSSH2_ERROR_EAGAIN);
477
478 return res;
479 }
480
481
482
483
484
485
486
487
488
489
490
491 int
492 sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror)
493 {
494 sftpfs_super_t *super = NULL;
495 const vfs_path_element_t *path_element = NULL;
496 LIBSSH2_SFTP_ATTRIBUTES attrs;
497 const GString *fixfname;
498 int res;
499
500 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
501 if (res < 0)
502 return res;
503
504 attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
505 attrs.permissions = mode;
506
507 fixfname = sftpfs_fix_filename (path_element->path);
508
509 do
510 {
511 res =
512 libssh2_sftp_stat_ex (super->sftp_session, fixfname->str, fixfname->len,
513 LIBSSH2_SFTP_SETSTAT, &attrs);
514 if (res >= 0)
515 break;
516
517 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
518 return -ENOENT;
519
520 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
521 {
522 res = 0;
523 break;
524 }
525
526 if (!sftpfs_waitsocket (super, res, mcerror))
527 return -1;
528 }
529 while (res == LIBSSH2_ERROR_EAGAIN);
530
531 return res;
532 }
533
534
535
536
537
538
539
540
541
542
543 int
544 sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror)
545 {
546 sftpfs_super_t *super = NULL;
547 const vfs_path_element_t *path_element = NULL;
548 const GString *fixfname;
549 int res;
550
551 if (!sftpfs_op_init (&super, &path_element, vpath, mcerror))
552 return -1;
553
554 fixfname = sftpfs_fix_filename (path_element->path);
555
556 do
557 {
558 res = libssh2_sftp_unlink_ex (super->sftp_session, fixfname->str, fixfname->len);
559 if (res >= 0)
560 break;
561
562 if (!sftpfs_waitsocket (super, res, mcerror))
563 return -1;
564 }
565 while (res == LIBSSH2_ERROR_EAGAIN);
566
567 return res;
568 }
569
570
571
572
573
574
575
576
577
578
579
580 int
581 sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror)
582 {
583 sftpfs_super_t *super = NULL;
584 const vfs_path_element_t *path_element1;
585 const vfs_path_element_t *path_element2 = NULL;
586 const GString *ctmp_path;
587 char *tmp_path;
588 unsigned int tmp_path_len;
589 const GString *fixfname;
590 int res;
591
592 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
593 return -1;
594
595 ctmp_path = sftpfs_fix_filename (path_element2->path);
596 tmp_path = g_strndup (ctmp_path->str, ctmp_path->len);
597 tmp_path_len = ctmp_path->len;
598
599 path_element1 = vfs_path_get_by_index (vpath1, -1);
600
601 fixfname = sftpfs_fix_filename (path_element1->path);
602
603 do
604 {
605 res =
606 libssh2_sftp_rename_ex (super->sftp_session, fixfname->str, fixfname->len, tmp_path,
607 tmp_path_len, LIBSSH2_SFTP_SYMLINK);
608 if (res >= 0)
609 break;
610
611 if (!sftpfs_waitsocket (super, res, mcerror))
612 {
613 g_free (tmp_path);
614 return -1;
615 }
616 }
617 while (res == LIBSSH2_ERROR_EAGAIN);
618 g_free (tmp_path);
619
620 return 0;
621 }
622
623