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