newfs_v7fs.c revision 1.2 1 1.2 uch /* $NetBSD: newfs_v7fs.c,v 1.2 2011/08/10 11:31:49 uch 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.2 uch __RCSID("$NetBSD: newfs_v7fs.c,v 1.2 2011/08/10 11:31:49 uch 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.1 uch #include <err.h>
40 1.1 uch #include <stdio.h>
41 1.1 uch #include <string.h>
42 1.1 uch #include <stdlib.h>
43 1.1 uch #include <unistd.h>
44 1.1 uch #include <fcntl.h>
45 1.1 uch #include <sys/ioctl.h>
46 1.1 uch #include <sys/disklabel.h>
47 1.1 uch
48 1.1 uch #include <fs/v7fs/v7fs.h>
49 1.1 uch #include "v7fs_impl.h"
50 1.1 uch #include "progress.h"
51 1.1 uch #include "newfs_v7fs.h"
52 1.1 uch
53 1.1 uch static void usage(void) __dead;
54 1.1 uch static bool progress_bar_enable = false;
55 1.2 uch int v7fs_newfs_verbose = 3; /* newfs compatible */
56 1.1 uch
57 1.1 uch int
58 1.1 uch main(int argc, char **argv)
59 1.1 uch {
60 1.1 uch const char *device;
61 1.1 uch struct disklabel d;
62 1.1 uch struct partition *p;
63 1.1 uch struct stat st;
64 1.1 uch uint32_t partsize;
65 1.1 uch int Fflag, Zflag;
66 1.1 uch int part;
67 1.1 uch int fd, ch;
68 1.1 uch int endian = _BYTE_ORDER;
69 1.1 uch int32_t maxfile = 0;
70 1.1 uch
71 1.1 uch if (argc < 2)
72 1.1 uch usage();
73 1.1 uch
74 1.1 uch Fflag = Zflag = partsize = 0;
75 1.2 uch while ((ch = getopt(argc, argv, "Fs:Zs:n:B:V:")) != -1) {
76 1.1 uch switch (ch) {
77 1.2 uch case 'V':
78 1.2 uch v7fs_newfs_verbose = atoi(optarg);
79 1.1 uch break;
80 1.1 uch case 'F':
81 1.1 uch Fflag = 1;
82 1.1 uch break;
83 1.1 uch case 's':
84 1.1 uch partsize = atoi(optarg);
85 1.1 uch break;
86 1.1 uch case 'n':
87 1.1 uch maxfile = atoi(optarg);
88 1.1 uch break;
89 1.1 uch case 'Z':
90 1.1 uch Zflag = 1;
91 1.1 uch break;
92 1.1 uch case 'B':
93 1.1 uch switch (optarg[0]) {
94 1.1 uch case 'l':
95 1.1 uch endian = _LITTLE_ENDIAN;
96 1.1 uch break;
97 1.1 uch case 'b':
98 1.1 uch endian = _BIG_ENDIAN;
99 1.1 uch break;
100 1.1 uch case 'p':
101 1.1 uch endian = _PDP_ENDIAN;
102 1.1 uch break;
103 1.1 uch }
104 1.1 uch break;
105 1.1 uch default:
106 1.1 uch usage();
107 1.1 uch /*NOTREACHED*/
108 1.1 uch }
109 1.1 uch }
110 1.1 uch argc -= optind;
111 1.1 uch argv += optind;
112 1.1 uch
113 1.1 uch if (argc != 1)
114 1.1 uch usage();
115 1.1 uch device = argv[0];
116 1.1 uch
117 1.2 uch progress_bar_enable = v7fs_newfs_verbose > 1;
118 1.2 uch
119 1.2 uch
120 1.1 uch if (progress_bar_enable) {
121 1.1 uch progress_switch(progress_bar_enable);
122 1.1 uch progress_init();
123 1.1 uch progress(&(struct progress_arg){ .cdev = device });
124 1.1 uch }
125 1.1 uch
126 1.1 uch if (!Fflag) {
127 1.1 uch if ((fd = open(device, O_RDWR)) == -1) {
128 1.1 uch err(EXIT_FAILURE, "%s", device);
129 1.1 uch }
130 1.1 uch if (fstat(fd, &st) != 0) {
131 1.1 uch goto err_exit;
132 1.1 uch }
133 1.1 uch if (!S_ISCHR(st.st_mode)) {
134 1.1 uch warnx("not a raw device.\n");
135 1.1 uch }
136 1.1 uch
137 1.1 uch part = DISKPART(st.st_rdev);
138 1.1 uch
139 1.1 uch if (ioctl(fd, DIOCGDINFO, &d) == -1) {
140 1.1 uch goto err_exit;
141 1.1 uch }
142 1.1 uch p = &d.d_partitions[part];
143 1.2 uch if (v7fs_newfs_verbose) {
144 1.1 uch printf("partition=%d size=%d offset=%d fstype=%d"
145 1.1 uch " secsize=%d\n", part, p->p_size, p->p_offset,
146 1.1 uch p->p_fstype, d.d_secsize);
147 1.1 uch }
148 1.1 uch if (p->p_fstype != FS_V7) {
149 1.1 uch warnx("not a Version 7 partition.");
150 1.1 uch goto err_exit;
151 1.1 uch }
152 1.1 uch partsize = p->p_size;
153 1.1 uch } else {
154 1.1 uch off_t filesize;
155 1.1 uch uint8_t zbuf[8192] = {0, };
156 1.1 uch
157 1.1 uch if (partsize == 0) {
158 1.1 uch errx(EXIT_FAILURE, "-F requires -s");
159 1.1 uch }
160 1.1 uch
161 1.1 uch filesize = partsize << V7FS_BSHIFT;
162 1.1 uch
163 1.1 uch fd = open(device, O_RDWR|O_CREAT|O_TRUNC, 0666);
164 1.1 uch if (fd == -1) {
165 1.1 uch err(EXIT_FAILURE, "%s", device);
166 1.1 uch }
167 1.1 uch
168 1.1 uch if (Zflag) {
169 1.1 uch while (filesize > 0) {
170 1.1 uch size_t writenow = MIN(filesize,
171 1.1 uch (off_t)sizeof(zbuf));
172 1.1 uch
173 1.1 uch if ((size_t)write(fd, zbuf, writenow) !=
174 1.1 uch writenow) {
175 1.1 uch err(EXIT_FAILURE, NULL);
176 1.1 uch }
177 1.1 uch filesize -= writenow;
178 1.1 uch }
179 1.1 uch } else {
180 1.1 uch if (lseek(fd, filesize - 1, SEEK_SET) == -1) {
181 1.1 uch goto err_exit;
182 1.1 uch }
183 1.1 uch if (write(fd, zbuf, 1) != 1) {
184 1.1 uch goto err_exit;
185 1.1 uch }
186 1.1 uch if (lseek(fd, 0, SEEK_SET) == -1) {
187 1.1 uch goto err_exit;
188 1.1 uch }
189 1.1 uch }
190 1.1 uch }
191 1.1 uch
192 1.1 uch if (v7fs_newfs(&(struct v7fs_mount_device)
193 1.1 uch { .device.fd = fd, .endian = endian, .sectors = partsize },
194 1.1 uch maxfile) != 0)
195 1.1 uch goto err_exit;
196 1.1 uch
197 1.1 uch close(fd);
198 1.1 uch
199 1.1 uch return EXIT_SUCCESS;
200 1.1 uch err_exit:
201 1.1 uch close(fd);
202 1.1 uch err(EXIT_FAILURE, NULL);
203 1.1 uch }
204 1.1 uch
205 1.1 uch void
206 1.1 uch progress(const struct progress_arg *p)
207 1.1 uch {
208 1.1 uch static struct progress_arg Progress;
209 1.1 uch static char cdev[32];
210 1.1 uch static char label[32];
211 1.1 uch
212 1.1 uch if (!progress_bar_enable)
213 1.1 uch return;
214 1.1 uch
215 1.1 uch if (p) {
216 1.1 uch Progress = *p;
217 1.1 uch if (p->cdev)
218 1.1 uch strcpy(cdev, p->cdev);
219 1.1 uch if (p->label)
220 1.1 uch strcpy(label, p->label);
221 1.1 uch }
222 1.1 uch
223 1.1 uch if (!Progress.tick)
224 1.1 uch return;
225 1.1 uch if (++Progress.cnt > Progress.tick) {
226 1.1 uch Progress.cnt = 0;
227 1.1 uch Progress.total++;
228 1.1 uch progress_bar(cdev, label, Progress.total, PROGRESS_BAR_GRANULE);
229 1.1 uch }
230 1.1 uch }
231 1.1 uch
232 1.1 uch static void
233 1.1 uch usage(void)
234 1.1 uch {
235 1.1 uch
236 1.1 uch (void)fprintf(stderr, "usage: \n%s [-vP] [-n maxfile]"
237 1.1 uch " [-B endian] special\n", getprogname());
238 1.1 uch (void)fprintf(stderr, "%s -F -s partsize [-vPZ] [-n maxfile]"
239 1.1 uch " [-B endian] file\n", getprogname());
240 1.1 uch
241 1.1 uch exit(EXIT_FAILURE);
242 1.1 uch }
243