diff --git a/MAINTAINERS b/MAINTAINERS index 258290070fdc..09449ae77c33 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 980bd36a35b6..e900b8f6f6cf 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 000000000000..04195ebb3e5a --- /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 diff --git a/lib/libufs/block.c b/lib/libufs/block.c new file mode 100644 index 000000000000..054896f3d483 --- /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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +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 000000000000..770f2177fd2e --- /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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +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 000000000000..0a5a67db4fa9 --- /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 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 000000000000..278c8ef1a916 --- /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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +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 000000000000..cdedf3cfce7c --- /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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +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; +}