summaryrefslogtreecommitdiffstats
path: root/sbin/newfs
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/newfs')
-rw-r--r--sbin/newfs/Makefile5
-rw-r--r--sbin/newfs/mkfs.c8
-rw-r--r--sbin/newfs/newfs.812
-rw-r--r--sbin/newfs/newfs.c87
-rw-r--r--sbin/newfs/newfs.h16
5 files changed, 112 insertions, 16 deletions
diff --git a/sbin/newfs/Makefile b/sbin/newfs/Makefile
index efbe7ab..9454e53 100644
--- a/sbin/newfs/Makefile
+++ b/sbin/newfs/Makefile
@@ -1,10 +1,13 @@
# @(#)Makefile 8.2 (Berkeley) 3/27/94
# $FreeBSD$
+.PATH: ${.CURDIR}/../../sys/geom
+
PROG= newfs
DPADD= ${LIBUFS}
LDADD= -lufs
-SRCS= newfs.c mkfs.c
+SRCS= newfs.c mkfs.c geom_bsd_enc.c
+
WARNS?= 2
MAN= newfs.8
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index b3bbcbf..072e528 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -459,7 +459,7 @@ mkfs(struct partition *pp, char *fsys)
* Wipe out old UFS1 superblock(s) if necessary.
*/
if (!Nflag && Oflag != 1) {
- i = bread(&disk, SBLOCK_UFS1 / disk.d_bsize, chdummy, SBLOCKSIZE);
+ i = bread(&disk, part_ofs + SBLOCK_UFS1 / disk.d_bsize, chdummy, SBLOCKSIZE);
if (i == -1)
err(1, "can't read old UFS1 superblock: %s", disk.d_error);
@@ -872,7 +872,7 @@ alloc(int size, int mode)
{
int i, d, blkno, frag;
- bread(&disk, fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
+ bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
sblock.fs_cgsize);
if (acg.cg_magic != CG_MAGIC) {
printf("cg 0: bad magic number\n");
@@ -925,7 +925,7 @@ iput(union dinode *ip, ino_t ino)
int c;
c = ino_to_cg(&sblock, ino);
- bread(&disk, fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
+ bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
sblock.fs_cgsize);
if (acg.cg_magic != CG_MAGIC) {
printf("cg 0: bad magic number\n");
@@ -942,7 +942,7 @@ iput(union dinode *ip, ino_t ino)
exit(32);
}
d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
- bread(&disk, d, (char *)iobuf, sblock.fs_bsize);
+ bread(&disk, part_ofs + d, (char *)iobuf, sblock.fs_bsize);
if (sblock.fs_magic == FS_UFS1_MAGIC)
((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
ip->dp1;
diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8
index 8771188..6dcb859 100644
--- a/sbin/newfs/newfs.8
+++ b/sbin/newfs/newfs.8
@@ -52,6 +52,7 @@
.Op Fl i Ar bytes
.Op Fl m Ar free-space
.Op Fl o Ar optimization
+.Op Fl p Ar partition
.Op Fl r Ar reserved
.Op Fl s Ar size
.Ar special
@@ -201,6 +202,17 @@ the default is to optimize for
See
.Xr tunefs 8
for more details on how to set this option.
+.It Fl p Ar partition
+The partition name (a..h) you want to use in case the underlying image
+is a file, so you don't have access to individual partitions through the
+filesystem.
+Can also be used with a device, e.g.
+.Nm
+.Fl p Ar f
+.Ar /dev/da1s3
+is equivalent to
+.Nm
+.Ar /dev/da1s3f .
.It Fl r Ar reserved
The size, in sectors, of reserved space
at the end of the partition specified in
diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c
index d5fb66d..269707b 100644
--- a/sbin/newfs/newfs.c
+++ b/sbin/newfs/newfs.c
@@ -139,6 +139,9 @@ u_char *volumelabel = NULL; /* volume label for filesystem */
struct uufsd disk; /* libufs disk structure */
static char device[MAXPATHLEN];
+static u_char bootarea[BBSIZE];
+static int is_file; /* work on a file, not a device */
+static char *dkname;
static char *disktype;
static int unlabeled;
@@ -147,6 +150,18 @@ static struct disklabel *getdisklabel(char *s);
static void rewritelabel(char *s, struct disklabel *lp);
static void usage(void);
+ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */
+
+/*
+ * need to replace the library's bwrite so that sbwrite uses this one
+ */
+ssize_t
+bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
+{
+ return pwrite(disk->d_fd, data, size,
+ (off_t)((part_ofs + blockno) * disk->d_bsize));
+}
+
int
main(int argc, char *argv[])
{
@@ -158,7 +173,9 @@ main(int argc, char *argv[])
intmax_t reserved;
int ch, i;
off_t mediasize;
+ char part_name; /* partition name, default to full disk */
+ part_name = 'c';
reserved = 0;
while ((ch = getopt(argc, argv,
"EJL:NO:RS:T:UXa:b:c:d:e:f:g:h:i:lm:no:r:s:")) != -1)
@@ -276,6 +293,11 @@ main(int argc, char *argv[])
*cp != '\0' || reserved < 0)
errx(1, "%s: bad reserved size", optarg);
break;
+ case 'p':
+ is_file = 1;
+ part_name = optarg[0];
+ break;
+
case 's':
errno = 0;
fssize = strtoimax(optarg, &cp, 0);
@@ -294,6 +316,8 @@ main(int argc, char *argv[])
usage();
special = argv[0];
+ if (!special[0])
+ err(1, "empty file/special name");
cp = strrchr(special, '/');
if (cp == 0) {
/*
@@ -303,7 +327,16 @@ main(int argc, char *argv[])
special = device;
}
- if (ufs_disk_fillout_blank(&disk, special) == -1 ||
+ if (is_file) {
+ /* bypass ufs_disk_fillout_blank */
+ bzero( &disk, sizeof(disk));
+ disk.d_bsize = 1;
+ disk.d_name = special;
+ disk.d_fd = open(special, O_RDONLY);
+ if (disk.d_fd < 0 ||
+ (!Nflag && ufs_disk_write(&disk) == -1))
+ errx(1, "%s: ", special);
+ } else if (ufs_disk_fillout_blank(&disk, special) == -1 ||
(!Nflag && ufs_disk_write(&disk) == -1)) {
if (disk.d_error != NULL)
errx(1, "%s: %s", special, disk.d_error);
@@ -312,22 +345,30 @@ main(int argc, char *argv[])
}
if (fstat(disk.d_fd, &st) < 0)
err(1, "%s", special);
- if ((st.st_mode & S_IFMT) != S_IFCHR)
- errx(1, "%s: not a character-special device", special);
+ if ((st.st_mode & S_IFMT) != S_IFCHR) {
+ warn("%s: not a character-special device", special);
+ is_file = 1; /* assume it is a file */
+ dkname = special;
+ if (sectorsize == 0)
+ sectorsize = 512;
+ mediasize = st.st_size;
+ /* set fssize from the partition */
+ } else {
+ part_name = special[strlen(special) - 1];
+ if ((part_name < 'a' || part_name > 'h') && !isdigit(part_name))
+ errx(1, "%s: can't figure out file system partition",
+ special);
- if (sectorsize == 0)
+ if (sectorsize == 0)
if (ioctl(disk.d_fd, DIOCGSECTORSIZE, &sectorsize) == -1)
- sectorsize = 0; /* back out on error for safety */
- if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) != -1)
+ sectorsize = 0; /* back out on error for safety */
+ if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) != -1)
getfssize(&fssize, special, mediasize / sectorsize, reserved);
+ }
pp = NULL;
lp = getdisklabel(special);
if (lp != NULL) {
- cp = strchr(special, '\0');
- cp--;
- if ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))
- errx(1, "%s: can't figure out file system partition",
- special);
+ cp = &part_name;
if (isdigit(*cp))
pp = &lp->d_partitions[RAW_PART];
else
@@ -346,6 +387,8 @@ main(int argc, char *argv[])
fsize = pp->p_fsize;
if (bsize == 0)
bsize = pp->p_frag * pp->p_fsize;
+ if (is_file)
+ part_ofs = pp->p_offset;
}
if (sectorsize <= 0)
errx(1, "%s: no default sector size", special);
@@ -414,6 +457,19 @@ getdisklabel(char *s)
static struct disklabel lab;
struct disklabel *lp;
+ if (is_file) {
+ if (read(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
+ err(4, "cannot read bootarea");
+ if (bsd_disklabel_le_dec(
+ bootarea + (0 /* labeloffset */ +
+ 1 /* labelsoffset */ * sectorsize),
+ &lab, MAXPARTITIONS))
+ errx(1, "no valid label found");
+
+ lp = &lab;
+ return &lab;
+ }
+
if (ioctl(disk.d_fd, DIOCGDINFO, (char *)&lab) != -1)
return (&lab);
unlabeled++;
@@ -432,6 +488,14 @@ rewritelabel(char *s, struct disklabel *lp)
return;
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
+ if (is_file) {
+ bsd_disklabel_le_enc(bootarea + 0 /* labeloffset */ +
+ 1 /* labelsoffset */ * sectorsize, lp);
+ lseek(disk.d_fd, 0, SEEK_SET);
+ if (write(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
+ errx(1, "cannot write label");
+ return;
+ }
if (ioctl(disk.d_fd, DIOCWDINFO, (char *)lp) == -1)
warn("ioctl (WDINFO): %s: can't rewrite disk label", s);
}
@@ -467,6 +531,7 @@ usage()
fprintf(stderr, "\t-n do not create .snap directory\n");
fprintf(stderr, "\t-m minimum free space %%\n");
fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
+ fprintf(stderr, "\t-p partition name (a..h)\n");
fprintf(stderr, "\t-r reserved sectors at the end of device\n");
fprintf(stderr, "\t-s file system size (sectors)\n");
exit(1);
diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h
index 5c428c4..0d7cb62 100644
--- a/sbin/newfs/newfs.h
+++ b/sbin/newfs/newfs.h
@@ -70,4 +70,20 @@ extern int avgfilesperdir; /* expected number of files per directory */
extern u_char *volumelabel; /* volume label for filesystem */
extern struct uufsd disk; /* libufs disk structure */
+/*
+ * To override a limitation in libufs, export the offset (in sectors) of the
+ * partition on the underlying media (file or disk). The value is used as
+ * an offset for all accesses to the media through bread(), which is only
+ * invoked directly in this program.
+ * For bwrite() we need a different approach, namely override the library
+ * version with one defined here. This is because bwrite() is called also
+ * by the library function sbwrite() which we cannot intercept nor want to
+ * rewrite. As a consequence, the internal version of bwrite() adds the
+ * partition offset itself when calling the underlying function, pwrite().
+ *
+ * XXX This info really ought to go into the struct uufsd, at which point
+ * we can remove the above hack.
+ */
+extern ufs2_daddr_t part_ofs; /* partition offset in blocks */
+
void mkfs (struct partition *, char *);
OpenPOWER on IntegriCloud