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 | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP
158 | 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
207 if (sftpfs_fstat (fh, &file_info, mcerror) == 0)
208 libssh2_sftp_seek64 (file->handle, file_info.st_size);
209 }
210 return TRUE;
211 }
212
213
214
215
216
217
218
219
220
221
222
223 int
224 sftpfs_fstat (void *data, struct stat *buf, GError **mcerror)
225 {
226 int res;
227 LIBSSH2_SFTP_ATTRIBUTES attrs;
228 vfs_file_handler_t *fh = VFS_FILE_HANDLER (data);
229 sftpfs_file_handler_t *sftpfs_fh = (sftpfs_file_handler_t *) data;
230 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
231 sftpfs_super_t *sftpfs_super = SFTP_SUPER (super);
232
233 mc_return_val_if_error (mcerror, -1);
234
235 if (sftpfs_fh->handle == NULL)
236 return -1;
237
238 do
239 {
240 int err;
241
242 res = libssh2_sftp_fstat_ex (sftpfs_fh->handle, &attrs, 0);
243 if (res >= 0)
244 break;
245
246 err = sftpfs_file__handle_error (sftpfs_super, res, mcerror);
247 if (err < 0)
248 return err;
249 }
250 while (res == LIBSSH2_ERROR_EAGAIN);
251
252 sftpfs_attr_to_stat (&attrs, buf);
253
254 return 0;
255 }
256
257
258
259
260
261
262
263
264
265
266
267
268
269 ssize_t
270 sftpfs_read_file (vfs_file_handler_t *fh, char *buffer, size_t count, GError **mcerror)
271 {
272 ssize_t rc;
273 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
274 sftpfs_super_t *super;
275
276 mc_return_val_if_error (mcerror, -1);
277
278 if (fh == NULL)
279 {
280 mc_propagate_error (mcerror, 0, "%s",
281 _ ("sftp: No file handler data present for reading file"));
282 return -1;
283 }
284
285 super = SFTP_SUPER (VFS_FILE_HANDLER_SUPER (fh));
286
287 do
288 {
289 int err;
290
291 rc = libssh2_sftp_read (file->handle, buffer, count);
292 if (rc >= 0)
293 break;
294
295 err = sftpfs_file__handle_error (super, (int) rc, mcerror);
296 if (err < 0)
297 return err;
298 }
299 while (rc == LIBSSH2_ERROR_EAGAIN);
300
301 fh->pos = (off_t) libssh2_sftp_tell64 (file->handle);
302
303 return rc;
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319 ssize_t
320 sftpfs_write_file (vfs_file_handler_t *fh, const char *buffer, size_t count, GError **mcerror)
321 {
322 ssize_t rc;
323 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
324 sftpfs_super_t *super = SFTP_SUPER (VFS_FILE_HANDLER_SUPER (fh));
325
326 mc_return_val_if_error (mcerror, -1);
327
328 fh->pos = (off_t) libssh2_sftp_tell64 (file->handle);
329
330 do
331 {
332 int err;
333
334 rc = libssh2_sftp_write (file->handle, buffer, count);
335 if (rc >= 0)
336 break;
337
338 err = sftpfs_file__handle_error (super, (int) rc, mcerror);
339 if (err < 0)
340 return err;
341 }
342 while (rc == LIBSSH2_ERROR_EAGAIN);
343
344 return rc;
345 }
346
347
348
349
350
351
352
353
354
355
356
357
358 int
359 sftpfs_close_file (vfs_file_handler_t *fh, GError **mcerror)
360 {
361 int ret;
362
363 mc_return_val_if_error (mcerror, -1);
364
365 ret = libssh2_sftp_close (SFTP_FILE_HANDLER (fh)->handle);
366
367 return ret == 0 ? 0 : -1;
368 }
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383 off_t
384 sftpfs_lseek (vfs_file_handler_t *fh, off_t offset, int whence, GError **mcerror)
385 {
386 sftpfs_file_handler_t *file = SFTP_FILE_HANDLER (fh);
387
388 mc_return_val_if_error (mcerror, 0);
389
390 switch (whence)
391 {
392 case SEEK_SET:
393
394
395
396
397 if (fh->pos > offset || offset == 0)
398 {
399 sftpfs_reopen (fh, mcerror);
400 mc_return_val_if_error (mcerror, 0);
401 }
402 fh->pos = offset;
403 break;
404 case SEEK_CUR:
405 fh->pos += offset;
406 break;
407 case SEEK_END:
408 if (fh->pos > fh->ino->st.st_size - offset)
409 {
410 sftpfs_reopen (fh, mcerror);
411 mc_return_val_if_error (mcerror, 0);
412 }
413 fh->pos = fh->ino->st.st_size - offset;
414 break;
415 default:
416 break;
417 }
418
419 libssh2_sftp_seek64 (file->handle, fh->pos);
420 fh->pos = (off_t) libssh2_sftp_tell64 (file->handle);
421
422 return fh->pos;
423 }
424
425