Add 'realpath' command.
[libguestfs.git] / fish / alloc.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
28 #include "fish.h"
29
30 static int parse_size (const char *str, off_t *size_rtn);
31
32 int
33 do_alloc (const char *cmd, int argc, char *argv[])
34 {
35   off_t size;
36   int fd;
37
38   if (argc != 2) {
39     fprintf (stderr, _("use 'alloc file size' to create an image\n"));
40     return -1;
41   }
42
43   if (parse_size (argv[1], &size) == -1)
44     return -1;
45
46   if (!guestfs_is_config (g)) {
47     fprintf (stderr, _("can't allocate or add disks after launching\n"));
48     return -1;
49   }
50
51   fd = open (argv[0], O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666);
52   if (fd == -1) {
53     perror (argv[0]);
54     return -1;
55   }
56
57   if (posix_fallocate (fd, 0, size) == -1) {
58     perror ("fallocate");
59     close (fd);
60     unlink (argv[0]);
61     return -1;
62   }
63
64   if (close (fd) == -1) {
65     perror (argv[0]);
66     unlink (argv[0]);
67     return -1;
68   }
69
70   if (guestfs_add_drive (g, argv[0]) == -1) {
71     unlink (argv[0]);
72     return -1;
73   }
74
75   return 0;
76 }
77
78 static int
79 parse_size (const char *str, off_t *size_rtn)
80 {
81   uint64_t size;
82   char type;
83
84   /* Note that the parsing here is looser than what is specified in the
85    * help, but we may tighten it up in future so beware.
86    */
87   if (sscanf (str, "%"SCNu64"%c", &size, &type) == 2) {
88     switch (type) {
89     case 'k': case 'K': size *= 1024; break;
90     case 'm': case 'M': size *= 1024 * 1024; break;
91     case 'g': case 'G': size *= 1024 * 1024 * 1024; break;
92     case 's': size *= 512; break;
93     default:
94       fprintf (stderr, _("could not parse size specification '%s'\n"), str);
95       return -1;
96     }
97   }
98   else if (sscanf (str, "%"SCNu64, &size) == 1)
99     size *= 1024;
100   else {
101     fprintf (stderr, _("could not parse size specification '%s'\n"), str);
102     return -1;
103   }
104
105   /* XXX 32 bit file offsets, if anyone uses them?  GCC should give
106    * a warning here anyhow.
107    */
108   *size_rtn = size;
109
110   return 0;
111 }