/*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2013 Juniper Networks, Inc. * Copyright (c) 2022-2023 Klara, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. */ #ifndef _FS_TARFS_TARFS_H_ #define _FS_TARFS_TARFS_H_ #ifndef _KERNEL #error Should only be included by kernel #endif MALLOC_DECLARE(M_TARFSMNT); MALLOC_DECLARE(M_TARFSNODE); MALLOC_DECLARE(M_TARFSNAME); #ifdef SYSCTL_DECL SYSCTL_DECL(_vfs_tarfs); #endif struct componentname; struct mount; struct vnode; /* * Internal representation of a tarfs file system node. */ struct tarfs_node { TAILQ_ENTRY(tarfs_node) entries; TAILQ_ENTRY(tarfs_node) dirents; struct mtx lock; struct vnode *vnode; struct tarfs_mount *tmp; __enum_uint8(vtype) type; ino_t ino; off_t offset; size_t size; size_t physize; char *name; size_t namelen; /* Node attributes */ uid_t uid; gid_t gid; mode_t mode; unsigned int flags; nlink_t nlink; struct timespec atime; struct timespec mtime; struct timespec ctime; struct timespec birthtime; unsigned long gen; /* Block map */ size_t nblk; struct tarfs_blk *blk; struct tarfs_node *parent; union { /* VDIR */ struct { TAILQ_HEAD(, tarfs_node) dirhead; off_t lastcookie; struct tarfs_node *lastnode; } dir; /* VLNK */ struct { char *name; size_t namelen; } link; /* VBLK or VCHR */ dev_t rdev; /* VREG */ struct tarfs_node *other; }; }; /* * Entry in sparse file block map. */ struct tarfs_blk { off_t i; /* input (physical) offset */ off_t o; /* output (logical) offset */ size_t l; /* length */ }; /* * Decompression buffer. */ #define TARFS_ZBUF_SIZE 1048576 struct tarfs_zbuf { u_char buf[TARFS_ZBUF_SIZE]; size_t off; /* offset of contents */ size_t len; /* length of contents */ }; /* * Internal representation of a tarfs mount point. */ struct tarfs_mount { TAILQ_HEAD(, tarfs_node) allnodes; struct mtx allnode_lock; struct tarfs_node *root; struct vnode *vp; struct mount *vfs; ino_t ino; struct unrhdr *ino_unr; size_t iosize; size_t nblocks; size_t nfiles; time_t mtime; /* default mtime for directories */ struct tarfs_zio *zio; struct vnode *znode; }; struct tarfs_zio { struct tarfs_mount *tmp; /* decompression state */ #ifdef ZSTDIO struct tarfs_zstd *zstd; /* decompression state (zstd) */ #endif off_t ipos; /* current input position */ off_t opos; /* current output position */ /* index of compression frames */ unsigned int curidx; /* current index position*/ unsigned int nidx; /* number of index entries */ unsigned int szidx; /* index capacity */ struct tarfs_idx { off_t i, o; } *idx; }; struct tarfs_fid { u_short len; /* length of data in bytes */ u_short data0; /* force alignment */ ino_t ino; unsigned long gen; }; #define TARFS_NODE_LOCK(tnp) \ mtx_lock(&(tnp)->lock) #define TARFS_NODE_UNLOCK(tnp) \ mtx_unlock(&(tnp)->lock) #define TARFS_ALLNODES_LOCK(tnp) \ mtx_lock(&(tmp)->allnode_lock) #define TARFS_ALLNODES_UNLOCK(tnp) \ mtx_unlock(&(tmp)->allnode_lock) /* * Data and metadata within tar files are aligned on 512-byte boundaries, * to match the block size of the magnetic tapes they were originally * intended for. */ #define TARFS_BSHIFT 9 #define TARFS_BLOCKSIZE (size_t)(1U << TARFS_BSHIFT) #define TARFS_BLKOFF(l) ((l) % TARFS_BLOCKSIZE) #define TARFS_BLKNUM(l) ((l) >> TARFS_BSHIFT) #define TARFS_SZ2BLKS(sz) (((sz) + TARFS_BLOCKSIZE - 1) / TARFS_BLOCKSIZE) /* * Our preferred I/O size. */ extern unsigned int tarfs_ioshift; #define TARFS_IOSHIFT_MIN TARFS_BSHIFT #define TARFS_IOSHIFT_DEFAULT PAGE_SHIFT #define TARFS_IOSHIFT_MAX PAGE_SHIFT #define TARFS_ROOTINO ((ino_t)3) #define TARFS_ZIOINO ((ino_t)4) #define TARFS_MININO ((ino_t)65535) #define TARFS_COOKIE_DOT 0 #define TARFS_COOKIE_DOTDOT 1 #define TARFS_COOKIE_EOF OFF_MAX #define TARFS_ZIO_NAME ".tar" #define TARFS_ZIO_NAMELEN (sizeof(TARFS_ZIO_NAME) - 1) extern struct vop_vector tarfs_vnodeops; static inline struct tarfs_mount * MP_TO_TARFS_MOUNT(struct mount *mp) { MPASS(mp != NULL && mp->mnt_data != NULL); return (mp->mnt_data); } static inline struct tarfs_node * VP_TO_TARFS_NODE(struct vnode *vp) { MPASS(vp != NULL && vp->v_data != NULL); return (vp->v_data); } int tarfs_alloc_node(struct tarfs_mount *tmp, const char *name, size_t namelen, __enum_uint8(vtype) type, off_t off, size_t sz, time_t mtime, uid_t uid, gid_t gid, mode_t mode, unsigned int flags, const char *linkname, dev_t rdev, struct tarfs_node *parent, struct tarfs_node **node); int tarfs_load_blockmap(struct tarfs_node *tnp, size_t realsize); void tarfs_free_node(struct tarfs_node *tnp); struct tarfs_node * tarfs_lookup_dir(struct tarfs_node *tnp, off_t cookie); struct tarfs_node * tarfs_lookup_node(struct tarfs_node *tnp, struct tarfs_node *f, struct componentname *cnp); int tarfs_read_file(struct tarfs_node *tnp, size_t len, struct uio *uiop); int tarfs_io_init(struct tarfs_mount *tmp); int tarfs_io_fini(struct tarfs_mount *tmp); int tarfs_io_read(struct tarfs_mount *tmp, bool raw, struct uio *uiop); ssize_t tarfs_io_read_buf(struct tarfs_mount *tmp, bool raw, void *buf, off_t off, size_t len); unsigned int tarfs_strtofflags(const char *str, char **end); #endif /* _FS_TARFS_TARFS_H_ */