Handle Enter/Escape keys in message dialog.
[helenos.git] / uspace / app / bdsh / cmds / modules / mkfile / mkfile.c
blob146afb2d4295bbdde2efd9c3ee324d13b486807e
1 /*
2 * Copyright (c) 2009 Jiri Svoboda
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <str_error.h>
34 #include <dirent.h>
35 #include <macros.h>
36 #include <getopt.h>
37 #include <stdarg.h>
38 #include <str.h>
39 #include <ctype.h>
40 #include <vfs/vfs.h>
42 #include "config.h"
43 #include "errors.h"
44 #include "util.h"
45 #include "entry.h"
46 #include "mkfile.h"
47 #include "cmds.h"
49 /** Number of bytes to write at a time */
50 #define BUFFER_SIZE 16384
52 static const char *cmdname = "mkfile";
54 static struct option const long_options[] = {
55 { "size", required_argument, 0, 's' },
56 { "sparse", no_argument, 0, 'p' },
57 { "help", no_argument, 0, 'h' },
58 { 0, 0, 0, 0 }
61 void help_cmd_mkfile(unsigned int level)
63 if (level == HELP_SHORT) {
64 printf("`%s' creates a new zero-filled file\n", cmdname);
65 } else {
66 help_cmd_mkfile(HELP_SHORT);
67 printf(
68 "Usage: %s [options] <path>\n"
69 "Options:\n"
70 " -h, --help A short option summary\n"
71 " -s, --size sz Size of the file\n"
72 " -p, --sparse Create a sparse file\n"
73 "\n"
74 "Size is a number followed by 'k', 'm' or 'g' for kB, MB, GB.\n"
75 "E.g. 100k, 2m, 1g.\n",
76 cmdname);
79 return;
82 /** Parse size specification.
84 * Size specification is in the form <decimal_number><unit> where
85 * <unit> is 'k', 'm' or 'g' for kB, MB, GB.
87 * @param str String containing the size specification.
88 * @param rsize Place to store size in bytes
89 * @return EOK on success or an error code
91 static errno_t read_size(const char *str, size_t *rsize)
93 size_t number, unit;
94 char *ep;
96 number = strtol(str, &ep, 10);
97 if (ep[0] == '\0') {
98 *rsize = number;
99 return EOK;
102 if (ep[1] != '\0')
103 return EINVAL;
105 switch (tolower(ep[0])) {
106 case 'k':
107 unit = 1024;
108 break;
109 case 'm':
110 unit = 1024 * 1024;
111 break;
112 case 'g':
113 unit = 1024 * 1024 * 1024;
114 break;
115 default:
116 return EINVAL;
119 *rsize = number * unit;
120 return EOK;
123 int cmd_mkfile(char **argv)
125 unsigned int argc;
126 int c, opt_ind;
127 int fd;
128 size_t file_size;
129 size_t total_written;
130 size_t to_write;
131 size_t nwritten;
132 errno_t rc;
133 char *file_name;
134 void *buffer;
135 bool create_sparse = false;
136 aoff64_t pos = 0;
138 file_size = 0;
140 argc = cli_count_args(argv);
142 c = 0;
143 optreset = 1;
144 optind = 0;
145 opt_ind = 0;
147 while (c != -1) {
148 c = getopt_long(argc, argv, "ps:h", long_options, &opt_ind);
149 switch (c) {
150 case 'h':
151 help_cmd_mkfile(HELP_LONG);
152 return CMD_SUCCESS;
153 case 'p':
154 create_sparse = true;
155 break;
156 case 's':
157 rc = read_size(optarg, &file_size);
158 if (rc != EOK) {
159 printf("%s: Invalid file size specification.\n",
160 cmdname);
161 return CMD_FAILURE;
163 break;
167 argc -= optind;
169 if (argc != 1) {
170 printf("%s: incorrect number of arguments. Try `%s --help'\n",
171 cmdname, cmdname);
172 return CMD_FAILURE;
175 file_name = argv[optind];
177 rc = vfs_lookup_open(file_name, WALK_REGULAR | WALK_MUST_CREATE, MODE_WRITE, &fd);
178 if (rc != EOK) {
179 printf("%s: failed to create file %s.\n", cmdname, file_name);
180 return CMD_FAILURE;
183 if (create_sparse && file_size > 0) {
184 const char byte = 0x00;
186 pos = file_size - 1;
187 rc = vfs_write(fd, &pos, &byte, sizeof(char), &nwritten);
188 if (rc != EOK) {
189 vfs_put(fd);
190 goto error;
192 return CMD_SUCCESS;
195 buffer = calloc(BUFFER_SIZE, 1);
196 if (buffer == NULL) {
197 printf("%s: Error, out of memory.\n", cmdname);
198 return CMD_FAILURE;
201 total_written = 0;
202 while (total_written < file_size) {
203 to_write = min(file_size - total_written, BUFFER_SIZE);
204 rc = vfs_write(fd, &pos, buffer, to_write, &nwritten);
205 if (rc != EOK) {
206 printf("%s: Error writing file (%s).\n", cmdname, str_error(rc));
207 vfs_put(fd);
208 free(buffer);
209 return CMD_FAILURE;
211 total_written += nwritten;
214 free(buffer);
216 rc = vfs_put(fd);
217 if (rc != EOK)
218 goto error;
220 return CMD_SUCCESS;
221 error:
222 printf("%s: Error writing file (%s).\n", cmdname, str_error(rc));
223 return CMD_FAILURE;