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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
35 * make file system for udfs (UDF - ISO13346)
39 * mkfs [-F FSType] [-V] [-m] [options]
40 * [-o specific_options] special size
42 * where specific_options are:
44 * label - volume label
45 * psize - physical block size
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>
67 #include <sys/isa_defs.h> /* for ENDIAN defines */
71 #include <sys/fs/udf_volume.h>
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 *);
82 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
83 #define MB (1024*1024)
86 * Forward declarations
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
);
93 static int match(char *s
);
94 static int readvolseq();
95 static uint32_t get_last_block();
98 * variables set up by front end.
100 static int Nflag
= 0; /* run mkfs without writing */
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 */
115 static uint32_t number_flags
= 0;
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();
128 #define VOLRECSTART (32 * 1024)
130 #define VOLSEQSTART 128
132 #define INTSEQSTART 192
133 #define INTSEQLEN 8192
134 #define FIRSTAVDP 256
140 #define SPACEMAP_OFF 24
143 static time_t mkfstime
;
144 static struct tm res
;
146 static char vsibuf
[128];
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";
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
];
161 uint32_t ecma_version
= 2;
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
;
173 /* Set by readvolseq for -m option */
174 static uint32_t oldfssize
;
175 static char *oldlabel
;
178 main(int32_t argc
, int8_t *argv
[])
183 char *special
, *raw_special
;
184 struct stat statarea
;
185 struct ustat ustatarea
;
190 (void) setlocale(LC_ALL
, "");
192 #if !defined(TEXT_DOMAIN)
193 #define TEXT_DOMAIN "SYS_TEST"
195 (void) textdomain(TEXT_DOMAIN
);
197 while ((c
= getopt(argc
, argv
, "F:Vmo:")) != EOF
) {
202 if (strcmp(string
, "udfs") != 0) {
212 (void) fprintf(stdout
,
213 gettext("mkfs -F udfs "));
214 for (opt_count
= 1; opt_count
< argc
;
216 opt_text
= argv
[opt_count
];
218 (void) fprintf(stdout
,
222 (void) fprintf(stdout
, "\n");
228 * return command line used
236 * udfs specific options.
239 while (*string
!= '\0') {
242 } else if (match("psize=")) {
244 sectorsize
= number(BIG
,
246 } else if (match("label=")) {
247 for (i
= 0; i
< 31; i
++) {
248 if (*string
== '\0') {
254 udfs_label
[i
] = '\0';
255 } else if (*string
== '\0') {
258 (void) fprintf(stdout
,
264 if (*string
== ',') {
267 if (*string
== ' ') {
279 (void) time(&mkfstime
);
280 if (optind
> (argc
- 1)) {
285 argv
= &argv
[optind
];
287 raw_special
= getfullrawname(fsys
);
288 fsi
= open(raw_special
, O_RDONLY
);
290 (void) fprintf(stdout
,
291 gettext("%s: cannot open\n"), fsys
);
296 if ((temp_secsz
= get_bsize()) != 0) {
297 sectorsize
= temp_secsz
;
300 /* Get old file system information */
305 * Figure out the block size and
306 * file system size and print the information
309 dump_fscmd(fsys
, fsi
);
311 (void) printf(gettext(
312 "[not currently a valid file system]\n"));
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.
321 disk_size
= get_last_block();
323 if (argc
< 2 && disk_size
== 0 || argc
< 1) {
328 (void) printf(gettext("No size specified, entire partition "
329 "of %u sectors used\n"), disk_size
);
334 fssize
= number(BIG
, "size");
338 (void) fprintf(stderr
,
339 gettext("Negative number of sectors(%d) not allowed\n"),
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
));
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
);
356 } else if (fssize
< disk_size
) {
357 unused
= disk_size
- fssize
;
359 gettext("File system size %d smaller than "
360 "partition, %u sectors unused\n"),
364 /* Use passed-in size */
369 special
= getfullblkname(fsys
);
372 * If we found the block device name,
373 * then check the mount table.
374 * if mounted, write lock the file system
377 if ((special
!= NULL
) && (*special
!= '\0')) {
378 mnttab
= fopen(MNTTAB
, "r");
379 while ((getmntent(mnttab
, &mntp
)) == 0) {
380 if (strcmp(special
, mntp
.mnt_special
) == 0) {
381 (void) fprintf(stdout
,
382 gettext("%s is mounted,"
383 " can't mkfs\n"), special
);
387 (void) fclose(mnttab
);
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"),
398 if (ismounted
== 0) {
399 (void) fprintf(stdout
,
400 gettext("%s is not mounted\n"),
405 fso
= creat(fsys
, 0666);
407 (void) fprintf(stdout
,
408 gettext("%s: cannot create\n"), fsys
);
411 if (stat(fsys
, &statarea
) < 0) {
412 (void) fprintf(stderr
,
413 gettext("%s: %s: cannot stat\n"),
417 if (ustat(statarea
.st_rdev
, &ustatarea
) >= 0) {
418 (void) fprintf(stderr
,
419 gettext("%s is mounted, can't mkfs\n"), fsys
);
424 * For the -N case, a file descriptor is needed for the llseek()
425 * in wtfs(). See the comment in wtfs() for more information.
427 * Get a file descriptor that's read-only so that this code
428 * doesn't accidentally write to the file.
430 fso
= open(fsys
, O_RDONLY
);
432 (void) fprintf(stderr
, gettext("%s: cannot open\n"),
440 * Validate the given file system size.
441 * Verify that its last block can actually be accessed.
443 fssize
= fssize
/ (sectorsize
/ DEV_BSIZE
);
445 (void) fprintf(stdout
,
446 gettext("preposterous size %d. sectors\n"), fssize
);
454 rdfs(fssize
- 1, sectorsize
, buf
);
456 if ((sectorsize
< DEV_BSIZE
) ||
457 (sectorsize
> MAXBSIZE
)) {
458 (void) fprintf(stdout
,
459 gettext("sector size must be"
460 " between 512, 8192 bytes\n"));
462 if (!POWEROF2(sectorsize
)) {
463 (void) fprintf(stdout
,
464 gettext("sector size must be a power of 2, not %d\n"),
472 (void) printf(gettext("Creating file system with sector size of "
473 "%d bytes\n"), sectorsize
);
476 * Set up time stamp values
479 (void) localtime_r(&mkfstime
, &res
);
480 if (res
.tm_isdst
> 0) {
481 tzone
= altzone
/ 60;
482 } else if (res
.tm_isdst
== 0) {
485 tzone
= 2047; /* Unknown */
489 * Initialize the volume recognition sequence, the volume descriptor
490 * sequences and the anchor pointer.
502 setstamp(tstamp_t
*tp
)
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
;
515 tp
->ts_tzone
= 0x1000 + (-tzone
& 0xFFF);
519 setextad(extent_ad_t
*eap
, uint32_t len
, uint32_t loc
)
526 setdstring(dstring_t
*dp
, char *cp
, int len
)
532 if (length
> len
- 3) {
535 dp
[len
- 1] = length
+ 1;
537 (void) strncpy(dp
, cp
, len
-2);
541 wtvolseq(tag_t
*tp
, daddr_t blk1
, daddr_t blk2
)
543 static uint32_t vdsn
= 0;
546 switch (tp
->tag_id
) {
547 case UD_PRI_VOL_DESC
:
548 ((struct pri_vol_desc
*)tp
)->pvd_vdsn
= vdsn
++;
550 case UD_VOL_DESC_PTR
:
551 ((struct vol_desc_ptr
*)tp
)->vdp_vdsn
= vdsn
++;
553 case UD_IMPL_USE_DESC
:
554 ((struct iuvd_desc
*)tp
)->iuvd_vdsn
= vdsn
++;
557 ((struct part_desc
*)tp
)->pd_vdsn
= vdsn
++;
559 case UD_LOG_VOL_DESC
:
560 ((struct log_vol_desc
*)tp
)->lvd_vdsn
= vdsn
++;
562 case UD_UNALL_SPA_DESC
:
563 ((struct unall_spc_desc
*)tp
)->ua_vdsn
= vdsn
++;
567 bzero(buf2
, sectorsize
);
569 maketag(tp
, (struct tag
*)buf2
);
572 * Write at Main Volume Descriptor Sequence
574 wtfs(blk1
, sectorsize
, buf2
);
577 switch (tp
->tag_id
) {
578 case UD_PRI_VOL_DESC
:
579 ((struct pri_vol_desc
*)tp
)->pvd_vdsn
= vdsn
++;
581 case UD_VOL_DESC_PTR
:
582 ((struct vol_desc_ptr
*)tp
)->vdp_vdsn
= vdsn
++;
584 case UD_IMPL_USE_DESC
:
585 ((struct iuvd_desc
*)tp
)->iuvd_vdsn
= vdsn
++;
588 ((struct part_desc
*)tp
)->pd_vdsn
= vdsn
++;
590 case UD_LOG_VOL_DESC
:
591 ((struct log_vol_desc
*)tp
)->lvd_vdsn
= vdsn
++;
593 case UD_UNALL_SPA_DESC
:
594 ((struct unall_spc_desc
*)tp
)->ua_vdsn
= vdsn
++;
599 * Write at Reserve Volume Descriptor Sequence
601 wtfs(blk2
, sectorsize
, buf
);
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
;
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
;
624 struct short_ad
*sap
;
626 struct space_bmap_desc
*sbp
;
628 daddr_t nextblock
, endblock
;
629 int32_t volseq_sectors
, nextlogblock
, rootfelen
, i
;
630 uint32_t mvds_loc
, rvds_loc
;
632 bzero(buf
, MAXBSIZE
);
635 * Starting from MAXBSIZE, clear out till 256 sectors.
637 for (i
= MAXBSIZE
/ sectorsize
; i
< FIRSTAVDP
; i
++) {
638 wtfs(i
, sectorsize
, buf
);
641 /* Zero out the avdp at N - 257 */
642 wtfs(fssize
- 256, sectorsize
, buf
);
645 * Leave 1st 32K for O.S.
647 nextblock
= VOLRECSTART
/ sectorsize
;
650 * Write BEA01/NSR02/TEA01 sequence.
651 * Each one must be 2K bytes in length.
653 nsp
= (struct nsr_desc
*)buf
;
654 nsp
->nsr_str_type
= 0;
656 (void) strncpy((int8_t *)nsp
->nsr_id
, "BEA01", 5);
658 nsp
= (struct nsr_desc
*)&buf
[2048];
659 nsp
->nsr_str_type
= 0;
661 (void) strncpy((int8_t *)nsp
->nsr_id
, "NSR02", 5);
663 nsp
= (struct nsr_desc
*)&buf
[4096];
664 nsp
->nsr_str_type
= 0;
666 (void) strncpy((int8_t *)nsp
->nsr_id
, "TEA01", 5);
668 wtfs(nextblock
, 8192, buf
);
669 bzero(buf
, MAXBSIZE
);
672 * Minimum length of volume sequences
677 * Round up to next 32K boundary for
678 * volume descriptor sequences
680 nextblock
= VOLSEQSTART
;
681 bzero(buf
, sectorsize
);
682 mvds_loc
= VOLSEQSTART
;
683 rvds_loc
= mvds_loc
+ volseq_sectors
;
686 * Primary Volume Descriptor
689 pvdp
= (struct pri_vol_desc
*)buf
;
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
) -
698 setdstring(pvdp
->pvd_vol_id
, udfs_label
, 32);
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
));
716 wtvolseq(tp
, nextblock
, nextblock
+ volseq_sectors
);
720 * Implementation Use Descriptor
722 bzero(buf
, sectorsize
);
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
) -
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);
736 setdstring(iudp
->iuvd_ifo1
, "", 36);
737 setdstring(iudp
->iuvd_ifo2
, "", 36);
738 setdstring(iudp
->iuvd_ifo3
, "", 36);
742 * info1,2,3 = user specified
744 bcopy(&sunmicro
, &iudp
->iuvd_iid
, sizeof (regid_t
));
745 wtvolseq(tp
, nextblock
, nextblock
+ volseq_sectors
);
749 * Partition Descriptor
751 bzero(buf
, sectorsize
);
753 pp
= (struct part_desc
*)buf
;
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
) -
761 pp
->pd_pflags
= 1; /* Allocated */
763 bcopy(&partid
, &pp
->pd_pcontents
, sizeof (regid_t
));
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) /
771 pp
->pd_part_start
= part_start
;
772 pp
->pd_part_length
= part_len
;
774 pp
->pd_acc_type
= acctype
;
778 * Do the partition header
781 php
= (struct phdr_desc
*)&pp
->pd_pc_use
;
784 * Set up unallocated space bitmap
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) &
790 php
->phdr_usb
.sad_ext_loc
= nextlogblock
;
791 part_unalloc
= nextlogblock
;
792 nextlogblock
+= part_bmp_sectors
;
795 bcopy(&sunmicro
, &pp
->pd_ii
, sizeof (regid_t
));
796 wtvolseq(tp
, nextblock
, nextblock
+ volseq_sectors
);
800 * Logical Volume Descriptor
802 bzero(buf
, sectorsize
);
804 lvp
= (struct log_vol_desc
*)buf
;
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
) -
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
));
825 pmp
= (struct pmap_typ1
*)&lvp
->lvd_pmaps
;
827 pmp
->map1_length
= 6;
828 pmp
->map1_vsn
= SWAP_16(1);
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
);
836 * Unallocated Space Descriptor
838 bzero(buf
, sectorsize
);
840 uap
= (struct unall_spc_desc
*)buf
;
842 tp
->tag_id
= UD_UNALL_SPA_DESC
;
843 tp
->tag_desc_ver
= ecma_version
;
844 tp
->tag_sno
= serialnum
;
847 tp
->tag_crc_len
= (char *)uap
->ua_al_dsc
- buf
- sizeof (struct tag
);
848 wtvolseq(tp
, nextblock
, nextblock
+ volseq_sectors
);
852 * Terminating Descriptor
854 bzero(buf
, sectorsize
);
856 tdp
= (struct term_desc
*)buf
;
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
) -
863 tp
->tag_loc
= nextblock
;
864 wtvolseq(tp
, nextblock
, nextblock
+ volseq_sectors
);
868 * Do the anchor volume descriptor
870 if (nextblock
> FIRSTAVDP
) {
871 (void) fprintf(stdout
,
872 gettext("Volume integrity sequence"
873 " descriptors too long\n"));
877 nextblock
= FIRSTAVDP
;
878 bzero(buf
, sectorsize
);
880 avp
= (struct anch_vol_desc_ptr
*)buf
;
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
) -
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
);
894 maketag(tp
, (struct tag
*)buf2
);
895 wtfs(nextblock
, sectorsize
, buf2
);
898 tp
->tag_loc
= fssize
;
900 maketag(tp
, (struct tag
*)buf2
);
901 wtfs(fssize
, sectorsize
, buf2
);
904 * File Set Descriptor
906 bzero(buf
, sectorsize
);
908 fsp
= (struct file_set_desc
*)&buf
;
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
) -
915 tp
->tag_loc
= nextlogblock
;
916 setstamp(&fsp
->fsd_time
);
918 fsp
->fsd_mi_level
= 3;
919 fsp
->fsd_cs_list
= 1;
920 fsp
->fsd_mcs_list
= 1;
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
));
935 wtfs(nextlogblock
+ part_start
, sectorsize
, (char *)tp
);
939 * Terminating Descriptor
941 bzero(buf
, sectorsize
);
943 tdp
= (struct term_desc
*)buf
;
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
) -
950 tp
->tag_loc
= nextlogblock
;
952 wtfs(nextlogblock
+ part_start
, sectorsize
, (char *)tp
);
955 if (nextlogblock
> filesetblock
+ FILESETLEN
) {
956 (void) fprintf(stdout
,
957 gettext("File set descriptor too long\n"));
960 nextlogblock
= filesetblock
+ FILESETLEN
;
965 bzero(buf
, sectorsize
);
967 fp
= (struct file_entry
*)&buf
;
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
;
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;
989 fp
->fe_info_len
= sizeof (struct file_id
);
991 setstamp(&fp
->fe_acc_time
);
992 setstamp(&fp
->fe_mod_time
);
993 setstamp(&fp
->fe_attr_time
);
995 bcopy(&sunmicro
, &fp
->fe_impl_id
, sizeof (regid_t
));
998 fp
->fe_len_adesc
= sizeof (short_ad_t
);
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
);
1007 wtfs(nextlogblock
+ part_start
, sectorsize
, (char *)tp
);
1013 bzero(buf
, sectorsize
);
1015 fip
= (struct file_id
*)&buf
;
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
;
1024 fip
->fid_flags
= FID_DIR
| FID_PARENT
;
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;
1031 wtfs(nextlogblock
+ part_start
, sectorsize
, (char *)tp
);
1035 * Now do the space bitmaps
1037 if (part_unalloc
>= 0) {
1038 int size
= sectorsize
* part_bmp_sectors
;
1040 sbp
= (struct space_bmap_desc
*)malloc(size
);
1042 (void) fprintf(stdout
,
1043 gettext("Can't allocate bitmap space\n"));
1046 bzero((char *)sbp
, sectorsize
* part_bmp_sectors
);
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
;
1056 if (part_unalloc
>= 0) {
1059 cp
= (uint8_t *)sbp
+ SPACEMAP_OFF
;
1060 i
= nextlogblock
/ NBBY
;
1061 cp
[i
++] = (0xff << (nextlogblock
% NBBY
)) & 0xff;
1062 while (i
< part_bmp_bytes
)
1064 if (part_len
% NBBY
)
1065 cp
[--i
] = (unsigned)0xff >>
1066 (NBBY
- part_len
% NBBY
);
1068 wtfs(part_unalloc
+ part_start
, size
, (char *)tp
);
1074 * Volume Integrity Descriptor
1076 nextblock
= INTSEQSTART
;
1077 endblock
= nextblock
+ INTSEQLEN
/ sectorsize
;
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
);
1103 wtfs(nextblock
, sectorsize
, (char *)tp
);
1107 * Terminating Descriptor
1109 bzero(buf
, sectorsize
);
1111 tdp
= (struct term_desc
*)buf
;
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
;
1119 wtfs(nextblock
, sectorsize
, (char *)tp
);
1122 /* Zero out the rest of the LVI extent */
1123 bzero(buf
, sectorsize
);
1124 while (nextblock
< endblock
)
1125 wtfs(nextblock
++, sectorsize
, buf
);
1129 * read a block from the file system
1132 rdfs(daddr_t bno
, int size
, char *bf
)
1136 if (llseek(fsi
, (offset_t
)bno
* sectorsize
, 0) < 0) {
1138 (void) fprintf(stderr
,
1139 gettext("seek error on sector %ld: %s\n"),
1140 bno
, strerror(saverr
));
1143 n
= read(fsi
, bf
, size
);
1146 (void) fprintf(stderr
,
1147 gettext("read error on sector %ld: %s\n"),
1148 bno
, strerror(saverr
));
1154 * write a block to the file system
1157 wtfs(daddr_t bno
, int size
, char *bf
)
1164 if (llseek(fso
, (offset_t
)bno
* sectorsize
, 0) < 0) {
1166 (void) fprintf(stderr
,
1167 gettext("seek error on sector %ld: %s\n"),
1168 bno
, strerror(saverr
));
1173 n
= write(fso
, bf
, size
);
1176 (void) fprintf(stderr
,
1177 gettext("write error on sector %ld: %s\n"),
1178 bno
, strerror(saverr
));
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"));
1207 dump_fscmd(char *fsys
, int fsi
)
1209 (void) printf(gettext("mkfs -F udfs -o "));
1210 (void) printf("psize=%d,label=\"%s\" %s %d\n",
1211 sectorsize
, oldlabel
, fsys
, oldfssize
);
1214 /* number ************************************************************* */
1216 /* Convert a numeric arg to binary */
1218 /* Arg: big - maximum valid input number */
1219 /* Global arg: string - pointer to command arg */
1221 /* Valid forms: 123 | 123k | 123*123 | 123x123 */
1223 /* Return: converted number */
1225 /* ******************************************************************** */
1228 number(long big
, char *param
)
1235 #define FOUND_MULT 0x1
1244 while ((*cs
!= ' ') && (*cs
!= '\0') && (*cs
!= ',')) {
1245 if ((*cs
>= '0') && (*cs
<= '9')) {
1246 n
= n
* 10 + *cs
- '0';
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"));
1255 number_flags
|= FOUND_MULT
;
1258 n
= n
* number(big
, param
);
1261 } else if (*cs
== 'k') {
1262 if (number_flags
& FOUND_K
) {
1263 (void) fprintf(stderr
,
1264 gettext("mkfs: only one \"k\" allowed\n"));
1267 number_flags
|= FOUND_K
;
1272 (void) fprintf(stderr
,
1273 gettext("mkfs: bad numeric arg: \"%s\"\n"),
1280 (void) fprintf(stderr
,
1281 gettext("mkfs: value for %s overflowed\n"), param
);
1289 if ((n
> big
) || (n
< 0)) {
1290 (void) fprintf(stderr
,
1291 gettext("mkfs: argument %s out of range\n"), param
);
1296 return ((int32_t)n
);
1299 /* match ************************************************************** */
1301 /* Compare two text strings for equality */
1303 /* Arg: s - pointer to string to match with a command arg */
1304 /* Global arg: string - pointer to command arg */
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. */
1310 /* ******************************************************************** */
1318 while (*cs
++ == *s
) {
1336 struct dk_cinfo info
;
1337 struct fd_char fd_char
;
1338 struct dk_minfo dkminfo
;
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"));
1348 switch (info
.dki_ctype
) {
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
) {
1357 gettext("The device sector size "
1358 "%u is not supported by udfs!\n"),
1359 dkminfo
.dki_lbsize
);
1365 case DKC_INTEL82072
:
1367 case DKC_INTEL82077
:
1370 if (ioctl(fso
, FDIOGCHAR
, &fd_char
) >= 0) {
1371 return (fd_char
.fdc_sec_size
);
1374 case DKC_PCMCIA_ATA
:
1382 * Read in the volume sequences descriptors.
1390 struct pri_vol_desc
*pvolp
;
1391 struct part_desc
*partp
;
1392 struct log_vol_desc
*logvp
;
1393 struct anch_vol_desc_ptr
*avp
;
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
);
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"));
1409 rdfs(avp
->avd_main_vdse
.ext_loc
, avp
->avd_main_vdse
.ext_len
,
1411 end
= (uint8_t *)main_vdbuf
+ avp
->avd_main_vdse
.ext_len
;
1413 nextblock
= avp
->avd_main_vdse
.ext_loc
;
1414 for (cp
= (uint8_t *)main_vdbuf
; cp
< end
; cp
+= sectorsize
,
1417 tp
= (struct tag
*)cp
;
1418 err
= verifytag(tp
, nextblock
, tp
, 0);
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;
1429 case UD_ANCH_VOL_DESC
:
1430 avp
= (struct anch_vol_desc_ptr
*)tp
;
1432 case UD_VOL_DESC_PTR
:
1434 case UD_IMPL_USE_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
;
1442 case UD_LOG_VOL_DESC
:
1443 logvp
= (struct log_vol_desc
*)tp
;
1445 case UD_UNALL_SPA_DESC
:
1450 case UD_LOG_VOL_INT
:
1457 if (!partp
|| !logvp
) {
1467 struct dk_cinfo dki_info
;
1469 if (ioctl(fsi
, DKIOCGVTOC
, (intptr_t)&vtoc
) != 0) {
1470 (void) fprintf(stderr
, gettext("Unable to read VTOC\n"));
1474 if (vtoc
.v_sanity
!= VTOC_SANE
) {
1475 (void) fprintf(stderr
, gettext("Vtoc.v_sanity != VTOC_SANE\n"));
1479 if (ioctl(fsi
, DKIOCINFO
, (intptr_t)&dki_info
) != 0) {
1480 (void) fprintf(stderr
,
1481 gettext("Could not get the slice information\n"));
1485 if (dki_info
.dki_partition
> V_NUMPAR
) {
1486 (void) fprintf(stderr
,
1487 gettext("dki_info.dki_partition > V_NUMPAR\n"));
1491 return ((uint32_t)vtoc
.v_part
[dki_info
.dki_partition
].p_size
);