Module Name:    src
Committed By:   reinoud
Date:           Tue Jul  2 14:59:01 UTC 2013

Modified Files:
        src/sbin/newfs_udf: newfs_udf.8 newfs_udf.c

Log Message:
Update newfs_udf to allow for creating file images with -F and specifying
sector sizes with -S.

For this i had to recycle the -S parameter but its preserved as an extension
to the -P parameter. These parameters are hardly ever use though since using
either or both the origional -S and the -P parameter without specific values
would break the standard. Also the -F now has a double meaning.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sbin/newfs_udf/newfs_udf.8
cvs rdiff -u -r1.12 -r1.13 src/sbin/newfs_udf/newfs_udf.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/newfs_udf/newfs_udf.8
diff -u src/sbin/newfs_udf/newfs_udf.8:1.9 src/sbin/newfs_udf/newfs_udf.8:1.10
--- src/sbin/newfs_udf/newfs_udf.8:1.9	Sat Jun 29 20:41:47 2013
+++ src/sbin/newfs_udf/newfs_udf.8	Tue Jul  2 14:59:01 2013
@@ -1,4 +1,4 @@
-.\" $NetBSD: newfs_udf.8,v 1.9 2013/06/29 20:41:47 reinoud Exp $
+.\" $NetBSD: newfs_udf.8,v 1.10 2013/07/02 14:59:01 reinoud Exp $
 .\"
 .\" Copyright (c) 2008 Reinoud Zandijk
 .\" All rights reserved.
@@ -26,7 +26,7 @@
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\"
-.Dd June 29, 2013
+.Dd July 2, 2013
 .Dt NEWFS_UDF 8
 .Os
 .Sh NAME
@@ -38,7 +38,7 @@
 .Op Fl L Ar loglabel
 .Op Fl P Ar discid
 .Op Fl p Ar percentage
-.Op Fl S Ar setlabel
+.Op Fl S Ar sectorsize
 .Op Fl s Ar size
 .Op Fl t Ar gmtoff
 .Op Fl V Ar max_udf
@@ -57,7 +57,8 @@ The options are as follow:
 Perform a crude surface check first to weed out disc faults on rewritable
 media.
 .It Fl F
-Force file system construction on non-empty recordable media.
+Force file system construction on non-empty recordable media or create an
+image file.
 .It Fl L Ar loglabel
 Set the disc logical label to the specified
 .Ar loglabel .
@@ -69,17 +70,20 @@ its causing problems.
 .It Fl P Ar discid
 Set the physical disc label to the specified
 .Ar discid .
+Prepend
+.Ar discid
+with volsetname separated with a ':' if wanted.
 For strict conformance and interchange, don't set this manually.
 .It Fl p Ar percentage
 Percentage of partition to be initially reserved for metadata on the Metadata
 partition.
 It defaults to 20 %.
-.It Fl S Ar setlabel
-Set the disc set label to the specified
-.Ar setlabel .
+.It Fl S Ar sectorsize
+Set the sectorsize for image files.
 For strict conformance and interchange, don't set this manually.
 .It Fl s Ar size
-Ignored for now.
+For image files, set the file size to the humanized size
+.Ar size .
 .It Fl t Ar gmtoff
 Use the specified
 .Ar gmtoff
@@ -123,7 +127,7 @@ Create a file system, using the specifie
 .Pa /dev/rcd0d
 with the default UDF version :
 .Bd -literal -offset indent
-newfs_udf -S "Encyclopedia" -L "volume 2" -P "copy-nr-1" /dev/rcd0d
+newfs_udf -P "Encyclopedia:copy-nr-1" -L "volume 2" /dev/rcd0d
 .Ed
 .Pp
 Create a 4.8 GiB sparse file and configure it using
@@ -137,12 +141,32 @@ vnconfig -c vnd0 bigdisk.2048.udf 2048/1
 newfs_udf -L bigdisk /dev/rvnd0d
 .Ed
 .Pp
+Create a 2 GiB file and create a new UDF file system on it using the default
+512 byte sector size :
+.Bd -literal -offset indent
+newfs_udf -L bigdisk2 -F -s 2G bigdisk2.iso
+.Ed
+.Pp
+Create a 200 MiB file and create a new UDF file system on it using a sector size
+of 2048 :
+.Bd -literal -offset indent
+newfs_udf -L bigdisk2 -F -s 200M -S 2048 bigdisk3.iso
+.Ed
+.Pp
 Create a new UDF file system on the inserted USB stick using its
-.Dq native
-sectorsize of 512 :
+native sectorsize of 512 :
 .Bd -literal -offset indent
 newfs_udf -L "My USB stick" /dev/rsd0d
 .Ed
+.Sh BUGS
+The
+.Ar P
+and the
+.Ar S
+arguments have changed meaning. The meaning of
+.Ar S
+has been merged into
+.Ar P since NetBSD 6.1.
 .Sh SEE ALSO
 .Xr disktab 5 ,
 .Xr disklabel 8 ,

Index: src/sbin/newfs_udf/newfs_udf.c
diff -u src/sbin/newfs_udf/newfs_udf.c:1.12 src/sbin/newfs_udf/newfs_udf.c:1.13
--- src/sbin/newfs_udf/newfs_udf.c:1.12	Thu May 26 07:59:08 2011
+++ src/sbin/newfs_udf/newfs_udf.c	Tue Jul  2 14:59:01 2013
@@ -1,7 +1,7 @@
-/* $NetBSD: newfs_udf.c,v 1.12 2011/05/26 07:59:08 reinoud Exp $ */
+/* $NetBSD: newfs_udf.c,v 1.13 2013/07/02 14:59:01 reinoud Exp $ */
 
 /*
- * Copyright (c) 2006, 2008 Reinoud Zandijk
+ * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -95,6 +95,7 @@ char	*format_str;			/* format: string re
 int	 format_flags;			/* format: attribute flags	 */
 int	 media_accesstype;		/* derived from current mmc cap  */
 int	 check_surface;			/* for rewritables               */
+int	 imagefile_secsize;		/* for files			 */
 
 int	 wrtrack_skew;
 int	 meta_perc = UDF_META_PERC;
@@ -283,9 +284,10 @@ udf_dump_discinfo(struct mmc_discinfo *d
 static int
 udf_update_discinfo(struct mmc_discinfo *di)
 {
+	struct stat st;
 	struct disklabel  disklab;
 	struct partition *dp;
-	struct stat st;
+	off_t size, sectors, secsize;
 	int partnr, error;
 
 	memset(di, 0, sizeof(struct mmc_discinfo));
@@ -295,20 +297,39 @@ udf_update_discinfo(struct mmc_discinfo 
 	if (error == 0)
 		return 0;
 
-	/*
-	 * disc partition support; note we can't use DIOCGPART in userland so
-	 * get disc label and use the stat info to get the partition number.
-	 */
-	if (ioctl(fd, DIOCGDINFO, &disklab) == -1) {
-		/* failed to get disclabel! */
-		perror("disklabel");
-		return errno;
-	}
-
-	/* get disk partition it refers to */
+	/* (re)fstat the file */
 	fstat(fd, &st);
-	partnr = DISKPART(st.st_rdev);
-	dp = &disklab.d_partitions[partnr];
+
+	if (S_ISREG(st.st_mode)) {
+		/* file support; we pick the minimum sector size allowed */
+		size = st.st_size;
+		secsize = imagefile_secsize;
+		sectors = size / secsize;
+	} else {
+		/*
+		 * disc partition support; note we can't use DIOCGPART in userland so
+		 * get disc label and use the stat info to get the partition number.
+		 */
+		if (ioctl(fd, DIOCGDINFO, &disklab) == -1) {
+			/* failed to get disclabel! */
+			perror("disklabel");
+			return errno;
+		}
+
+		/* get disk partition it refers to */
+		fstat(fd, &st);
+		partnr = DISKPART(st.st_rdev);
+		dp = &disklab.d_partitions[partnr];
+
+		/* TODO problem with last_possible_lba on resizable VND; request */
+		if (dp->p_size == 0) {
+			perror("faulty disklabel partition returned, check label\n");
+			return EIO;
+		}
+
+		sectors = dp->p_size;
+		secsize = disklab.d_secsize;
+	}
 
 	/* set up a disc info profile for partitions */
 	di->mmc_profile		= 0x01;	/* disc type */
@@ -323,13 +344,8 @@ udf_update_discinfo(struct mmc_discinfo 
 	di->mmc_cap    = di->mmc_cur;
 	di->disc_flags = MMC_DFLAGS_UNRESTRICTED;
 
-	/* TODO problem with last_possible_lba on resizable VND; request */
-	if (dp->p_size == 0) {
-		perror("faulty disklabel partition returned, check label\n");
-		return EIO;
-	}
-	di->last_possible_lba = dp->p_size - 1;
-	di->sector_size       = disklab.d_secsize;
+	di->last_possible_lba = sectors - 1;
+	di->sector_size       = secsize;
 
 	di->num_sessions = 1;
 	di->num_tracks   = 1;
@@ -1437,7 +1453,7 @@ static void
 usage(void)
 {
 	(void)fprintf(stderr, "Usage: %s [-cFM] [-L loglabel] "
-	    "[-P discid] [-S setlabel] [-s size] [-p perc] "
+	    "[-P discid] [-S sectorsize] [-s size] [-p perc] "
 	    "[-t gmtoff] [-v min_udf] [-V max_udf] special\n", getprogname());
 	exit(EXIT_FAILURE);
 }
@@ -1449,7 +1465,8 @@ main(int argc, char **argv)
 	struct tm *tm;
 	struct stat st;
 	time_t now;
-	char  scrap[255];
+	off_t setsize;
+	char  scrap[255], *colon;
 	int ch, req_enable, req_disable, force;
 	int error;
 
@@ -1461,6 +1478,8 @@ main(int argc, char **argv)
 	format_flags  = FORMAT_INVALID;
 	force         = 0;
 	check_surface = 0;
+	setsize       = 0;
+	imagefile_secsize = 512;	/* minimum allowed sector size */
 
 	srandom((unsigned long) time(NULL));
 	udf_init_create_context();
@@ -1512,14 +1531,34 @@ main(int argc, char **argv)
 				context.min_udf = context.max_udf;
 			break;
 		case 'P' :
+			/* check if there is a ':' in the name */
+			if ((colon = strstr(optarg, ":"))) {
+				if (context.volset_name)
+					free(context.volset_name);
+				*colon = 0;
+				context.volset_name = strdup(optarg);
+				optarg = colon+1;
+			}
+			if (context.primary_name)
+				free(context.primary_name);
+			if ((strstr(optarg, ":"))) {
+				perror("primary name can't have ':' in its name");
+				return EXIT_FAILURE;
+			}
 			context.primary_name = strdup(optarg);
 			break;
 		case 's' :
-			/* TODO size argument; recordable emulation */
+			/* support for files, set file size */
+			/* XXX support for formatting recordables on vnd/file? */
+			if (dehumanize_number(optarg, &setsize) < 0) {
+				perror("can't parse size argument");
+				return EXIT_FAILURE;
+			}
+			setsize = MAX(0, setsize);
 			break;
 		case 'S' :
-			if (context.volset_name) free(context.volset_name);
-			context.volset_name = strdup(optarg);
+			imagefile_secsize = a_num(optarg, "secsize");
+			imagefile_secsize = MAX(512, imagefile_secsize);
 			break;
 		case 't' :
 			/* time zone overide */
@@ -1539,8 +1578,26 @@ main(int argc, char **argv)
 
 	/* open device */
 	if ((fd = open(dev, O_RDWR, 0)) == -1) {
-		perror("can't open device");
-		return EXIT_FAILURE;
+		/* check if we need to create a file */
+		fd = open(dev, O_RDONLY, 0);
+		if (fd > 0) {
+			perror("device is there but can't be opened for read/write");
+			return EXIT_FAILURE;
+		}
+		if (!force) {
+			perror("can't open device");
+			return EXIT_FAILURE;
+		}
+		if (setsize == 0) {
+			perror("need to create image file but no size specified");
+			return EXIT_FAILURE;
+		}
+		/* need to create a file */
+		fd = open(dev, O_RDWR | O_CREAT | O_TRUNC, 0777);
+		if (fd == -1) {
+			perror("can't create image file");
+			return EXIT_FAILURE;
+		}
 	}
 
 	/* stat the device */
@@ -1550,8 +1607,21 @@ main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
+	if (S_ISREG(st.st_mode)) {
+		if (setsize == 0)
+			setsize = st.st_size;
+		/* sanitise arguments */
+		imagefile_secsize &= ~511;
+		setsize &= ~(imagefile_secsize-1);
+
+		if (ftruncate(fd, setsize)) {
+			perror("can't resize file");
+			return EXIT_FAILURE;
+		}
+	}
+
 	/* formatting can only be done on raw devices */
-	if (!S_ISCHR(st.st_mode)) {
+	if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
 		printf("%s is not a raw device\n", dev);
 		close(fd);
 		return EXIT_FAILURE;
@@ -1560,7 +1630,7 @@ main(int argc, char **argv)
 	/* just in case something went wrong, synchronise the drive's cache */
 	udf_synchronise_caches();
 
-	/* get disc information */
+	/* get 'disc' information */
 	error = udf_update_discinfo(&mmc_discinfo);
 	if (error) {
 		perror("can't retrieve discinfo");

Reply via email to