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