summaryrefslogtreecommitdiffstats
path: root/lib/libufs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libufs')
-rw-r--r--lib/libufs/Makefile12
-rw-r--r--lib/libufs/block.c95
-rw-r--r--lib/libufs/cgroup.c73
-rw-r--r--lib/libufs/inode.c95
-rw-r--r--lib/libufs/libufs.h137
-rw-r--r--lib/libufs/sblock.c119
-rw-r--r--lib/libufs/type.c204
7 files changed, 735 insertions, 0 deletions
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
new file mode 100644
index 0000000..64b0bca
--- /dev/null
+++ b/lib/libufs/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+LIB= ufs
+SRCS= block.c cgroup.c inode.c sblock.c type.c
+INCS= libufs.h
+CFLAGS+= -I${.CURDIR} -D_LIBUFS
+.if defined(LIBUFS_DEBUG)
+CFLAGS+= -D_LIBUFS_DEBUGGING
+.endif
+WARNS?= 2
+
+.include <bsd.lib.mk>
diff --git a/lib/libufs/block.c b/lib/libufs/block.c
new file mode 100644
index 0000000..efc39ef
--- /dev/null
+++ b/lib/libufs/block.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 <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;
+
+ ERROR(disk, 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) {
+ ERROR(disk, "short read from block device");
+ for (cnt = 0; cnt < MIN(size, 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;
+ int rv;
+
+ ERROR(disk, NULL);
+
+ rv = ufs_disk_write(disk);
+ if (rv == -1) {
+ ERROR(disk, "failed to open disk for writing");
+ return -1;
+ }
+
+ cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize));
+ if (cnt != size) {
+ ERROR(disk, "short write to block device");
+ return -1;
+ }
+
+ return cnt;
+}
diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c
new file mode 100644
index 0000000..a1d624d
--- /dev/null
+++ b/lib/libufs/cgroup.c
@@ -0,0 +1,73 @@
+/*
+ * 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;
+}
diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c
new file mode 100644
index 0000000..bce5567
--- /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.h b/lib/libufs/libufs.h
new file mode 100644
index 0000000..035f2a5
--- /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);
+
+/*
+ * cgroup.c
+ */
+int cgread(struct uufsd *);
+int cgread1(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
+ */
+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 *);
+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..455fee0
--- /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) &&
+ (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/type.c b/lib/libufs/type.c
new file mode 100644
index 0000000..e5cb062
--- /dev/null
+++ b/lib/libufs/type.c
@@ -0,0 +1,204 @@
+/*
+ * 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
+
+struct uufsd *
+ufs_disk_ctor(const char *name)
+{
+ struct uufsd *new;
+
+ new = NULL;
+
+ ERROR(new, NULL);
+
+ new = malloc(sizeof(*new));
+ if (new == NULL) {
+ ERROR(new, "unable to allocate memory for disk");
+ return NULL;
+ }
+
+ if (ufs_disk_fillout(new, name) == -1) {
+ ERROR(new, "could not fill out disk");
+ free(new);
+ return NULL;
+ }
+
+ return new;
+}
+
+void
+ufs_disk_dtor(struct uufsd **diskp)
+{
+ struct uufsd *disk;
+
+ if (diskp != NULL)
+ disk = *diskp;
+ else
+ return;
+
+ ERROR(disk, NULL);
+
+ ufs_disk_close(disk);
+ free(disk);
+ *diskp = NULL;
+}
+
+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;
+ const char *oname;
+ char dev[MAXPATHLEN];
+ int fd;
+
+ ERROR(disk, NULL);
+
+ oname = name;
+ fs = getfsfile(name);
+ if (fs != NULL)
+ name = fs->fs_spec;
+again: if (stat(name, &st) < 0) {
+ if (*name != '/') {
+ if (*name == 'r')
+ name++;
+ snprintf(dev, sizeof(dev), "%s%s", _PATH_DEV, name);
+ name = dev;
+ goto again;
+ }
+ 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)
+{
+ int rofd;
+
+ ERROR(disk, NULL);
+
+ if (disk->d_mine & MINE_WRITE)
+ return 0;
+
+ rofd = 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");
+ disk->d_fd = rofd;
+ return -1;
+ }
+
+ disk->d_mine |= MINE_WRITE;
+
+ return 0;
+}
OpenPOWER on IntegriCloud