xref: /illumos-gate/usr/src/cmd/fs.d/udfs/mkfs/mkfs.c (revision fe0e7ec4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 /*
30  * Portions of this source code were derived from Berkeley 4.3 BSD
31  * under license from the Regents of the University of California.
32  */
33 
34 #pragma ident	"%Z%%M%	%I%	%E% SMI"
35 
36 /*
37  * make file system for udfs (UDF - ISO13346)
38  *
39  * usage:
40  *
41  *    mkfs [-F FSType] [-V] [-m] [options]
42  *	[-o specific_options]  special size
43  *
44  *  where specific_options are:
45  *	N - no create
46  *	label - volume label
47  *	psize - physical block size
48  */
49 
50 #include	<stdio.h>
51 #include	<strings.h>
52 #include	<string.h>
53 #include	<stdlib.h>
54 #include	<unistd.h>
55 #include	<time.h>
56 #include	<locale.h>
57 #include	<fcntl.h>
58 #include	<errno.h>
59 #include	<limits.h>
60 #include	<sys/mnttab.h>
61 #include	<sys/param.h>
62 #include	<sys/types.h>
63 #include	<sys/sysmacros.h>
64 #include	<sys/vnode.h>
65 #include	<sys/mntent.h>
66 #include	<sys/filio.h>
67 #include	<sys/stat.h>
68 #include	<ustat.h>
69 #include 	<sys/isa_defs.h>	/* for ENDIAN defines */
70 #include	<sys/dkio.h>
71 #include	<sys/fdio.h>
72 #include	<sys/vtoc.h>
73 #include	<sys/fs/udf_volume.h>
74 
75 extern char	*getfullrawname(char *);
76 extern char	*getfullblkname(char *);
77 extern struct tm *localtime_r(const time_t *, struct tm *);
78 extern void	maketag(struct tag *, struct tag *);
79 extern int	verifytag(struct tag *, uint32_t, struct tag *, int);
80 extern void	setcharspec(struct charspec *, int32_t, uint8_t *);
81 
82 
83 #define	UMASK		0755
84 #define	POWEROF2(num)	(((num) & ((num) - 1)) == 0)
85 #define	MB		(1024*1024)
86 
87 /*
88  * Forward declarations
89  */
90 static void rdfs(daddr_t bno, int size, char *bf);
91 static void wtfs(daddr_t bno, int size, char *bf);
92 static void dump_fscmd(char *fsys, int fsi);
93 static int32_t number(long big, char *param);
94 static void usage();
95 static int match(char *s);
96 static int readvolseq();
97 static uint32_t get_last_block();
98 
99 /*
100  * variables set up by front end.
101  */
102 static int	Nflag = 0;		/* run mkfs without writing */
103 					/* file system */
104 static int	mflag = 0;		/* return the command line used */
105 					/* to create this FS */
106 static int	fssize;			/* file system size */
107 static uint32_t	disk_size;		/* partition size from VTOC */
108 static uint32_t unused;			/* unused sectors in partition */
109 static int	sectorsize = 2048;	/* bytes/sector default */
110 					/* If nothing specified */
111 
112 static char	*fsys;
113 static int	fsi;
114 static int	fso;
115 
116 #define	BIG	LONG_MAX
117 static	uint32_t	number_flags = 0;
118 
119 static char	*string;
120 
121 static void	setstamp(tstamp_t *);
122 static void	setextad(extent_ad_t *, uint32_t, uint32_t);
123 static void	setdstring(dstring_t *, char *, int32_t);
124 static void	wtvolseq(tag_t *, daddr_t, daddr_t);
125 static void	volseqinit();
126 static void	setstamp(tstamp_t *);
127 static uint32_t	get_bsize();
128 
129 
130 #define	VOLRECSTART	(32 * 1024)
131 
132 #define	VOLSEQSTART	128
133 #define	VOLSEQLEN	16
134 #define	INTSEQSTART	192
135 #define	INTSEQLEN	8192
136 #define	FIRSTAVDP	256
137 #define	AVDPLEN		1
138 
139 
140 #define	FILESETLEN	2
141 
142 #define	SPACEMAP_OFF	24
143 #define	MAXID		16
144 
145 static time_t mkfstime;
146 static struct tm res;
147 static long tzone;
148 static char vsibuf[128];
149 
150 static regid_t sunmicro = { 0, "*SUN SOLARIS UDF", 4, 2 };
151 static regid_t lvinfo = { 0, "*UDF LV Info", 0x50, 0x1, 4, 2 };
152 static regid_t partid = { 0, "+NSR02", 0 };
153 static regid_t udf_compliant = { 0, "*OSTA UDF Compliant", 0x50, 0x1, 0 };
154 static uint8_t osta_unicode[] = "OSTA Compressed Unicode";
155 
156 static int bdevismounted;
157 static int ismounted;
158 static int directory;
159 static char buf[MAXBSIZE];
160 static char buf2[MAXBSIZE];
161 static char lvid[MAXBSIZE];
162 
163 uint32_t ecma_version = 2;
164 
165 static int serialnum = 1;	/* Tag serial number */
166 static char udfs_label[128] = "*NoLabel*";
167 static int acctype = PART_ACC_OW;
168 static uint32_t part_start;
169 static uint32_t part_len;
170 static uint32_t part_bmp_bytes;
171 static uint32_t part_bmp_sectors;
172 static int32_t part_unalloc = -1;
173 static uint32_t filesetblock;
174 
175 /* Set by readvolseq for -m option */
176 static uint32_t oldfssize;
177 static char *oldlabel;
178 
179 int
180 main(int32_t argc, int8_t *argv[])
181 {
182 	long i;
183 	FILE *mnttab;
184 	struct mnttab mntp;
185 	char *special, *raw_special;
186 	struct stat statarea;
187 	struct ustat ustatarea;
188 	int32_t	c;
189 	uint32_t temp_secsz;
190 	int isfs;
191 
192 	(void) setlocale(LC_ALL, "");
193 
194 #if !defined(TEXT_DOMAIN)
195 #define	TEXT_DOMAIN "SYS_TEST"
196 #endif
197 	(void) textdomain(TEXT_DOMAIN);
198 
199 	while ((c = getopt(argc, argv, "F:Vmo:")) != EOF) {
200 		switch (c) {
201 
202 			case 'F':
203 				string = optarg;
204 				if (strcmp(string, "udfs") != 0) {
205 					usage();
206 				}
207 				break;
208 
209 			case 'V':
210 				{
211 					char	*opt_text;
212 					int	opt_count;
213 
214 					(void) fprintf(stdout,
215 					gettext("mkfs -F udfs "));
216 					for (opt_count = 1; opt_count < argc;
217 							opt_count++) {
218 						opt_text = argv[opt_count];
219 						if (opt_text) {
220 							(void) fprintf(stdout,
221 							" %s ", opt_text);
222 						}
223 					}
224 					(void) fprintf(stdout, "\n");
225 				}
226 				break;
227 
228 			case 'm':
229 				/*
230 				 * return command line used
231 				 * to create this FS
232 				 */
233 				mflag++;
234 				break;
235 
236 			case 'o':
237 				/*
238 				 * udfs specific options.
239 				 */
240 				string = optarg;
241 				while (*string != '\0') {
242 					if (match("N")) {
243 						Nflag++;
244 					} else if (match("psize=")) {
245 						number_flags = 0;
246 						sectorsize = number(BIG,
247 							"psize");
248 					} else if (match("label=")) {
249 						for (i = 0; i < 31; i++) {
250 							if (*string == '\0') {
251 								break;
252 							}
253 							udfs_label[i] =
254 								*string++;
255 						}
256 						udfs_label[i] = '\0';
257 					} else if (*string == '\0') {
258 						break;
259 					} else {
260 						(void) fprintf(stdout,
261 							gettext("illegal "
262 							"option: %s\n"),
263 							string);
264 						usage();
265 					}
266 					if (*string == ',') {
267 						string++;
268 					}
269 					if (*string == ' ') {
270 						string++;
271 					}
272 				}
273 				break;
274 
275 			case '?':
276 				usage();
277 				break;
278 		}
279 	}
280 
281 	(void) time(&mkfstime);
282 	if (optind > (argc - 1)) {
283 		usage();
284 	}
285 
286 	argc -= optind;
287 	argv = &argv[optind];
288 	fsys = argv[0];
289 	raw_special = getfullrawname(fsys);
290 	fsi = open(raw_special, 0);
291 	if (fsi < 0) {
292 		(void) fprintf(stdout,
293 			gettext("%s: cannot open\n"), fsys);
294 		exit(32);
295 	}
296 	fso = fsi;
297 
298 	if ((temp_secsz = get_bsize()) != 0) {
299 		sectorsize = temp_secsz;
300 	}
301 
302 	/* Get old file system information */
303 	isfs = readvolseq();
304 
305 	if (mflag) {
306 		/*
307 		 * Figure out the block size and
308 		 * file system size and print the information
309 		 */
310 		if (isfs)
311 			dump_fscmd(fsys, fsi);
312 		else
313 			(void) printf(gettext(
314 				"[not currently a valid file system]\n"));
315 		exit(0);
316 	}
317 
318 	/*
319 	 * Get the disk size from the drive or VTOC for the N and N-256
320 	 * AVDPs and to make sure we don't want to create a file system
321 	 * bigger than the partition.
322 	 */
323 	disk_size = get_last_block();
324 
325 	if (argc < 2 && disk_size == 0 || argc < 1) {
326 		usage();
327 	}
328 
329 	if (argc < 2) {
330 		(void) printf(gettext("No size specified, entire partition "
331 			"of %u sectors used\n"), disk_size);
332 		fssize = disk_size;
333 	} else {
334 		string = argv[1];
335 		number_flags = 0;
336 		fssize = number(BIG, "size");
337 	}
338 
339 	if (fssize < 0) {
340 		(void) fprintf(stderr,
341 			gettext("Negative number of sectors(%d) not allowed\n"),
342 			fssize);
343 		exit(32);
344 	}
345 
346 	if (fssize < (512 * sectorsize / DEV_BSIZE)) {
347 		(void) fprintf(stdout,
348 			gettext("size should be at least %d sectors\n"),
349 			(512 * sectorsize / DEV_BSIZE));
350 		exit(32);
351 	}
352 
353 	if (disk_size != 0) {
354 		if (fssize > disk_size) {
355 			(void) fprintf(stderr, gettext("Invalid size: %d "
356 				"larger than the partition size\n"), fssize);
357 			exit(32);
358 		} else if (fssize < disk_size) {
359 			unused = disk_size - fssize;
360 			(void) printf(
361 			    gettext("File system size %d smaller than "
362 				"partition, %u sectors unused\n"),
363 				fssize, unused);
364 		}
365 	} else {
366 		/* Use passed-in size */
367 		disk_size = fssize;
368 	}
369 
370 	if (!Nflag) {
371 		special = getfullblkname(fsys);
372 
373 		/*
374 		 * If we found the block device name,
375 		 * then check the mount table.
376 		 * if mounted, write lock the file system
377 		 *
378 		 */
379 		if ((special != NULL) && (*special != '\0')) {
380 			mnttab = fopen(MNTTAB, "r");
381 			while ((getmntent(mnttab, &mntp)) == NULL) {
382 				if (strcmp(special, mntp.mnt_special) == 0) {
383 					(void) fprintf(stdout,
384 						gettext("%s is mounted,"
385 						" can't mkfs\n"), special);
386 					exit(32);
387 				}
388 			}
389 			(void) fclose(mnttab);
390 		}
391 		if ((bdevismounted) && (ismounted == 0)) {
392 			(void) fprintf(stdout,
393 				gettext("can't check mount point; "));
394 			(void) fprintf(stdout,
395 				gettext("%s is mounted but not in mnttab(4)\n"),
396 				special);
397 			exit(32);
398 		}
399 		if (directory) {
400 			if (ismounted == 0) {
401 				(void) fprintf(stdout,
402 					gettext("%s is not mounted\n"),
403 					special);
404 				exit(32);
405 			}
406 		}
407 		fso = creat(fsys, 0666);
408 		if (fso < 0) {
409 			(void) fprintf(stdout,
410 				gettext("%s: cannot create\n"), fsys);
411 			exit(32);
412 		}
413 		if (stat(fsys, &statarea) < 0) {
414 			(void) fprintf(stderr,
415 				gettext("%s: %s: cannot stat\n"),
416 				argv[0], fsys);
417 			exit(32);
418 		}
419 		if (ustat(statarea.st_rdev, &ustatarea) >= 0) {
420 			(void) fprintf(stderr,
421 				gettext("%s is mounted, can't mkfs\n"), fsys);
422 			exit(32);
423 		}
424 	} else {
425 		/*
426 		 * For the -N case, a file descriptor is needed for the llseek()
427 		 * in wtfs(). See the comment in wtfs() for more information.
428 		 *
429 		 * Get a file descriptor that's read-only so that this code
430 		 * doesn't accidentally write to the file.
431 		 */
432 		fso = open(fsys, O_RDONLY);
433 		if (fso < 0) {
434 			(void) fprintf(stderr, gettext("%s: cannot open\n"),
435 				fsys);
436 			exit(32);
437 		}
438 	}
439 
440 
441 	/*
442 	 * Validate the given file system size.
443 	 * Verify that its last block can actually be accessed.
444 	 */
445 	fssize = fssize / (sectorsize / DEV_BSIZE);
446 	if (fssize <= 0) {
447 		(void) fprintf(stdout,
448 			gettext("preposterous size %d. sectors\n"), fssize);
449 		exit(32);
450 	}
451 	fssize --;
452 
453 	/*
454 	 * verify device size
455 	 */
456 	rdfs(fssize - 1, sectorsize, buf);
457 
458 	if ((sectorsize < DEV_BSIZE) ||
459 		(sectorsize > MAXBSIZE)) {
460 		(void) fprintf(stdout,
461 			gettext("sector size must be"
462 			" between 512, 8192 bytes\n"));
463 	}
464 	if (!POWEROF2(sectorsize)) {
465 		(void) fprintf(stdout,
466 			gettext("sector size must be a power of 2, not %d\n"),
467 			sectorsize);
468 		exit(32);
469 	}
470 	if (Nflag) {
471 		exit(0);
472 	}
473 
474 	(void) printf(gettext("Creating file system with sector size of "
475 		"%d bytes\n"), sectorsize);
476 
477 	/*
478 	 * Set up time stamp values
479 	 */
480 	mkfstime = time(0);
481 	(void) localtime_r(&mkfstime, &res);
482 	if (res.tm_isdst > 0) {
483 		tzone = altzone / 60;
484 	} else if (res.tm_isdst == 0) {
485 		tzone = tzone / 60;
486 	} else {
487 		tzone = 2047;	/* Unknown */
488 	}
489 
490 	/*
491 	 * Initialize the volume recognition sequence, the volume descriptor
492 	 * sequences and the anchor pointer.
493 	 */
494 	volseqinit();
495 
496 	(void) fsync(fso);
497 	(void) close(fsi);
498 	(void) close(fso);
499 
500 	return (0);
501 }
502 
503 static void
504 setstamp(tstamp_t *tp)
505 {
506 	tp->ts_usec = 0;
507 	tp->ts_husec = 0;
508 	tp->ts_csec = 0;
509 
510 	tp->ts_sec = res.tm_sec;
511 	tp->ts_min = res.tm_min;
512 	tp->ts_hour = res.tm_hour;
513 	tp->ts_day = res.tm_mday;
514 	tp->ts_month = res.tm_mon + 1;
515 	tp->ts_year = 1900 + res.tm_year;
516 
517 	tp->ts_tzone = 0x1000 + (-tzone & 0xFFF);
518 }
519 
520 static void
521 setextad(extent_ad_t *eap, uint32_t len, uint32_t loc)
522 {
523 	eap->ext_len = len;
524 	eap->ext_loc = loc;
525 }
526 
527 static void
528 setdstring(dstring_t *dp, char *cp, int len)
529 {
530 	int32_t length;
531 
532 	bzero(dp, len);
533 	length = strlen(cp);
534 	if (length > len - 3) {
535 		length = len - 3;
536 	}
537 	dp[len - 1] = length + 1;
538 	*dp++ = 8;
539 	(void) strncpy(dp, cp, len-2);
540 }
541 
542 static void
543 wtvolseq(tag_t *tp, daddr_t blk1, daddr_t blk2)
544 {
545 	static uint32_t vdsn = 0;
546 
547 	tp->tag_loc = blk1;
548 	switch (tp->tag_id) {
549 	case UD_PRI_VOL_DESC :
550 		((struct pri_vol_desc *)tp)->pvd_vdsn = vdsn++;
551 		break;
552 	case UD_VOL_DESC_PTR :
553 		((struct vol_desc_ptr *)tp)->vdp_vdsn = vdsn++;
554 		break;
555 	case UD_IMPL_USE_DESC :
556 		((struct iuvd_desc *)tp)->iuvd_vdsn = vdsn++;
557 		break;
558 	case UD_PART_DESC :
559 		((struct part_desc *)tp)->pd_vdsn = vdsn++;
560 		break;
561 	case UD_LOG_VOL_DESC :
562 		((struct log_vol_desc *)tp)->lvd_vdsn = vdsn++;
563 		break;
564 	case UD_UNALL_SPA_DESC :
565 		((struct unall_spc_desc *)tp)->ua_vdsn = vdsn++;
566 		break;
567 	}
568 
569 	bzero(buf2, sectorsize);
570 	/* LINTED */
571 	maketag(tp, (struct tag *)buf2);
572 
573 	/*
574 	 * Write at Main Volume Descriptor Sequence
575 	 */
576 	wtfs(blk1, sectorsize, buf2);
577 
578 	tp->tag_loc = blk2;
579 	switch (tp->tag_id) {
580 	case UD_PRI_VOL_DESC :
581 		((struct pri_vol_desc *)tp)->pvd_vdsn = vdsn++;
582 		break;
583 	case UD_VOL_DESC_PTR :
584 		((struct vol_desc_ptr *)tp)->vdp_vdsn = vdsn++;
585 		break;
586 	case UD_IMPL_USE_DESC :
587 		((struct iuvd_desc *)tp)->iuvd_vdsn = vdsn++;
588 		break;
589 	case UD_PART_DESC :
590 		((struct part_desc *)tp)->pd_vdsn = vdsn++;
591 		break;
592 	case UD_LOG_VOL_DESC :
593 		((struct log_vol_desc *)tp)->lvd_vdsn = vdsn++;
594 		break;
595 	case UD_UNALL_SPA_DESC :
596 		((struct unall_spc_desc *)tp)->ua_vdsn = vdsn++;
597 		break;
598 	}
599 	maketag(tp, tp);
600 	/*
601 	 * Write at Reserve Volume Descriptor Sequence
602 	 */
603 	wtfs(blk2, sectorsize, buf);
604 }
605 
606 static void
607 volseqinit()
608 {
609 	struct tag *tp;
610 	struct nsr_desc *nsp;
611 	struct pri_vol_desc *pvdp;
612 	struct iuvd_desc *iudp;
613 	struct part_desc *pp;
614 	struct phdr_desc *php;
615 	struct log_vol_desc *lvp;
616 	long_ad_t *lap;
617 	struct pmap_typ1 *pmp;
618 	struct unall_spc_desc *uap;
619 	struct log_vol_int_desc *lvip;
620 	struct term_desc *tdp;
621 	struct anch_vol_desc_ptr *avp;
622 	struct lvid_iu *lviup;
623 	struct file_set_desc *fsp;
624 	struct file_entry *fp;
625 	struct icb_tag *icb;
626 	struct short_ad *sap;
627 	struct file_id *fip;
628 	struct space_bmap_desc *sbp;
629 	uint8_t *cp;
630 	daddr_t nextblock, endblock;
631 	int32_t volseq_sectors, nextlogblock, rootfelen, i;
632 	uint32_t mvds_loc, rvds_loc;
633 
634 	bzero(buf, MAXBSIZE);
635 
636 	/*
637 	 * Starting from MAXBSIZE, clear out till 256 sectors.
638 	 */
639 	for (i = MAXBSIZE / sectorsize; i < FIRSTAVDP; i++) {
640 		wtfs(i, sectorsize, buf);
641 	}
642 
643 	/* Zero out the avdp at N - 257 */
644 	wtfs(fssize - 256, sectorsize, buf);
645 
646 	/*
647 	 * Leave 1st 32K for O.S.
648 	 */
649 	nextblock = VOLRECSTART / sectorsize;
650 
651 	/*
652 	 * Write BEA01/NSR02/TEA01 sequence.
653 	 * Each one must be 2K bytes in length.
654 	 */
655 	nsp = (struct nsr_desc *)buf;
656 	nsp->nsr_str_type = 0;
657 	nsp->nsr_ver = 1;
658 	(void) strncpy((int8_t *)nsp->nsr_id, "BEA01", 5);
659 
660 	nsp = (struct nsr_desc *)&buf[2048];
661 	nsp->nsr_str_type = 0;
662 	nsp->nsr_ver = 1;
663 	(void) strncpy((int8_t *)nsp->nsr_id, "NSR02", 5);
664 
665 	nsp = (struct nsr_desc *)&buf[4096];
666 	nsp->nsr_str_type = 0;
667 	nsp->nsr_ver = 1;
668 	(void) strncpy((int8_t *)nsp->nsr_id, "TEA01", 5);
669 
670 	wtfs(nextblock, 8192, buf);
671 	bzero(buf, MAXBSIZE);
672 
673 	/*
674 	 * Minimum length of volume sequences
675 	 */
676 	volseq_sectors = 16;
677 
678 	/*
679 	 * Round up to next 32K boundary for
680 	 * volume descriptor sequences
681 	 */
682 	nextblock = VOLSEQSTART;
683 	bzero(buf, sectorsize);
684 	mvds_loc = VOLSEQSTART;
685 	rvds_loc = mvds_loc + volseq_sectors;
686 
687 	/*
688 	 * Primary Volume Descriptor
689 	 */
690 	/* LINTED */
691 	pvdp = (struct pri_vol_desc *)buf;
692 	tp = &pvdp->pvd_tag;
693 	tp->tag_id =  UD_PRI_VOL_DESC;
694 	tp->tag_desc_ver = ecma_version;
695 	tp->tag_sno = serialnum;
696 	tp->tag_crc_len = sizeof (struct pri_vol_desc) -
697 			sizeof (struct tag);
698 	pvdp->pvd_vdsn = 0;
699 	pvdp->pvd_pvdn = 0;
700 	setdstring(pvdp->pvd_vol_id, udfs_label, 32);
701 	pvdp->pvd_vsn = 1;
702 	pvdp->pvd_mvsn = 1;
703 	pvdp->pvd_il = 2;		/* Single-volume */
704 	pvdp->pvd_mil = 3;		/* Multi-volume */
705 	pvdp->pvd_csl = 1;		/* CS0 */
706 	pvdp->pvd_mcsl = 1;		/* CS0 */
707 	(void) sprintf(vsibuf, "%08X", SWAP_32((uint32_t)mkfstime));
708 	setdstring(pvdp->pvd_vsi, vsibuf, 128);
709 	(void) strncpy(pvdp->pvd_vsi + 17, udfs_label, 128 - 17);
710 	setcharspec(&pvdp->pvd_desc_cs, 0, osta_unicode);
711 	setcharspec(&pvdp->pvd_exp_cs, 0, osta_unicode);
712 	setextad(&pvdp->pvd_vol_abs, 0, 0);
713 	setextad(&pvdp->pvd_vcn, 0, 0);
714 	bzero(&pvdp->pvd_appl_id, sizeof (regid_t));
715 	setstamp(&pvdp->pvd_time);
716 	bcopy(&sunmicro, &pvdp->pvd_ii, sizeof (regid_t));
717 	pvdp->pvd_flags = 0;
718 	wtvolseq(tp, nextblock, nextblock + volseq_sectors);
719 	nextblock++;
720 
721 	/*
722 	 * Implementation Use Descriptor
723 	 */
724 	bzero(buf, sectorsize);
725 	/* LINTED */
726 	iudp = (struct iuvd_desc *)buf;
727 	tp = &iudp->iuvd_tag;
728 	tp->tag_id =  UD_IMPL_USE_DESC;
729 	tp->tag_desc_ver = ecma_version;
730 	tp->tag_sno = serialnum;
731 	tp->tag_crc_len = sizeof (struct iuvd_desc) -
732 			sizeof (struct tag);
733 	iudp->iuvd_vdsn = 0;
734 	bcopy(&lvinfo, &iudp->iuvd_ii, sizeof (regid_t));
735 	setcharspec(&iudp->iuvd_cset, 0, osta_unicode);
736 	setdstring(iudp->iuvd_lvi, udfs_label, 128);
737 
738 	setdstring(iudp->iuvd_ifo1, "", 36);
739 	setdstring(iudp->iuvd_ifo2, "", 36);
740 	setdstring(iudp->iuvd_ifo3, "", 36);
741 
742 
743 	/*
744 	 * info1,2,3 = user specified
745 	 */
746 	bcopy(&sunmicro, &iudp->iuvd_iid, sizeof (regid_t));
747 	wtvolseq(tp, nextblock, nextblock + volseq_sectors);
748 	nextblock++;
749 
750 	/*
751 	 * Partition Descriptor
752 	 */
753 	bzero(buf, sectorsize);
754 	/* LINTED */
755 	pp = (struct part_desc *)buf;
756 	tp = &pp->pd_tag;
757 	tp->tag_id =  UD_PART_DESC;
758 	tp->tag_desc_ver = ecma_version;
759 	tp->tag_sno = serialnum;
760 	tp->tag_crc_len = sizeof (struct part_desc) -
761 			sizeof (struct tag);
762 	pp->pd_vdsn = 0;
763 	pp->pd_pflags = 1;			/* Allocated */
764 	pp->pd_pnum = 0;
765 	bcopy(&partid, &pp->pd_pcontents, sizeof (regid_t));
766 
767 	part_start = FIRSTAVDP + AVDPLEN;
768 	part_len = fssize - part_start;
769 	part_bmp_bytes = (part_len + NBBY - 1) / NBBY;
770 	part_bmp_sectors = (part_bmp_bytes + SPACEMAP_OFF + sectorsize - 1) /
771 		sectorsize;
772 
773 	pp->pd_part_start = part_start;
774 	pp->pd_part_length = part_len;
775 
776 	pp->pd_acc_type = acctype;
777 	nextlogblock = 0;
778 
779 	/*
780 	 * Do the partition header
781 	 */
782 	/* LINTED */
783 	php = (struct phdr_desc *)&pp->pd_pc_use;
784 
785 	/*
786 	 * Set up unallocated space bitmap
787 	 */
788 	if (acctype == PART_ACC_RW || acctype == PART_ACC_OW) {
789 		php->phdr_usb.sad_ext_len =
790 			(part_bmp_bytes + SPACEMAP_OFF + sectorsize - 1) &
791 				(~(sectorsize - 1));
792 		php->phdr_usb.sad_ext_loc = nextlogblock;
793 		part_unalloc = nextlogblock;
794 		nextlogblock += part_bmp_sectors;
795 	}
796 
797 	bcopy(&sunmicro, &pp->pd_ii, sizeof (regid_t));
798 	wtvolseq(tp, nextblock, nextblock + volseq_sectors);
799 	nextblock++;
800 
801 	/*
802 	 * Logical Volume Descriptor
803 	 */
804 	bzero(buf, sectorsize);
805 	/* LINTED */
806 	lvp = (struct log_vol_desc *)buf;
807 	tp = &lvp->lvd_tag;
808 	tp->tag_id =  UD_LOG_VOL_DESC;
809 	tp->tag_desc_ver = ecma_version;
810 	tp->tag_sno = serialnum;
811 	tp->tag_crc_len = sizeof (struct log_vol_desc) -
812 			sizeof (struct tag);
813 	lvp->lvd_vdsn = 0;
814 	setcharspec(&lvp->lvd_desc_cs, 0, osta_unicode);
815 	setdstring(lvp->lvd_lvid, udfs_label, 128);
816 	lvp->lvd_log_bsize = sectorsize;
817 	bcopy(&udf_compliant, &lvp->lvd_dom_id, sizeof (regid_t));
818 	lap = (long_ad_t *)&lvp->lvd_lvcu;
819 	lap->lad_ext_len = FILESETLEN * sectorsize;
820 	filesetblock = nextlogblock;
821 	lap->lad_ext_loc = nextlogblock;
822 	lap->lad_ext_prn = 0;
823 	lvp->lvd_mtbl_len = 6;
824 	lvp->lvd_num_pmaps = 1;
825 	bcopy(&sunmicro, &lvp->lvd_ii, sizeof (regid_t));
826 	/* LINTED */
827 	pmp = (struct pmap_typ1 *)&lvp->lvd_pmaps;
828 	pmp->map1_type = 1;
829 	pmp->map1_length = 6;
830 	pmp->map1_vsn = SWAP_16(1);
831 	pmp->map1_pn  = 0;
832 	tp->tag_crc_len = (char *)(pmp + 1) - buf - sizeof (struct tag);
833 	setextad(&lvp->lvd_int_seq_ext, INTSEQLEN, INTSEQSTART);
834 	wtvolseq(tp, nextblock, nextblock + volseq_sectors);
835 	nextblock++;
836 
837 	/*
838 	 * Unallocated Space Descriptor
839 	 */
840 	bzero(buf, sectorsize);
841 	/* LINTED */
842 	uap = (struct unall_spc_desc *)buf;
843 	tp = &uap->ua_tag;
844 	tp->tag_id =  UD_UNALL_SPA_DESC;
845 	tp->tag_desc_ver = ecma_version;
846 	tp->tag_sno = serialnum;
847 	uap->ua_vdsn = 0;
848 	uap->ua_nad = 0;
849 	tp->tag_crc_len = (char *)uap->ua_al_dsc - buf - sizeof (struct tag);
850 	wtvolseq(tp, nextblock, nextblock + volseq_sectors);
851 	nextblock++;
852 
853 	/*
854 	 * Terminating Descriptor
855 	 */
856 	bzero(buf, sectorsize);
857 	/* LINTED */
858 	tdp = (struct term_desc *)buf;
859 	tp = &tdp->td_tag;
860 	tp->tag_id =  UD_TERM_DESC;
861 	tp->tag_desc_ver = ecma_version;
862 	tp->tag_sno = serialnum;
863 	tp->tag_crc_len = sizeof (struct term_desc) -
864 			sizeof (struct tag);
865 	tp->tag_loc = nextblock;
866 	wtvolseq(tp, nextblock, nextblock + volseq_sectors);
867 	nextblock++;
868 
869 	/*
870 	 * Do the anchor volume descriptor
871 	 */
872 	if (nextblock > FIRSTAVDP) {
873 		(void) fprintf(stdout,
874 			gettext("Volume integrity sequence"
875 			" descriptors too long\n"));
876 		exit(32);
877 	}
878 
879 	nextblock = FIRSTAVDP;
880 	bzero(buf, sectorsize);
881 	/* LINTED */
882 	avp = (struct anch_vol_desc_ptr *)buf;
883 	tp = &avp->avd_tag;
884 	tp->tag_id =  UD_ANCH_VOL_DESC;
885 	tp->tag_desc_ver = ecma_version;
886 	tp->tag_sno = serialnum;
887 	tp->tag_crc_len = sizeof (struct anch_vol_desc_ptr) -
888 			sizeof (struct tag);
889 	tp->tag_loc = nextblock;
890 	setextad(&avp->avd_main_vdse,
891 			volseq_sectors * sectorsize, mvds_loc);
892 	setextad(&avp->avd_res_vdse,
893 			volseq_sectors * sectorsize, rvds_loc);
894 	bzero(buf2, sectorsize);
895 	/* LINTED */
896 	maketag(tp, (struct tag *)buf2);
897 	wtfs(nextblock, sectorsize, buf2);
898 	nextblock++;
899 
900 	tp->tag_loc = fssize;
901 	/* LINTED */
902 	maketag(tp, (struct tag *)buf2);
903 	wtfs(fssize, sectorsize, buf2);
904 
905 	/*
906 	 * File Set Descriptor
907 	 */
908 	bzero(buf, sectorsize);
909 	/* LINTED */
910 	fsp = (struct file_set_desc *)&buf;
911 	tp = &fsp->fsd_tag;
912 	tp->tag_id =  UD_FILE_SET_DESC;
913 	tp->tag_desc_ver = ecma_version;
914 	tp->tag_sno = serialnum;
915 	tp->tag_crc_len = sizeof (struct file_set_desc) -
916 			sizeof (struct tag);
917 	tp->tag_loc = nextlogblock;
918 	setstamp(&fsp->fsd_time);
919 	fsp->fsd_ilevel = 3;
920 	fsp->fsd_mi_level = 3;
921 	fsp->fsd_cs_list = 1;
922 	fsp->fsd_mcs_list = 1;
923 	fsp->fsd_fs_no = 0;
924 	fsp->fsd_fsd_no = 0;
925 	setcharspec(&fsp->fsd_lvidcs, 0, osta_unicode);
926 	setdstring(fsp->fsd_lvid, udfs_label, 128);
927 	setcharspec(&fsp->fsd_fscs, 0, osta_unicode);
928 	setdstring(fsp->fsd_fsi, udfs_label, 32);
929 	setdstring(fsp->fsd_cfi, "", 32);
930 	setdstring(fsp->fsd_afi, "", 32);
931 	lap = (long_ad_t *)&fsp->fsd_root_icb;
932 	lap->lad_ext_len = sectorsize;
933 	lap->lad_ext_loc = filesetblock + FILESETLEN;
934 	lap->lad_ext_prn = 0;
935 	bcopy(&udf_compliant, &fsp->fsd_did, sizeof (regid_t));
936 	maketag(tp, tp);
937 	wtfs(nextlogblock + part_start, sectorsize, (char *)tp);
938 	nextlogblock++;
939 
940 	/*
941 	 * Terminating Descriptor
942 	 */
943 	bzero(buf, sectorsize);
944 	/* LINTED */
945 	tdp = (struct term_desc *)buf;
946 	tp = &tdp->td_tag;
947 	tp->tag_id =  UD_TERM_DESC;
948 	tp->tag_desc_ver = ecma_version;
949 	tp->tag_sno = serialnum;
950 	tp->tag_crc_len = sizeof (struct term_desc) -
951 			sizeof (struct tag);
952 	tp->tag_loc = nextlogblock;
953 	maketag(tp, tp);
954 	wtfs(nextlogblock + part_start, sectorsize, (char *)tp);
955 	nextlogblock++;
956 
957 	if (nextlogblock > filesetblock + FILESETLEN) {
958 		(void) fprintf(stdout,
959 			gettext("File set descriptor too long\n"));
960 		exit(32);
961 	}
962 	nextlogblock = filesetblock + FILESETLEN;
963 
964 	/*
965 	 * Root File Entry
966 	 */
967 	bzero(buf, sectorsize);
968 	/* LINTED */
969 	fp = (struct file_entry *)&buf;
970 	tp = &fp->fe_tag;
971 	tp->tag_id =  UD_FILE_ENTRY;
972 	tp->tag_desc_ver = ecma_version;
973 	tp->tag_sno = serialnum;
974 	tp->tag_loc = nextlogblock;
975 	icb = &fp->fe_icb_tag;
976 	icb->itag_prnde = 0;
977 	icb->itag_strategy = STRAT_TYPE4;
978 	icb->itag_param = 0; /* what does this mean? */
979 	icb->itag_max_ent = 1;
980 	icb->itag_ftype = FTYPE_DIRECTORY;
981 	icb->itag_lb_loc = 0;
982 	icb->itag_lb_prn = 0;
983 	icb->itag_flags = ICB_FLAG_ARCHIVE;
984 	fp->fe_uid = getuid();
985 	fp->fe_gid = getgid();
986 	fp->fe_perms = (0x1f << 10) | (0x5 << 5) | 0x5;
987 	fp->fe_lcount = 1;
988 	fp->fe_rec_for = 0;
989 	fp->fe_rec_dis = 0;
990 	fp->fe_rec_len = 0;
991 	fp->fe_info_len = sizeof (struct file_id);
992 	fp->fe_lbr = 1;
993 	setstamp(&fp->fe_acc_time);
994 	setstamp(&fp->fe_mod_time);
995 	setstamp(&fp->fe_attr_time);
996 	fp->fe_ckpoint = 1;
997 	bcopy(&sunmicro, &fp->fe_impl_id, sizeof (regid_t));
998 	fp->fe_uniq_id = 0;
999 	fp->fe_len_ear = 0;
1000 	fp->fe_len_adesc = sizeof (short_ad_t);
1001 
1002 	/* LINTED */
1003 	sap = (short_ad_t *)(fp->fe_spec + fp->fe_len_ear);
1004 	sap->sad_ext_len = sizeof (struct file_id);
1005 	sap->sad_ext_loc = nextlogblock + 1;
1006 	rootfelen = (char *)(sap + 1) - buf;
1007 	tp->tag_crc_len = rootfelen - sizeof (struct tag);
1008 	maketag(tp, tp);
1009 	wtfs(nextlogblock + part_start, sectorsize, (char *)tp);
1010 	nextlogblock++;
1011 
1012 	/*
1013 	 * Root Directory
1014 	 */
1015 	bzero(buf, sectorsize);
1016 	/* LINTED */
1017 	fip = (struct file_id *)&buf;
1018 	tp = &fip->fid_tag;
1019 	tp->tag_id =  UD_FILE_ID_DESC;
1020 	tp->tag_desc_ver = ecma_version;
1021 	tp->tag_sno = serialnum;
1022 	tp->tag_crc_len = sizeof (struct file_id) -
1023 			sizeof (struct tag);
1024 	tp->tag_loc = nextlogblock;
1025 	fip->fid_ver = 1;
1026 	fip->fid_flags = FID_DIR | FID_PARENT;
1027 	fip->fid_idlen = 0;
1028 	fip->fid_iulen = 0;
1029 	fip->fid_icb.lad_ext_len = sectorsize; /* rootfelen; */
1030 	fip->fid_icb.lad_ext_loc = nextlogblock - 1;
1031 	fip->fid_icb.lad_ext_prn = 0;
1032 	maketag(tp, tp);
1033 	wtfs(nextlogblock + part_start, sectorsize, (char *)tp);
1034 	nextlogblock++;
1035 
1036 	/*
1037 	 * Now do the space bitmaps
1038 	 */
1039 	if (part_unalloc >= 0) {
1040 		int size = sectorsize * part_bmp_sectors;
1041 
1042 		sbp = (struct space_bmap_desc *)malloc(size);
1043 		if (!sbp) {
1044 			(void) fprintf(stdout,
1045 				gettext("Can't allocate bitmap space\n"));
1046 			exit(32);
1047 		}
1048 		bzero((char *)sbp, sectorsize * part_bmp_sectors);
1049 		tp = &sbp->sbd_tag;
1050 		tp->tag_id =  UD_SPA_BMAP_DESC;
1051 		tp->tag_desc_ver = ecma_version;
1052 		tp->tag_sno = serialnum;
1053 		tp->tag_crc_len = 0;	/* Don't do CRCs on bitmaps */
1054 		tp->tag_loc = part_unalloc;
1055 		sbp->sbd_nbits = part_len;
1056 		sbp->sbd_nbytes = part_bmp_bytes;
1057 		maketag(tp, tp);
1058 		if (part_unalloc >= 0) {
1059 			int32_t i;
1060 
1061 			cp = (uint8_t *)sbp + SPACEMAP_OFF;
1062 			i = nextlogblock / NBBY;
1063 			cp[i++] = (0xff << (nextlogblock % NBBY)) & 0xff;
1064 			while (i < part_bmp_bytes)
1065 				cp[i++] = 0xff;
1066 			if (part_len % NBBY)
1067 				cp[--i] = (unsigned)0xff >>
1068 					(NBBY - part_len % NBBY);
1069 
1070 			wtfs(part_unalloc + part_start, size, (char *)tp);
1071 		}
1072 		free((char *)sbp);
1073 	}
1074 
1075 	/*
1076 	 * Volume Integrity Descriptor
1077 	 */
1078 	nextblock = INTSEQSTART;
1079 	endblock = nextblock + INTSEQLEN / sectorsize;
1080 	/* LINTED */
1081 	lvip = (struct log_vol_int_desc *)&lvid;
1082 	tp = &lvip->lvid_tag;
1083 	tp->tag_id =  UD_LOG_VOL_INT;
1084 	tp->tag_desc_ver = ecma_version;
1085 	tp->tag_sno = serialnum;
1086 	tp->tag_loc = nextblock;
1087 	setstamp(&lvip->lvid_tstamp);
1088 	lvip->lvid_int_type = LOG_VOL_CLOSE_INT;
1089 	setextad(&lvip->lvid_nie, 0, 0);
1090 	lvip->lvid_npart = 1;
1091 	lvip->lvid_liu = 0x2e;
1092 	lvip->lvid_uniqid = MAXID + 1;
1093 	lvip->lvid_fst[0] = part_len - nextlogblock;	/* Free space */
1094 	lvip->lvid_fst[1] = part_len;			/* Size */
1095 	lviup = (struct lvid_iu *)&lvip->lvid_fst[2];
1096 	bcopy(&sunmicro, &lviup->lvidiu_regid, sizeof (regid_t));
1097 	lviup->lvidiu_nfiles = 0;
1098 	lviup->lvidiu_ndirs = 1;
1099 	lviup->lvidiu_mread = 0x102;
1100 	lviup->lvidiu_mwrite = 0x102;
1101 	lviup->lvidiu_maxwr = 0x150;
1102 	tp->tag_crc_len = sizeof (struct log_vol_int_desc) + lvip->lvid_liu -
1103 		sizeof (struct tag);
1104 	maketag(tp, tp);
1105 	wtfs(nextblock, sectorsize, (char *)tp);
1106 	nextblock++;
1107 
1108 	/*
1109 	 * Terminating Descriptor
1110 	 */
1111 	bzero(buf, sectorsize);
1112 	/* LINTED */
1113 	tdp = (struct term_desc *)buf;
1114 	tp = &tdp->td_tag;
1115 	tp->tag_id =  UD_TERM_DESC;
1116 	tp->tag_desc_ver = ecma_version;
1117 	tp->tag_sno = serialnum;
1118 	tp->tag_crc_len = sizeof (struct term_desc) - sizeof (struct tag);
1119 	tp->tag_loc = nextblock;
1120 	maketag(tp, tp);
1121 	wtfs(nextblock, sectorsize, (char *)tp);
1122 	nextblock++;
1123 
1124 	/* Zero out the rest of the LVI extent */
1125 	bzero(buf, sectorsize);
1126 	while (nextblock < endblock)
1127 		wtfs(nextblock++, sectorsize, buf);
1128 }
1129 
1130 /*
1131  * read a block from the file system
1132  */
1133 static void
1134 rdfs(daddr_t bno, int size, char *bf)
1135 {
1136 	int n, saverr;
1137 
1138 	if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) {
1139 		saverr = errno;
1140 		(void) fprintf(stderr,
1141 			gettext("seek error on sector %ld: %s\n"),
1142 			bno, strerror(saverr));
1143 		exit(32);
1144 	}
1145 	n = read(fsi, bf, size);
1146 	if (n != size) {
1147 		saverr = errno;
1148 		(void) fprintf(stderr,
1149 			gettext("read error on sector %ld: %s\n"),
1150 			bno, strerror(saverr));
1151 		exit(32);
1152 	}
1153 }
1154 
1155 /*
1156  * write a block to the file system
1157  */
1158 static void
1159 wtfs(daddr_t bno, int size, char *bf)
1160 {
1161 	int n, saverr;
1162 
1163 	if (fso == -1)
1164 		return;
1165 
1166 	if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
1167 		saverr = errno;
1168 		(void) fprintf(stderr,
1169 			gettext("seek error on sector %ld: %s\n"),
1170 			bno, strerror(saverr));
1171 		exit(32);
1172 	}
1173 	if (Nflag)
1174 		return;
1175 	n = write(fso, bf, size);
1176 	if (n != size) {
1177 		saverr = errno;
1178 		(void) fprintf(stderr,
1179 			gettext("write error on sector %ld: %s\n"),
1180 			bno, strerror(saverr));
1181 		exit(32);
1182 	}
1183 }
1184 
1185 static void
1186 usage()
1187 {
1188 	(void) fprintf(stderr,
1189 		gettext("udfs usage: mkfs [-F FSType] [-V]"
1190 		" [-m] [-o options] special size(sectors)\n"));
1191 	(void) fprintf(stderr,
1192 		gettext(" -m : dump fs cmd line used to make"
1193 		" this partition\n"));
1194 	(void) fprintf(stderr,
1195 		gettext(" -V : print this command line and return\n"));
1196 	(void) fprintf(stderr,
1197 		gettext(" -o : udfs options: :psize=%d:label=%s\n"),
1198 		sectorsize, udfs_label);
1199 	(void) fprintf(stderr,
1200 		gettext("NOTE that all -o suboptions: must"
1201 		" be separated only by commas so as to\n"));
1202 	(void) fprintf(stderr,
1203 		gettext("be parsed as a single argument\n"));
1204 	exit(32);
1205 }
1206 
1207 /*ARGSUSED*/
1208 static void
1209 dump_fscmd(char *fsys, int fsi)
1210 {
1211 	(void) printf(gettext("mkfs -F udfs -o "));
1212 	(void) printf("psize=%d,label=\"%s\" %s %d\n",
1213 		sectorsize, oldlabel, fsys, oldfssize);
1214 }
1215 
1216 /* number ************************************************************* */
1217 /*									*/
1218 /* Convert a numeric arg to binary					*/
1219 /*									*/
1220 /* Arg:	 big - maximum valid input number				*/
1221 /* Global arg:  string - pointer to command arg				*/
1222 /*									*/
1223 /* Valid forms: 123 | 123k | 123*123 | 123x123				*/
1224 /*									*/
1225 /* Return:	converted number					*/
1226 /*									*/
1227 /* ******************************************************************** */
1228 
1229 static int32_t
1230 number(long big, char *param)
1231 {
1232 	char		*cs;
1233 	int64_t		n = 0;
1234 	int64_t		cut = BIG;
1235 	int32_t		minus = 0;
1236 
1237 #define	FOUND_MULT	0x1
1238 #define	FOUND_K		0x2
1239 
1240 	cs = string;
1241 	if (*cs == '-') {
1242 		minus = 1;
1243 		cs++;
1244 	}
1245 	n = 0;
1246 	while ((*cs != ' ') && (*cs != '\0') && (*cs != ',')) {
1247 		if ((*cs >= '0') && (*cs <= '9')) {
1248 			n = n * 10 + *cs - '0';
1249 			cs++;
1250 		} else if ((*cs == '*') || (*cs == 'x')) {
1251 			if (number_flags & FOUND_MULT) {
1252 				(void) fprintf(stderr,
1253 				gettext("mkfs: only one \"*\" "
1254 				"or \"x\" allowed\n"));
1255 				exit(2);
1256 			}
1257 			number_flags |= FOUND_MULT;
1258 			cs++;
1259 			string = cs;
1260 			n = n * number(big, param);
1261 			cs = string;
1262 			continue;
1263 		} else if (*cs == 'k') {
1264 			if (number_flags & FOUND_K) {
1265 				(void) fprintf(stderr,
1266 				gettext("mkfs: only one \"k\" allowed\n"));
1267 				exit(2);
1268 			}
1269 			number_flags |= FOUND_K;
1270 			n = n * 1024;
1271 			cs++;
1272 			continue;
1273 		} else {
1274 			(void) fprintf(stderr,
1275 				gettext("mkfs: bad numeric arg: \"%s\"\n"),
1276 				string);
1277 			exit(2);
1278 		}
1279 	}
1280 
1281 	if (n > cut) {
1282 		(void) fprintf(stderr,
1283 			gettext("mkfs: value for %s overflowed\n"), param);
1284 		exit(2);
1285 	}
1286 
1287 	if (minus) {
1288 		n = -n;
1289 	}
1290 
1291 	if ((n > big) || (n < 0)) {
1292 		(void) fprintf(stderr,
1293 			gettext("mkfs: argument %s out of range\n"), param);
1294 		exit(2);
1295 	}
1296 
1297 	string = cs;
1298 	return ((int32_t)n);
1299 }
1300 
1301 /* match ************************************************************** */
1302 /*									*/
1303 /* Compare two text strings for equality				*/
1304 /*									*/
1305 /* Arg:	 s - pointer to string to match with a command arg		*/
1306 /* Global arg:  string - pointer to command arg				*/
1307 /*									*/
1308 /* Return:	1 if match, 0 if no match				*/
1309 /*		If match, also reset `string' to point to the text	*/
1310 /*		that follows the matching text.				*/
1311 /*									*/
1312 /* ******************************************************************** */
1313 
1314 static int
1315 match(char *s)
1316 {
1317 	char *cs;
1318 
1319 	cs = string;
1320 	while (*cs++ == *s) {
1321 		if (*s++ == '\0') {
1322 			goto true;
1323 		}
1324 	}
1325 	if (*s != '\0') {
1326 		return (0);
1327 	}
1328 
1329 true:
1330 	cs--;
1331 	string = cs;
1332 	return (1);
1333 }
1334 
1335 static uint32_t
1336 get_bsize()
1337 {
1338 	struct dk_cinfo info;
1339 	struct fd_char fd_char;
1340 
1341 	if (ioctl(fso, DKIOCINFO, &info) < 0) {
1342 		perror("mkfs DKIOCINFO ");
1343 		(void) fprintf(stdout,
1344 			gettext("DKIOCINFO failed using psize = 2048"
1345 			" for creating file-system\n"));
1346 		return (0);
1347 	}
1348 
1349 	switch (info.dki_ctype) {
1350 		case DKC_CDROM :
1351 			return (2048);
1352 		case DKC_SCSI_CCS :
1353 			/* FALLTHROUGH */
1354 		case DKC_INTEL82072 :
1355 			/* FALLTHROUGH */
1356 		case DKC_INTEL82077 :
1357 			/* FALLTHROUGH */
1358 		case DKC_DIRECT :
1359 			if (ioctl(fso, FDIOGCHAR, &fd_char) >= 0) {
1360 				return (fd_char.fdc_sec_size);
1361 			}
1362 			/* FALLTHROUGH */
1363 		case DKC_PCMCIA_ATA :
1364 			return (512);
1365 		default :
1366 			return (0);
1367 	}
1368 }
1369 
1370 /*
1371  * Read in the volume sequences descriptors.
1372  */
1373 static int
1374 readvolseq()
1375 {
1376 	struct tag *tp;
1377 	uint8_t *cp, *end;
1378 	int err;
1379 	struct pri_vol_desc *pvolp;
1380 	struct part_desc *partp;
1381 	struct log_vol_desc *logvp;
1382 	struct anch_vol_desc_ptr *avp;
1383 	char *main_vdbuf;
1384 	uint32_t nextblock;
1385 
1386 	avp = (struct anch_vol_desc_ptr *)malloc(sectorsize);
1387 	rdfs(FIRSTAVDP, sectorsize, (char *)avp);
1388 	tp = (struct tag *)avp;
1389 	err = verifytag(tp, FIRSTAVDP, tp, UD_ANCH_VOL_DESC);
1390 	if (err)
1391 		return (0);
1392 	main_vdbuf = malloc(avp->avd_main_vdse.ext_len);
1393 	if (main_vdbuf == NULL) {
1394 		(void) fprintf(stderr, gettext("Cannot allocate space for "
1395 			"volume sequences\n"));
1396 		exit(32);
1397 	}
1398 	rdfs(avp->avd_main_vdse.ext_loc, avp->avd_main_vdse.ext_len,
1399 		main_vdbuf);
1400 	end = (uint8_t *)main_vdbuf + avp->avd_main_vdse.ext_len;
1401 
1402 	nextblock = avp->avd_main_vdse.ext_loc;
1403 	for (cp = (uint8_t *)main_vdbuf; cp < end; cp += sectorsize,
1404 		nextblock++) {
1405 		/* LINTED */
1406 		tp = (struct tag *)cp;
1407 		err = verifytag(tp, nextblock, tp, 0);
1408 		if (err)
1409 			continue;
1410 
1411 		switch (tp->tag_id) {
1412 		case UD_PRI_VOL_DESC:
1413 			/* Bump serial number, according to spec. */
1414 			serialnum = tp->tag_sno + 1;
1415 			pvolp = (struct pri_vol_desc *)tp;
1416 			oldlabel = pvolp->pvd_vol_id + 1;
1417 			break;
1418 		case UD_ANCH_VOL_DESC:
1419 			avp = (struct anch_vol_desc_ptr *)tp;
1420 			break;
1421 		case UD_VOL_DESC_PTR:
1422 			break;
1423 		case UD_IMPL_USE_DESC:
1424 			break;
1425 		case UD_PART_DESC:
1426 			partp = (struct part_desc *)tp;
1427 			part_start = partp->pd_part_start;
1428 			part_len = partp->pd_part_length;
1429 			oldfssize = part_start + part_len;
1430 			break;
1431 		case UD_LOG_VOL_DESC:
1432 			logvp = (struct log_vol_desc *)tp;
1433 			break;
1434 		case UD_UNALL_SPA_DESC:
1435 			break;
1436 		case UD_TERM_DESC:
1437 			goto done;
1438 			break;
1439 		case UD_LOG_VOL_INT:
1440 			break;
1441 		default:
1442 			break;
1443 		}
1444 	}
1445 done:
1446 	if (!partp || !logvp) {
1447 		return (0);
1448 	}
1449 	return (1);
1450 }
1451 
1452 uint32_t
1453 get_last_block()
1454 {
1455 	struct vtoc vtoc;
1456 	struct dk_cinfo dki_info;
1457 
1458 	if (ioctl(fsi, DKIOCGVTOC, (intptr_t)&vtoc) != 0) {
1459 		(void) fprintf(stderr, gettext("Unable to read VTOC\n"));
1460 		return (0);
1461 	}
1462 
1463 	if (vtoc.v_sanity != VTOC_SANE) {
1464 		(void) fprintf(stderr, gettext("Vtoc.v_sanity != VTOC_SANE\n"));
1465 		return (0);
1466 	}
1467 
1468 	if (ioctl(fsi, DKIOCINFO, (intptr_t)&dki_info) != 0) {
1469 		(void) fprintf(stderr,
1470 		    gettext("Could not get the slice information\n"));
1471 		return (0);
1472 	}
1473 
1474 	if (dki_info.dki_partition > V_NUMPAR) {
1475 		(void) fprintf(stderr,
1476 		    gettext("dki_info.dki_partition > V_NUMPAR\n"));
1477 		return (0);
1478 	}
1479 
1480 	return ((uint32_t)vtoc.v_part[dki_info.dki_partition].p_size);
1481 }
1482