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