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 int res;
146
147 if (!sftpfs_op_init (super, path_element, vpath, mcerror))
148 return -1;
149
150 do
151 {
152 const char *fixfname;
153 unsigned int fixfname_len;
154
155 fixfname = sftpfs_fix_filename ((*path_element)->path, &fixfname_len);
156
157 res = libssh2_sftp_stat_ex ((*super)->sftp_session, fixfname, fixfname_len,
158 stat_type, attrs);
159 if (res >= 0)
160 break;
161
162 if (sftpfs_is_sftp_error ((*super)->sftp_session, res, LIBSSH2_FX_PERMISSION_DENIED))
163 return -EACCES;
164
165 if (sftpfs_is_sftp_error ((*super)->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
166 return -ENOENT;
167
168 if (!sftpfs_waitsocket (*super, res, mcerror))
169 return -1;
170 }
171 while (res == LIBSSH2_ERROR_EAGAIN);
172
173 return res;
174 }
175
176
177
178
179
180 gboolean
181 sftpfs_waitsocket (sftpfs_super_t * super, int sftp_res, GError ** mcerror)
182 {
183 if (sftp_res != LIBSSH2_ERROR_EAGAIN)
184 {
185 sftpfs_ssherror_to_gliberror (super, sftp_res, mcerror);
186 return FALSE;
187 }
188
189 sftpfs_internal_waitsocket (super, mcerror);
190
191 return (mcerror == NULL || *mcerror == NULL);
192 }
193
194
195
196 gboolean
197 sftpfs_is_sftp_error (LIBSSH2_SFTP * sftp_session, int sftp_res, int sftp_error)
198 {
199 return (sftp_res == LIBSSH2_ERROR_SFTP_PROTOCOL &&
200 libssh2_sftp_last_error (sftp_session) == (unsigned long) sftp_error);
201 }
202
203
204
205
206
207
208
209
210
211
212 void
213 sftpfs_ssherror_to_gliberror (sftpfs_super_t * super, int libssh_errno, GError ** mcerror)
214 {
215 char *err = NULL;
216 int err_len;
217
218 mc_return_if_error (mcerror);
219
220 libssh2_session_last_error (super->session, &err, &err_len, 1);
221 if (libssh_errno == LIBSSH2_ERROR_SFTP_PROTOCOL && super->sftp_session != NULL)
222 mc_propagate_error (mcerror, libssh_errno, "%s %lu", err,
223 libssh2_sftp_last_error (super->sftp_session));
224 else
225 mc_propagate_error (mcerror, libssh_errno, "%s", err);
226 g_free (err);
227 }
228
229
230
231
232
233
234
235
236
237
238
239 const char *
240 sftpfs_fix_filename (const char *file_name, unsigned int *length)
241 {
242 g_string_printf (sftpfs_filename_buffer, "%c%s", PATH_SEP, file_name);
243 *length = sftpfs_filename_buffer->len;
244 return sftpfs_filename_buffer->str;
245 }
246
247
248
249 void
250 sftpfs_attr_to_stat (const LIBSSH2_SFTP_ATTRIBUTES * attrs, struct stat *s)
251 {
252 if ((attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
253 {
254 s->st_uid = attrs->uid;
255 s->st_gid = attrs->gid;
256 }
257
258 if ((attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
259 {
260 s->st_atime = attrs->atime;
261 s->st_mtime = attrs->mtime;
262 s->st_ctime = attrs->mtime;
263 #ifdef HAVE_STRUCT_STAT_ST_MTIM
264 s->st_atim.tv_nsec = s->st_mtim.tv_nsec = s->st_ctim.tv_nsec = 0;
265 #endif
266 }
267
268 if ((attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
269 {
270 s->st_size = attrs->filesize;
271 sftpfs_blksize (s);
272 }
273
274 if ((attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0)
275 s->st_mode = attrs->permissions;
276 }
277
278
279
280
281
282
283
284
285
286
287
288 int
289 sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror)
290 {
291 sftpfs_super_t *super = NULL;
292 const vfs_path_element_t *path_element = NULL;
293 LIBSSH2_SFTP_ATTRIBUTES attrs;
294 int res;
295
296 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
297 if (res >= 0)
298 {
299 sftpfs_attr_to_stat (&attrs, buf);
300 res = 0;
301 }
302
303 return res;
304 }
305
306
307
308
309
310
311
312
313
314
315
316 int
317 sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror)
318 {
319 sftpfs_super_t *super = NULL;
320 const vfs_path_element_t *path_element = NULL;
321 LIBSSH2_SFTP_ATTRIBUTES attrs;
322 int res;
323
324 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_STAT, &attrs);
325 if (res >= 0)
326 {
327 buf->st_nlink = 1;
328 sftpfs_attr_to_stat (&attrs, buf);
329 res = 0;
330 }
331
332 return res;
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346 int
347 sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mcerror)
348 {
349 sftpfs_super_t *super = NULL;
350 const vfs_path_element_t *path_element = NULL;
351 int res;
352
353 if (!sftpfs_op_init (&super, &path_element, vpath, mcerror))
354 return -1;
355
356 do
357 {
358 const char *fixfname;
359 unsigned int fixfname_len = 0;
360
361 fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
362
363 res =
364 libssh2_sftp_symlink_ex (super->sftp_session, fixfname, fixfname_len, buf, size,
365 LIBSSH2_SFTP_READLINK);
366 if (res >= 0)
367 break;
368
369 if (!sftpfs_waitsocket (super, res, mcerror))
370 return -1;
371 }
372 while (res == LIBSSH2_ERROR_EAGAIN);
373
374 return res;
375 }
376
377
378
379
380
381
382
383
384
385
386
387 int
388 sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror)
389 {
390 sftpfs_super_t *super = NULL;
391 const vfs_path_element_t *path_element1;
392 const vfs_path_element_t *path_element2 = NULL;
393 char *tmp_path;
394 unsigned int tmp_path_len;
395 int res;
396
397 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
398 return -1;
399
400 tmp_path = (char *) sftpfs_fix_filename (path_element2->path, &tmp_path_len);
401 tmp_path = g_strndup (tmp_path, tmp_path_len);
402
403 path_element1 = vfs_path_get_by_index (vpath1, -1);
404
405 do
406 {
407 const char *fixfname;
408 unsigned int fixfname_len = 0;
409
410 fixfname = sftpfs_fix_filename (path_element1->path, &fixfname_len);
411
412 res =
413 libssh2_sftp_symlink_ex (super->sftp_session, fixfname, fixfname_len, tmp_path,
414 tmp_path_len, LIBSSH2_SFTP_SYMLINK);
415 if (res >= 0)
416 break;
417
418 if (!sftpfs_waitsocket (super, res, mcerror))
419 {
420 g_free (tmp_path);
421 return -1;
422 }
423 }
424 while (res == LIBSSH2_ERROR_EAGAIN);
425 g_free (tmp_path);
426
427 return 0;
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441 int
442 sftpfs_utime (const vfs_path_t * vpath, time_t atime, time_t mtime, GError ** mcerror)
443 {
444 sftpfs_super_t *super = NULL;
445 const vfs_path_element_t *path_element = NULL;
446 LIBSSH2_SFTP_ATTRIBUTES attrs;
447 int res;
448
449 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
450 if (res < 0)
451 return res;
452
453 attrs.atime = atime;
454 attrs.mtime = mtime;
455
456 do
457 {
458 const char *fixfname;
459 unsigned int fixfname_len = 0;
460
461 fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
462
463 res =
464 libssh2_sftp_stat_ex (super->sftp_session, fixfname, fixfname_len,
465 LIBSSH2_SFTP_SETSTAT, &attrs);
466 if (res >= 0)
467 break;
468
469 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
470 return -ENOENT;
471
472 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
473 {
474 res = 0;
475 break;
476 }
477
478 if (!sftpfs_waitsocket (super, res, mcerror))
479 return -1;
480 }
481 while (res == LIBSSH2_ERROR_EAGAIN);
482
483 return res;
484 }
485
486
487
488
489
490
491
492
493
494
495
496 int
497 sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror)
498 {
499 sftpfs_super_t *super = NULL;
500 const vfs_path_element_t *path_element = NULL;
501 LIBSSH2_SFTP_ATTRIBUTES attrs;
502 int res;
503
504 res = sftpfs_stat_init (&super, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
505 if (res < 0)
506 return res;
507
508 attrs.permissions = mode;
509
510 do
511 {
512 const char *fixfname;
513 unsigned int fixfname_len = 0;
514
515 fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
516
517 res =
518 libssh2_sftp_stat_ex (super->sftp_session, fixfname, fixfname_len,
519 LIBSSH2_SFTP_SETSTAT, &attrs);
520 if (res >= 0)
521 break;
522
523 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
524 return -ENOENT;
525
526 if (sftpfs_is_sftp_error (super->sftp_session, res, LIBSSH2_FX_FAILURE))
527 {
528 res = 0;
529 break;
530 }
531
532 if (!sftpfs_waitsocket (super, res, mcerror))
533 return -1;
534 }
535 while (res == LIBSSH2_ERROR_EAGAIN);
536
537 return res;
538 }
539
540
541
542
543
544
545
546
547
548
549 int
550 sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror)
551 {
552 sftpfs_super_t *super = NULL;
553 const vfs_path_element_t *path_element = NULL;
554 int res;
555
556 if (!sftpfs_op_init (&super, &path_element, vpath, mcerror))
557 return -1;
558
559 do
560 {
561 const char *fixfname;
562 unsigned int fixfname_len = 0;
563
564 fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
565
566 res = libssh2_sftp_unlink_ex (super->sftp_session, fixfname, fixfname_len);
567 if (res >= 0)
568 break;
569
570 if (!sftpfs_waitsocket (super, res, mcerror))
571 return -1;
572 }
573 while (res == LIBSSH2_ERROR_EAGAIN);
574
575 return res;
576 }
577
578
579
580
581
582
583
584
585
586
587
588 int
589 sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror)
590 {
591 sftpfs_super_t *super = NULL;
592 const vfs_path_element_t *path_element1;
593 const vfs_path_element_t *path_element2 = NULL;
594 char *tmp_path;
595 unsigned int tmp_path_len;
596 int res;
597
598 if (!sftpfs_op_init (&super, &path_element2, vpath2, mcerror))
599 return -1;
600
601 tmp_path = (char *) sftpfs_fix_filename (path_element2->path, &tmp_path_len);
602 tmp_path = g_strndup (tmp_path, tmp_path_len);
603
604 path_element1 = vfs_path_get_by_index (vpath1, -1);
605
606 do
607 {
608 const char *fixfname;
609 unsigned int fixfname_len = 0;
610
611 fixfname = sftpfs_fix_filename (path_element1->path, &fixfname_len);
612
613 res =
614 libssh2_sftp_rename_ex (super->sftp_session, fixfname, fixfname_len, tmp_path,
615 tmp_path_len, LIBSSH2_SFTP_SYMLINK);
616 if (res >= 0)
617 break;
618
619 if (!sftpfs_waitsocket (super, res, mcerror))
620 {
621 g_free (tmp_path);
622 return -1;
623 }
624 }
625 while (res == LIBSSH2_ERROR_EAGAIN);
626 g_free (tmp_path);
627
628 return 0;
629 }
630
631