This source file includes following definitions.
- fish_set_blksize
- fish_default_stat
- fish_load_script_from_file
- fish_decode_reply
- fish_get_reply
- fish_command
- G_GNUC_PRINTF
- G_GNUC_PRINTF
- G_GNUC_PRINTF
- fish_new_archive
- fish_free_archive
- fish_pipeopen
- fish_set_env
- fish_info
- fish_open_archive_pipeopen
- fish_open_archive_talk
- fish_open_archive_int
- fish_open_archive
- fish_archive_same
- fish_dir_load
- fish_file_store
- fish_linear_start
- fish_linear_abort
- fish_linear_read
- fish_linear_close
- fish_ctl
- fish_rename
- fish_link
- fish_symlink
- fish_stat
- fish_lstat
- fish_fstat
- fish_chmod
- fish_chown
- fish_get_atime
- fish_get_mtime
- fish_utime
- fish_unlink
- fish_exists
- fish_mkdir
- fish_rmdir
- fish_fh_new
- fish_fh_open
- fish_fill_names
- fish_open
- vfs_init_fish
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include <config.h>
54 #include <errno.h>
55 #include <pwd.h>
56 #include <grp.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <inttypes.h>
60
61 #include "lib/global.h"
62 #include "lib/tty/tty.h"
63 #include "lib/strescape.h"
64 #include "lib/unixcompat.h"
65 #include "lib/fileloc.h"
66 #include "lib/util.h"
67 #include "lib/mcconfig.h"
68
69 #include "src/execute.h"
70
71 #include "lib/vfs/vfs.h"
72 #include "lib/vfs/utilvfs.h"
73 #include "lib/vfs/netutil.h"
74 #include "lib/vfs/xdirentry.h"
75 #include "lib/vfs/gc.h"
76
77 #include "fish.h"
78 #include "fishdef.h"
79
80
81
82 int fish_directory_timeout = 900;
83
84
85
86 #define DO_RESOLVE_SYMLINK 1
87 #define DO_OPEN 2
88 #define DO_FREE_RESOURCE 4
89
90 #define FISH_FLAG_COMPRESSED 1
91 #define FISH_FLAG_RSH 2
92
93 #define OPT_FLUSH 1
94 #define OPT_IGNORE_ERROR 2
95
96
97
98
99 #define PRELIM 1
100 #define COMPLETE 2
101 #define CONTINUE 3
102 #define TRANSIENT 4
103 #define ERROR 5
104
105
106 #define NONE 0x00
107 #define WAIT_REPLY 0x01
108 #define WANT_STRING 0x02
109
110
111 #define FISH_HAVE_HEAD 1
112 #define FISH_HAVE_SED 2
113 #define FISH_HAVE_AWK 4
114 #define FISH_HAVE_PERL 8
115 #define FISH_HAVE_LSQ 16
116 #define FISH_HAVE_DATE_MDYT 32
117 #define FISH_HAVE_TAIL 64
118
119 #define FISH_SUPER(super) ((fish_super_t *) (super))
120 #define FISH_FILE_HANDLER(fh) ((fish_file_handler_t *) fh)
121
122
123
124 typedef struct
125 {
126 struct vfs_s_super base;
127
128 int sockr;
129 int sockw;
130 char *scr_ls;
131 char *scr_chmod;
132 char *scr_utime;
133 char *scr_exists;
134 char *scr_mkdir;
135 char *scr_unlink;
136 char *scr_chown;
137 char *scr_rmdir;
138 char *scr_ln;
139 char *scr_mv;
140 char *scr_hardlink;
141 char *scr_get;
142 char *scr_send;
143 char *scr_append;
144 char *scr_info;
145 int host_flags;
146 char *scr_env;
147 } fish_super_t;
148
149 typedef struct
150 {
151 vfs_file_handler_t base;
152
153 off_t got;
154 off_t total;
155 gboolean append;
156 } fish_file_handler_t;
157
158
159
160 static char reply_str[80];
161
162 static struct vfs_s_subclass fish_subclass;
163 static struct vfs_class *vfs_fish_ops = VFS_CLASS (&fish_subclass);
164
165
166
167
168
169 static void
170 fish_set_blksize (struct stat *s)
171 {
172 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
173
174 s->st_blksize = 64 * 1024;
175 #endif
176 }
177
178
179
180 static struct stat *
181 fish_default_stat (struct vfs_class *me)
182 {
183 struct stat *s;
184
185 s = vfs_s_default_stat (me, S_IFDIR | 0755);
186 fish_set_blksize (s);
187 vfs_adjust_stat (s);
188
189 return s;
190 }
191
192
193
194 static char *
195 fish_load_script_from_file (const char *hostname, const char *script_name, const char *def_content)
196 {
197 char *scr_filename = NULL;
198 char *scr_content;
199 gsize scr_len = 0;
200
201
202 scr_filename = g_build_path (PATH_SEP_STR, mc_config_get_data_path (), FISH_PREFIX, hostname,
203 script_name, (char *) NULL);
204
205 g_file_get_contents (scr_filename, &scr_content, &scr_len, NULL);
206 g_free (scr_filename);
207
208 if (scr_content == NULL)
209 {
210 scr_filename =
211 g_build_path (PATH_SEP_STR, LIBEXECDIR, FISH_PREFIX, script_name, (char *) NULL);
212 g_file_get_contents (scr_filename, &scr_content, &scr_len, NULL);
213 g_free (scr_filename);
214 }
215
216 if (scr_content != NULL)
217 return scr_content;
218
219 return g_strdup (def_content);
220 }
221
222
223
224 static int
225 fish_decode_reply (char *s, gboolean was_garbage)
226 {
227 int code;
228
229
230 if (sscanf (s, "%d", &code) == 0)
231 {
232 code = 500;
233 return 5;
234 }
235 if (code < 100)
236 return was_garbage ? ERROR : (code == 0 ? COMPLETE : PRELIM);
237 return code / 100;
238 }
239
240
241
242
243 static int
244 fish_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len)
245 {
246 char answer[BUF_1K];
247 gboolean was_garbage = FALSE;
248
249 while (TRUE)
250 {
251 if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n'))
252 {
253 if (string_buf != NULL)
254 *string_buf = '\0';
255 return 4;
256 }
257
258 if (strncmp (answer, "### ", 4) == 0)
259 return fish_decode_reply (answer + 4, was_garbage ? 1 : 0);
260
261 was_garbage = TRUE;
262 if (string_buf != NULL)
263 g_strlcpy (string_buf, answer, string_len);
264 }
265 }
266
267
268
269 static int
270 fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *cmd,
271 size_t cmd_len)
272 {
273 ssize_t status;
274 FILE *logfile = me->logfile;
275
276 if (cmd_len == (size_t) (-1))
277 cmd_len = strlen (cmd);
278
279 if (logfile != NULL)
280 {
281 size_t ret;
282
283 ret = fwrite (cmd, cmd_len, 1, logfile);
284 ret = fflush (logfile);
285 (void) ret;
286 }
287
288 tty_enable_interrupt_key ();
289 status = write (FISH_SUPER (super)->sockw, cmd, cmd_len);
290 tty_disable_interrupt_key ();
291
292 if (status < 0)
293 return TRANSIENT;
294
295 if (wait_reply)
296 return fish_get_reply (me, FISH_SUPER (super)->sockr,
297 (wait_reply & WANT_STRING) != 0 ? reply_str :
298 NULL, sizeof (reply_str) - 1);
299 return COMPLETE;
300 }
301
302
303
304 static int
305 G_GNUC_PRINTF (5, 0)
306 fish_command_va (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *scr,
307 const char *vars, va_list ap)
308 {
309 int r;
310 GString *command;
311
312 command = g_string_new (FISH_SUPER (super)->scr_env);
313 g_string_append_vprintf (command, vars, ap);
314 g_string_append (command, scr);
315 r = fish_command (me, super, wait_reply, command->str, command->len);
316 g_string_free (command, TRUE);
317
318 return r;
319 }
320
321
322
323 static int
324 G_GNUC_PRINTF (5, 6)
325 fish_command_v (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *scr,
326 const char *vars, ...)
327 {
328 int r;
329 va_list ap;
330
331 va_start (ap, vars);
332 r = fish_command_va (me, super, wait_reply, scr, vars, ap);
333 va_end (ap);
334
335 return r;
336 }
337
338
339
340 static int
341 G_GNUC_PRINTF (5, 6)
342 fish_send_command (struct vfs_class *me, struct vfs_s_super *super, int flags, const char *scr,
343 const char *vars, ...)
344 {
345 int r;
346 va_list ap;
347
348 va_start (ap, vars);
349 r = fish_command_va (me, super, WAIT_REPLY, scr, vars, ap);
350 va_end (ap);
351 vfs_stamp_create (vfs_fish_ops, super);
352
353 if (r != COMPLETE)
354 ERRNOR (E_REMOTE, -1);
355 if ((flags & OPT_FLUSH) != 0)
356 vfs_s_invalidate (me, super);
357
358 return 0;
359 }
360
361
362
363 static struct vfs_s_super *
364 fish_new_archive (struct vfs_class *me)
365 {
366 fish_super_t *arch;
367
368 arch = g_new0 (fish_super_t, 1);
369 arch->base.me = me;
370
371 return VFS_SUPER (arch);
372 }
373
374
375
376 static void
377 fish_free_archive (struct vfs_class *me, struct vfs_s_super *super)
378 {
379 fish_super_t *fish_super = FISH_SUPER (super);
380
381 if ((fish_super->sockw != -1) || (fish_super->sockr != -1))
382 {
383 vfs_print_message (_("fish: Disconnecting from %s"), super->name ? super->name : "???");
384 fish_command (me, super, NONE, "#BYE\nexit\n", -1);
385 close (fish_super->sockw);
386 close (fish_super->sockr);
387 fish_super->sockw = fish_super->sockr = -1;
388 }
389 g_free (fish_super->scr_ls);
390 g_free (fish_super->scr_exists);
391 g_free (fish_super->scr_mkdir);
392 g_free (fish_super->scr_unlink);
393 g_free (fish_super->scr_chown);
394 g_free (fish_super->scr_chmod);
395 g_free (fish_super->scr_utime);
396 g_free (fish_super->scr_rmdir);
397 g_free (fish_super->scr_ln);
398 g_free (fish_super->scr_mv);
399 g_free (fish_super->scr_hardlink);
400 g_free (fish_super->scr_get);
401 g_free (fish_super->scr_send);
402 g_free (fish_super->scr_append);
403 g_free (fish_super->scr_info);
404 g_free (fish_super->scr_env);
405 }
406
407
408
409 static void
410 fish_pipeopen (struct vfs_s_super *super, const char *path, const char *argv[])
411 {
412 int fileset1[2], fileset2[2];
413 int res;
414
415 if ((pipe (fileset1) < 0) || (pipe (fileset2) < 0))
416 vfs_die ("Cannot pipe(): %m.");
417
418 res = fork ();
419
420 if (res != 0)
421 {
422 if (res < 0)
423 vfs_die ("Cannot fork(): %m.");
424
425 close (fileset1[0]);
426 FISH_SUPER (super)->sockw = fileset1[1];
427 close (fileset2[1]);
428 FISH_SUPER (super)->sockr = fileset2[0];
429 }
430 else
431 {
432 res = dup2 (fileset1[0], STDIN_FILENO);
433 close (fileset1[0]);
434 close (fileset1[1]);
435 res = dup2 (fileset2[1], STDOUT_FILENO);
436 close (STDERR_FILENO);
437
438 res = open ("/dev/null", O_WRONLY);
439 close (fileset2[0]);
440 close (fileset2[1]);
441 execvp (path, (char **) argv);
442 my_exit (3);
443 }
444 }
445
446
447
448 static char *
449 fish_set_env (int flags)
450 {
451 GString *tmp;
452
453 tmp = g_string_sized_new (250);
454
455 if ((flags & FISH_HAVE_HEAD) != 0)
456 g_string_append (tmp, "FISH_HAVE_HEAD=1 export FISH_HAVE_HEAD; ");
457
458 if ((flags & FISH_HAVE_SED) != 0)
459 g_string_append (tmp, "FISH_HAVE_SED=1 export FISH_HAVE_SED; ");
460
461 if ((flags & FISH_HAVE_AWK) != 0)
462 g_string_append (tmp, "FISH_HAVE_AWK=1 export FISH_HAVE_AWK; ");
463
464 if ((flags & FISH_HAVE_PERL) != 0)
465 g_string_append (tmp, "FISH_HAVE_PERL=1 export FISH_HAVE_PERL; ");
466
467 if ((flags & FISH_HAVE_LSQ) != 0)
468 g_string_append (tmp, "FISH_HAVE_LSQ=1 export FISH_HAVE_LSQ; ");
469
470 if ((flags & FISH_HAVE_DATE_MDYT) != 0)
471 g_string_append (tmp, "FISH_HAVE_DATE_MDYT=1 export FISH_HAVE_DATE_MDYT; ");
472
473 if ((flags & FISH_HAVE_TAIL) != 0)
474 g_string_append (tmp, "FISH_HAVE_TAIL=1 export FISH_HAVE_TAIL; ");
475
476 return g_string_free (tmp, FALSE);
477 }
478
479
480
481 static gboolean
482 fish_info (struct vfs_class *me, struct vfs_s_super *super)
483 {
484 fish_super_t *fish_super = FISH_SUPER (super);
485
486 if (fish_command (me, super, NONE, fish_super->scr_info, -1) == COMPLETE)
487 {
488 while (TRUE)
489 {
490 int res;
491 char buffer[BUF_8K] = "";
492
493 res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), fish_super->sockr);
494 if ((res == 0) || (res == EINTR))
495 ERRNOR (ECONNRESET, FALSE);
496 if (strncmp (buffer, "### ", 4) == 0)
497 break;
498 fish_super->host_flags = atol (buffer);
499 }
500 return TRUE;
501 }
502 ERRNOR (E_PROTO, FALSE);
503 }
504
505
506
507 static void
508 fish_open_archive_pipeopen (struct vfs_s_super *super)
509 {
510 char gbuf[10];
511 const char *argv[10];
512 const char *xsh = (super->path_element->port == FISH_FLAG_RSH ? "rsh" : "ssh");
513 int i = 0;
514
515 argv[i++] = xsh;
516 if (super->path_element->port == FISH_FLAG_COMPRESSED)
517 argv[i++] = "-C";
518
519 if (super->path_element->port > FISH_FLAG_RSH)
520 {
521 argv[i++] = "-p";
522 g_snprintf (gbuf, sizeof (gbuf), "%d", super->path_element->port);
523 argv[i++] = gbuf;
524 }
525
526
527
528
529
530
531
532
533 if (super->path_element->user != NULL)
534 {
535 argv[i++] = "-l";
536 argv[i++] = super->path_element->user;
537 }
538 else
539 {
540
541 super->path_element->user = vfs_get_local_username ();
542 }
543
544 argv[i++] = super->path_element->host;
545 argv[i++] = "echo FISH:; /bin/sh";
546 argv[i++] = NULL;
547
548 fish_pipeopen (super, xsh, argv);
549 }
550
551
552
553 static gboolean
554 fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
555 {
556 fish_super_t *fish_super = FISH_SUPER (super);
557 char answer[2048];
558
559 printf ("\n%s\n", _("fish: Waiting for initial line..."));
560
561 if (vfs_s_get_line (me, fish_super->sockr, answer, sizeof (answer), ':') == 0)
562 return FALSE;
563
564 if (strstr (answer, "assword") != NULL)
565 {
566
567
568
569 printf ("\n%s\n", _("Sorry, we cannot do password authenticated connections for now."));
570
571 return FALSE;
572 #if 0
573 if (super->path_element->password == NULL)
574 {
575 char *p, *op;
576
577 p = g_strdup_printf (_("fish: Password is required for %s"), super->path_element->user);
578 op = vfs_get_password (p);
579 g_free (p);
580 if (op == NULL)
581 return FALSE;
582 super->path_element->password = op;
583 }
584
585 printf ("\n%s\n", _("fish: Sending password..."));
586
587 {
588 size_t str_len;
589
590 str_len = strlen (super->path_element->password);
591 if ((write (fish_super.sockw, super->path_element->password, str_len) !=
592 (ssize_t) str_len) || (write (fish_super->sockw, "\n", 1) != 1))
593 return FALSE;
594 }
595 #endif
596 }
597 return TRUE;
598 }
599
600
601
602 static int
603 fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
604 {
605 gboolean ftalk;
606
607
608 pre_exec ();
609
610
611 fish_open_archive_pipeopen (super);
612
613
614 ftalk = fish_open_archive_talk (me, super);
615
616
617 post_exec ();
618
619 if (!ftalk)
620 ERRNOR (E_PROTO, -1);
621
622 vfs_print_message ("%s", _("fish: Sending initial line..."));
623
624
625
626
627
628 if (fish_command
629 (me, super, WAIT_REPLY, "#FISH\necho; start_fish_server 2>&1; echo '### 200'\n",
630 -1) != COMPLETE)
631 ERRNOR (E_PROTO, -1);
632
633 vfs_print_message ("%s", _("fish: Handshaking version..."));
634 if (fish_command (me, super, WAIT_REPLY, "#VER 0.0.3\necho '### 000'\n", -1) != COMPLETE)
635 ERRNOR (E_PROTO, -1);
636
637
638 if (fish_command
639 (me, super, WAIT_REPLY,
640 "LANG=C LC_ALL=C LC_TIME=C; export LANG LC_ALL LC_TIME;\n" "echo '### 200'\n",
641 -1) != COMPLETE)
642 ERRNOR (E_PROTO, -1);
643
644 vfs_print_message ("%s", _("fish: Getting host info..."));
645 if (fish_info (me, super))
646 FISH_SUPER (super)->scr_env = fish_set_env (FISH_SUPER (super)->host_flags);
647
648 #if 0
649 super->name =
650 g_strconcat ("sh://", super->path_element->user, "@", super->path_element->host,
651 PATH_SEP_STR, (char *) NULL);
652 #else
653 super->name = g_strdup (PATH_SEP_STR);
654 #endif
655
656 super->root = vfs_s_new_inode (me, super, fish_default_stat (me));
657
658 return 0;
659 }
660
661
662
663 static int
664 fish_open_archive (struct vfs_s_super *super,
665 const vfs_path_t * vpath, const vfs_path_element_t * vpath_element)
666 {
667 fish_super_t *fish_super = FISH_SUPER (super);
668
669 (void) vpath;
670
671 super->path_element = vfs_path_element_clone (vpath_element);
672
673 if (strncmp (vpath_element->vfs_prefix, "rsh", 3) == 0)
674 super->path_element->port = FISH_FLAG_RSH;
675
676 fish_super->scr_ls =
677 fish_load_script_from_file (super->path_element->host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
678 fish_super->scr_exists =
679 fish_load_script_from_file (super->path_element->host, FISH_EXISTS_FILE,
680 FISH_EXISTS_DEF_CONTENT);
681 fish_super->scr_mkdir =
682 fish_load_script_from_file (super->path_element->host, FISH_MKDIR_FILE,
683 FISH_MKDIR_DEF_CONTENT);
684 fish_super->scr_unlink =
685 fish_load_script_from_file (super->path_element->host, FISH_UNLINK_FILE,
686 FISH_UNLINK_DEF_CONTENT);
687 fish_super->scr_chown =
688 fish_load_script_from_file (super->path_element->host, FISH_CHOWN_FILE,
689 FISH_CHOWN_DEF_CONTENT);
690 fish_super->scr_chmod =
691 fish_load_script_from_file (super->path_element->host, FISH_CHMOD_FILE,
692 FISH_CHMOD_DEF_CONTENT);
693 fish_super->scr_utime =
694 fish_load_script_from_file (super->path_element->host, FISH_UTIME_FILE,
695 FISH_UTIME_DEF_CONTENT);
696 fish_super->scr_rmdir =
697 fish_load_script_from_file (super->path_element->host, FISH_RMDIR_FILE,
698 FISH_RMDIR_DEF_CONTENT);
699 fish_super->scr_ln =
700 fish_load_script_from_file (super->path_element->host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
701 fish_super->scr_mv =
702 fish_load_script_from_file (super->path_element->host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
703 fish_super->scr_hardlink =
704 fish_load_script_from_file (super->path_element->host, FISH_HARDLINK_FILE,
705 FISH_HARDLINK_DEF_CONTENT);
706 fish_super->scr_get =
707 fish_load_script_from_file (super->path_element->host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
708 fish_super->scr_send =
709 fish_load_script_from_file (super->path_element->host, FISH_SEND_FILE,
710 FISH_SEND_DEF_CONTENT);
711 fish_super->scr_append =
712 fish_load_script_from_file (super->path_element->host, FISH_APPEND_FILE,
713 FISH_APPEND_DEF_CONTENT);
714 fish_super->scr_info =
715 fish_load_script_from_file (super->path_element->host, FISH_INFO_FILE,
716 FISH_INFO_DEF_CONTENT);
717
718 return fish_open_archive_int (vpath_element->class, super);
719 }
720
721
722
723 static int
724 fish_archive_same (const vfs_path_element_t * vpath_element, struct vfs_s_super *super,
725 const vfs_path_t * vpath, void *cookie)
726 {
727 vfs_path_element_t *path_element;
728 int result;
729
730 (void) vpath;
731 (void) cookie;
732
733 path_element = vfs_path_element_clone (vpath_element);
734
735 if (path_element->user == NULL)
736 path_element->user = vfs_get_local_username ();
737
738 result = ((strcmp (path_element->host, super->path_element->host) == 0)
739 && (strcmp (path_element->user, super->path_element->user) == 0)
740 && (path_element->port == super->path_element->port)) ? 1 : 0;
741
742 vfs_path_element_free (path_element);
743
744 return result;
745 }
746
747
748
749 static int
750 fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
751 {
752 struct vfs_s_super *super = dir->super;
753 char buffer[BUF_8K] = "\0";
754 struct vfs_s_entry *ent = NULL;
755 char *quoted_path;
756 int reply_code;
757
758
759
760
761 #if 0
762 if (me->logfile == NULL)
763 me->logfile = fopen ("/tmp/mc-FISH.sh", "w");
764 #endif
765
766 vfs_print_message (_("fish: Reading directory %s..."), remote_path);
767
768 dir->timestamp = g_get_real_time () + fish_directory_timeout * G_USEC_PER_SEC;
769
770 quoted_path = strutils_shell_escape (remote_path);
771 (void) fish_command_v (me, super, NONE, FISH_SUPER (super)->scr_ls, "FISH_FILENAME=%s;\n",
772 quoted_path);
773 g_free (quoted_path);
774
775 ent = vfs_s_generate_entry (me, NULL, dir, 0);
776
777 while (TRUE)
778 {
779 int res;
780
781 res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), FISH_SUPER (super)->sockr);
782
783 if ((res == 0) || (res == EINTR))
784 {
785 vfs_s_free_entry (me, ent);
786 me->verrno = ECONNRESET;
787 goto error;
788 }
789 if (me->logfile != NULL)
790 {
791 fputs (buffer, me->logfile);
792 fputs ("\n", me->logfile);
793 fflush (me->logfile);
794 }
795 if (strncmp (buffer, "### ", 4) == 0)
796 break;
797 if (buffer[0] == '\0')
798 {
799 if (ent->name != NULL)
800 {
801 vfs_s_insert_entry (me, dir, ent);
802 ent = vfs_s_generate_entry (me, NULL, dir, 0);
803 }
804 continue;
805 }
806
807 #define ST ent->ino->st
808
809 switch (buffer[0])
810 {
811 case ':':
812 {
813 char *temp;
814 char *data_start = buffer + 1;
815 char *filename = data_start;
816 char *filename_bound;
817
818 filename_bound = filename + strlen (filename);
819
820 if (strcmp (data_start, "\".\"") == 0 || strcmp (data_start, "\"..\"") == 0)
821 break;
822
823 if (S_ISLNK (ST.st_mode))
824 {
825 char *linkname;
826 char *linkname_bound;
827
828
829
830
831
832 linkname_bound = filename_bound;
833
834 if (*filename == '"')
835 ++filename;
836
837 linkname = strstr (filename, "\" -> \"");
838 if (linkname == NULL)
839 {
840
841 linkname = filename_bound;
842 if (filename_bound > filename && *(filename_bound - 1) == '"')
843 --filename_bound;
844 }
845 else
846 {
847 filename_bound = linkname;
848 linkname += 6;
849 if (*(linkname_bound - 1) == '"')
850 --linkname_bound;
851 }
852
853 ent->name = g_strndup (filename, filename_bound - filename);
854 temp = ent->name;
855 ent->name = strutils_shell_unescape (ent->name);
856 g_free (temp);
857
858 ent->ino->linkname = g_strndup (linkname, linkname_bound - linkname);
859 temp = ent->ino->linkname;
860 ent->ino->linkname = strutils_shell_unescape (ent->ino->linkname);
861 g_free (temp);
862 }
863 else
864 {
865
866 if (filename_bound - filename > 2)
867 {
868
869
870
871
872 if (*filename == '"')
873 ++filename;
874 if (*(filename_bound - 1) == '"')
875 --filename_bound;
876 }
877 ent->name = g_strndup (filename, filename_bound - filename);
878 temp = ent->name;
879 ent->name = strutils_shell_unescape (ent->name);
880 g_free (temp);
881 }
882 break;
883 }
884 case 'S':
885 ST.st_size = (off_t) g_ascii_strtoll (buffer + 1, NULL, 10);
886 break;
887 case 'P':
888 {
889 size_t skipped;
890
891 vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode);
892 break;
893 }
894 case 'R':
895 {
896
897
898
899
900 size_t skipped;
901
902 vfs_parse_raw_filemode (buffer + 1, &skipped, &ST.st_mode);
903 break;
904 }
905 case 'd':
906 {
907 vfs_split_text (buffer + 1);
908 if (vfs_parse_filedate (0, &ST.st_ctime) == 0)
909 break;
910 ST.st_atime = ST.st_mtime = ST.st_ctime;
911 #ifdef HAVE_STRUCT_STAT_ST_MTIM
912 ST.st_atim.tv_nsec = ST.st_mtim.tv_nsec = ST.st_ctim.tv_nsec = 0;
913 #endif
914 }
915 break;
916 case 'D':
917 {
918 struct tm tim;
919
920 memset (&tim, 0, sizeof (tim));
921
922 if (sscanf (buffer + 1, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon,
923 &tim.tm_mday, &tim.tm_hour, &tim.tm_min, &tim.tm_sec) != 6)
924 break;
925 ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim);
926 #ifdef HAVE_STRUCT_STAT_ST_MTIM
927 ST.st_atim.tv_nsec = ST.st_mtim.tv_nsec = ST.st_ctim.tv_nsec = 0;
928 #endif
929 }
930 break;
931 case 'E':
932 {
933 int maj, min;
934
935
936 if (sscanf (buffer + 1, "%d,%d", &maj, &min) != 2)
937 break;
938 #ifdef HAVE_STRUCT_STAT_ST_RDEV
939 ST.st_rdev = makedev (maj, min);
940 #endif
941 }
942 break;
943 default:
944 break;
945 }
946 }
947
948 vfs_s_free_entry (me, ent);
949 reply_code = fish_decode_reply (buffer + 4, 0);
950 if (reply_code == COMPLETE)
951 {
952 vfs_print_message (_("%s: done."), me->name);
953 return 0;
954 }
955
956 me->verrno = reply_code == ERROR ? EACCES : E_REMOTE;
957
958 error:
959 vfs_print_message (_("%s: failure"), me->name);
960 return -1;
961 }
962
963
964
965 static int
966 fish_file_store (struct vfs_class *me, vfs_file_handler_t * fh, char *name, char *localname)
967 {
968 fish_file_handler_t *fish = FISH_FILE_HANDLER (fh);
969 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
970 fish_super_t *fish_super = FISH_SUPER (super);
971 int code;
972 off_t total = 0;
973 char buffer[BUF_8K];
974 struct stat s;
975 int h;
976 char *quoted_name;
977
978 h = open (localname, O_RDONLY);
979 if (h == -1)
980 ERRNOR (EIO, -1);
981 if (fstat (h, &s) < 0)
982 {
983 close (h);
984 ERRNOR (EIO, -1);
985 }
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 quoted_name = strutils_shell_escape (name);
1017 vfs_print_message (_("fish: store %s: sending command..."), quoted_name);
1018
1019
1020 code =
1021 fish_command_v (me, super, WAIT_REPLY,
1022 fish->append ? fish_super->scr_append : fish_super->scr_send,
1023 "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n", quoted_name,
1024 (uintmax_t) s.st_size);
1025 g_free (quoted_name);
1026
1027 if (code != PRELIM)
1028 {
1029 close (h);
1030 ERRNOR (E_REMOTE, -1);
1031 }
1032
1033 while (TRUE)
1034 {
1035 ssize_t n, t;
1036
1037 while ((n = read (h, buffer, sizeof (buffer))) < 0)
1038 {
1039 if ((errno == EINTR) && tty_got_interrupt ())
1040 continue;
1041 vfs_print_message ("%s", _("fish: Local read failed, sending zeros"));
1042 close (h);
1043 h = open ("/dev/zero", O_RDONLY);
1044 }
1045
1046 if (n == 0)
1047 break;
1048
1049 t = write (fish_super->sockw, buffer, n);
1050 if (t != n)
1051 {
1052 if (t == -1)
1053 me->verrno = errno;
1054 else
1055 me->verrno = EIO;
1056 goto error_return;
1057 }
1058 tty_disable_interrupt_key ();
1059 total += n;
1060 vfs_print_message ("%s: %" PRIuMAX "/%" PRIuMAX, _("fish: storing file"),
1061 (uintmax_t) total, (uintmax_t) s.st_size);
1062 }
1063 close (h);
1064
1065 if (fish_get_reply (me, fish_super->sockr, NULL, 0) != COMPLETE)
1066 ERRNOR (E_REMOTE, -1);
1067 return 0;
1068
1069 error_return:
1070 close (h);
1071 fish_get_reply (me, fish_super->sockr, NULL, 0);
1072 return -1;
1073 }
1074
1075
1076
1077 static int
1078 fish_linear_start (struct vfs_class *me, vfs_file_handler_t * fh, off_t offset)
1079 {
1080 fish_file_handler_t *fish = FISH_FILE_HANDLER (fh);
1081 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1082 char *name;
1083 char *quoted_name;
1084
1085 name = vfs_s_fullpath (me, fh->ino);
1086 if (name == NULL)
1087 return 0;
1088 quoted_name = strutils_shell_escape (name);
1089 g_free (name);
1090 fish->append = FALSE;
1091
1092
1093
1094
1095
1096
1097
1098
1099 offset =
1100 fish_command_v (me, super, WANT_STRING, FISH_SUPER (super)->scr_get,
1101 "FISH_FILENAME=%s FISH_START_OFFSET=%" PRIuMAX ";\n", quoted_name,
1102 (uintmax_t) offset);
1103 g_free (quoted_name);
1104
1105 if (offset != PRELIM)
1106 ERRNOR (E_REMOTE, 0);
1107 fh->linear = LS_LINEAR_OPEN;
1108 fish->got = 0;
1109 errno = 0;
1110 #if SIZEOF_OFF_T == SIZEOF_LONG
1111 fish->total = (off_t) strtol (reply_str, NULL, 10);
1112 #else
1113 fish->total = (off_t) g_ascii_strtoll (reply_str, NULL, 10);
1114 #endif
1115 if (errno != 0)
1116 ERRNOR (E_REMOTE, 0);
1117 return 1;
1118 }
1119
1120
1121
1122 static void
1123 fish_linear_abort (struct vfs_class *me, vfs_file_handler_t * fh)
1124 {
1125 fish_file_handler_t *fish = FISH_FILE_HANDLER (fh);
1126 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1127 char buffer[BUF_8K];
1128 ssize_t n;
1129
1130 vfs_print_message ("%s", _("Aborting transfer..."));
1131
1132 do
1133 {
1134 n = MIN ((off_t) sizeof (buffer), (fish->total - fish->got));
1135 if (n != 0)
1136 {
1137 n = read (FISH_SUPER (super)->sockr, buffer, n);
1138 if (n < 0)
1139 return;
1140 fish->got += n;
1141 }
1142 }
1143 while (n != 0);
1144
1145 if (fish_get_reply (me, FISH_SUPER (super)->sockr, NULL, 0) != COMPLETE)
1146 vfs_print_message ("%s", _("Error reported after abort."));
1147 else
1148 vfs_print_message ("%s", _("Aborted transfer would be successful."));
1149 }
1150
1151
1152
1153 static ssize_t
1154 fish_linear_read (struct vfs_class *me, vfs_file_handler_t * fh, void *buf, size_t len)
1155 {
1156 fish_file_handler_t *fish = FISH_FILE_HANDLER (fh);
1157 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1158 ssize_t n = 0;
1159
1160 len = MIN ((size_t) (fish->total - fish->got), len);
1161 tty_disable_interrupt_key ();
1162 while (len != 0 && ((n = read (FISH_SUPER (super)->sockr, buf, len)) < 0))
1163 {
1164 if ((errno == EINTR) && !tty_got_interrupt ())
1165 continue;
1166 break;
1167 }
1168 tty_enable_interrupt_key ();
1169
1170 if (n > 0)
1171 fish->got += n;
1172 else if (n < 0)
1173 fish_linear_abort (me, fh);
1174 else if (fish_get_reply (me, FISH_SUPER (super)->sockr, NULL, 0) != COMPLETE)
1175 ERRNOR (E_REMOTE, -1);
1176 ERRNOR (errno, n);
1177 }
1178
1179
1180
1181 static void
1182 fish_linear_close (struct vfs_class *me, vfs_file_handler_t * fh)
1183 {
1184 fish_file_handler_t *fish = FISH_FILE_HANDLER (fh);
1185
1186 if (fish->total != fish->got)
1187 fish_linear_abort (me, fh);
1188 }
1189
1190
1191
1192 static int
1193 fish_ctl (void *fh, int ctlop, void *arg)
1194 {
1195 (void) arg;
1196 (void) fh;
1197 (void) ctlop;
1198
1199 return 0;
1200
1201 #if 0
1202 switch (ctlop)
1203 {
1204 case VFS_CTL_IS_NOTREADY:
1205 {
1206 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1207 int v;
1208
1209 if (file->linear == LS_NOT_LINEAR)
1210 vfs_die ("You may not do this");
1211 if (file->linear == LS_LINEAR_CLOSED || file->linear == LS_LINEAR_PREOPEN)
1212 return 0;
1213
1214 v = vfs_s_select_on_two (VFS_FILE_HANDLER_SUPER (fh)->u.fish.sockr, 0);
1215
1216 return (((v < 0) && (errno == EINTR)) || v == 0) ? 1 : 0;
1217 }
1218 default:
1219 return 0;
1220 }
1221 #endif
1222 }
1223
1224
1225
1226 static int
1227 fish_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
1228 {
1229 const char *crpath1, *crpath2;
1230 char *rpath1, *rpath2;
1231 struct vfs_s_super *super, *super2;
1232 const vfs_path_element_t *path_element;
1233 int ret;
1234
1235 path_element = vfs_path_get_by_index (vpath1, -1);
1236
1237 crpath1 = vfs_s_get_path (vpath1, &super, 0);
1238 if (crpath1 == NULL)
1239 return -1;
1240
1241 crpath2 = vfs_s_get_path (vpath2, &super2, 0);
1242 if (crpath2 == NULL)
1243 return -1;
1244
1245 rpath1 = strutils_shell_escape (crpath1);
1246 rpath2 = strutils_shell_escape (crpath2);
1247
1248 ret =
1249 fish_send_command (path_element->class, super2, OPT_FLUSH, FISH_SUPER (super)->scr_mv,
1250 "FISH_FILEFROM=%s FISH_FILETO=%s;\n", rpath1, rpath2);
1251
1252 g_free (rpath1);
1253 g_free (rpath2);
1254
1255 return ret;
1256 }
1257
1258
1259
1260 static int
1261 fish_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
1262 {
1263 const char *crpath1, *crpath2;
1264 char *rpath1, *rpath2;
1265 struct vfs_s_super *super, *super2;
1266 const vfs_path_element_t *path_element;
1267 int ret;
1268
1269 path_element = vfs_path_get_by_index (vpath1, -1);
1270
1271 crpath1 = vfs_s_get_path (vpath1, &super, 0);
1272 if (crpath1 == NULL)
1273 return -1;
1274
1275 crpath2 = vfs_s_get_path (vpath2, &super2, 0);
1276 if (crpath2 == NULL)
1277 return -1;
1278
1279 rpath1 = strutils_shell_escape (crpath1);
1280 rpath2 = strutils_shell_escape (crpath2);
1281
1282 ret =
1283 fish_send_command (path_element->class, super2, OPT_FLUSH, FISH_SUPER (super)->scr_hardlink,
1284 "FISH_FILEFROM=%s FISH_FILETO=%s;\n", rpath1, rpath2);
1285
1286 g_free (rpath1);
1287 g_free (rpath2);
1288
1289 return ret;
1290 }
1291
1292
1293
1294 static int
1295 fish_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
1296 {
1297 char *qsetto;
1298 const char *crpath;
1299 char *rpath;
1300 struct vfs_s_super *super;
1301 const vfs_path_element_t *path_element;
1302 int ret;
1303
1304 path_element = vfs_path_get_by_index (vpath2, -1);
1305
1306 crpath = vfs_s_get_path (vpath2, &super, 0);
1307 if (crpath == NULL)
1308 return -1;
1309
1310 rpath = strutils_shell_escape (crpath);
1311 qsetto = strutils_shell_escape (vfs_path_get_by_index (vpath1, -1)->path);
1312
1313 ret =
1314 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_ln,
1315 "FISH_FILEFROM=%s FISH_FILETO=%s;\n", qsetto, rpath);
1316
1317 g_free (qsetto);
1318 g_free (rpath);
1319
1320 return ret;
1321 }
1322
1323
1324
1325 static int
1326 fish_stat (const vfs_path_t * vpath, struct stat *buf)
1327 {
1328 int ret;
1329
1330 ret = vfs_s_stat (vpath, buf);
1331 fish_set_blksize (buf);
1332 return ret;
1333 }
1334
1335
1336
1337 static int
1338 fish_lstat (const vfs_path_t * vpath, struct stat *buf)
1339 {
1340 int ret;
1341
1342 ret = vfs_s_lstat (vpath, buf);
1343 fish_set_blksize (buf);
1344 return ret;
1345 }
1346
1347
1348
1349 static int
1350 fish_fstat (void *vfs_info, struct stat *buf)
1351 {
1352 int ret;
1353
1354 ret = vfs_s_fstat (vfs_info, buf);
1355 fish_set_blksize (buf);
1356 return ret;
1357 }
1358
1359
1360
1361 static int
1362 fish_chmod (const vfs_path_t * vpath, mode_t mode)
1363 {
1364 const char *crpath;
1365 char *rpath;
1366 struct vfs_s_super *super;
1367 const vfs_path_element_t *path_element;
1368 int ret;
1369
1370 path_element = vfs_path_get_by_index (vpath, -1);
1371
1372 crpath = vfs_s_get_path (vpath, &super, 0);
1373 if (crpath == NULL)
1374 return -1;
1375
1376 rpath = strutils_shell_escape (crpath);
1377
1378 ret =
1379 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_chmod,
1380 "FISH_FILENAME=%s FISH_FILEMODE=%4.4o;\n", rpath,
1381 (unsigned int) (mode & 07777));
1382
1383 g_free (rpath);
1384
1385 return ret;;
1386 }
1387
1388
1389
1390 static int
1391 fish_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
1392 {
1393 char *sowner, *sgroup;
1394 struct passwd *pw;
1395 struct group *gr;
1396 const char *crpath;
1397 char *rpath;
1398 struct vfs_s_super *super;
1399 const vfs_path_element_t *path_element;
1400 int ret;
1401
1402 pw = getpwuid (owner);
1403 if (pw == NULL)
1404 return 0;
1405
1406 gr = getgrgid (group);
1407 if (gr == NULL)
1408 return 0;
1409
1410 sowner = pw->pw_name;
1411 sgroup = gr->gr_name;
1412
1413 path_element = vfs_path_get_by_index (vpath, -1);
1414
1415 crpath = vfs_s_get_path (vpath, &super, 0);
1416 if (crpath == NULL)
1417 return -1;
1418
1419 rpath = strutils_shell_escape (crpath);
1420
1421
1422 ret =
1423 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_chown,
1424 "FISH_FILENAME=%s FISH_FILEOWNER=%s FISH_FILEGROUP=%s;\n", rpath, sowner,
1425 sgroup);
1426
1427 g_free (rpath);
1428
1429 return ret;
1430 }
1431
1432
1433
1434 static void
1435 fish_get_atime (mc_timesbuf_t * times, time_t * sec, long *nsec)
1436 {
1437 #ifdef HAVE_UTIMENSAT
1438 *sec = (*times)[0].tv_sec;
1439 *nsec = (*times)[0].tv_nsec;
1440 #else
1441 *sec = times->actime;
1442 *nsec = 0;
1443 #endif
1444 }
1445
1446
1447
1448 static void
1449 fish_get_mtime (mc_timesbuf_t * times, time_t * sec, long *nsec)
1450 {
1451 #ifdef HAVE_UTIMENSAT
1452 *sec = (*times)[1].tv_sec;
1453 *nsec = (*times)[1].tv_nsec;
1454 #else
1455 *sec = times->modtime;
1456 *nsec = 0;
1457 #endif
1458 }
1459
1460
1461
1462 static int
1463 fish_utime (const vfs_path_t * vpath, mc_timesbuf_t * times)
1464 {
1465 char utcatime[16], utcmtime[16];
1466 char utcatime_w_nsec[30], utcmtime_w_nsec[30];
1467 time_t atime, mtime;
1468 long atime_nsec, mtime_nsec;
1469 struct tm *gmt;
1470 const char *crpath;
1471 char *rpath;
1472 struct vfs_s_super *super;
1473 const vfs_path_element_t *path_element;
1474 int ret;
1475
1476 path_element = vfs_path_get_by_index (vpath, -1);
1477
1478 crpath = vfs_s_get_path (vpath, &super, 0);
1479 if (crpath == NULL)
1480 return -1;
1481
1482 rpath = strutils_shell_escape (crpath);
1483
1484 fish_get_atime (times, &atime, &atime_nsec);
1485 gmt = gmtime (&atime);
1486 g_snprintf (utcatime, sizeof (utcatime), "%04d%02d%02d%02d%02d.%02d",
1487 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1488 gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
1489 g_snprintf (utcatime_w_nsec, sizeof (utcatime_w_nsec), "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
1490 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1491 gmt->tm_hour, gmt->tm_min, gmt->tm_sec, atime_nsec);
1492
1493 fish_get_mtime (times, &mtime, &mtime_nsec);
1494 gmt = gmtime (&mtime);
1495 g_snprintf (utcmtime, sizeof (utcmtime), "%04d%02d%02d%02d%02d.%02d",
1496 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1497 gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
1498 g_snprintf (utcmtime_w_nsec, sizeof (utcmtime_w_nsec), "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
1499 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1500 gmt->tm_hour, gmt->tm_min, gmt->tm_sec, mtime_nsec);
1501
1502 ret = fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_utime,
1503 "FISH_FILENAME=%s FISH_FILEATIME=%ld FISH_FILEMTIME=%ld "
1504 "FISH_TOUCHATIME=%s FISH_TOUCHMTIME=%s FISH_TOUCHATIME_W_NSEC=\"%s\" "
1505 "FISH_TOUCHMTIME_W_NSEC=\"%s\";\n", rpath, (long) atime, (long) mtime,
1506 utcatime, utcmtime, utcatime_w_nsec, utcmtime_w_nsec);
1507
1508 g_free (rpath);
1509
1510 return ret;
1511 }
1512
1513
1514
1515 static int
1516 fish_unlink (const vfs_path_t * vpath)
1517 {
1518 const char *crpath;
1519 char *rpath;
1520 struct vfs_s_super *super;
1521 const vfs_path_element_t *path_element;
1522 int ret;
1523
1524 path_element = vfs_path_get_by_index (vpath, -1);
1525
1526 crpath = vfs_s_get_path (vpath, &super, 0);
1527 if (crpath == NULL)
1528 return -1;
1529
1530 rpath = strutils_shell_escape (crpath);
1531
1532 ret =
1533 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_unlink,
1534 "FISH_FILENAME=%s;\n", rpath);
1535
1536 g_free (rpath);
1537
1538 return ret;
1539 }
1540
1541
1542
1543 static int
1544 fish_exists (const vfs_path_t * vpath)
1545 {
1546 const char *crpath;
1547 char *rpath;
1548 struct vfs_s_super *super;
1549 const vfs_path_element_t *path_element;
1550 int ret;
1551
1552 path_element = vfs_path_get_by_index (vpath, -1);
1553
1554 crpath = vfs_s_get_path (vpath, &super, 0);
1555 if (crpath == NULL)
1556 return -1;
1557
1558 rpath = strutils_shell_escape (crpath);
1559
1560 ret =
1561 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_exists,
1562 "FISH_FILENAME=%s;\n", rpath);
1563
1564 g_free (rpath);
1565
1566 return (ret == 0 ? 1 : 0);
1567 }
1568
1569
1570
1571 static int
1572 fish_mkdir (const vfs_path_t * vpath, mode_t mode)
1573 {
1574 const char *crpath;
1575 char *rpath;
1576 struct vfs_s_super *super;
1577 const vfs_path_element_t *path_element;
1578 int ret;
1579
1580 (void) mode;
1581
1582 path_element = vfs_path_get_by_index (vpath, -1);
1583
1584 crpath = vfs_s_get_path (vpath, &super, 0);
1585 if (crpath == NULL)
1586 return -1;
1587
1588 rpath = strutils_shell_escape (crpath);
1589
1590 ret =
1591 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_mkdir,
1592 "FISH_FILENAME=%s;\n", rpath);
1593 g_free (rpath);
1594
1595 if (ret != 0)
1596 return ret;
1597
1598 if (fish_exists (vpath) == 0)
1599 {
1600 path_element->class->verrno = EACCES;
1601 return -1;
1602 }
1603 return 0;
1604 }
1605
1606
1607
1608 static int
1609 fish_rmdir (const vfs_path_t * vpath)
1610 {
1611 const char *crpath;
1612 char *rpath;
1613 struct vfs_s_super *super;
1614 const vfs_path_element_t *path_element;
1615 int ret;
1616
1617 path_element = vfs_path_get_by_index (vpath, -1);
1618
1619 crpath = vfs_s_get_path (vpath, &super, 0);
1620 if (crpath == NULL)
1621 return -1;
1622
1623 rpath = strutils_shell_escape (crpath);
1624
1625 ret =
1626 fish_send_command (path_element->class, super, OPT_FLUSH, FISH_SUPER (super)->scr_rmdir,
1627 "FISH_FILENAME=%s;\n", rpath);
1628
1629 g_free (rpath);
1630
1631 return ret;
1632 }
1633
1634
1635
1636 static vfs_file_handler_t *
1637 fish_fh_new (struct vfs_s_inode *ino, gboolean changed)
1638 {
1639 fish_file_handler_t *fh;
1640
1641 fh = g_new0 (fish_file_handler_t, 1);
1642 vfs_s_init_fh (VFS_FILE_HANDLER (fh), ino, changed);
1643
1644 return VFS_FILE_HANDLER (fh);
1645 }
1646
1647
1648
1649 static int
1650 fish_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
1651 {
1652 fish_file_handler_t *fish = FISH_FILE_HANDLER (fh);
1653
1654 (void) mode;
1655
1656
1657 if (((flags & O_WRONLY) == O_WRONLY) && ((flags & (O_RDONLY | O_RDWR)) == 0))
1658 {
1659
1660 if ((flags & O_APPEND) != 0)
1661 fish->append = TRUE;
1662
1663 if (fh->ino->localname == NULL)
1664 {
1665 vfs_path_t *vpath;
1666 int tmp_handle;
1667
1668 tmp_handle = vfs_mkstemps (&vpath, me->name, fh->ino->ent->name);
1669 if (tmp_handle == -1)
1670 {
1671 vfs_path_free (vpath);
1672 goto fail;
1673 }
1674 fh->ino->localname = g_strdup (vfs_path_as_str (vpath));
1675 vfs_path_free (vpath);
1676 close (tmp_handle);
1677 }
1678 return 0;
1679 }
1680 if (fh->ino->localname == NULL && vfs_s_retrieve_file (me, fh->ino) == -1)
1681 goto fail;
1682 if (fh->ino->localname == NULL)
1683 vfs_die ("retrieve_file failed to fill in localname");
1684 return 0;
1685
1686 fail:
1687 return -1;
1688 }
1689
1690
1691
1692 static void
1693 fish_fill_names (struct vfs_class *me, fill_names_f func)
1694 {
1695 GList *iter;
1696
1697 for (iter = VFS_SUBCLASS (me)->supers; iter != NULL; iter = g_list_next (iter))
1698 {
1699 const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
1700
1701 char *name;
1702 char gbuf[10];
1703 const char *flags = "";
1704
1705 switch (super->path_element->port)
1706 {
1707 case FISH_FLAG_RSH:
1708 flags = ":r";
1709 break;
1710 case FISH_FLAG_COMPRESSED:
1711 flags = ":C";
1712 break;
1713 default:
1714 if (super->path_element->port > FISH_FLAG_RSH)
1715 {
1716 g_snprintf (gbuf, sizeof (gbuf), ":%d", super->path_element->port);
1717 flags = gbuf;
1718 }
1719 break;
1720 }
1721
1722 name =
1723 g_strconcat (vfs_fish_ops->prefix, VFS_PATH_URL_DELIMITER,
1724 super->path_element->user, "@", super->path_element->host, flags,
1725 PATH_SEP_STR, super->path_element->path, (char *) NULL);
1726 func (name);
1727 g_free (name);
1728 }
1729 }
1730
1731
1732
1733 static void *
1734 fish_open (const vfs_path_t * vpath, int flags, mode_t mode)
1735 {
1736
1737
1738
1739
1740 flags &= ~O_EXCL;
1741 return vfs_s_open (vpath, flags, mode);
1742 }
1743
1744
1745
1746
1747
1748 void
1749 vfs_init_fish (void)
1750 {
1751 tcp_init ();
1752
1753 vfs_init_subclass (&fish_subclass, "fish", VFSF_REMOTE | VFSF_USETMP, "sh");
1754 vfs_fish_ops->fill_names = fish_fill_names;
1755 vfs_fish_ops->stat = fish_stat;
1756 vfs_fish_ops->lstat = fish_lstat;
1757 vfs_fish_ops->fstat = fish_fstat;
1758 vfs_fish_ops->chmod = fish_chmod;
1759 vfs_fish_ops->chown = fish_chown;
1760 vfs_fish_ops->utime = fish_utime;
1761 vfs_fish_ops->open = fish_open;
1762 vfs_fish_ops->symlink = fish_symlink;
1763 vfs_fish_ops->link = fish_link;
1764 vfs_fish_ops->unlink = fish_unlink;
1765 vfs_fish_ops->rename = fish_rename;
1766 vfs_fish_ops->mkdir = fish_mkdir;
1767 vfs_fish_ops->rmdir = fish_rmdir;
1768 vfs_fish_ops->ctl = fish_ctl;
1769 fish_subclass.archive_same = fish_archive_same;
1770 fish_subclass.new_archive = fish_new_archive;
1771 fish_subclass.open_archive = fish_open_archive;
1772 fish_subclass.free_archive = fish_free_archive;
1773 fish_subclass.fh_new = fish_fh_new;
1774 fish_subclass.fh_open = fish_fh_open;
1775 fish_subclass.dir_load = fish_dir_load;
1776 fish_subclass.file_store = fish_file_store;
1777 fish_subclass.linear_start = fish_linear_start;
1778 fish_subclass.linear_read = fish_linear_read;
1779 fish_subclass.linear_close = fish_linear_close;
1780 vfs_register_class (vfs_fish_ops);
1781 }
1782
1783