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
main(int32_t argc,int8_t * argv[])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
setstamp(tstamp_t * tp)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
setextad(extent_ad_t * eap,uint32_t len,uint32_t loc)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
setdstring(dstring_t * dp,char * cp,int len)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
wtvolseq(tag_t * tp,daddr_t blk1,daddr_t blk2)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
volseqinit()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
rdfs(daddr_t bno,int size,char * bf)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
wtfs(daddr_t bno,int size,char * bf)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
usage()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
dump_fscmd(char * fsys,int fsi)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
number(long big,char * param)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
match(char * s)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
get_bsize()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
readvolseq()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
get_last_block()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