source: mainline/uspace/app/mkminix/mkminix.c@ 68ed0fb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 68ed0fb was 68ed0fb, checked in by Maurizio Lombardi <m.lombardi85@…>, 14 years ago

prepare V1/V2 superblock and write it to disk

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * Copyright (c) 2011 Maurizio Lombardi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup fs
31 * @{
32 */
33
34/**
35 * @file mkminix.c
36 * @brief Tool for creating new Minix file systems.
37 *
38 */
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <libblock.h>
43#include <unistd.h>
44#include <errno.h>
45#include <sys/typefmt.h>
46#include <inttypes.h>
47#include <str.h>
48#include <getopt.h>
49#include <mem.h>
50#include <minix.h>
51
52#define NAME "mkminix"
53
54typedef enum {
55 HELP_SHORT,
56 HELP_LONG
57} help_level_t;
58
59typedef struct mfs_params {
60 uint16_t fs_magic;
61 uint32_t block_size;
62 size_t devblock_size;
63 unsigned long n_inodes;
64 aoff64_t dev_nblocks;
65 bool fs_longnames;
66} mfs_params_t;
67
68static void help_cmd_mkminix(help_level_t level);
69static int num_of_set_bits(uint32_t n);
70static void prepare_superblock(struct mfs_superblock *sb, mfs_params_t *opt);
71static void prepare_superblock_v3(struct mfs3_superblock *sb, mfs_params_t *opt);
72
73static struct option const long_options[] = {
74 { "help", no_argument, 0, 'h' },
75 { "long-names", no_argument, 0, 'l' },
76 { "blocks", required_argument, 0, 'b' },
77 { "inodes", required_argument, 0, 'i' },
78 { NULL, no_argument, 0, '1' },
79 { NULL, no_argument, 0, '2' },
80 { NULL, no_argument, 0, '3' },
81 { 0, 0, 0, 0 }
82};
83
84int main (int argc, char **argv)
85{
86 int rc, c, opt_ind;
87 char *device_name;
88 devmap_handle_t handle;
89
90 struct mfs_superblock *sb;
91 struct mfs3_superblock *sb3;
92
93 mfs_params_t opt;
94
95 /*Default is MinixFS V3*/
96 opt.fs_magic = MFS_MAGIC_V3;
97
98 /*Default block size is 4Kb*/
99 opt.block_size = MFS_MAX_BLOCKSIZE;
100 opt.n_inodes = 0;
101 opt.fs_longnames = false;
102
103 if (argc == 1) {
104 help_cmd_mkminix(HELP_SHORT);
105 printf("Incorrect number of arguments, try `mkminix --help'\n");
106 exit(0);
107 }
108
109 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
110 c = getopt_long(argc, argv, "eh123b:i:", long_options, &opt_ind);
111 switch (c) {
112 case 'h':
113 help_cmd_mkminix(HELP_LONG);
114 exit(0);
115 case '1':
116 opt.fs_magic = MFS_MAGIC_V1;
117 opt.block_size = MFS_BLOCKSIZE;
118 break;
119 case '2':
120 opt.fs_magic = MFS_MAGIC_V2;
121 opt.block_size = MFS_BLOCKSIZE;
122 break;
123 case '3':
124 opt.fs_magic = MFS_MAGIC_V3;
125 break;
126 case 'b':
127 opt.block_size = (uint32_t) strtol(optarg, NULL, 10);
128 break;
129 case 'i':
130 opt.n_inodes = (unsigned long) strtol(optarg, NULL, 10);
131 break;
132 case 'l':
133 opt.fs_longnames = true;
134 break;
135 }
136 }
137
138 if (opt.block_size < MFS_MIN_BLOCKSIZE ||
139 opt.block_size > MFS_MAX_BLOCKSIZE) {
140 printf(NAME ":Error! Invalid block size.\n");
141 exit(0);
142 } else if (num_of_set_bits(opt.block_size) != 1) {
143 /*Block size must be a power of 2.*/
144 printf(NAME ":Error! Invalid block size.\n");
145 exit(0);
146 } else if (opt.block_size > MFS_BLOCKSIZE &&
147 opt.fs_magic != MFS_MAGIC_V3) {
148 printf(NAME ":Error! Block size > 1024 is supported by V3 filesystem only.\n");
149 exit(0);
150 } else if (opt.fs_magic == MFS_MAGIC_V3 && opt.fs_longnames) {
151 printf(NAME ":Error! Long filenames are supported by V1/V2 filesystem only.\n");
152 exit(0);
153 }
154
155 argv += optind;
156
157 device_name = argv[0];
158
159 if (!device_name) {
160 help_cmd_mkminix(HELP_LONG);
161 exit(0);
162 }
163
164 rc = devmap_device_get_handle(device_name, &handle, 0);
165 if (rc != EOK) {
166 printf(NAME ": Error resolving device `%s'.\n", device_name);
167 return 2;
168 }
169
170 rc = block_init(handle, MFS_MIN_BLOCKSIZE);
171 if (rc != EOK) {
172 printf(NAME ": Error initializing libblock.\n");
173 return 2;
174 }
175
176 rc = block_get_bsize(handle, &opt.devblock_size);
177 if (rc != EOK) {
178 printf(NAME ": Error determining device block size.\n");
179 return 2;
180 }
181
182 rc = block_get_nblocks(handle, &opt.dev_nblocks);
183 if (rc != EOK) {
184 printf(NAME ": Warning, failed to obtain block device size.\n");
185 } else {
186 printf(NAME ": Block device has %" PRIuOFF64 " blocks.\n",
187 opt.dev_nblocks);
188 }
189
190 if (opt.devblock_size != 512) {
191 printf(NAME ": Error. Device block size is not 512 bytes.\n");
192 return 2;
193 }
194
195 /*Minimum block size is 1 Kb*/
196 opt.dev_nblocks /= 2;
197
198 printf(NAME ": Creating Minix file system on device\n");
199
200 /*Prepare superblock*/
201
202 if (opt.fs_magic == MFS_MAGIC_V3) {
203 sb3 = (struct mfs3_superblock *) malloc(sizeof(struct mfs3_superblock));
204 if (!sb3) {
205 printf(NAME ": Error, not enough memory");
206 return 2;
207 }
208 prepare_superblock_v3(sb3, &opt);
209 } else {
210 sb = (struct mfs_superblock *) malloc(sizeof(struct mfs_superblock));
211 if (!sb) {
212 printf(NAME ": Error, not enough memory");
213 return 2;
214 }
215 prepare_superblock(sb, &opt);
216 block_write_direct(handle, MFS_SUPERBLOCK, 1, sb);
217 }
218
219 return 0;
220}
221
222static void prepare_superblock(struct mfs_superblock *sb, mfs_params_t *opt)
223{
224 int ino_per_block = 0;
225 int fs_version;
226 aoff64_t tmp;
227
228 if (opt->fs_magic == MFS_MAGIC_V1) {
229 fs_version = 1;
230 ino_per_block = V1_INODES_PER_BLOCK;
231 if (opt->fs_longnames)
232 opt->fs_magic = MFS_MAGIC_V1L;
233 } else {
234 fs_version = 2;
235 ino_per_block = V1_INODES_PER_BLOCK;
236 if (opt->fs_longnames)
237 opt->fs_magic = MFS_MAGIC_V2L;
238 }
239
240 sb->s_magic = opt->fs_magic;
241
242 /*Valid only for MFS V1*/
243 sb->s_nzones = opt->dev_nblocks > UINT16_MAX ?
244 UINT16_MAX : opt->dev_nblocks;
245
246 /*Valid only for MFS V2*/
247 sb->s_nzones2 = opt->dev_nblocks > UINT32_MAX ?
248 UINT32_MAX : opt->dev_nblocks;
249
250 if (opt->n_inodes == 0)
251 tmp = opt->dev_nblocks / 3;
252 else
253 tmp = opt->n_inodes;
254
255 /*Round up the number of inodes to fill block size*/
256 if (tmp % ino_per_block)
257 tmp = ((tmp / ino_per_block) + 1) * ino_per_block;
258 sb->s_ninodes = tmp > UINT16_MAX ? UINT16_MAX : tmp;
259
260 /*Compute inode bitmap size in blocks*/
261 sb->s_ibmap_blocks = sb->s_ninodes / (MFS_BLOCKSIZE * 8);
262 if (sb->s_ibmap_blocks == 0)
263 sb->s_ibmap_blocks = 1;
264
265 /*Compute zone bitmap size in blocks*/
266 if (fs_version == 1)
267 sb->s_zbmap_blocks = sb->s_nzones / (MFS_BLOCKSIZE * 8);
268 else
269 sb->s_zbmap_blocks = sb->s_nzones2 / (MFS_BLOCKSIZE * 8);
270 if (sb->s_zbmap_blocks == 0)
271 sb->s_zbmap_blocks = 1;
272
273 /*Compute first data zone position*/
274 sb->s_first_data_zone = 2 + sb->s_zbmap_blocks + sb->s_ibmap_blocks;
275 unsigned long ninodes_blocks = 1 + (sb->s_ninodes / (fs_version == 1 ?
276 V1_INODES_PER_BLOCK :
277 V2_INODES_PER_BLOCK));
278 sb->s_first_data_zone += ninodes_blocks;
279 sb->s_log2_zone_size = 0;
280 /*Superblock is now ready to be written on disk*/
281 printf(NAME ": %d inodes\n", sb->s_ninodes);
282 printf(NAME ": %d zones\n", sb->s_nzones2);
283 printf(NAME ": %d first data zone\n", sb->s_first_data_zone);
284}
285
286static void prepare_superblock_v3(struct mfs3_superblock *sb, mfs_params_t *opt)
287{
288}
289
290static void help_cmd_mkminix(help_level_t level)
291{
292 if (level == HELP_SHORT) {
293 printf(NAME": tool to create new Minix file systems\n");
294 } else {
295 printf("Usage: [options] device\n"
296 "-1 Make a Minix version 1 filesystem\n"
297 "-2 Make a Minix version 2 filesystem\n"
298 "-3 Make a Minix version 3 filesystem\n"
299 "-b ## Specify the block size in bytes (V3 only),\n"
300 " valid block size values are 1024, 2048 and 4096 bytes per block\n"
301 "-i ## Specify the number of inodes for the filesystem\n"
302 "-l Use 30-char long filenames (V1/V2 only)\n");
303 }
304}
305
306static int num_of_set_bits(uint32_t n)
307{
308 n = n - ((n >> 1) & 0x55555555);
309 n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
310 return (((n + (n >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
311}
312
313
314/**
315 * @}
316 */
Note: See TracBrowser for help on using the repository browser.