Home | History | Annotate | Line # | Download | only in newfs_sysvbfs
newfs_sysvbfs.c revision 1.9
      1 /*	$NetBSD: newfs_sysvbfs.c,v 1.9 2014/03/23 05:10:56 dholland 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);
     49 static int bfs_newfs(int, uint32_t);
     50 
     51 int
     52 main(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 
    173 static int
    174 bfs_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 	strcpy(dirent->name, ".");
    224 	dirent++;
    225 	dirent->inode = BFS_ROOT_INODE;
    226 	strcpy(dirent->name, "..");
    227 	if (write(fd, buf, BFS_BSIZE) < 0) {
    228 		perror("write dirent");
    229 		return -1;
    230 	}
    231 
    232 	return 0;
    233 }
    234 
    235 static void
    236 usage(void)
    237 {
    238 
    239 	(void)fprintf(stderr, "usage: %s [-FZ] [-s sectors] special-device\n",
    240 	    getprogname());
    241 	exit(EXIT_FAILURE);
    242 }
    243