diff options
Diffstat (limited to 'lib/libufs')
-rw-r--r-- | lib/libufs/Makefile | 27 | ||||
-rw-r--r-- | lib/libufs/block.c | 154 | ||||
-rw-r--r-- | lib/libufs/bread.3 | 99 | ||||
-rw-r--r-- | lib/libufs/cgread.3 | 106 | ||||
-rw-r--r-- | lib/libufs/cgroup.c | 87 | ||||
-rw-r--r-- | lib/libufs/inode.c | 95 | ||||
-rw-r--r-- | lib/libufs/libufs.3 | 78 | ||||
-rw-r--r-- | lib/libufs/libufs.h | 137 | ||||
-rw-r--r-- | lib/libufs/sblock.c | 119 | ||||
-rw-r--r-- | lib/libufs/sbread.3 | 81 | ||||
-rw-r--r-- | lib/libufs/type.c | 189 | ||||
-rw-r--r-- | lib/libufs/ufs_disk_close.3 | 112 |
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 |