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