1/* $NetBSD: newfs_v7fs.c,v 1.2 2011/08/10 11:31:49 uch 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.2 2011/08/10 11:31:49 uch 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 53static void usage(void) __dead; 54static bool progress_bar_enable = false; 55int v7fs_newfs_verbose = 3; /* newfs compatible */ 56 57int 58main(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.\n"); 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 205void 206progress(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 232static void 233usage(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