This source file includes following definitions.
- sftpfs_reopen
- sftpfs_file__handle_error
- sftpfs_fh_new
- sftpfs_open_file
- sftpfs_fstat
- sftpfs_read_file
- sftpfs_write_file
- sftpfs_close_file
- sftpfs_lseek
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
29 #include <errno.h>
30
31 #include <libssh2.h>
32 #include <libssh2_sftp.h>
33
34 #include "lib/global.h"
35 #include "lib/util.h"
36
37 #include "internal.h"
38
39
40
41
42
43 #define SFTP_FILE_HANDLER(a) ((sftpfs_file_handler_t *) a)
44
45
46
47 typedef struct
48 {
49 vfs_file_handler_t base;
50
51 LIBSSH2_SFTP_HANDLE *handle;
52 int flags;
53 mode_t mode;
54 } sftpfs_file_handler_t;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 static void
70 sftpfs_reopen (vfs_file_handler_t *fh, GError **mcerror)
71 {
72 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
73 int flags;
74 mode_t mode;
75
76 g_return_if_fail (mcerror == NULL || *mcerror == NULL);
77
78 flags = file->flags;
79 mode = file->mode;
80
81 sftpfs_close_file (fh, mcerror);
82 sftpfs_open_file (fh, flags, mode, mcerror);
83 }
84
85
86
87 static int
88 sftpfs_file__handle_error (sftpfs_super_t *super, int sftp_res, GError **mcerror)
89 {
90 if (sftpfs_is_sftp_error (super->sftp_session, sftp_res, LIBSSH2_FX_PERMISSION_DENIED))
91 return -EACCES;
92
93 if (sftpfs_is_sftp_error (super->sftp_session, sftp_res, LIBSSH2_FX_NO_SUCH_FILE))
94 return -ENOENT;
95
96 if (!sftpfs_waitsocket (super, sftp_res, mcerror))
97 return -1;
98
99 return 0;
100 }
101
102
103
104
105
106 vfs_file_handler_t *
107 sftpfs_fh_new (struct vfs_s_inode *ino, gboolean changed)
108 {
109 sftpfs_file_handler_t *fh;
110
111 fh = g_new0 (sftpfs_file_handler_t, 1);
112 vfs_s_init_fh (VFS_FILE_HANDLER (fh), ino, changed);
113
114 return VFS_FILE_HANDLER (fh);
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128 gboolean
129 sftpfs_open_file (vfs_file_handler_t *fh, int flags, mode_t mode, GError **mcerror)
130 {
131 unsigned long sftp_open_flags = 0;
132 int sftp_open_mode = 0;
133 gboolean do_append = FALSE;
134 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
135 sftpfs_super_t *super = SFTP_SUPER (fh->ino->super);
136 char *name;
137 const GString *fixfname;
138
139 (void) mode;
140 mc_return_val_if_error (mcerror, FALSE);
141
142 name = vfs_s_fullpath (vfs_sftpfs_ops, fh->ino);
143 if (name == NULL)
144 return FALSE;
145
146 if ((flags & O_CREAT) != 0 || (flags & O_WRONLY) != 0)
147 {
148 sftp_open_flags = (flags & O_WRONLY) != 0 ? LIBSSH2_FXF_WRITE : 0;
149 sftp_open_flags |= (flags & O_CREAT) != 0 ? LIBSSH2_FXF_CREAT : 0;
150 if ((flags & O_APPEND) != 0)
151 {
152 sftp_open_flags |= LIBSSH2_FXF_APPEND;
153 do_append = TRUE;
154 }
155 sftp_open_flags |= (flags & O_TRUNC) != 0 ? LIBSSH2_FXF_TRUNC : 0;
156
157 sftp_open_mode = LIBSSH2_SFTP_S_IRUSR |
158 LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IROTH;
159 }
160 else
161 sftp_open_flags = LIBSSH2_FXF_READ;
162
163 fixfname = sftpfs_fix_filename (name);
164
165 while (TRUE)
166 {
167 int libssh_errno;
168
169 file->handle =
170 libssh2_sftp_open_ex (super->sftp_session, fixfname->str, fixfname->len,
171 sftp_open_flags, sftp_open_mode, LIBSSH2_SFTP_OPENFILE);
172 if (file->handle != NULL)
173 break;
174
175 libssh_errno = libssh2_session_last_errno (super->session);
176 if (libssh_errno != LIBSSH2_ERROR_EAGAIN)
177 {
178 sftpfs_ssherror_to_gliberror (super, libssh_errno, mcerror);
179 g_free (name);
180 return FALSE;
181 }
182 }
183
184 g_free (name);
185
186 file->flags = flags;
187 file->mode = mode;
188
189 if (do_append)
190 {
191 struct stat file_info = {
192 .st_dev = 0
193 };
194
195
196
197
198
199
200
201
202
203
204
205
206 if (sftpfs_fstat (fh, &file_info, mcerror) == 0)
207 libssh2_sftp_seek64 (file->handle, file_info.st_size);
208 }
209 return TRUE;
210 }
211
212
213
214
215
216
217
218
219
220
221
222 int
223 sftpfs_fstat (void *data, struct stat *buf, GError **mcerror)
224 {
225 int res;
226 LIBSSH2_SFTP_ATTRIBUTES attrs;
227 vfs_file_handler_t *fh = VFS_FILE_HANDLER (data);
228 sftpfs_file_handler_t *sftpfs_fh = (sftpfs_file_handler_t *) data;
229 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
230 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
231
232 mc_return_val_if_error (mcerror, -1);
233
234 if (sftpfs_fh->handle == NULL)
235 return -1;
236
237 do
238 {
239 int err;
240
241 res = libssh2_sftp_fstat_ex (sftpfs_fh->handle, &attrs, 0);
242 if (res >= 0)
243 break;
244
245 err = sftpfs_file__handle_error (sftpfs_super, res, mcerror);
246 if (err < 0)
247 return err;
248 }
249 while (res == LIBSSH2_ERROR_EAGAIN);
250
251 sftpfs_attr_to_stat (&attrs, buf);
252
253 return 0;
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267
268 ssize_t
269 sftpfs_read_file (vfs_file_handler_t *fh, char *buffer, size_t count, GError **mcerror)
270 {
271 ssize_t rc;
272 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
273 sftpfs_super_t *super;
274
275 mc_return_val_if_error (mcerror, -1);
276
277 if (fh == NULL)
278 {
279 mc_propagate_error (mcerror, 0, "%s",
280 _("sftp: No file handler data present for reading file"));
281 return -1;
282 }
283
284 super = SFTP_SUPER (VFS_FILE_HANDLER_SUPER (fh));
285
286 do
287 {
288 int err;
289
290 rc = libssh2_sftp_read (file->handle, buffer, count);
291 if (rc >= 0)
292 break;
293
294 err = sftpfs_file__handle_error (super, (int) rc, mcerror);
295 if (err < 0)
296 return err;
297 }
298 while (rc == LIBSSH2_ERROR_EAGAIN);
299
300 fh->pos = (off_t) libssh2_sftp_tell64 (file->handle);
301
302 return rc;
303 }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 ssize_t
319 sftpfs_write_file (vfs_file_handler_t *fh, const char *buffer, size_t count, GError **mcerror)
320 {
321 ssize_t rc;
322 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
323 sftpfs_super_t *super = SFTP_SUPER (VFS_FILE_HANDLER_SUPER (fh));
324
325 mc_return_val_if_error (mcerror, -1);
326
327 fh->pos = (off_t) libssh2_sftp_tell64 (file->handle);
328
329 do
330 {
331 int err;
332
333 rc = libssh2_sftp_write (file->handle, buffer, count);
334 if (rc >= 0)
335 break;
336
337 err = sftpfs_file__handle_error (super, (int) rc, mcerror);
338 if (err < 0)
339 return err;
340 }
341 while (rc == LIBSSH2_ERROR_EAGAIN);
342
343 return rc;
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357 int
358 sftpfs_close_file (vfs_file_handler_t *fh, GError **mcerror)
359 {
360 int ret;
361
362 mc_return_val_if_error (mcerror, -1);
363
364 ret = libssh2_sftp_close (SFTP_FILE_HANDLER (fh)->handle);
365
366 return ret == 0 ? 0 : -1;
367 }
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 off_t
383 sftpfs_lseek (vfs_file_handler_t *fh, off_t offset, int whence, GError **mcerror)
384 {
385 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
386
387 mc_return_val_if_error (mcerror, 0);
388
389 switch (whence)
390 {
391 case SEEK_SET:
392
393
394
395
396 if (fh->pos > offset || offset == 0)
397 {
398 sftpfs_reopen (fh, mcerror);
399 mc_return_val_if_error (mcerror, 0);
400 }
401 fh->pos = offset;
402 break;
403 case SEEK_CUR:
404 fh->pos += offset;
405 break;
406 case SEEK_END:
407 if (fh->pos > fh->ino->st.st_size - offset)
408 {
409 sftpfs_reopen (fh, mcerror);
410 mc_return_val_if_error (mcerror, 0);
411 }
412 fh->pos = fh->ino->st.st_size - offset;
413 break;
414 default:
415 break;
416 }
417
418 libssh2_sftp_seek64 (file->handle, fh->pos);
419 fh->pos = (off_t) libssh2_sftp_tell64 (file->handle);
420
421 return fh->pos;
422 }
423
424