1/* $NetBSD: newfs_sysvbfs.c,v 1.7 2009/04/11 07:37:50 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2004 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/types.h> 33#include <sys/param.h> 34#include <err.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <unistd.h> 39#include <fcntl.h> 40#include <time.h> 41#include <assert.h> 42#include <sys/errno.h> 43#include <sys/ioctl.h> 44#include <sys/disklabel.h> 45 46#include <fs/sysvbfs/bfs.h> 47 48__dead static void usage(void); 49static int bfs_newfs(int, uint32_t); 50 51int 52main(int argc, char **argv) 53{ 54 const char *device; 55 struct disklabel d; 56 struct partition *p; 57 struct stat st; 58 uint32_t partsize; 59 int Fflag, Zflag; 60 int part; 61 int fd, ch; 62 63 if (argc < 2) 64 usage(); 65 66 Fflag = Zflag = partsize = 0; 67 while ((ch = getopt(argc, argv, "Fs:Z")) != -1) { 68 switch (ch) { 69 case 'F': 70 Fflag = 1; 71 break; 72 case 's': 73 partsize = atoi(optarg); 74 break; 75 case 'Z': 76 Zflag = 1; 77 break; 78 default: 79 usage(); 80 /*NOTREACHED*/ 81 } 82 } 83 argc -= optind; 84 argv += optind; 85 86 if (argc != 1) 87 usage(); 88 device = argv[0]; 89 90 if (!Fflag) { 91 if ((fd = open(device, O_RDWR)) == -1) { 92 perror("open device"); 93 exit(EXIT_FAILURE); 94 } 95 if (fstat(fd, &st) != 0) { 96 perror("device stat"); 97 goto err_exit; 98 } 99 if (!S_ISCHR(st.st_mode)) { 100 fprintf(stderr, "WARNING: not a raw device.\n"); 101 } 102 103 part = DISKPART(st.st_rdev); 104 105 if (ioctl(fd, DIOCGDINFO, &d) == -1) { 106 perror("disklabel"); 107 goto err_exit; 108 } 109 p = &d.d_partitions[part]; 110 printf("partition = %d\n", part); 111 printf("size=%d offset=%d fstype=%d secsize=%d\n", 112 p->p_size, p->p_offset, p->p_fstype, d.d_secsize); 113 114 if (p->p_fstype != FS_SYSVBFS) { 115 fprintf(stderr, "not a SysVBFS partition.\n"); 116 goto err_exit; 117 } 118 partsize = p->p_size; 119 } else { 120 off_t filesize; 121 uint8_t zbuf[8192] = {0, }; 122 123 if (partsize == 0) { 124 warnx("-F requires -s"); 125 exit(EXIT_FAILURE); 126 } 127 128 filesize = partsize << BFS_BSHIFT; 129 130 fd = open(device, O_RDWR|O_CREAT|O_TRUNC, 0666); 131 if (fd == -1) { 132 perror("open file"); 133 exit(EXIT_FAILURE); 134 } 135 136 if (Zflag) { 137 while (filesize > 0) { 138 size_t writenow = MIN(filesize, (off_t)sizeof(zbuf)); 139 140 if ((size_t)write(fd, zbuf, writenow) != writenow) { 141 perror("zwrite"); 142 exit(EXIT_FAILURE); 143 } 144 filesize -= writenow; 145 } 146 } else { 147 if (lseek(fd, filesize-1, SEEK_SET) == -1) { 148 perror("lseek"); 149 exit(EXIT_FAILURE); 150 } 151 if (write(fd, zbuf, 1) != 1) { 152 perror("write"); 153 exit(EXIT_FAILURE); 154 } 155 if (lseek(fd, 0, SEEK_SET) == -1) { 156 perror("lseek 2"); 157 exit(EXIT_FAILURE); 158 } 159 } 160 } 161 162 if (bfs_newfs(fd, partsize) != 0) 163 goto err_exit; 164 165 close(fd); 166 167 return 0; 168 err_exit: 169 close(fd); 170 exit(EXIT_FAILURE); 171} 172 173static int 174bfs_newfs(int fd, uint32_t nsectors) 175{ 176 uint8_t buf[DEV_BSIZE]; 177 struct bfs_super_block *bfs = (void *)buf; 178 struct bfs_inode *inode = (void *)buf; 179 struct bfs_dirent *dirent = (void *)buf; 180 time_t t = time(0); 181 int error; 182 183 /* Super block */ 184 memset(buf, 0, DEV_BSIZE); 185 bfs->header.magic = BFS_MAGIC; 186 bfs->header.data_start_byte = DEV_BSIZE * 2; /* super block + inode */ 187 bfs->header.data_end_byte = nsectors * BFS_BSIZE - 1; 188 bfs->compaction.from = 0xffffffff; 189 bfs->compaction.to = 0xffffffff; 190 bfs->compaction.from_backup = 0xffffffff; 191 bfs->compaction.to_backup = 0xffffffff; 192 193 if ((error = lseek(fd, 0, SEEK_SET)) == -1) { 194 perror("seek super block"); 195 return -1; 196 } 197 if (write(fd, buf, BFS_BSIZE) < 0) { 198 perror("write super block"); 199 return -1; 200 } 201 202 /* i-node table */ 203 memset(buf, 0, BFS_BSIZE); 204 inode->number = BFS_ROOT_INODE; 205 inode->start_sector = 2; 206 inode->end_sector = 2; 207 inode->eof_offset_byte = sizeof(struct bfs_dirent) + 208 inode->start_sector * BFS_BSIZE; 209 inode->attr.atime = t; 210 inode->attr.mtime = t; 211 inode->attr.ctime = t; 212 inode->attr.mode = 0755; 213 inode->attr.type = 2; /* DIR */ 214 inode->attr.nlink = 2; /* . + .. */ 215 if (write(fd, buf, BFS_BSIZE) < 0) { 216 perror("write i-node"); 217 return -1; 218 } 219 220 /* dirent table */ 221 memset(buf, 0, BFS_BSIZE); 222 dirent->inode = BFS_ROOT_INODE; 223 sprintf(dirent->name, "."); 224 dirent++; 225 dirent->inode = BFS_ROOT_INODE; 226 sprintf(dirent->name, ".."); 227 if (write(fd, buf, BFS_BSIZE) < 0) { 228 perror("write dirent"); 229 return -1; 230 } 231 232 return 0; 233} 234 235static void 236usage(void) 237{ 238 239 (void)fprintf(stderr, "usage: %s [-FZ] [-s sectors] special-device\n", 240 getprogname()); 241 exit(EXIT_FAILURE); 242} 243