summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS4
-rw-r--r--lib/Makefile3
-rw-r--r--lib/libufs/Makefile12
-rw-r--r--lib/libufs/block.c87
-rw-r--r--lib/libufs/inode.c95
-rw-r--r--lib/libufs/libufs.h104
-rw-r--r--lib/libufs/sblock.c122
-rw-r--r--lib/libufs/type.c114
8 files changed, 539 insertions, 2 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 2582900..09449ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -68,6 +68,8 @@ share/mk ru Recommends pre-commit review.
ipfw ipfw Pre-commit review preferred. send to ipfw@freebsd.org
xten imp Looking after it, don't remove, don't break it.
drm anholt Just keep me informed of changes, try not to break it.
-xargs jmallett Willing to handle problems. appreciate heads-up
+xargs jmallett Willing to handle problems, appreciate heads-up
but just try not to break it.
regression jmallett Will help write new tests, etc.
+libufs jmallett Willing to handle problems, appreciate heads-up
+ but just try not to break it.
diff --git a/lib/Makefile b/lib/Makefile
index 980bd36..e900b8f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -29,7 +29,8 @@ SUBDIR= ${_csu} libcom_err libcrypt libkvm msun libmd \
libipx libisc libmenu ${_libmilter} ${_libmp} ${_libncp} \
libnetgraph libopie libpam libpanel libpcap \
${_libsm} ${_libsmb} ${_libsmdb} ${_libsmutil} \
- libstand ${_libtelnet} libusbhid ${_libvgl} libwrap libxpg4 liby libz
+ libstand ${_libtelnet} libufs libusbhid ${_libvgl} libwrap libxpg4 \
+ liby libz
.if exists(${.CURDIR}/csu/${MACHINE_ARCH}-${OBJFORMAT})
_csu=csu/${MACHINE_ARCH}-${OBJFORMAT}
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
new file mode 100644
index 0000000..04195eb
--- /dev/null
+++ b/lib/libufs/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+LIB= ufs
+SRCS= block.c inode.c sblock.c type.c
+INCS= libufs.h
+NOMAN= noman
+CFLAGS+= -I${.CURDIR} -D_LIBUFS
+.if defined(DEBUG)
+CFLAGS+= -D_LIBUFS_DEBUGGING
+.endif
+
+.include <bsd.lib.mk>
diff --git a/lib/libufs/block.c b/lib/libufs/block.c
new file mode 100644
index 0000000..054896f
--- /dev/null
+++ b/lib/libufs/block.c
@@ -0,0 +1,87 @@
+/*
+ * 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>
+
+ssize_t
+bread(struct uufsd *disk, ufs2_daddr_t blockno, void *data, size_t size)
+{
+ char *buf;
+ ssize_t cnt;
+
+ DEBUG(NULL);
+
+ /*
+ * For when we need to work with the data as a buffer.
+ */
+ buf = data;
+
+ cnt = pread(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize));
+ /*
+ * In case of failure, zero data, which must be fs_bsize.
+ */
+ if (cnt != size) {
+ DEBUG("short read");
+ for (cnt = 0; cnt < disk->d_fs.fs_bsize; cnt++)
+ buf[cnt] = 0;
+ return -1;
+ }
+ return cnt;
+}
+
+ssize_t
+bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
+{
+ ssize_t cnt;
+
+ DEBUG(NULL);
+
+ cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize));
+ if (cnt != size) {
+ DEBUG("short write");
+ return -1;
+ }
+
+ return cnt;
+}
diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c
new file mode 100644
index 0000000..770f217
--- /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;
+
+ DEBUG(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) {
+ DEBUG(NULL);
+ 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);
+ min = inode - (inode & INOPB(fs));
+ 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;
+ }
+ DEBUG(NULL);
+ return -1;
+}
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
new file mode 100644
index 0000000..0a5a67d
--- /dev/null
+++ b/lib/libufs/libufs.h
@@ -0,0 +1,104 @@
+/*
+ * 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$
+ */
+
+/*
+ * libufs macros (internal, non-exported).
+ */
+#ifdef _LIBUFS
+#ifdef _LIBUFS_DEBUGGING
+/*
+ * Trace steps through libufs, to be used at entry and erroneous return.
+ */
+#define DEBUG(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"); \
+} while (0)
+#else /* _LIBUFS_DEBUGGING */
+#define DEBUG(str) /* nil */
+#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;
+#define d_fs d_sbunion.d_fs
+#define d_sb d_sbunion.d_sb
+};
+
+/*
+ * 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);
+
+/*
+ * inode.c
+ */
+int getino(struct uufsd *, void **, ino_t, int *);
+
+/*
+ * sblock.c
+ */
+int sbread(struct uufsd *);
+int sbwrite(struct uufsd *, int);
+
+/*
+ * type.c
+ */
+struct uufsd *ufs_disk_ctor(const char *);
+int ufs_disk_close(struct uufsd *);
+void ufs_disk_dtor(struct uufsd **);
+int ufs_disk_fillout(struct uufsd *, const char *);
diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c
new file mode 100644
index 0000000..278c8ef
--- /dev/null
+++ b/lib/libufs/sblock.c
@@ -0,0 +1,122 @@
+/*
+ * 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 <string.h>
+#include <unistd.h>
+
+#include <libufs.h>
+
+static int superblocks[] = SBLOCKSEARCH;
+
+int
+sbread(struct uufsd *disk)
+{
+ struct fs *fs;
+ int sb, superblock;
+
+ DEBUG(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) {
+ DEBUG(NULL);
+ return -1;
+ }
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ disk->d_ufs = 1;
+ if ((fs->fs_magic == FS_UFS2_MAGIC) &&
+ (fs->fs_sblockloc == numfrags(fs, superblock)))
+ disk->d_ufs = 2;
+ if ((fs->fs_bsize <= MAXBSIZE) &&
+ (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.
+ */
+ DEBUG("no 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, rofd;
+
+ fs = &disk->d_fs;
+
+ rofd = disk->d_fd;
+ disk->d_fd = open(disk->d_name, O_WRONLY);
+ if (disk->d_fd < 0) {
+ DEBUG("open");
+ return -1;
+ }
+ if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) {
+ DEBUG(NULL);
+ return -1;
+ }
+ if (all) {
+ for (i = 0; i < fs->fs_ncg; i++)
+ if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),
+ fs, SBLOCKSIZE) == -1) {
+ DEBUG(NULL);
+ return -1;
+ }
+ }
+ close(disk->d_fd);
+ disk->d_fd = rofd;
+ return 0;
+}
diff --git a/lib/libufs/type.c b/lib/libufs/type.c
new file mode 100644
index 0000000..cdedf3c
--- /dev/null
+++ b/lib/libufs/type.c
@@ -0,0 +1,114 @@
+/*
+ * 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>
+
+struct uufsd *
+ufs_disk_ctor(const char *name)
+{
+ struct uufsd *new;
+
+ DEBUG(NULL);
+
+ new = malloc(sizeof(*new));
+ if (new == NULL) {
+ DEBUG(NULL);
+ return NULL;
+ }
+
+ if (ufs_disk_fillout(new, name) == -1) {
+ DEBUG(NULL);
+ free(new);
+ return NULL;
+ }
+
+ return new;
+}
+
+void
+ufs_disk_dtor(struct uufsd **disk)
+{
+ DEBUG(NULL);
+ ufs_disk_close(*disk);
+ free(*disk);
+ *disk = NULL;
+}
+
+int
+ufs_disk_close(struct uufsd *disk)
+{
+ DEBUG(NULL);
+ close(disk->d_fd);
+ if (disk->d_inoblock != NULL) {
+ free(disk->d_inoblock);
+ disk->d_inoblock = NULL;
+ }
+ return 0;
+}
+
+int
+ufs_disk_fillout(struct uufsd *disk, const char *name)
+{
+ int fd;
+
+ fd = open(name, O_RDONLY);
+ if (fd == -1) {
+ DEBUG("open");
+ return -1;
+ }
+
+ disk->d_bsize = 1;
+ disk->d_fd = fd;
+ disk->d_inoblock = NULL;
+ disk->d_name = name;
+
+ if (sbread(disk) == -1) {
+ DEBUG(NULL);
+ return -1;
+ }
+
+ return 0;
+}
OpenPOWER on IntegriCloud