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