generator: Don't use real uuidgen for UUIDs.
[libguestfs.git] / fish / edit.c
1 /* guestfish - the filesystem interactive shell
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <inttypes.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29
30 #include "fish.h"
31
32 /* guestfish edit command, suggested by Ján Ondrej, implemented by RWMJ */
33
34 int
35 do_edit (const char *cmd, int argc, char *argv[])
36 {
37   char filename[] = "/tmp/guestfishXXXXXX";
38   char buf[256];
39   const char *editor;
40   struct stat oldstat, newstat;
41   int r, fd;
42
43   if (argc != 1) {
44     fprintf (stderr, _("use '%s filename' to edit a file\n"), cmd);
45     return -1;
46   }
47
48   /* Choose an editor. */
49   if (STRCASEEQ (cmd, "vi"))
50     editor = "vi";
51   else if (STRCASEEQ (cmd, "emacs"))
52     editor = "emacs -nw";
53   else {
54     editor = getenv ("EDITOR");
55     if (editor == NULL)
56       editor = "vi"; /* could be cruel here and choose ed(1) */
57   }
58
59   /* Download the file and write it to a temporary. */
60   fd = mkstemp (filename);
61   if (fd == -1) {
62     perror ("mkstemp");
63     return -1;
64   }
65
66   snprintf (buf, sizeof buf, "/dev/fd/%d", fd);
67
68   if (guestfs_download (g, argv[0], buf) == -1) {
69     close (fd);
70     unlink (filename);
71     return -1;
72   }
73
74   if (close (fd) == -1) {
75     perror (filename);
76     unlink (filename);
77     return -1;
78   }
79
80   /* Get the old stat. */
81   if (stat (filename, &oldstat) == -1) {
82     perror (filename);
83     unlink (filename);
84     return -1;
85   }
86
87   /* Edit it. */
88   /* XXX Safe? */
89   snprintf (buf, sizeof buf, "%s %s", editor, filename);
90
91   r = system (buf);
92   if (r != 0) {
93     perror (buf);
94     unlink (filename);
95     return -1;
96   }
97
98   /* Get the new stat. */
99   if (stat (filename, &newstat) == -1) {
100     perror (filename);
101     unlink (filename);
102     return -1;
103   }
104
105   /* Changed? */
106   if (oldstat.st_ctime == newstat.st_ctime &&
107       oldstat.st_size == newstat.st_size) {
108     unlink (filename);
109     return 0;
110   }
111
112   /* Write new content. */
113   if (guestfs_upload (g, filename, argv[0]) == -1) {
114     unlink (filename);
115     return -1;
116   }
117
118   unlink (filename);
119   return 0;
120 }