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_get_atime
- shell_get_mtime
- 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/strescape.h"
64 #include "lib/unixcompat.h"
65 #include "lib/fileloc.h"
66 #include "lib/util.h"
67 #include "lib/mcconfig.h"
68
69 #include "src/execute.h"
70
71 #include "lib/vfs/vfs.h"
72 #include "lib/vfs/utilvfs.h"
73 #include "lib/vfs/netutil.h"
74 #include "lib/vfs/xdirentry.h"
75 #include "lib/vfs/gc.h"
76
77 #include "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 = 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 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 = strutils_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 = strutils_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 = strutils_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 if (vfs_parse_filedate (0, &ST.st_ctime) == 0)
864 break;
865 ST.st_atime = ST.st_mtime = ST.st_ctime;
866 #ifdef HAVE_STRUCT_STAT_ST_MTIM
867 ST.st_atim.tv_nsec = ST.st_mtim.tv_nsec = ST.st_ctim.tv_nsec = 0;
868 #endif
869 break;
870
871 case 'D':
872 {
873 struct tm tim;
874
875 memset (&tim, 0, sizeof (tim));
876
877 if (sscanf (buffer, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon,
878 &tim.tm_mday, &tim.tm_hour, &tim.tm_min, &tim.tm_sec) != 6)
879 break;
880 ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim);
881 #ifdef HAVE_STRUCT_STAT_ST_MTIM
882 ST.st_atim.tv_nsec = ST.st_mtim.tv_nsec = ST.st_ctim.tv_nsec = 0;
883 #endif
884 }
885 break;
886
887 case 'E':
888 {
889 int maj, min;
890
891
892 if (sscanf (buffer, "%d,%d", &maj, &min) != 2)
893 break;
894 #ifdef HAVE_STRUCT_STAT_ST_RDEV
895 ST.st_rdev = makedev (maj, min);
896 #endif
897 }
898 break;
899
900 default:
901 break;
902 }
903
904 #undef ST
905 }
906
907
908
909 static int
910 shell_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, const char *remote_path)
911 {
912 struct vfs_s_super *super = dir->super;
913 char buffer[BUF_8K] = "\0";
914 struct vfs_s_entry *ent = NULL;
915 char *quoted_path;
916 int reply_code;
917
918
919
920
921 #if 0
922 if (me->logfile == NULL)
923 me->logfile = fopen ("/tmp/mc-SHELL.sh", "w");
924 #endif
925
926 vfs_print_message (_("shell: Reading directory %s..."), remote_path);
927
928 dir->timestamp = g_get_monotonic_time () + shell_directory_timeout * G_USEC_PER_SEC;
929
930 quoted_path = strutils_shell_escape (remote_path);
931 (void) shell_command_v (me, super, NONE, SHELL_SUPER (super)->scr_ls, "SHELL_FILENAME=%s;\n",
932 quoted_path);
933 g_free (quoted_path);
934
935 ent = vfs_s_generate_entry (me, NULL, dir, 0);
936
937 while (TRUE)
938 {
939 int res;
940
941 res =
942 vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SHELL_SUPER (super)->sockr);
943
944 if ((res == 0) || (res == EINTR))
945 {
946 vfs_s_free_entry (me, ent);
947 me->verrno = ECONNRESET;
948 goto error;
949 }
950 if (me->logfile != NULL)
951 {
952 fputs (buffer, me->logfile);
953 fputs ("\n", me->logfile);
954 fflush (me->logfile);
955 }
956 if (strncmp (buffer, "### ", 4) == 0)
957 break;
958
959 if (buffer[0] != '\0')
960 shell_parse_ls (buffer, ent);
961 else if (ent->name != NULL)
962 {
963 vfs_s_insert_entry (me, dir, ent);
964 ent = vfs_s_generate_entry (me, NULL, dir, 0);
965 }
966 }
967
968 vfs_s_free_entry (me, ent);
969 reply_code = shell_decode_reply (buffer + 4, 0);
970 if (reply_code == COMPLETE)
971 {
972 vfs_print_message (_("%s: done."), me->name);
973 return 0;
974 }
975
976 me->verrno = reply_code == ERROR ? EACCES : E_REMOTE;
977
978 error:
979 vfs_print_message (_("%s: failure"), me->name);
980 return -1;
981 }
982
983
984
985 static int
986 shell_file_store (struct vfs_class *me, vfs_file_handler_t * fh, char *name, char *localname)
987 {
988 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
989 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
990 shell_super_t *shell_super = SHELL_SUPER (super);
991 int code;
992 off_t total = 0;
993 char buffer[BUF_8K];
994 struct stat s;
995 int h;
996 char *quoted_name;
997
998 h = open (localname, O_RDONLY);
999 if (h == -1)
1000 ERRNOR (EIO, -1);
1001 if (fstat (h, &s) < 0)
1002 {
1003 close (h);
1004 ERRNOR (EIO, -1);
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
1034
1035
1036 quoted_name = strutils_shell_escape (name);
1037 vfs_print_message (_("shell: store %s: sending command..."), quoted_name);
1038
1039
1040 code =
1041 shell_command_v (me, super, WAIT_REPLY,
1042 shell->append ? shell_super->scr_append : shell_super->scr_send,
1043 "SHELL_FILENAME=%s SHELL_FILESIZE=%" PRIuMAX ";\n", quoted_name,
1044 (uintmax_t) s.st_size);
1045 g_free (quoted_name);
1046
1047 if (code != PRELIM)
1048 {
1049 close (h);
1050 ERRNOR (E_REMOTE, -1);
1051 }
1052
1053 while (TRUE)
1054 {
1055 ssize_t n, t;
1056
1057 while ((n = read (h, buffer, sizeof (buffer))) < 0)
1058 {
1059 if ((errno == EINTR) && tty_got_interrupt ())
1060 continue;
1061 vfs_print_message ("%s", _("shell: Local read failed, sending zeros"));
1062 close (h);
1063 h = open ("/dev/zero", O_RDONLY);
1064 }
1065
1066 if (n == 0)
1067 break;
1068
1069 t = write (shell_super->sockw, buffer, n);
1070 if (t != n)
1071 {
1072 if (t == -1)
1073 me->verrno = errno;
1074 else
1075 me->verrno = EIO;
1076 goto error_return;
1077 }
1078 tty_disable_interrupt_key ();
1079 total += n;
1080 vfs_print_message ("%s: %" PRIuMAX "/%" PRIuMAX, _("shell: storing file"),
1081 (uintmax_t) total, (uintmax_t) s.st_size);
1082 }
1083 close (h);
1084
1085 if (shell_get_reply (me, shell_super->sockr, NULL, 0) != COMPLETE)
1086 ERRNOR (E_REMOTE, -1);
1087 return 0;
1088
1089 error_return:
1090 close (h);
1091 shell_get_reply (me, shell_super->sockr, NULL, 0);
1092 return -1;
1093 }
1094
1095
1096
1097 static int
1098 shell_linear_start (struct vfs_class *me, vfs_file_handler_t * fh, off_t offset)
1099 {
1100 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1101 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1102 char *name;
1103 char *quoted_name;
1104
1105 name = vfs_s_fullpath (me, fh->ino);
1106 if (name == NULL)
1107 return 0;
1108 quoted_name = strutils_shell_escape (name);
1109 g_free (name);
1110 shell->append = FALSE;
1111
1112
1113
1114
1115
1116
1117
1118
1119 offset =
1120 shell_command_v (me, super, WANT_STRING, SHELL_SUPER (super)->scr_get,
1121 "SHELL_FILENAME=%s SHELL_START_OFFSET=%" PRIuMAX ";\n", quoted_name,
1122 (uintmax_t) offset);
1123 g_free (quoted_name);
1124
1125 if (offset != PRELIM)
1126 ERRNOR (E_REMOTE, 0);
1127 fh->linear = LS_LINEAR_OPEN;
1128 shell->got = 0;
1129 errno = 0;
1130 #if SIZEOF_OFF_T == SIZEOF_LONG
1131 shell->total = (off_t) strtol (reply_str, NULL, 10);
1132 #else
1133 shell->total = (off_t) g_ascii_strtoll (reply_str, NULL, 10);
1134 #endif
1135 if (errno != 0)
1136 ERRNOR (E_REMOTE, 0);
1137 return 1;
1138 }
1139
1140
1141
1142 static void
1143 shell_linear_abort (struct vfs_class *me, vfs_file_handler_t * fh)
1144 {
1145 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1146 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1147 char buffer[BUF_8K];
1148 ssize_t n;
1149
1150 vfs_print_message ("%s", _("Aborting transfer..."));
1151
1152 do
1153 {
1154 n = MIN ((off_t) sizeof (buffer), (shell->total - shell->got));
1155 if (n != 0)
1156 {
1157 n = read (SHELL_SUPER (super)->sockr, buffer, n);
1158 if (n < 0)
1159 return;
1160 shell->got += n;
1161 }
1162 }
1163 while (n != 0);
1164
1165 if (shell_get_reply (me, SHELL_SUPER (super)->sockr, NULL, 0) != COMPLETE)
1166 vfs_print_message ("%s", _("Error reported after abort."));
1167 else
1168 vfs_print_message ("%s", _("Aborted transfer would be successful."));
1169 }
1170
1171
1172
1173 static ssize_t
1174 shell_linear_read (struct vfs_class *me, vfs_file_handler_t * fh, void *buf, size_t len)
1175 {
1176 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1177 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1178 ssize_t n = 0;
1179
1180 len = MIN ((size_t) (shell->total - shell->got), len);
1181 tty_disable_interrupt_key ();
1182 while (len != 0 && ((n = read (SHELL_SUPER (super)->sockr, buf, len)) < 0))
1183 {
1184 if ((errno == EINTR) && !tty_got_interrupt ())
1185 continue;
1186 break;
1187 }
1188 tty_enable_interrupt_key ();
1189
1190 if (n > 0)
1191 shell->got += n;
1192 else if (n < 0)
1193 shell_linear_abort (me, fh);
1194 else if (shell_get_reply (me, SHELL_SUPER (super)->sockr, NULL, 0) != COMPLETE)
1195 ERRNOR (E_REMOTE, -1);
1196 ERRNOR (errno, n);
1197 }
1198
1199
1200
1201 static void
1202 shell_linear_close (struct vfs_class *me, vfs_file_handler_t * fh)
1203 {
1204 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1205
1206 if (shell->total != shell->got)
1207 shell_linear_abort (me, fh);
1208 }
1209
1210
1211
1212 static int
1213 shell_ctl (void *fh, int ctlop, void *arg)
1214 {
1215 (void) arg;
1216 (void) fh;
1217 (void) ctlop;
1218
1219 return 0;
1220
1221 #if 0
1222 switch (ctlop)
1223 {
1224 case VFS_CTL_IS_NOTREADY:
1225 {
1226 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1227 int v;
1228
1229 if (file->linear == LS_NOT_LINEAR)
1230 vfs_die ("You may not do this");
1231 if (file->linear == LS_LINEAR_CLOSED || file->linear == LS_LINEAR_PREOPEN)
1232 return 0;
1233
1234 v = vfs_s_select_on_two (VFS_FILE_HANDLER_SUPER (fh)->u.shell.sockr, 0);
1235
1236 return (((v < 0) && (errno == EINTR)) || v == 0) ? 1 : 0;
1237 }
1238 default:
1239 return 0;
1240 }
1241 #endif
1242 }
1243
1244
1245
1246 static int
1247 shell_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
1248 {
1249 const char *crpath1, *crpath2;
1250 char *rpath1, *rpath2;
1251 struct vfs_s_super *super, *super2;
1252 struct vfs_class *me;
1253 int ret;
1254
1255 crpath1 = vfs_s_get_path (vpath1, &super, 0);
1256 if (crpath1 == NULL)
1257 return -1;
1258
1259 crpath2 = vfs_s_get_path (vpath2, &super2, 0);
1260 if (crpath2 == NULL)
1261 return -1;
1262
1263 rpath1 = strutils_shell_escape (crpath1);
1264 rpath2 = strutils_shell_escape (crpath2);
1265
1266 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath1));
1267
1268 ret =
1269 shell_send_command (me, super2, OPT_FLUSH, SHELL_SUPER (super)->scr_mv,
1270 "SHELL_FILEFROM=%s SHELL_FILETO=%s;\n", rpath1, rpath2);
1271
1272 g_free (rpath1);
1273 g_free (rpath2);
1274
1275 return ret;
1276 }
1277
1278
1279
1280 static int
1281 shell_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
1282 {
1283 const char *crpath1, *crpath2;
1284 char *rpath1, *rpath2;
1285 struct vfs_s_super *super, *super2;
1286 struct vfs_class *me;
1287 int ret;
1288
1289 crpath1 = vfs_s_get_path (vpath1, &super, 0);
1290 if (crpath1 == NULL)
1291 return -1;
1292
1293 crpath2 = vfs_s_get_path (vpath2, &super2, 0);
1294 if (crpath2 == NULL)
1295 return -1;
1296
1297 rpath1 = strutils_shell_escape (crpath1);
1298 rpath2 = strutils_shell_escape (crpath2);
1299
1300 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath1));
1301
1302 ret =
1303 shell_send_command (me, super2, OPT_FLUSH, SHELL_SUPER (super)->scr_hardlink,
1304 "SHELL_FILEFROM=%s SHELL_FILETO=%s;\n", rpath1, rpath2);
1305
1306 g_free (rpath1);
1307 g_free (rpath2);
1308
1309 return ret;
1310 }
1311
1312
1313
1314 static int
1315 shell_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
1316 {
1317 char *qsetto;
1318 const char *crpath;
1319 char *rpath;
1320 struct vfs_s_super *super;
1321 struct vfs_class *me;
1322 int ret;
1323
1324 crpath = vfs_s_get_path (vpath2, &super, 0);
1325 if (crpath == NULL)
1326 return -1;
1327
1328 rpath = strutils_shell_escape (crpath);
1329 qsetto = strutils_shell_escape (vfs_path_get_last_path_str (vpath1));
1330
1331 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath2));
1332
1333 ret =
1334 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_ln,
1335 "SHELL_FILEFROM=%s SHELL_FILETO=%s;\n", qsetto, rpath);
1336
1337 g_free (qsetto);
1338 g_free (rpath);
1339
1340 return ret;
1341 }
1342
1343
1344
1345 static int
1346 shell_stat (const vfs_path_t * vpath, struct stat *buf)
1347 {
1348 int ret;
1349
1350 ret = vfs_s_stat (vpath, buf);
1351 shell_set_blksize (buf);
1352 return ret;
1353 }
1354
1355
1356
1357 static int
1358 shell_lstat (const vfs_path_t * vpath, struct stat *buf)
1359 {
1360 int ret;
1361
1362 ret = vfs_s_lstat (vpath, buf);
1363 shell_set_blksize (buf);
1364 return ret;
1365 }
1366
1367
1368
1369 static int
1370 shell_fstat (void *vfs_info, struct stat *buf)
1371 {
1372 int ret;
1373
1374 ret = vfs_s_fstat (vfs_info, buf);
1375 shell_set_blksize (buf);
1376 return ret;
1377 }
1378
1379
1380
1381 static int
1382 shell_chmod (const vfs_path_t * vpath, mode_t mode)
1383 {
1384 const char *crpath;
1385 char *rpath;
1386 struct vfs_s_super *super;
1387 struct vfs_class *me;
1388 int ret;
1389
1390 crpath = vfs_s_get_path (vpath, &super, 0);
1391 if (crpath == NULL)
1392 return -1;
1393
1394 rpath = strutils_shell_escape (crpath);
1395
1396 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1397
1398 ret =
1399 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_chmod,
1400 "SHELL_FILENAME=%s SHELL_FILEMODE=%4.4o;\n", rpath,
1401 (unsigned int) (mode & 07777));
1402
1403 g_free (rpath);
1404
1405 return ret;;
1406 }
1407
1408
1409
1410 static int
1411 shell_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
1412 {
1413 char *sowner, *sgroup;
1414 struct passwd *pw;
1415 struct group *gr;
1416 const char *crpath;
1417 char *rpath;
1418 struct vfs_s_super *super;
1419 struct vfs_class *me;
1420 int ret;
1421
1422 pw = getpwuid (owner);
1423 if (pw == NULL)
1424 return 0;
1425
1426 gr = getgrgid (group);
1427 if (gr == NULL)
1428 return 0;
1429
1430 sowner = pw->pw_name;
1431 sgroup = gr->gr_name;
1432
1433 crpath = vfs_s_get_path (vpath, &super, 0);
1434 if (crpath == NULL)
1435 return -1;
1436
1437 rpath = strutils_shell_escape (crpath);
1438
1439 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1440
1441
1442 ret =
1443 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_chown,
1444 "SHELL_FILENAME=%s SHELL_FILEOWNER=%s SHELL_FILEGROUP=%s;\n", rpath,
1445 sowner, sgroup);
1446
1447 g_free (rpath);
1448
1449 return ret;
1450 }
1451
1452
1453
1454 static void
1455 shell_get_atime (mc_timesbuf_t * times, time_t * sec, long *nsec)
1456 {
1457 #ifdef HAVE_UTIMENSAT
1458 *sec = (*times)[0].tv_sec;
1459 *nsec = (*times)[0].tv_nsec;
1460 #else
1461 *sec = times->actime;
1462 *nsec = 0;
1463 #endif
1464 }
1465
1466
1467
1468 static void
1469 shell_get_mtime (mc_timesbuf_t * times, time_t * sec, long *nsec)
1470 {
1471 #ifdef HAVE_UTIMENSAT
1472 *sec = (*times)[1].tv_sec;
1473 *nsec = (*times)[1].tv_nsec;
1474 #else
1475 *sec = times->modtime;
1476 *nsec = 0;
1477 #endif
1478 }
1479
1480
1481
1482 static int
1483 shell_utime (const vfs_path_t * vpath, mc_timesbuf_t * times)
1484 {
1485 char utcatime[16], utcmtime[16];
1486 char utcatime_w_nsec[30], utcmtime_w_nsec[30];
1487 time_t atime, mtime;
1488 long atime_nsec, mtime_nsec;
1489 struct tm *gmt;
1490 const char *crpath;
1491 char *rpath;
1492 struct vfs_s_super *super;
1493 struct vfs_class *me;
1494 int ret;
1495
1496 crpath = vfs_s_get_path (vpath, &super, 0);
1497 if (crpath == NULL)
1498 return -1;
1499
1500 rpath = strutils_shell_escape (crpath);
1501
1502 shell_get_atime (times, &atime, &atime_nsec);
1503 gmt = gmtime (&atime);
1504 g_snprintf (utcatime, sizeof (utcatime), "%04d%02d%02d%02d%02d.%02d",
1505 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1506 gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
1507 g_snprintf (utcatime_w_nsec, sizeof (utcatime_w_nsec), "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
1508 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1509 gmt->tm_hour, gmt->tm_min, gmt->tm_sec, atime_nsec);
1510
1511 shell_get_mtime (times, &mtime, &mtime_nsec);
1512 gmt = gmtime (&mtime);
1513 g_snprintf (utcmtime, sizeof (utcmtime), "%04d%02d%02d%02d%02d.%02d",
1514 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1515 gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
1516 g_snprintf (utcmtime_w_nsec, sizeof (utcmtime_w_nsec), "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
1517 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
1518 gmt->tm_hour, gmt->tm_min, gmt->tm_sec, mtime_nsec);
1519
1520 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1521
1522 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_utime,
1523 "SHELL_FILENAME=%s SHELL_FILEATIME=%ld SHELL_FILEMTIME=%ld "
1524 "SHELL_TOUCHATIME=%s SHELL_TOUCHMTIME=%s SHELL_TOUCHATIME_W_NSEC=\"%s\" "
1525 "SHELL_TOUCHMTIME_W_NSEC=\"%s\";\n", rpath, (long) atime,
1526 (long) mtime, utcatime, utcmtime, utcatime_w_nsec, utcmtime_w_nsec);
1527
1528 g_free (rpath);
1529
1530 return ret;
1531 }
1532
1533
1534
1535 static int
1536 shell_unlink (const vfs_path_t * vpath)
1537 {
1538 const char *crpath;
1539 char *rpath;
1540 struct vfs_s_super *super;
1541 struct vfs_class *me;
1542 int ret;
1543
1544 crpath = vfs_s_get_path (vpath, &super, 0);
1545 if (crpath == NULL)
1546 return -1;
1547
1548 rpath = strutils_shell_escape (crpath);
1549
1550 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1551
1552 ret =
1553 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_unlink,
1554 "SHELL_FILENAME=%s;\n", rpath);
1555
1556 g_free (rpath);
1557
1558 return ret;
1559 }
1560
1561
1562
1563 static int
1564 shell_exists (const vfs_path_t * vpath)
1565 {
1566 const char *crpath;
1567 char *rpath;
1568 struct vfs_s_super *super;
1569 struct vfs_class *me;
1570 int ret;
1571
1572 crpath = vfs_s_get_path (vpath, &super, 0);
1573 if (crpath == NULL)
1574 return -1;
1575
1576 rpath = strutils_shell_escape (crpath);
1577
1578 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1579
1580 ret =
1581 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_exists,
1582 "SHELL_FILENAME=%s;\n", rpath);
1583
1584 g_free (rpath);
1585
1586 return (ret == 0 ? 1 : 0);
1587 }
1588
1589
1590
1591 static int
1592 shell_mkdir (const vfs_path_t * vpath, mode_t mode)
1593 {
1594 const char *crpath;
1595 char *rpath;
1596 struct vfs_s_super *super;
1597 struct vfs_class *me;
1598 int ret;
1599
1600 (void) mode;
1601
1602 crpath = vfs_s_get_path (vpath, &super, 0);
1603 if (crpath == NULL)
1604 return -1;
1605
1606 rpath = strutils_shell_escape (crpath);
1607
1608 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1609
1610 ret =
1611 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_mkdir,
1612 "SHELL_FILENAME=%s;\n", rpath);
1613 g_free (rpath);
1614
1615 if (ret != 0)
1616 return ret;
1617
1618 if (shell_exists (vpath) == 0)
1619 {
1620 me->verrno = EACCES;
1621 return -1;
1622 }
1623 return 0;
1624 }
1625
1626
1627
1628 static int
1629 shell_rmdir (const vfs_path_t * vpath)
1630 {
1631 const char *crpath;
1632 char *rpath;
1633 struct vfs_s_super *super;
1634 struct vfs_class *me;
1635 int ret;
1636
1637 crpath = vfs_s_get_path (vpath, &super, 0);
1638 if (crpath == NULL)
1639 return -1;
1640
1641 rpath = strutils_shell_escape (crpath);
1642
1643 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1644
1645 ret =
1646 shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_rmdir,
1647 "SHELL_FILENAME=%s;\n", rpath);
1648
1649 g_free (rpath);
1650
1651 return ret;
1652 }
1653
1654
1655
1656 static vfs_file_handler_t *
1657 shell_fh_new (struct vfs_s_inode *ino, gboolean changed)
1658 {
1659 shell_file_handler_t *fh;
1660
1661 fh = g_new0 (shell_file_handler_t, 1);
1662 vfs_s_init_fh (VFS_FILE_HANDLER (fh), ino, changed);
1663
1664 return VFS_FILE_HANDLER (fh);
1665 }
1666
1667
1668
1669 static int
1670 shell_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
1671 {
1672 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1673
1674 (void) mode;
1675
1676
1677 if (((flags & O_WRONLY) == O_WRONLY) && ((flags & (O_RDONLY | O_RDWR)) == 0))
1678 {
1679
1680 if ((flags & O_APPEND) != 0)
1681 shell->append = TRUE;
1682
1683 if (fh->ino->localname == NULL)
1684 {
1685 vfs_path_t *vpath = NULL;
1686 int tmp_handle;
1687
1688 tmp_handle = vfs_mkstemps (&vpath, me->name, fh->ino->ent->name);
1689 if (tmp_handle == -1)
1690 return (-1);
1691
1692 fh->ino->localname = vfs_path_free (vpath, FALSE);
1693 close (tmp_handle);
1694 }
1695 return 0;
1696 }
1697
1698 if (fh->ino->localname == NULL && vfs_s_retrieve_file (me, fh->ino) == -1)
1699 return (-1);
1700
1701 if (fh->ino->localname == NULL)
1702 vfs_die ("retrieve_file failed to fill in localname");
1703 return 0;
1704 }
1705
1706
1707
1708 static void
1709 shell_fill_names (struct vfs_class *me, fill_names_f func)
1710 {
1711 GList *iter;
1712
1713 for (iter = VFS_SUBCLASS (me)->supers; iter != NULL; iter = g_list_next (iter))
1714 {
1715 const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
1716
1717 char *name;
1718 char gbuf[10];
1719 const char *flags = "";
1720
1721 switch (super->path_element->port)
1722 {
1723 case SHELL_FLAG_RSH:
1724 flags = ":r";
1725 break;
1726 case SHELL_FLAG_COMPRESSED:
1727 flags = ":C";
1728 break;
1729 default:
1730 if (super->path_element->port > SHELL_FLAG_RSH)
1731 {
1732 g_snprintf (gbuf, sizeof (gbuf), ":%d", super->path_element->port);
1733 flags = gbuf;
1734 }
1735 break;
1736 }
1737
1738 name =
1739 g_strconcat (vfs_shell_ops->prefix, VFS_PATH_URL_DELIMITER,
1740 super->path_element->user, "@", super->path_element->host, flags,
1741 PATH_SEP_STR, super->path_element->path, (char *) NULL);
1742 func (name);
1743 g_free (name);
1744 }
1745 }
1746
1747
1748
1749 static void *
1750 shell_open (const vfs_path_t * vpath, int flags, mode_t mode)
1751 {
1752
1753
1754
1755
1756 flags &= ~O_EXCL;
1757 return vfs_s_open (vpath, flags, mode);
1758 }
1759
1760
1761
1762
1763
1764 void
1765 vfs_init_shell (void)
1766 {
1767 tcp_init ();
1768
1769 vfs_init_subclass (&shell_subclass, "shell", VFSF_REMOTE | VFSF_USETMP, "sh");
1770 vfs_shell_ops->fill_names = shell_fill_names;
1771 vfs_shell_ops->stat = shell_stat;
1772 vfs_shell_ops->lstat = shell_lstat;
1773 vfs_shell_ops->fstat = shell_fstat;
1774 vfs_shell_ops->chmod = shell_chmod;
1775 vfs_shell_ops->chown = shell_chown;
1776 vfs_shell_ops->utime = shell_utime;
1777 vfs_shell_ops->open = shell_open;
1778 vfs_shell_ops->symlink = shell_symlink;
1779 vfs_shell_ops->link = shell_link;
1780 vfs_shell_ops->unlink = shell_unlink;
1781 vfs_shell_ops->rename = shell_rename;
1782 vfs_shell_ops->mkdir = shell_mkdir;
1783 vfs_shell_ops->rmdir = shell_rmdir;
1784 vfs_shell_ops->ctl = shell_ctl;
1785 shell_subclass.archive_same = shell_archive_same;
1786 shell_subclass.new_archive = shell_new_archive;
1787 shell_subclass.open_archive = shell_open_archive;
1788 shell_subclass.free_archive = shell_free_archive;
1789 shell_subclass.fh_new = shell_fh_new;
1790 shell_subclass.fh_open = shell_fh_open;
1791 shell_subclass.dir_load = shell_dir_load;
1792 shell_subclass.file_store = shell_file_store;
1793 shell_subclass.linear_start = shell_linear_start;
1794 shell_subclass.linear_read = shell_linear_read;
1795 shell_subclass.linear_close = shell_linear_close;
1796 vfs_register_class (vfs_shell_ops);
1797 }
1798
1799