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