date and time created 92/07/10 16:29:35 by heideman
[unix-history] / usr / src / sbin / newlfs / newfs.c
CommitLineData
2a5c97d5
KB
1/*
2 * Copyright (c) 1983, 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)newfs.c 6.28 (Berkeley) 8/6/91";
36#endif /* not lint */
37
38#ifndef lint
39char copyright[] =
40"@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
41 All rights reserved.\n";
42#endif /* not lint */
43
44/*
45 * newfs: friendly front end to mkfs
46 */
47#include <sys/param.h>
be25f164 48#include <sys/ucred.h>
2a5c97d5 49#include <sys/stat.h>
2a5c97d5
KB
50#include <sys/ioctl.h>
51#include <sys/disklabel.h>
52#include <sys/file.h>
53#include <sys/mount.h>
54
5f4034eb
KB
55#include <ufs/ufs/dir.h>
56#include <ufs/ufs/dinode.h>
57#include <ufs/ffs/fs.h>
58
2a5c97d5
KB
59#include <errno.h>
60#include <unistd.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <ctype.h>
64#include <string.h>
65#include <paths.h>
66#include "config.h"
67#include "extern.h"
68
69#define COMPAT /* allow non-labeled disks */
70
71int mfs; /* run as the memory based filesystem */
72int Nflag; /* run without writing file system */
73int fssize; /* file system size */
74int ntracks; /* # tracks/cylinder */
75int nsectors; /* # sectors/track */
76int nphyssectors; /* # sectors/track including spares */
77int secpercyl; /* sectors per cylinder */
78int trackspares = -1; /* spare sectors per track */
79int cylspares = -1; /* spare sectors per cylinder */
80int sectorsize; /* bytes/sector */
81#ifdef tahoe
82int realsectorsize; /* bytes/sector in hardware */
83#endif
84int rpm; /* revolutions/minute of drive */
85int interleave; /* hardware sector interleave */
86int trackskew = -1; /* sector 0 skew, per track */
87int headswitch; /* head switch time, usec */
88int trackseek; /* track-to-track seek, usec */
89int fsize = 0; /* fragment size */
90int bsize = 0; /* block size */
91int cpg = DESCPG; /* cylinders/cylinder group */
92int cpgflg; /* cylinders/cylinder group flag was given */
93int minfree = MINFREE; /* free space threshold */
94int opt = DEFAULTOPT; /* optimization preference (space or time) */
95int density; /* number of bytes per inode */
96int maxcontig = MAXCONTIG; /* max contiguous blocks to allocate */
97int rotdelay = ROTDELAY; /* rotational delay between blocks */
98int maxbpg; /* maximum blocks per file in a cyl group */
99int nrpos = NRPOS; /* # of distinguished rotational positions */
100int bbsize = BBSIZE; /* boot block size */
101int sbsize = SBSIZE; /* superblock size */
102int mntflags; /* flags to be passed to mount */
103u_long memleft; /* virtual memory available */
104caddr_t membase; /* start address of memory based filesystem */
105#ifdef COMPAT
106char *disktype;
107int unlabeled;
108#endif
109
110char device[MAXPATHLEN];
111char *progname, *special;
112
113static struct disklabel *getdisklabel __P((char *, int));
114static struct disklabel *debug_readlabel __P((int));
115static void rewritelabel __P((char *, int, struct disklabel *));
116static void usage __P((void));
117
118int
119main(argc, argv)
120 int argc;
121 char *argv[];
122{
123 register int ch;
124 register struct partition *pp;
125 register struct disklabel *lp;
126 struct partition oldpartition;
127 struct stat st;
128 int debug, lfs, fsi, fso, segsize;
129 char *cp, *opstring;
130
131 if (progname = rindex(*argv, '/'))
132 ++progname;
133 else
134 progname = *argv;
135
136 if (strstr(progname, "mfs")) {
137 mfs = 1;
138 Nflag++;
139 }
140
141 /* -F is mfs only and MUST come first! */
142 opstring = "F:B:DLNS:T:a:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:x:";
143 if (!mfs)
144 opstring += 2;
145
146 debug = lfs = segsize = 0;
147 while ((ch = getopt(argc, argv, opstring)) != EOF)
148 switch(ch) {
149 case 'B': /* LFS segment size */
150 if ((segsize = atoi(optarg)) < LFS_MINSEGSIZE)
151 fatal("%s: bad segment size", optarg);
152 break;
153 case 'D':
154 debug = 1;
155 break;
156 case 'F':
157 if ((mntflags = atoi(optarg)) == 0)
158 fatal("%s: bad mount flags", optarg);
159 break;
160 case 'L': /* Create lfs */
161 lfs = 1;
162 break;
163 case 'N':
164 Nflag++;
165 break;
166 case 'S':
167 if ((sectorsize = atoi(optarg)) <= 0)
168 fatal("%s: bad sector size", optarg);
169 break;
170#ifdef COMPAT
171 case 'T':
172 disktype = optarg;
173 break;
174#endif
175 case 'a':
176 if ((maxcontig = atoi(optarg)) <= 0)
177 fatal("%s: bad max contiguous blocks\n",
178 optarg);
179 break;
180 case 'b': /* used for LFS */
181 if ((bsize = atoi(optarg)) < MINBSIZE)
182 fatal("%s: bad block size", optarg);
183 break;
184 case 'c':
185 if ((cpg = atoi(optarg)) <= 0)
186 fatal("%s: bad cylinders/group", optarg);
187 cpgflg++;
188 break;
189 case 'd':
190 if ((rotdelay = atoi(optarg)) < 0)
191 fatal("%s: bad rotational delay\n", optarg);
192 break;
193 case 'e':
194 if ((maxbpg = atoi(optarg)) <= 0)
195 fatal("%s: bad blocks per file in a cyl group\n",
196 optarg);
197 break;
198 case 'f':
199 if ((fsize = atoi(optarg)) <= 0)
200 fatal("%s: bad frag size", optarg);
201 break;
202 case 'i':
203 if ((density = atoi(optarg)) <= 0)
204 fatal("%s: bad bytes per inode\n", optarg);
205 break;
206 case 'k':
207 if ((trackskew = atoi(optarg)) < 0)
208 fatal("%s: bad track skew", optarg);
209 break;
210 case 'l':
211 if ((interleave = atoi(optarg)) <= 0)
212 fatal("%s: bad interleave", optarg);
213 break;
214 case 'm': /* used for LFS */
215 if ((minfree = atoi(optarg)) < 0 || minfree > 99)
216 fatal("%s: bad free space %%\n", optarg);
217 break;
218 case 'n':
219 if ((nrpos = atoi(optarg)) <= 0)
220 fatal("%s: bad rotational layout count\n",
221 optarg);
222 break;
223 case 'o':
224 if (strcmp(optarg, "space") == 0)
225 opt = FS_OPTSPACE;
226 else if (strcmp(optarg, "time") == 0)
227 opt = FS_OPTTIME;
228 else
229 fatal("%s: bad optimization preference %s",
230 optarg, "(options are `space' or `time')");
231 break;
232 case 'p':
233 if ((trackspares = atoi(optarg)) < 0)
234 fatal("%s: bad spare sectors per track",
235 optarg);
236 break;
237 case 'r':
238 if ((rpm = atoi(optarg)) <= 0)
239 fatal("%s: bad revs/minute\n", optarg);
240 break;
241 case 's': /* used for LFS */
242 if ((fssize = atoi(optarg)) <= 0)
243 fatal("%s: bad file system size", optarg);
244 break;
245 case 't':
246 if ((ntracks = atoi(optarg)) <= 0)
247 fatal("%s: bad total tracks", optarg);
248 break;
249 case 'u':
250 if ((nsectors = atoi(optarg)) <= 0)
251 fatal("%s: bad sectors/track", optarg);
252 break;
253 case 'x':
254 if ((cylspares = atoi(optarg)) < 0)
255 fatal("%s: bad spare sectors per cylinder",
256 optarg);
257 break;
258 case '?':
259 default:
260 usage();
261 }
262 argc -= optind;
263 argv += optind;
264
265 if (argc != 2 && (mfs || argc != 1))
266 usage();
267
268 /*
269 * If the -N flag isn't specified, open the output file. If no path
270 * prefix, try /dev/r%s and then /dev/%s.
271 */
272 special = argv[0];
273 if (index(special, '/') == NULL) {
274 (void)sprintf(device, "%sr%s", _PATH_DEV, special);
275 if (stat(device, &st) == -1)
276 (void)sprintf(device, "%s%s", _PATH_DEV, special);
277 special = device;
278 }
279 if (!Nflag) {
280 fso = open(special,
281 (debug ? O_CREAT : 0) | O_WRONLY, DEFFILEMODE);
282 if (fso < 0)
283 fatal("%s: %s", special, strerror(errno));
284 } else
285 fso = -1;
286
287 /* Open the input file. */
288 fsi = open(special, O_RDONLY);
289 if (fsi < 0)
290 fatal("%s: %s", special, strerror(errno));
291 if (fstat(fsi, &st) < 0)
292 fatal("%s: %s", special, strerror(errno));
293
9ef376b4 294 if (!debug && !mfs && !S_ISCHR(st.st_mode))
2a5c97d5
KB
295 (void)printf("%s: %s: not a character-special device\n",
296 progname, special);
297 cp = index(argv[0], '\0') - 1;
298 if (!debug && (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)))
299 fatal("%s: can't figure out file system partition", argv[0]);
300
301#ifdef COMPAT
302 if (!mfs && disktype == NULL)
303 disktype = argv[1];
304#endif
305 if (debug)
306 lp = debug_readlabel(fsi);
307 else
308 lp = getdisklabel(special, fsi);
309
310 if (isdigit(*cp))
311 pp = &lp->d_partitions[0];
312 else
313 pp = &lp->d_partitions[*cp - 'a'];
314 if (pp->p_size == 0)
315 fatal("%s: `%c' partition is unavailable", argv[0], *cp);
316
317 /* If we're making a LFS, we break out here */
0f68007b 318 exit(make_lfs(fso, lp, pp, minfree, bsize, segsize));
2a5c97d5
KB
319}
320
321#ifdef COMPAT
322char lmsg[] = "%s: can't read disk label; disk type must be specified";
323#else
324char lmsg[] = "%s: can't read disk label";
325#endif
326
327static struct disklabel *
328getdisklabel(s, fd)
329 char *s;
330 int fd;
331{
332 static struct disklabel lab;
333
334 if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
335#ifdef COMPAT
336 if (disktype) {
337 struct disklabel *lp, *getdiskbyname();
338
339 unlabeled++;
340 lp = getdiskbyname(disktype);
341 if (lp == NULL)
342 fatal("%s: unknown disk type", disktype);
343 return (lp);
344 }
345#endif
346 (void)fprintf(stderr,
347 "%s: ioctl (GDINFO): %s\n", progname, strerror(errno));
348 fatal(lmsg, s);
349 }
350 return (&lab);
351}
352
353
354static struct disklabel *
355debug_readlabel(fd)
356 int fd;
357{
358 static struct disklabel lab;
359 int n;
360
361 if ((n = read(fd, &lab, sizeof(struct disklabel))) < 0)
362 fatal("unable to read disk label: %s", strerror(errno));
363 else if (n < sizeof(struct disklabel))
364 fatal("short read of disklabel: %d of %d bytes", n,
365 sizeof(struct disklabel));
366 return(&lab);
367}
368
369static void
370rewritelabel(s, fd, lp)
371 char *s;
372 int fd;
373 register struct disklabel *lp;
374{
375#ifdef COMPAT
376 if (unlabeled)
377 return;
378#endif
379 lp->d_checksum = 0;
380 lp->d_checksum = dkcksum(lp);
381 if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
382 (void)fprintf(stderr,
383 "%s: ioctl (WDINFO): %s\n", progname, strerror(errno));
384 fatal("%s: can't rewrite disk label", s);
385 }
386#if vax
387 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
388 register i;
389 int cfd;
390 daddr_t alt;
391 char specname[64];
392 char blk[1024];
393 char *cp;
394
395 /*
396 * Make name for 'c' partition.
397 */
398 strcpy(specname, s);
399 cp = specname + strlen(specname) - 1;
400 if (!isdigit(*cp))
401 *cp = 'c';
402 cfd = open(specname, O_WRONLY);
403 if (cfd < 0)
404 fatal("%s: %s", specname, strerror(errno));
405 bzero(blk, sizeof(blk));
406 *(struct disklabel *)(blk + LABELOFFSET) = *lp;
407 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
408 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
409 if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize,
410 L_SET) == -1)
411 fatal("lseek to badsector area: %s",
412 strerror(errno));
413 if (write(cfd, blk, lp->d_secsize) < lp->d_secsize)
414 fprintf(stderr,
415 "%s: alternate label %d write: %s\n",
416 progname, i/2, strerror(errno));
417 }
418 close(cfd);
419 }
420#endif
421}
422
423void
424usage()
425{
426 if (mfs) {
427 fprintf(stderr,
428 "usage: mfs [ -fsoptions ] special-device mount-point\n");
429 } else
430 fprintf(stderr,
431 "usage: newfs [ -fsoptions ] special-device%s\n",
432#ifdef COMPAT
433 " [device-type]");
434#else
435 "");
436#endif
437 fprintf(stderr, "where fsoptions are:\n");
438 fprintf(stderr, "\t-B LFS segment size\n");
439 fprintf(stderr, "\t-D debug\n");
440 fprintf(stderr, "\t-F mount flags\n");
441 fprintf(stderr, "\t-L create LFS file system\n");
442 fprintf(stderr,
443 "\t-N do not create file system, just print out parameters\n");
444 fprintf(stderr, "\t-S sector size\n");
445#ifdef COMPAT
446 fprintf(stderr, "\t-T disktype\n");
447#endif
448 fprintf(stderr, "\t-a maximum contiguous blocks\n");
449 fprintf(stderr, "\t-b block size\n");
450 fprintf(stderr, "\t-c cylinders/group\n");
451 fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
452 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
453 fprintf(stderr, "\t-f frag size\n");
454 fprintf(stderr, "\t-i number of bytes per inode\n");
455 fprintf(stderr, "\t-k sector 0 skew, per track\n");
456 fprintf(stderr, "\t-l hardware sector interleave\n");
457 fprintf(stderr, "\t-m minimum free space %%\n");
458 fprintf(stderr, "\t-n number of distinguished rotational positions\n");
459 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
460 fprintf(stderr, "\t-p spare sectors per track\n");
461 fprintf(stderr, "\t-r revolutions/minute\n");
462 fprintf(stderr, "\t-s file system size (sectors)\n");
463 fprintf(stderr, "\t-t tracks/cylinder\n");
464 fprintf(stderr, "\t-u sectors/track\n");
465 fprintf(stderr, "\t-x spare sectors per cylinder\n");
466 exit(1);
467}