source: mainline/uspace/app/bdsh/cmds/modules/mkfile/mkfile.c@ 200b03c9

Last change on this file since 200b03c9 was 200b03c9, checked in by Miroslav Cimerman <mc@…>, 5 months ago

mkfile: use DATA_XFER_LIMIT

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*
2 * Copyright (c) 2009 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29#include <abi/ipc/ipc.h>
30#include <errno.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <stdint.h>
34#include <str_error.h>
35#include <dirent.h>
36#include <macros.h>
37#include <getopt.h>
38#include <stdarg.h>
39#include <str.h>
40#include <ctype.h>
41#include <vfs/vfs.h>
42
43#include "config.h"
44#include "errors.h"
45#include "util.h"
46#include "entry.h"
47#include "mkfile.h"
48#include "cmds.h"
49
50/** Number of bytes to write at a time */
51#define BUFFER_SIZE DATA_XFER_LIMIT
52
53static const char *cmdname = "mkfile";
54
55static struct option const long_options[] = {
56 { "size", required_argument, 0, 's' },
57 { "sparse", no_argument, 0, 'p' },
58 { "help", no_argument, 0, 'h' },
59 { 0, 0, 0, 0 }
60};
61
62void help_cmd_mkfile(unsigned int level)
63{
64 if (level == HELP_SHORT) {
65 printf("`%s' creates a new zero-filled file\n", cmdname);
66 } else {
67 help_cmd_mkfile(HELP_SHORT);
68 printf(
69 "Usage: %s [options] <path>\n"
70 "Options:\n"
71 " -h, --help A short option summary\n"
72 " -s, --size sz Size of the file\n"
73 " -p, --sparse Create a sparse file\n"
74 "\n"
75 "Size is a number followed by 'k', 'm' or 'g' for kB, MB, GB.\n"
76 "E.g. 100k, 2m, 1g.\n",
77 cmdname);
78 }
79
80 return;
81}
82
83/** Parse size specification.
84 *
85 * Size specification is in the form <decimal_number><unit> where
86 * <unit> is 'k', 'm' or 'g' for kB, MB, GB.
87 *
88 * @param str String containing the size specification.
89 * @param rsize Place to store size in bytes
90 * @return EOK on success or an error code
91 */
92static errno_t read_size(const char *str, size_t *rsize)
93{
94 size_t number, unit;
95 char *ep;
96
97 number = strtol(str, &ep, 10);
98 if (ep[0] == '\0') {
99 *rsize = number;
100 return EOK;
101 }
102
103 if (ep[1] != '\0')
104 return EINVAL;
105
106 switch (tolower(ep[0])) {
107 case 'k':
108 unit = 1024;
109 break;
110 case 'm':
111 unit = 1024 * 1024;
112 break;
113 case 'g':
114 unit = 1024 * 1024 * 1024;
115 break;
116 default:
117 return EINVAL;
118 }
119
120 *rsize = number * unit;
121 return EOK;
122}
123
124int cmd_mkfile(char **argv)
125{
126 unsigned int argc;
127 int c, opt_ind;
128 int fd;
129 size_t file_size;
130 size_t total_written;
131 size_t to_write;
132 size_t nwritten;
133 errno_t rc;
134 char *file_name;
135 void *buffer;
136 bool create_sparse = false;
137 aoff64_t pos = 0;
138
139 file_size = 0;
140
141 argc = cli_count_args(argv);
142
143 c = 0;
144 optreset = 1;
145 optind = 0;
146 opt_ind = 0;
147
148 while (c != -1) {
149 c = getopt_long(argc, argv, "ps:h", long_options, &opt_ind);
150 switch (c) {
151 case 'h':
152 help_cmd_mkfile(HELP_LONG);
153 return CMD_SUCCESS;
154 case 'p':
155 create_sparse = true;
156 break;
157 case 's':
158 rc = read_size(optarg, &file_size);
159 if (rc != EOK) {
160 printf("%s: Invalid file size specification.\n",
161 cmdname);
162 return CMD_FAILURE;
163 }
164 break;
165 }
166 }
167
168 argc -= optind;
169
170 if (argc != 1) {
171 printf("%s: incorrect number of arguments. Try `%s --help'\n",
172 cmdname, cmdname);
173 return CMD_FAILURE;
174 }
175
176 file_name = argv[optind];
177
178 rc = vfs_lookup_open(file_name, WALK_REGULAR | WALK_MUST_CREATE, MODE_WRITE, &fd);
179 if (rc != EOK) {
180 printf("%s: failed to create file %s.\n", cmdname, file_name);
181 return CMD_FAILURE;
182 }
183
184 if (create_sparse && file_size > 0) {
185 const char byte = 0x00;
186
187 pos = file_size - 1;
188 rc = vfs_write(fd, &pos, &byte, sizeof(char), &nwritten);
189 if (rc != EOK) {
190 vfs_put(fd);
191 goto error;
192 }
193 return CMD_SUCCESS;
194 }
195
196 buffer = calloc(BUFFER_SIZE, 1);
197 if (buffer == NULL) {
198 printf("%s: Error, out of memory.\n", cmdname);
199 return CMD_FAILURE;
200 }
201
202 total_written = 0;
203 while (total_written < file_size) {
204 to_write = min(file_size - total_written, BUFFER_SIZE);
205 rc = vfs_write(fd, &pos, buffer, to_write, &nwritten);
206 if (rc != EOK) {
207 printf("%s: Error writing file (%s).\n", cmdname, str_error(rc));
208 vfs_put(fd);
209 free(buffer);
210 return CMD_FAILURE;
211 }
212 total_written += nwritten;
213 }
214
215 free(buffer);
216
217 rc = vfs_put(fd);
218 if (rc != EOK)
219 goto error;
220
221 return CMD_SUCCESS;
222error:
223 printf("%s: Error writing file (%s).\n", cmdname, str_error(rc));
224 return CMD_FAILURE;
225}
Note: See TracBrowser for help on using the repository browser.