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
main(int argc,char ** argv)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
bfs_newfs(int fd,uint32_t nsectors)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
usage(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