newfs_v7fs.c revision 1.5 1 1.5 christos /* $NetBSD: newfs_v7fs.c,v 1.5 2017/01/10 20:53:09 christos Exp $ */
2 1.1 uch
3 1.1 uch /*-
4 1.1 uch * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
5 1.1 uch * All rights reserved.
6 1.1 uch *
7 1.1 uch * This code is derived from software contributed to The NetBSD Foundation
8 1.1 uch * by UCHIYAMA Yasushi.
9 1.1 uch *
10 1.1 uch * Redistribution and use in source and binary forms, with or without
11 1.1 uch * modification, are permitted provided that the following conditions
12 1.1 uch * are met:
13 1.1 uch * 1. Redistributions of source code must retain the above copyright
14 1.1 uch * notice, this list of conditions and the following disclaimer.
15 1.1 uch * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 uch * notice, this list of conditions and the following disclaimer in the
17 1.1 uch * documentation and/or other materials provided with the distribution.
18 1.1 uch *
19 1.1 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 uch * POSSIBILITY OF SUCH DAMAGE.
30 1.1 uch */
31 1.1 uch
32 1.1 uch #include <sys/cdefs.h>
33 1.1 uch #ifndef lint
34 1.5 christos __RCSID("$NetBSD: newfs_v7fs.c,v 1.5 2017/01/10 20:53:09 christos Exp $");
35 1.1 uch #endif /* not lint */
36 1.1 uch
37 1.1 uch #include <sys/types.h>
38 1.1 uch #include <sys/param.h>
39 1.5 christos #include <sys/disklabel.h>
40 1.5 christos #include <sys/ioctl.h>
41 1.5 christos #include <sys/stat.h>
42 1.5 christos
43 1.1 uch #include <err.h>
44 1.1 uch #include <stdio.h>
45 1.1 uch #include <string.h>
46 1.1 uch #include <stdlib.h>
47 1.1 uch #include <unistd.h>
48 1.1 uch #include <fcntl.h>
49 1.1 uch
50 1.1 uch #include <fs/v7fs/v7fs.h>
51 1.1 uch #include "v7fs_impl.h"
52 1.1 uch #include "progress.h"
53 1.1 uch #include "newfs_v7fs.h"
54 1.1 uch
55 1.1 uch static void usage(void) __dead;
56 1.1 uch static bool progress_bar_enable = false;
57 1.2 uch int v7fs_newfs_verbose = 3; /* newfs compatible */
58 1.1 uch
59 1.1 uch int
60 1.1 uch main(int argc, char **argv)
61 1.1 uch {
62 1.1 uch const char *device;
63 1.1 uch struct disklabel d;
64 1.1 uch struct partition *p;
65 1.1 uch struct stat st;
66 1.1 uch uint32_t partsize;
67 1.1 uch int Fflag, Zflag;
68 1.1 uch int part;
69 1.1 uch int fd, ch;
70 1.1 uch int endian = _BYTE_ORDER;
71 1.1 uch int32_t maxfile = 0;
72 1.1 uch
73 1.1 uch if (argc < 2)
74 1.1 uch usage();
75 1.1 uch
76 1.1 uch Fflag = Zflag = partsize = 0;
77 1.2 uch while ((ch = getopt(argc, argv, "Fs:Zs:n:B:V:")) != -1) {
78 1.1 uch switch (ch) {
79 1.2 uch case 'V':
80 1.2 uch v7fs_newfs_verbose = atoi(optarg);
81 1.1 uch break;
82 1.1 uch case 'F':
83 1.1 uch Fflag = 1;
84 1.1 uch break;
85 1.1 uch case 's':
86 1.1 uch partsize = atoi(optarg);
87 1.1 uch break;
88 1.1 uch case 'n':
89 1.1 uch maxfile = atoi(optarg);
90 1.1 uch break;
91 1.1 uch case 'Z':
92 1.1 uch Zflag = 1;
93 1.1 uch break;
94 1.1 uch case 'B':
95 1.1 uch switch (optarg[0]) {
96 1.1 uch case 'l':
97 1.1 uch endian = _LITTLE_ENDIAN;
98 1.1 uch break;
99 1.1 uch case 'b':
100 1.1 uch endian = _BIG_ENDIAN;
101 1.1 uch break;
102 1.1 uch case 'p':
103 1.1 uch endian = _PDP_ENDIAN;
104 1.1 uch break;
105 1.1 uch }
106 1.1 uch break;
107 1.1 uch default:
108 1.1 uch usage();
109 1.1 uch /*NOTREACHED*/
110 1.1 uch }
111 1.1 uch }
112 1.1 uch argc -= optind;
113 1.1 uch argv += optind;
114 1.1 uch
115 1.1 uch if (argc != 1)
116 1.1 uch usage();
117 1.1 uch device = argv[0];
118 1.1 uch
119 1.2 uch progress_bar_enable = v7fs_newfs_verbose > 1;
120 1.2 uch
121 1.2 uch
122 1.1 uch if (progress_bar_enable) {
123 1.1 uch progress_switch(progress_bar_enable);
124 1.1 uch progress_init();
125 1.1 uch progress(&(struct progress_arg){ .cdev = device });
126 1.1 uch }
127 1.1 uch
128 1.1 uch if (!Fflag) {
129 1.1 uch if ((fd = open(device, O_RDWR)) == -1) {
130 1.1 uch err(EXIT_FAILURE, "%s", device);
131 1.1 uch }
132 1.1 uch if (fstat(fd, &st) != 0) {
133 1.1 uch goto err_exit;
134 1.1 uch }
135 1.1 uch if (!S_ISCHR(st.st_mode)) {
136 1.4 christos warnx("not a raw device");
137 1.1 uch }
138 1.1 uch
139 1.1 uch part = DISKPART(st.st_rdev);
140 1.1 uch
141 1.1 uch if (ioctl(fd, DIOCGDINFO, &d) == -1) {
142 1.1 uch goto err_exit;
143 1.1 uch }
144 1.1 uch p = &d.d_partitions[part];
145 1.2 uch if (v7fs_newfs_verbose) {
146 1.1 uch printf("partition=%d size=%d offset=%d fstype=%d"
147 1.1 uch " secsize=%d\n", part, p->p_size, p->p_offset,
148 1.1 uch p->p_fstype, d.d_secsize);
149 1.1 uch }
150 1.1 uch if (p->p_fstype != FS_V7) {
151 1.4 christos warnx("not a Version 7 partition");
152 1.1 uch goto err_exit;
153 1.1 uch }
154 1.1 uch partsize = p->p_size;
155 1.1 uch } else {
156 1.1 uch off_t filesize;
157 1.1 uch uint8_t zbuf[8192] = {0, };
158 1.1 uch
159 1.1 uch if (partsize == 0) {
160 1.1 uch errx(EXIT_FAILURE, "-F requires -s");
161 1.1 uch }
162 1.1 uch
163 1.1 uch filesize = partsize << V7FS_BSHIFT;
164 1.1 uch
165 1.1 uch fd = open(device, O_RDWR|O_CREAT|O_TRUNC, 0666);
166 1.1 uch if (fd == -1) {
167 1.1 uch err(EXIT_FAILURE, "%s", device);
168 1.1 uch }
169 1.1 uch
170 1.1 uch if (Zflag) {
171 1.1 uch while (filesize > 0) {
172 1.1 uch size_t writenow = MIN(filesize,
173 1.1 uch (off_t)sizeof(zbuf));
174 1.1 uch
175 1.1 uch if ((size_t)write(fd, zbuf, writenow) !=
176 1.1 uch writenow) {
177 1.1 uch err(EXIT_FAILURE, NULL);
178 1.1 uch }
179 1.1 uch filesize -= writenow;
180 1.1 uch }
181 1.1 uch } else {
182 1.1 uch if (lseek(fd, filesize - 1, SEEK_SET) == -1) {
183 1.1 uch goto err_exit;
184 1.1 uch }
185 1.1 uch if (write(fd, zbuf, 1) != 1) {
186 1.1 uch goto err_exit;
187 1.1 uch }
188 1.1 uch if (lseek(fd, 0, SEEK_SET) == -1) {
189 1.1 uch goto err_exit;
190 1.1 uch }
191 1.1 uch }
192 1.1 uch }
193 1.1 uch
194 1.1 uch if (v7fs_newfs(&(struct v7fs_mount_device)
195 1.1 uch { .device.fd = fd, .endian = endian, .sectors = partsize },
196 1.1 uch maxfile) != 0)
197 1.1 uch goto err_exit;
198 1.1 uch
199 1.1 uch close(fd);
200 1.1 uch
201 1.1 uch return EXIT_SUCCESS;
202 1.1 uch err_exit:
203 1.1 uch close(fd);
204 1.1 uch err(EXIT_FAILURE, NULL);
205 1.1 uch }
206 1.1 uch
207 1.1 uch void
208 1.1 uch progress(const struct progress_arg *p)
209 1.1 uch {
210 1.1 uch static struct progress_arg Progress;
211 1.1 uch static char cdev[32];
212 1.1 uch static char label[32];
213 1.1 uch
214 1.1 uch if (!progress_bar_enable)
215 1.1 uch return;
216 1.1 uch
217 1.1 uch if (p) {
218 1.1 uch Progress = *p;
219 1.1 uch if (p->cdev)
220 1.1 uch strcpy(cdev, p->cdev);
221 1.1 uch if (p->label)
222 1.1 uch strcpy(label, p->label);
223 1.1 uch }
224 1.1 uch
225 1.1 uch if (!Progress.tick)
226 1.1 uch return;
227 1.1 uch if (++Progress.cnt > Progress.tick) {
228 1.1 uch Progress.cnt = 0;
229 1.1 uch Progress.total++;
230 1.1 uch progress_bar(cdev, label, Progress.total, PROGRESS_BAR_GRANULE);
231 1.1 uch }
232 1.1 uch }
233 1.1 uch
234 1.1 uch static void
235 1.1 uch usage(void)
236 1.1 uch {
237 1.1 uch
238 1.3 wiz (void)fprintf(stderr, "usage: \n%s [-FZ] [-B byte-order]"
239 1.3 wiz " [-n inodes] [-s sectors] [-V verbose] special\n", getprogname());
240 1.1 uch
241 1.1 uch exit(EXIT_FAILURE);
242 1.1 uch }
243