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