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