summaryrefslogtreecommitdiffstats
path: root/lib/libufs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libufs')
-rw-r--r--lib/libufs/Makefile27
-rw-r--r--lib/libufs/block.c154
-rw-r--r--lib/libufs/bread.399
-rw-r--r--lib/libufs/cgread.3106
-rw-r--r--lib/libufs/cgroup.c87
-rw-r--r--lib/libufs/inode.c95
-rw-r--r--lib/libufs/libufs.378
-rw-r--r--lib/libufs/libufs.h137
-rw-r--r--lib/libufs/sblock.c119
-rw-r--r--lib/libufs/sbread.381
-rw-r--r--lib/libufs/type.c189
-rw-r--r--lib/libufs/ufs_disk_close.3112
12 files changed, 1284 insertions, 0 deletions
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
new file mode 100644
index 0000000..10726e4
--- /dev/null
+++ b/lib/libufs/Makefile
@@ -0,0 +1,27 @@
+# $FreeBSD$
+
+LIB= ufs
+SHLIBDIR?= /lib
+
+SRCS= block.c cgroup.c inode.c sblock.c type.c
+INCS= libufs.h
+
+MAN= bread.3 cgread.3 libufs.3 sbread.3 ufs_disk_close.3
+MLINKS+= bread.3 bwrite.3
+MLINKS+= bread.3 berase.3
+MLINKS+= cgread.3 cgread1.3
+MLINKS+= cgread.3 cgwrite1.3
+MLINKS+= sbread.3 sbwrite.3
+MLINKS+= ufs_disk_close.3 ufs_disk_fillout.3
+MLINKS+= ufs_disk_close.3 ufs_disk_fillout_blank.3
+MLINKS+= ufs_disk_close.3 ufs_disk_write.3
+
+WARNS?= 2
+
+CFLAGS+= -D_LIBUFS
+.if defined(LIBUFS_DEBUG)
+CFLAGS+= -D_LIBUFS_DEBUGGING
+.endif
+CFLAGS+= -I${.CURDIR}
+
+.include <bsd.lib.mk>
diff --git a/lib/libufs/block.c b/lib/libufs/block.c
new file mode 100644
index 0000000..5450a5d
--- /dev/null
+++ b/lib/libufs/block.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2002 Juli Mallett. All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project. Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/stat.h>
+
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libufs.h>
+
+ssize_t
+bread(struct uufsd *disk, ufs2_daddr_t blockno, void *data, size_t size)
+{
+ void *p2;
+ ssize_t cnt;
+
+ ERROR(disk, NULL);
+
+ p2 = data;
+ /*
+ * XXX: various disk controllers require alignment of our buffer
+ * XXX: which is stricter than struct alignment.
+ * XXX: Bounce the buffer if not 64 byte aligned.
+ * XXX: this can be removed if/when the kernel is fixed
+ */
+ if (((intptr_t)data) & 0x3f) {
+ p2 = malloc(size);
+ if (p2 == NULL)
+ ERROR(disk, "allocate bounce buffer");
+ }
+ cnt = pread(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize));
+ if (cnt == -1) {
+ ERROR(disk, "read error from block device");
+ goto fail;
+ }
+ if (cnt == 0) {
+ ERROR(disk, "end of file from block device");
+ goto fail;
+ }
+ if ((size_t)cnt != size) {
+ ERROR(disk, "short read or read error from block device");
+ goto fail;
+ }
+ if (p2 != data) {
+ memcpy(data, p2, size);
+ free(p2);
+ }
+ return (cnt);
+fail: memset(data, 0, size);
+ if (p2 != data) {
+ free(p2);
+ }
+ return (-1);
+}
+
+ssize_t
+bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
+{
+ ssize_t cnt;
+ int rv;
+ void *p2 = NULL;
+
+ ERROR(disk, NULL);
+
+ rv = ufs_disk_write(disk);
+ if (rv == -1) {
+ ERROR(disk, "failed to open disk for writing");
+ return (-1);
+ }
+
+ /*
+ * XXX: various disk controllers require alignment of our buffer
+ * XXX: which is stricter than struct alignment.
+ * XXX: Bounce the buffer if not 64 byte aligned.
+ * XXX: this can be removed if/when the kernel is fixed
+ */
+ if (((intptr_t)data) & 0x3f) {
+ p2 = malloc(size);
+ if (p2 == NULL)
+ ERROR(disk, "allocate bounce buffer");
+ memcpy(p2, data, size);
+ data = p2;
+ }
+ cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize));
+ if (p2 != NULL)
+ free(p2);
+ if (cnt == -1) {
+ ERROR(disk, "write error to block device");
+ return (-1);
+ }
+ if ((size_t)cnt != size) {
+ ERROR(disk, "short write to block device");
+ return (-1);
+ }
+
+ return (cnt);
+}
+
+int
+berase(struct uufsd *disk, ufs2_daddr_t blockno, ufs2_daddr_t size)
+{
+ off_t ioarg[2];
+ int rv;
+
+ ERROR(disk, NULL);
+ rv = ufs_disk_write(disk);
+ if (rv == -1) {
+ ERROR(disk, "failed to open disk for writing");
+ return(rv);
+ }
+ ioarg[0] = blockno * disk->d_bsize;
+ ioarg[1] = size;
+ rv = ioctl(disk->d_fd, DIOCGDELETE, ioarg);
+ return (rv);
+}
diff --git a/lib/libufs/bread.3 b/lib/libufs/bread.3
new file mode 100644
index 0000000..0a9b862
--- /dev/null
+++ b/lib/libufs/bread.3
@@ -0,0 +1,99 @@
+.\" Author: Juli Mallett <jmallett@FreeBSD.org>
+.\" Date: June 04, 2003
+.\" Description:
+.\" Manual page for libufs functions:
+.\" bread(3)
+.\" bwrite(3)
+.\"
+.\" This file is in the public domain.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 4, 2003
+.Dt BREAD 3
+.Os
+.Sh NAME
+.Nm bread , bwrite
+.Nd read and write blocks of a UFS file system
+.Sh LIBRARY
+.Lb libufs
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.In ufs/ufs/ufsmount.h
+.In ufs/ufs/dinode.h
+.In ufs/ffs/fs.h
+.In libufs.h
+.Ft ssize_t
+.Fn bread "struct uufsd *disk" "ufs2_daddr_t blockno" "void *data" "size_t size"
+.Ft ssize_t
+.Fo bwrite
+.Fa "struct uufsd *disk" "ufs2_daddr_t blockno"
+.Fa "const void *data" "size_t size"
+.Fc
+.Ft int
+.Fo berase
+.Fa "struct uufsd *disk" "ufs2_daddr_t blockno" "ufs2_daddr_t size"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn bread ,
+.Fn bwrite
+and
+.Fn berase
+functions provide a block read, write and erase API for
+.Xr libufs 3
+consumers.
+They operate on a userland UFS disk structure, and perform the read
+and write at a given block address, which uses the current
+.Va d_bsize
+value of the structure.
+.Sh RETURN VALUES
+The
+.Fn bread
+and
+.Fn bwrite
+functions return the amount read or written, or \-1 in case of any error,
+including short read.
+.Pp
+The
+.Fn berase
+function returns non-zero on error.
+.Sh ERRORS
+The function
+.Fn bread
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr ufs_disk_write 3
+or
+.Xr pread 2 .
+.Pp
+The function
+.Fn bwrite
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr pwrite 2 .
+.Pp
+The function
+.Fn berase
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr ioctl 2 .
+.Pp
+Additionally all three functions may follow the
+.Xr libufs 3
+error methodologies in situations where the amount of data written
+is not equal to the amount requested, or in case of a device error.
+.Sh SEE ALSO
+.Xr libufs 3 ,
+.Xr ufs_disk_write 3
+.Sh HISTORY
+These functions first appeared as part of
+.Xr libufs 3
+in
+.Fx 5.0 .
+.Sh AUTHORS
+.An Juli Mallett Aq jmallett@FreeBSD.org
diff --git a/lib/libufs/cgread.3 b/lib/libufs/cgread.3
new file mode 100644
index 0000000..38edf17
--- /dev/null
+++ b/lib/libufs/cgread.3
@@ -0,0 +1,106 @@
+.\" Author: Juli Mallett <jmallett@FreeBSD.org>
+.\" Date: June 04, 2003
+.\" Description:
+.\" Manual page for libufs functions:
+.\" cgread(3)
+.\" cgread1(3)
+.\" cgwrite1(3)
+.\"
+.\" This file is in the public domain.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 4, 2003
+.Dt CGREAD 3
+.Os
+.Sh NAME
+.Nm cgread , cgread1, cgwrite1
+.Nd read/write cylinder groups of UFS disks
+.Sh LIBRARY
+.Lb libufs
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.In ufs/ufs/ufsmount.h
+.In ufs/ufs/dinode.h
+.In ufs/ffs/fs.h
+.In libufs.h
+.Ft int
+.Fn cgread "struct uufsd *disk"
+.Ft int
+.Fn cgread1 "struct uufsd *disk" "int c"
+.Ft int
+.Fn cgwrite1 "struct uufsd *disk" "int c"
+.Sh DESCRIPTION
+The
+.Fn cgread
+and
+.Fn cgread1
+functions provide cylinder group reads for
+.Xr libufs 3
+consumers.
+The
+.Fn cgread1
+function reads from one cylinder group, specified by
+.Fa c
+into the
+.Va d_cg
+field of a userland UFS disk structure.
+It sets the
+.Va d_lcg
+field to the cylinder group number
+.Fa c .
+.Pp
+The
+.Fn cgread
+function operates on sequential cylinder groups.
+Calling the
+.Fn cgread
+function is equivalent to calling
+.Fn cgread1
+with a cylinder group specifier equivalent to the value of the current
+.Va d_ccg
+field, and then incrementing the
+.Va d_ccg
+field.
+.Pp
+The
+.Fn cgwrite1
+function stores cylinder group specified by
+.Fa c
+from
+.Va d_cg
+field of a userland UFS disk structure on disk.
+.Sh RETURN VALUES
+Both functions return 0 if there are no more cylinder groups to read,
+1 if there are more cylinder groups, and \-1 on error.
+.Sh ERRORS
+The function
+.Fn cgread
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr bread 3 .
+.Pp
+The function
+.Fn cgread1
+has semantically identical failure conditions to those of
+.Fn cgread .
+.Pp
+The function
+.Fn cgwrite1
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr bwrite 3 .
+.Sh SEE ALSO
+.Xr bread 3 ,
+.Xr bwrite 3 ,
+.Xr libufs 3
+.Sh HISTORY
+These functions first appeared as part of
+.Xr libufs 3
+in
+.Fx 5.1 .
+.Sh AUTHORS
+.An Juli Mallett Aq jmallett@FreeBSD.org
diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c
new file mode 100644
index 0000000..2185682
--- /dev/null
+++ b/lib/libufs/cgroup.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2003 Juli Mallett. All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project. Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/disklabel.h>
+#include <sys/stat.h>
+
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libufs.h>
+
+int
+cgread(struct uufsd *disk)
+{
+ return (cgread1(disk, disk->d_ccg++));
+}
+
+int
+cgread1(struct uufsd *disk, int c)
+{
+ struct fs *fs;
+ off_t ccg;
+
+ fs = &disk->d_fs;
+
+ if (c >= fs->fs_ncg) {
+ return (0);
+ }
+ ccg = fsbtodb(fs, cgtod(fs, c)) * disk->d_bsize;
+ if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf,
+ fs->fs_bsize) == -1) {
+ ERROR(disk, "unable to read cylinder group");
+ return (-1);
+ }
+ disk->d_lcg = c;
+ return (1);
+}
+
+int
+cgwrite1(struct uufsd *disk, int c)
+{
+ struct fs *fs;
+
+ fs = &disk->d_fs;
+ if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)),
+ disk->d_cgunion.d_buf, fs->fs_bsize) == -1) {
+ ERROR(disk, "unable to write cylinder group");
+ return (-1);
+ }
+ return (0);
+}
diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c
new file mode 100644
index 0000000..d8bef61
--- /dev/null
+++ b/lib/libufs/inode.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2002 Juli Mallett. All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project. Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/disklabel.h>
+#include <sys/stat.h>
+
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libufs.h>
+
+int
+getino(struct uufsd *disk, void **dino, ino_t inode, int *mode)
+{
+ ino_t min, max;
+ caddr_t inoblock;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
+ struct fs *fs;
+
+ ERROR(disk, NULL);
+
+ fs = &disk->d_fs;
+ inoblock = disk->d_inoblock;
+ min = disk->d_inomin;
+ max = disk->d_inomax;
+
+ if (inoblock == NULL) {
+ inoblock = malloc(fs->fs_bsize);
+ if (inoblock == NULL) {
+ ERROR(disk, "unable to allocate inode block");
+ return (-1);
+ }
+ disk->d_inoblock = inoblock;
+ }
+ if (inode >= min && inode < max)
+ goto gotit;
+ bread(disk, fsbtodb(fs, ino_to_fsba(fs, inode)), inoblock,
+ fs->fs_bsize);
+ disk->d_inomin = min = inode - (inode % INOPB(fs));
+ disk->d_inomax = max = min + INOPB(fs);
+gotit: switch (disk->d_ufs) {
+ case 1:
+ dp1 = &((struct ufs1_dinode *)inoblock)[inode - min];
+ *mode = dp1->di_mode & IFMT;
+ *dino = dp1;
+ return (0);
+ case 2:
+ dp2 = &((struct ufs2_dinode *)inoblock)[inode - min];
+ *mode = dp2->di_mode & IFMT;
+ *dino = dp2;
+ return (0);
+ default:
+ break;
+ }
+ ERROR(disk, "unknown UFS filesystem type");
+ return (-1);
+}
diff --git a/lib/libufs/libufs.3 b/lib/libufs/libufs.3
new file mode 100644
index 0000000..6a2c7f6
--- /dev/null
+++ b/lib/libufs/libufs.3
@@ -0,0 +1,78 @@
+.\" Author: Juli Mallett <jmallett@FreeBSD.org>
+.\" Date: June 04, 2003
+.\" Description:
+.\" Manual page for libufs.
+.\"
+.\" This file is in the public domain.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 4, 2003
+.Dt LIBUFS 3
+.Os
+.Sh NAME
+.Nm libufs
+.Nd operate on UFS file systems from userland
+.Sh LIBRARY
+.Lb libufs
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.In ufs/ufs/ufsmount.h
+.In ufs/ufs/dinode.h
+.In ufs/ffs/fs.h
+.In libufs.h
+.Sh DESCRIPTION
+The
+.Nm
+library and the functions it provides are used for implementing
+utilities which need to access a UFS file system at a low level from
+userland.
+Facilities provided are used to implement utilities such as
+.Xr newfs 8
+and
+.Xr dumpfs 8 .
+The
+.Nm
+library is designed to be simple, and to provide functions that are
+traditionally useful to have.
+.Pp
+A disk is represented as the type
+.Vt "struct uufsd"
+as defined in
+.In libufs.h .
+The structure is filled out, operations are performed, and the disk
+is closed.
+.Sh ERRORS
+Functions provided by
+.Nm
+return \-1 in every functional error situation.
+They also set the
+.Va d_error
+field of
+.Vt "struct uufsd"
+to a string describing the error.
+.Sh SEE ALSO
+.Xr bread 3 ,
+.Xr bwrite 3 ,
+.Xr cgread 3 ,
+.Xr cgread1 3 ,
+.Xr cgwrite1 3 ,
+.Xr sbread 3 ,
+.Xr sbwrite 3 ,
+.Xr ufs_disk_close 3 ,
+.Xr ufs_disk_fillout 3 ,
+.Xr ufs_disk_fillout_blank 3 ,
+.Xr ufs_disk_write 3 ,
+.Xr ffs 7
+.Sh HISTORY
+The
+.Xr libufs 3
+library first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+.An Juli Mallett Aq jmallett@FreeBSD.org
+.Pp
+.An -nosplit
+Additional design, feedback, and ideas were provided by
+.An Poul-Henning Kamp Aq phk@FreeBSD.org .
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
new file mode 100644
index 0000000..42a64f7
--- /dev/null
+++ b/lib/libufs/libufs.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2002 Juli Mallett. All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project. Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBUFS_H__
+#define __LIBUFS_H__
+
+/*
+ * libufs macros (internal, non-exported).
+ */
+#ifdef _LIBUFS
+#ifdef _LIBUFS_DEBUGGING
+/*
+ * Trace steps through libufs, to be used at entry and erroneous return.
+ */
+#define ERROR(uufsd, str) \
+do { \
+ fprintf(stderr, "libufs in %s", __func__); \
+ if (str != NULL) \
+ fprintf(stderr, ": %s", str); \
+ if (errno) \
+ fprintf(stderr, ": %s", strerror(errno)); \
+ fprintf(stderr, "\n"); \
+ if ((uufsd) != NULL) \
+ (uufsd)->d_error = str; \
+} while (0)
+#else /* _LIBUFS_DEBUGGING */
+#define ERROR(uufsd, str) \
+do { \
+ if ((uufsd) != NULL) \
+ (uufsd)->d_error = str; \
+} while (0)
+#endif /* _LIBUFS_DEBUGGING */
+#endif /* _LIBUFS */
+
+/*
+ * libufs structures.
+ */
+
+/*
+ * userland ufs disk.
+ */
+struct uufsd {
+ const char *d_name; /* disk name */
+ int d_ufs; /* decimal UFS version */
+ int d_fd; /* raw device file descriptor */
+ long d_bsize; /* device bsize */
+ ufs2_daddr_t d_sblock; /* superblock location */
+ caddr_t d_inoblock; /* inode block */
+ ino_t d_inomin; /* low inode */
+ ino_t d_inomax; /* high inode */
+ union {
+ struct fs d_fs; /* filesystem information */
+ char d_sb[MAXBSIZE];
+ /* superblock as buffer */
+ } d_sbunion;
+ union {
+ struct cg d_cg; /* cylinder group */
+ char d_buf[MAXBSIZE];
+ /* cylinder group storage */
+ } d_cgunion;
+ int d_ccg; /* current cylinder group */
+ int d_lcg; /* last cylinder group (in d_cg) */
+ const char *d_error; /* human readable disk error */
+ int d_mine; /* internal flags */
+#define d_fs d_sbunion.d_fs
+#define d_sb d_sbunion.d_sb
+#define d_cg d_cgunion.d_cg
+};
+
+__BEGIN_DECLS
+
+/*
+ * libufs prototypes.
+ */
+
+/*
+ * block.c
+ */
+ssize_t bread(struct uufsd *, ufs2_daddr_t, void *, size_t);
+ssize_t bwrite(struct uufsd *, ufs2_daddr_t, const void *, size_t);
+int berase(struct uufsd *, ufs2_daddr_t, ufs2_daddr_t);
+
+/*
+ * cgroup.c
+ */
+int cgread(struct uufsd *);
+int cgread1(struct uufsd *, int);
+int cgwrite1(struct uufsd *, int);
+
+/*
+ * inode.c
+ */
+int getino(struct uufsd *, void **, ino_t, int *);
+
+/*
+ * sblock.c
+ */
+int sbread(struct uufsd *);
+int sbwrite(struct uufsd *, int);
+
+/*
+ * type.c
+ */
+int ufs_disk_close(struct uufsd *);
+int ufs_disk_fillout(struct uufsd *, const char *);
+int ufs_disk_fillout_blank(struct uufsd *, const char *);
+int ufs_disk_write(struct uufsd *);
+
+__END_DECLS
+
+#endif /* __LIBUFS_H__ */
diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c
new file mode 100644
index 0000000..c9125f2
--- /dev/null
+++ b/lib/libufs/sblock.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002 Juli Mallett. All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project. Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/disklabel.h>
+#include <sys/stat.h>
+
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libufs.h>
+
+static int superblocks[] = SBLOCKSEARCH;
+
+int
+sbread(struct uufsd *disk)
+{
+ struct fs *fs;
+ int sb, superblock;
+
+ ERROR(disk, NULL);
+
+ fs = &disk->d_fs;
+ superblock = superblocks[0];
+
+ for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
+ if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) {
+ ERROR(disk, "non-existent or truncated superblock");
+ return (-1);
+ }
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ disk->d_ufs = 1;
+ if (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == superblock)
+ disk->d_ufs = 2;
+ if (fs->fs_bsize <= MAXBSIZE &&
+ (size_t)fs->fs_bsize >= sizeof(*fs)) {
+ if (disk->d_ufs)
+ break;
+ }
+ disk->d_ufs = 0;
+ }
+ if (superblock == -1 || disk->d_ufs == 0) {
+ /*
+ * Other error cases will result in errno being set, here we
+ * must set it to indicate no superblock could be found with
+ * which to associate this disk/filesystem.
+ */
+ ERROR(disk, "no usable known superblock found");
+ errno = ENOENT;
+ return (-1);
+ }
+ disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
+ disk->d_sblock = superblock / disk->d_bsize;
+ return (0);
+}
+
+int
+sbwrite(struct uufsd *disk, int all)
+{
+ struct fs *fs;
+ int i;
+
+ ERROR(disk, NULL);
+
+ fs = &disk->d_fs;
+
+ if (!disk->d_sblock) {
+ disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize;
+ }
+
+ if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) {
+ ERROR(disk, "failed to write superblock");
+ return (-1);
+ }
+ if (all) {
+ for (i = 0; i < fs->fs_ncg; i++)
+ if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),
+ fs, SBLOCKSIZE) == -1) {
+ ERROR(disk, "failed to update a superblock");
+ return (-1);
+ }
+ }
+ return (0);
+}
diff --git a/lib/libufs/sbread.3 b/lib/libufs/sbread.3
new file mode 100644
index 0000000..e59365a
--- /dev/null
+++ b/lib/libufs/sbread.3
@@ -0,0 +1,81 @@
+.\" Author: Juli Mallett <jmallett@FreeBSD.org>
+.\" Date: June 04, 2003
+.\" Description:
+.\" Manual page for libufs functions:
+.\" sbread(3)
+.\" sbwrite(3)
+.\"
+.\" This file is in the public domain.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 4, 2003
+.Dt SBREAD 3
+.Os
+.Sh NAME
+.Nm sbread , sbwrite
+.Nd read and write superblocks of a UFS file system
+.Sh LIBRARY
+.Lb libufs
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.In ufs/ufs/ufsmount.h
+.In ufs/ufs/dinode.h
+.In ufs/ffs/fs.h
+.In libufs.h
+.Ft int
+.Fn sbread "struct uufsd *disk"
+.Ft int
+.Fn sbwrite "struct uufsd *disk" "int all"
+.Sh DESCRIPTION
+The
+.Fn sbread
+and
+.Fn sbwrite
+functions provide superblock reads and writes for
+.Xr libufs 3
+consumers.
+The
+.Fn sbread
+and
+.Fn sbwrite
+functions operate on the superblock field,
+.Va d_sb ,
+associated with a given userland UFS disk structure.
+Additionally, the
+.Fn sbwrite
+function will write to all superblock locations if the
+.Fa all
+value is non-zero.
+.Sh RETURN VALUES
+.Rv -std sbread sbwrite
+.Sh ERRORS
+The function
+.Fn sbread
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr bread 3 .
+Additionally, it may follow the
+.Xr libufs 3
+error methodologies in situations where no usable superblock could be
+found.
+.Pp
+The function
+.Fn sbwrite
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr bwrite 3 .
+.Sh SEE ALSO
+.Xr bread 3 ,
+.Xr bwrite 3 ,
+.Xr libufs 3
+.Sh HISTORY
+These functions first appeared as part of
+.Xr libufs 3
+in
+.Fx 5.0 .
+.Sh AUTHORS
+.An Juli Mallett Aq jmallett@FreeBSD.org
diff --git a/lib/libufs/type.c b/lib/libufs/type.c
new file mode 100644
index 0000000..9b7470a
--- /dev/null
+++ b/lib/libufs/type.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2002 Juli Mallett. All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project. Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/disklabel.h>
+#include <sys/stat.h>
+
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <fstab.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libufs.h>
+
+/* Internally, track the 'name' value, it's ours. */
+#define MINE_NAME 0x01
+/* Track if its fd points to a writable device. */
+#define MINE_WRITE 0x02
+
+int
+ufs_disk_close(struct uufsd *disk)
+{
+ ERROR(disk, NULL);
+ close(disk->d_fd);
+ if (disk->d_inoblock != NULL) {
+ free(disk->d_inoblock);
+ disk->d_inoblock = NULL;
+ }
+ if (disk->d_mine & MINE_NAME) {
+ free((char *)(uintptr_t)disk->d_name);
+ disk->d_name = NULL;
+ }
+ return (0);
+}
+
+int
+ufs_disk_fillout(struct uufsd *disk, const char *name)
+{
+ if (ufs_disk_fillout_blank(disk, name) == -1) {
+ return (-1);
+ }
+ if (sbread(disk) == -1) {
+ ERROR(disk, "could not read superblock to fill out disk");
+ return (-1);
+ }
+ return (0);
+}
+
+int
+ufs_disk_fillout_blank(struct uufsd *disk, const char *name)
+{
+ struct stat st;
+ struct fstab *fs;
+ struct statfs sfs;
+ const char *oname;
+ char dev[MAXPATHLEN];
+ int fd, ret;
+
+ ERROR(disk, NULL);
+
+ oname = name;
+again: if ((ret = stat(name, &st)) < 0) {
+ if (*name != '/') {
+ snprintf(dev, sizeof(dev), "%s%s", _PATH_DEV, name);
+ name = dev;
+ goto again;
+ }
+ /*
+ * The given object doesn't exist, but don't panic just yet -
+ * it may be still mount point listed in /etc/fstab, but without
+ * existing corresponding directory.
+ */
+ name = oname;
+ }
+ if (ret >= 0 && S_ISCHR(st.st_mode)) {
+ /* This is what we need, do nothing. */
+ ;
+ } else if ((fs = getfsfile(name)) != NULL) {
+ /*
+ * The given mount point is listed in /etc/fstab.
+ * It is possible that someone unmounted file system by hand
+ * and different file system is mounted on this mount point,
+ * but we still prefer /etc/fstab entry, because on the other
+ * hand, there could be /etc/fstab entry for this mount
+ * point, but file system is not mounted yet (eg. noauto) and
+ * statfs(2) will point us at different file system.
+ */
+ name = fs->fs_spec;
+ } else if (ret >= 0 && S_ISDIR(st.st_mode)) {
+ /*
+ * The mount point is not listed in /etc/fstab, so it may be
+ * file system mounted by hand.
+ */
+ if (statfs(name, &sfs) < 0) {
+ ERROR(disk, "could not find special device");
+ return (-1);
+ }
+ strlcpy(dev, sfs.f_mntfromname, sizeof(dev));
+ name = dev;
+ } else {
+ ERROR(disk, "could not find special device");
+ return (-1);
+ }
+ fd = open(name, O_RDONLY);
+ if (fd == -1) {
+ ERROR(disk, "could not open special device");
+ return (-1);
+ }
+
+ disk->d_bsize = 1;
+ disk->d_ccg = 0;
+ disk->d_fd = fd;
+ disk->d_inoblock = NULL;
+ disk->d_inomin = 0;
+ disk->d_inomax = 0;
+ disk->d_lcg = 0;
+ disk->d_mine = 0;
+ disk->d_ufs = 0;
+ disk->d_error = NULL;
+
+ if (oname != name) {
+ name = strdup(name);
+ if (name == NULL) {
+ ERROR(disk, "could not allocate memory for disk name");
+ return (-1);
+ }
+ disk->d_mine |= MINE_NAME;
+ }
+ disk->d_name = name;
+
+ return (0);
+}
+
+int
+ufs_disk_write(struct uufsd *disk)
+{
+ ERROR(disk, NULL);
+
+ if (disk->d_mine & MINE_WRITE)
+ return (0);
+
+ close(disk->d_fd);
+
+ disk->d_fd = open(disk->d_name, O_RDWR);
+ if (disk->d_fd < 0) {
+ ERROR(disk, "failed to open disk for writing");
+ return (-1);
+ }
+
+ disk->d_mine |= MINE_WRITE;
+
+ return (0);
+}
diff --git a/lib/libufs/ufs_disk_close.3 b/lib/libufs/ufs_disk_close.3
new file mode 100644
index 0000000..a659116
--- /dev/null
+++ b/lib/libufs/ufs_disk_close.3
@@ -0,0 +1,112 @@
+.\" Author: Juli Mallett <jmallett@FreeBSD.org>
+.\" Date: June 04, 2003
+.\" Description:
+.\" Manual page for libufs functions:
+.\" ufs_disk_close(3)
+.\" ufs_disk_fillout(3)
+.\" ufs_disk_fillout_blank(3)
+.\" ufs_disk_write(3)
+.\"
+.\" This file is in the public domain.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 4, 2003
+.Dt UFS_DISK_CLOSE 3
+.Os
+.Sh NAME
+.Nm ufs_disk_close , ufs_disk_fillout , ufs_disk_fillout_blank, ufs_disk_write
+.Nd open and close userland UFS disks
+.Sh LIBRARY
+.Lb libufs
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.In ufs/ufs/ufsmount.h
+.In ufs/ufs/dinode.h
+.In ufs/ffs/fs.h
+.In libufs.h
+.Ft int
+.Fn ufs_disk_close "struct uufsd *disk"
+.Ft int
+.Fn ufs_disk_fillout "struct uufsd *disk" "const char *name"
+.Ft int
+.Fn ufs_disk_fillout_blank "struct uufsd *disk" "const char *name"
+.Ft int
+.Fn ufs_disk_write "struct uufsd *disk"
+.Sh DESCRIPTION
+The
+.Fn ufs_disk_close
+function closes a disk and frees internal memory related to it.
+It does not free the
+.Fa disk
+structure.
+.Pp
+The
+.Fn ufs_disk_fillout
+and
+.Fn ufs_disk_fillout_blank
+functions open a disk specified by
+.Fa name
+and populate the structure pointed to by
+.Fa disk .
+The disk is opened read-only.
+The specified
+.Fa name
+may be either a mountpoint, or a device name.
+The
+.Fn ufs_disk_fillout
+function assumes there is a valid superblock and will fail if not,
+whereas the
+.Fn ufs_disk_fillout_blank
+function makes no assumptions of that sort.
+.Pp
+The
+.Fn ufs_disk_write
+function attempts to re-open a disk as writable if it is not currently.
+.Sh ERRORS
+The function
+.Fn ufs_disk_close
+has no failure points.
+.Pp
+The function
+.Fn ufs_disk_fillout
+may fail for any of the reasons
+.Fn ufs_disk_fillout_blank
+might, as well as for any reason
+.Xr sbread 3
+might.
+.Pp
+The
+.Fn ufs_disk_fillout_blank
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr open 2 ,
+.Xr strdup 3 .
+Additionally, it may follow the
+.Xr libufs 3
+error methodologies in situations where no device could be found to
+open.
+.Pp
+The function
+.Fn ufs_disk_write
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr open 2
+and
+.Xr stat 2 .
+Namely, it will fail if the disk in question may not be written to.
+.Sh SEE ALSO
+.Xr open 2 ,
+.Xr getfsfile 3 ,
+.Xr libufs 3 ,
+.Xr sbread 3
+.Sh HISTORY
+These functions first appeared as part of
+.Xr libufs 3
+in
+.Fx 5.0 .
+.Sh AUTHORS
+.An Juli Mallett Aq jmallett@FreeBSD.org
OpenPOWER on IntegriCloud