1 /* guestfish - the filesystem interactive shell
2 * Copyright (C) 2010 Red Hat Inc.
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.
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.
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.
27 #include <sys/types.h>
32 #define MAX_DOWNLOAD_SIZE (16 * 1024 * 1024)
33 #define MAX_DOWNLOAD_SIZE_TEXT "16MB"
35 static off_t get_size (const char *filename);
38 run_hexedit (const char *cmd, size_t argc, char *argv[])
40 if (argc < 1 || argc > 3) {
41 fprintf (stderr, _("hexedit (device|filename) [max | start max]\n"));
45 const char *filename = argv[0];
46 off_t size = get_size (filename);
52 _("hexedit: %s is a zero length file or device\n"), filename);
59 if (argc == 1) { /* hexedit device */
60 /* Check we're not going to download a huge file. */
61 if (size > MAX_DOWNLOAD_SIZE) {
63 _("hexedit: %s is larger than %s. You must supply a limit using\n"
64 " 'hexedit %s <max>' (eg. 'hexedit %s 1M') or a range using\n"
65 " 'hexedit %s <start> <max>'.\n"),
66 filename, MAX_DOWNLOAD_SIZE_TEXT,
76 if (argc == 3) { /* hexedit device start max */
77 if (parse_size (argv[1], &start) == -1)
79 if (parse_size (argv[2], &max) == -1)
81 } else { /* hexedit device max */
83 if (parse_size (argv[1], &max) == -1)
87 if (start + max > size)
92 fprintf (stderr, _("hexedit: invalid range\n"));
96 /* Download the requested range from the remote file|device into a
97 * local temporary file.
101 struct stat oldstat, newstat;
103 TMP_TEMPLATE_ON_STACK (tmp);
104 int fd = mkstemp (tmp);
110 /* Choose an editor. */
111 editor = getenv ("HEXEDITOR");
115 snprintf (buf, sizeof buf, "/dev/fd/%d", fd);
117 if (guestfs_download_offset (g, filename, buf, start, max) == -1) {
123 if (close (fd) == -1) {
128 /* Get the old stat. */
129 if (stat (tmp, &oldstat) == -1) {
136 snprintf (buf, sizeof buf, "%s %s", editor, tmp);
145 /* Get the new stat. */
146 if (stat (tmp, &newstat) == -1) {
153 if (oldstat.st_ctime == newstat.st_ctime &&
154 oldstat.st_size == newstat.st_size) {
159 /* Write new content. */
160 if (guestfs_upload_offset (g, tmp, filename, start) == -1) {
169 /* Get the size of the file or block device. */
171 get_size (const char *filename)
175 if (STRPREFIX (filename, "/dev/")) {
176 size = guestfs_blockdev_getsize64 (g, filename);
181 size = guestfs_filesize (g, filename);
186 /* This case should be safe because we always compile with
187 * 64 bit file offsets.