mkfs.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2000 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* make file system for udfs (UDF - ISO13346)
*
* usage:
*
* mkfs [-F FSType] [-V] [-m] [options]
* [-o specific_options] special size
*
* where specific_options are:
* N - no create
* label - volume label
* psize - physical block size
*/
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <locale.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <sys/sysmacros.h>
#include <ustat.h>
extern char *getfullrawname(char *);
extern char *getfullblkname(char *);
#define UMASK 0755
/*
* Forward declarations
*/
static void usage();
static int match(char *s);
static int readvolseq();
static uint32_t get_last_block();
/*
* variables set up by front end.
*/
static int Nflag = 0; /* run mkfs without writing */
/* file system */
static int mflag = 0; /* return the command line used */
/* to create this FS */
static int fssize; /* file system size */
/* If nothing specified */
static char *fsys;
static int fsi;
static int fso;
static uint32_t number_flags = 0;
static char *string;
static void volseqinit();
#define VOLSEQSTART 128
#define VOLSEQLEN 16
#define INTSEQSTART 192
#define INTSEQLEN 8192
#define FIRSTAVDP 256
#define AVDPLEN 1
#define FILESETLEN 2
#define SPACEMAP_OFF 24
#define MAXID 16
static long tzone;
static char vsibuf[128];
static int bdevismounted;
static int ismounted;
static int directory;
static int acctype = PART_ACC_OW;
static uint32_t part_start;
static uint32_t part_bmp_bytes;
static uint32_t part_bmp_sectors;
static uint32_t filesetblock;
/* Set by readvolseq for -m option */
static char *oldlabel;
{
long i;
char *special, *raw_special;
int32_t c;
int isfs;
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case 'F':
usage();
}
break;
case 'V':
{
char *opt_text;
int opt_count;
gettext("mkfs -F udfs "));
opt_count++) {
if (opt_text) {
" %s ", opt_text);
}
}
}
break;
case 'm':
/*
* return command line used
* to create this FS
*/
mflag++;
break;
case 'o':
/*
* udfs specific options.
*/
while (*string != '\0') {
if (match("N")) {
Nflag++;
} else if (match("psize=")) {
number_flags = 0;
"psize");
} else if (match("label=")) {
for (i = 0; i < 31; i++) {
if (*string == '\0') {
break;
}
udfs_label[i] =
*string++;
}
udfs_label[i] = '\0';
} else if (*string == '\0') {
break;
} else {
gettext("illegal "
"option: %s\n"),
string);
usage();
}
if (*string == ',') {
string++;
}
if (*string == ' ') {
string++;
}
}
break;
case '?':
usage();
break;
}
}
usage();
}
if (fsi < 0) {
exit(32);
}
if ((temp_secsz = get_bsize()) != 0) {
}
/* Get old file system information */
isfs = readvolseq();
if (mflag) {
/*
* Figure out the block size and
* file system size and print the information
*/
if (isfs)
else
"[not currently a valid file system]\n"));
exit(0);
}
/*
* Get the disk size from the drive or VTOC for the N and N-256
* AVDPs and to make sure we don't want to create a file system
* bigger than the partition.
*/
disk_size = get_last_block();
usage();
}
if (argc < 2) {
"of %u sectors used\n"), disk_size);
} else {
number_flags = 0;
}
if (fssize < 0) {
gettext("Negative number of sectors(%d) not allowed\n"),
fssize);
exit(32);
}
gettext("size should be at least %d sectors\n"),
exit(32);
}
if (disk_size != 0) {
"larger than the partition size\n"), fssize);
exit(32);
(void) printf(
gettext("File system size %d smaller than "
"partition, %u sectors unused\n"),
}
} else {
/* Use passed-in size */
}
if (!Nflag) {
/*
* If we found the block device name,
* then check the mount table.
* if mounted, write lock the file system
*
*/
gettext("%s is mounted,"
" can't mkfs\n"), special);
exit(32);
}
}
}
if ((bdevismounted) && (ismounted == 0)) {
gettext("can't check mount point; "));
gettext("%s is mounted but not in mnttab(4)\n"),
special);
exit(32);
}
if (directory) {
if (ismounted == 0) {
gettext("%s is not mounted\n"),
special);
exit(32);
}
}
if (fso < 0) {
exit(32);
}
gettext("%s: %s: cannot stat\n"),
exit(32);
}
exit(32);
}
} else {
/*
* For the -N case, a file descriptor is needed for the llseek()
* in wtfs(). See the comment in wtfs() for more information.
*
* Get a file descriptor that's read-only so that this code
* doesn't accidentally write to the file.
*/
if (fso < 0) {
fsys);
exit(32);
}
}
/*
* Validate the given file system size.
* Verify that its last block can actually be accessed.
*/
if (fssize <= 0) {
exit(32);
}
fssize --;
/*
* verify device size
*/
if ((sectorsize < DEV_BSIZE) ||
(sectorsize > MAXBSIZE)) {
gettext("sector size must be"
" between 512, 8192 bytes\n"));
}
if (!POWEROF2(sectorsize)) {
gettext("sector size must be a power of 2, not %d\n"),
exit(32);
}
if (Nflag) {
exit(0);
}
"%d bytes\n"), sectorsize);
/*
* Set up time stamp values
*/
} else {
}
/*
* Initialize the volume recognition sequence, the volume descriptor
* sequences and the anchor pointer.
*/
volseqinit();
return (0);
}
static void
{
}
static void
{
}
static void
{
}
*dp++ = 8;
}
static void
{
case UD_PRI_VOL_DESC :
break;
case UD_VOL_DESC_PTR :
break;
case UD_IMPL_USE_DESC :
break;
case UD_PART_DESC :
break;
case UD_LOG_VOL_DESC :
break;
case UD_UNALL_SPA_DESC :
break;
}
/* LINTED */
/*
* Write at Main Volume Descriptor Sequence
*/
case UD_PRI_VOL_DESC :
break;
case UD_VOL_DESC_PTR :
break;
case UD_IMPL_USE_DESC :
break;
case UD_PART_DESC :
break;
case UD_LOG_VOL_DESC :
break;
case UD_UNALL_SPA_DESC :
break;
}
/*
* Write at Reserve Volume Descriptor Sequence
*/
}
static void
{
struct pri_vol_desc *pvdp;
struct log_vol_desc *lvp;
struct unall_spc_desc *uap;
struct log_vol_int_desc *lvip;
struct anch_vol_desc_ptr *avp;
struct file_set_desc *fsp;
struct file_entry *fp;
struct space_bmap_desc *sbp;
/*
* Starting from MAXBSIZE, clear out till 256 sectors.
*/
}
/* Zero out the avdp at N - 257 */
/*
* Leave 1st 32K for O.S.
*/
/*
* Each one must be 2K bytes in length.
*/
nsp->nsr_str_type = 0;
nsp->nsr_str_type = 0;
nsp->nsr_str_type = 0;
/*
* Minimum length of volume sequences
*/
volseq_sectors = 16;
/*
* Round up to next 32K boundary for
* volume descriptor sequences
*/
/*
* Primary Volume Descriptor
*/
/* LINTED */
sizeof (struct tag);
nextblock++;
/*
* Implementation Use Descriptor
*/
/* LINTED */
sizeof (struct tag);
/*
* info1,2,3 = user specified
*/
nextblock++;
/*
* Partition Descriptor
*/
/* LINTED */
sizeof (struct tag);
nextlogblock = 0;
/*
* Do the partition header
*/
/* LINTED */
/*
* Set up unallocated space bitmap
*/
(~(sectorsize - 1));
}
nextblock++;
/*
* Logical Volume Descriptor
*/
/* LINTED */
sizeof (struct tag);
lap->lad_ext_prn = 0;
/* LINTED */
nextblock++;
/*
* Unallocated Space Descriptor
*/
/* LINTED */
nextblock++;
/*
* Terminating Descriptor
*/
/* LINTED */
sizeof (struct tag);
nextblock++;
/*
* Do the anchor volume descriptor
*/
gettext("Volume integrity sequence"
" descriptors too long\n"));
exit(32);
}
/* LINTED */
sizeof (struct tag);
/* LINTED */
nextblock++;
/* LINTED */
/*
* File Set Descriptor
*/
/* LINTED */
sizeof (struct tag);
fsp->fsd_fsd_no = 0;
lap->lad_ext_prn = 0;
nextlogblock++;
/*
* Terminating Descriptor
*/
/* LINTED */
sizeof (struct tag);
nextlogblock++;
gettext("File set descriptor too long\n"));
exit(32);
}
/*
* Root File Entry
*/
/* LINTED */
icb->itag_prnde = 0;
icb->itag_lb_loc = 0;
icb->itag_lb_prn = 0;
fp->fe_rec_for = 0;
fp->fe_rec_dis = 0;
fp->fe_rec_len = 0;
fp->fe_uniq_id = 0;
fp->fe_len_ear = 0;
/* LINTED */
nextlogblock++;
/*
* Root Directory
*/
/* LINTED */
sizeof (struct tag);
nextlogblock++;
/*
* Now do the space bitmaps
*/
if (part_unalloc >= 0) {
if (!sbp) {
gettext("Can't allocate bitmap space\n"));
exit(32);
}
if (part_unalloc >= 0) {
int32_t i;
i = nextlogblock / NBBY;
while (i < part_bmp_bytes)
cp[i++] = 0xff;
cp[--i] = (unsigned)0xff >>
}
}
/*
* Volume Integrity Descriptor
*/
/* LINTED */
lviup->lvidiu_nfiles = 0;
sizeof (struct tag);
nextblock++;
/*
* Terminating Descriptor
*/
/* LINTED */
nextblock++;
/* Zero out the rest of the LVI extent */
}
/*
* read a block from the file system
*/
static void
{
int n, saverr;
gettext("seek error on sector %ld: %s\n"),
exit(32);
}
if (n != size) {
gettext("read error on sector %ld: %s\n"),
exit(32);
}
}
/*
* write a block to the file system
*/
static void
{
int n, saverr;
if (fso == -1)
return;
gettext("seek error on sector %ld: %s\n"),
exit(32);
}
if (Nflag)
return;
if (n != size) {
gettext("write error on sector %ld: %s\n"),
exit(32);
}
}
static void
usage()
{
gettext("udfs usage: mkfs [-F FSType] [-V]"
" [-m] [-o options] special size(sectors)\n"));
gettext(" -m : dump fs cmd line used to make"
" this partition\n"));
gettext(" -V : print this command line and return\n"));
gettext(" -o : udfs options: :psize=%d:label=%s\n"),
gettext("NOTE that all -o suboptions: must"
" be separated only by commas so as to\n"));
gettext("be parsed as a single argument\n"));
exit(32);
}
/*ARGSUSED*/
static void
{
(void) printf("psize=%d,label=\"%s\" %s %d\n",
}
/* number ************************************************************* */
/* */
/* Convert a numeric arg to binary */
/* */
/* Arg: big - maximum valid input number */
/* Global arg: string - pointer to command arg */
/* */
/* Valid forms: 123 | 123k | 123*123 | 123x123 */
/* */
/* Return: converted number */
/* */
/* ******************************************************************** */
static int32_t
{
char *cs;
int64_t n = 0;
#define FOUND_MULT 0x1
#define FOUND_K 0x2
if (*cs == '-') {
minus = 1;
cs++;
}
n = 0;
cs++;
if (number_flags & FOUND_MULT) {
gettext("mkfs: only one \"*\" "
"or \"x\" allowed\n"));
exit(2);
}
cs++;
continue;
} else if (*cs == 'k') {
if (number_flags & FOUND_K) {
gettext("mkfs: only one \"k\" allowed\n"));
exit(2);
}
number_flags |= FOUND_K;
n = n * 1024;
cs++;
continue;
} else {
gettext("mkfs: bad numeric arg: \"%s\"\n"),
string);
exit(2);
}
}
if (n > cut) {
exit(2);
}
if (minus) {
n = -n;
}
if ((n > big) || (n < 0)) {
exit(2);
}
return ((int32_t)n);
}
/* match ************************************************************** */
/* */
/* Compare two text strings for equality */
/* */
/* Arg: s - pointer to string to match with a command arg */
/* Global arg: string - pointer to command arg */
/* */
/* Return: 1 if match, 0 if no match */
/* If match, also reset `string' to point to the text */
/* that follows the matching text. */
/* */
/* ******************************************************************** */
static int
match(char *s)
{
char *cs;
while (*cs++ == *s) {
if (*s++ == '\0') {
goto true;
}
}
if (*s != '\0') {
return (0);
}
true:
cs--;
return (1);
}
static uint32_t
{
perror("mkfs DKIOCINFO ");
gettext("DKIOCINFO failed using psize = 2048"
" for creating file-system\n"));
return (0);
}
case DKC_CDROM :
return (2048);
case DKC_SCSI_CCS :
/* FALLTHROUGH */
case DKC_INTEL82072 :
/* FALLTHROUGH */
case DKC_INTEL82077 :
/* FALLTHROUGH */
case DKC_DIRECT :
return (fd_char.fdc_sec_size);
}
/* FALLTHROUGH */
case DKC_PCMCIA_ATA :
return (512);
default :
return (0);
}
}
/*
* Read in the volume sequences descriptors.
*/
static int
{
int err;
struct pri_vol_desc *pvolp;
struct log_vol_desc *logvp;
struct anch_vol_desc_ptr *avp;
char *main_vdbuf;
if (err)
return (0);
if (main_vdbuf == NULL) {
"volume sequences\n"));
exit(32);
}
nextblock++) {
/* LINTED */
if (err)
continue;
case UD_PRI_VOL_DESC:
/* Bump serial number, according to spec. */
break;
case UD_ANCH_VOL_DESC:
break;
case UD_VOL_DESC_PTR:
break;
case UD_IMPL_USE_DESC:
break;
case UD_PART_DESC:
break;
case UD_LOG_VOL_DESC:
break;
case UD_UNALL_SPA_DESC:
break;
case UD_TERM_DESC:
goto done;
break;
case UD_LOG_VOL_INT:
break;
default:
break;
}
}
done:
return (0);
}
return (1);
}
{
return (0);
}
return (0);
}
gettext("Could not get the slice information\n"));
return (0);
}
gettext("dki_info.dki_partition > V_NUMPAR\n"));
return (0);
}
}