169d94f4cSDag-Erling Smørgrav /*- 269d94f4cSDag-Erling Smørgrav * SPDX-License-Identifier: BSD-2-Clause 369d94f4cSDag-Erling Smørgrav * 469d94f4cSDag-Erling Smørgrav * Copyright (c) 2013 Juniper Networks, Inc. 569d94f4cSDag-Erling Smørgrav * Copyright (c) 2022-2023 Klara, Inc. 669d94f4cSDag-Erling Smørgrav * 769d94f4cSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 869d94f4cSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 969d94f4cSDag-Erling Smørgrav * are met: 1069d94f4cSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 1169d94f4cSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 1269d94f4cSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 1369d94f4cSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 1469d94f4cSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 1569d94f4cSDag-Erling Smørgrav * 1669d94f4cSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1769d94f4cSDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1869d94f4cSDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1969d94f4cSDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2069d94f4cSDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2169d94f4cSDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2269d94f4cSDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2369d94f4cSDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2469d94f4cSDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2569d94f4cSDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2669d94f4cSDag-Erling Smørgrav * SUCH DAMAGE. 2769d94f4cSDag-Erling Smørgrav */ 2869d94f4cSDag-Erling Smørgrav 2969d94f4cSDag-Erling Smørgrav #ifndef _FS_TARFS_TARFS_H_ 3069d94f4cSDag-Erling Smørgrav #define _FS_TARFS_TARFS_H_ 3169d94f4cSDag-Erling Smørgrav 3269d94f4cSDag-Erling Smørgrav #ifndef _KERNEL 3369d94f4cSDag-Erling Smørgrav #error Should only be included by kernel 3469d94f4cSDag-Erling Smørgrav #endif 3569d94f4cSDag-Erling Smørgrav 3669d94f4cSDag-Erling Smørgrav MALLOC_DECLARE(M_TARFSMNT); 3769d94f4cSDag-Erling Smørgrav MALLOC_DECLARE(M_TARFSNODE); 3869d94f4cSDag-Erling Smørgrav MALLOC_DECLARE(M_TARFSNAME); 3969d94f4cSDag-Erling Smørgrav 4069d94f4cSDag-Erling Smørgrav #ifdef SYSCTL_DECL 4169d94f4cSDag-Erling Smørgrav SYSCTL_DECL(_vfs_tarfs); 4269d94f4cSDag-Erling Smørgrav #endif 4369d94f4cSDag-Erling Smørgrav 4469d94f4cSDag-Erling Smørgrav struct componentname; 4569d94f4cSDag-Erling Smørgrav struct mount; 4669d94f4cSDag-Erling Smørgrav struct vnode; 4769d94f4cSDag-Erling Smørgrav 4869d94f4cSDag-Erling Smørgrav /* 4969d94f4cSDag-Erling Smørgrav * Internal representation of a tarfs file system node. 5069d94f4cSDag-Erling Smørgrav */ 5169d94f4cSDag-Erling Smørgrav struct tarfs_node { 5269d94f4cSDag-Erling Smørgrav TAILQ_ENTRY(tarfs_node) entries; 5369d94f4cSDag-Erling Smørgrav TAILQ_ENTRY(tarfs_node) dirents; 5469d94f4cSDag-Erling Smørgrav 5569d94f4cSDag-Erling Smørgrav struct mtx lock; 5669d94f4cSDag-Erling Smørgrav 5769d94f4cSDag-Erling Smørgrav struct vnode *vnode; 5869d94f4cSDag-Erling Smørgrav struct tarfs_mount *tmp; 59ba8cc6d7SMateusz Guzik __enum_uint8(vtype) type; 6069d94f4cSDag-Erling Smørgrav ino_t ino; 6169d94f4cSDag-Erling Smørgrav off_t offset; 6269d94f4cSDag-Erling Smørgrav size_t size; 6369d94f4cSDag-Erling Smørgrav size_t physize; 6469d94f4cSDag-Erling Smørgrav char *name; 6569d94f4cSDag-Erling Smørgrav size_t namelen; 6669d94f4cSDag-Erling Smørgrav 6769d94f4cSDag-Erling Smørgrav /* Node attributes */ 6869d94f4cSDag-Erling Smørgrav uid_t uid; 6969d94f4cSDag-Erling Smørgrav gid_t gid; 7069d94f4cSDag-Erling Smørgrav mode_t mode; 7169d94f4cSDag-Erling Smørgrav unsigned int flags; 7269d94f4cSDag-Erling Smørgrav nlink_t nlink; 7369d94f4cSDag-Erling Smørgrav struct timespec atime; 7469d94f4cSDag-Erling Smørgrav struct timespec mtime; 7569d94f4cSDag-Erling Smørgrav struct timespec ctime; 7669d94f4cSDag-Erling Smørgrav struct timespec birthtime; 77*cf0ede72SOlivier Certner uint32_t gen; 7869d94f4cSDag-Erling Smørgrav 7969d94f4cSDag-Erling Smørgrav /* Block map */ 8069d94f4cSDag-Erling Smørgrav size_t nblk; 8169d94f4cSDag-Erling Smørgrav struct tarfs_blk *blk; 8269d94f4cSDag-Erling Smørgrav 8369d94f4cSDag-Erling Smørgrav struct tarfs_node *parent; 8469d94f4cSDag-Erling Smørgrav union { 8569d94f4cSDag-Erling Smørgrav /* VDIR */ 8669d94f4cSDag-Erling Smørgrav struct { 8769d94f4cSDag-Erling Smørgrav TAILQ_HEAD(, tarfs_node) dirhead; 8869d94f4cSDag-Erling Smørgrav off_t lastcookie; 8969d94f4cSDag-Erling Smørgrav struct tarfs_node *lastnode; 9069d94f4cSDag-Erling Smørgrav } dir; 9169d94f4cSDag-Erling Smørgrav 9269d94f4cSDag-Erling Smørgrav /* VLNK */ 9369d94f4cSDag-Erling Smørgrav struct { 9469d94f4cSDag-Erling Smørgrav char *name; 9569d94f4cSDag-Erling Smørgrav size_t namelen; 9669d94f4cSDag-Erling Smørgrav } link; 9769d94f4cSDag-Erling Smørgrav 9869d94f4cSDag-Erling Smørgrav /* VBLK or VCHR */ 9969d94f4cSDag-Erling Smørgrav dev_t rdev; 10069d94f4cSDag-Erling Smørgrav 10169d94f4cSDag-Erling Smørgrav /* VREG */ 10269d94f4cSDag-Erling Smørgrav struct tarfs_node *other; 10369d94f4cSDag-Erling Smørgrav }; 10469d94f4cSDag-Erling Smørgrav }; 10569d94f4cSDag-Erling Smørgrav 10669d94f4cSDag-Erling Smørgrav /* 10769d94f4cSDag-Erling Smørgrav * Entry in sparse file block map. 10869d94f4cSDag-Erling Smørgrav */ 10969d94f4cSDag-Erling Smørgrav struct tarfs_blk { 11069d94f4cSDag-Erling Smørgrav off_t i; /* input (physical) offset */ 11169d94f4cSDag-Erling Smørgrav off_t o; /* output (logical) offset */ 11269d94f4cSDag-Erling Smørgrav size_t l; /* length */ 11369d94f4cSDag-Erling Smørgrav }; 11469d94f4cSDag-Erling Smørgrav 11569d94f4cSDag-Erling Smørgrav /* 11669d94f4cSDag-Erling Smørgrav * Decompression buffer. 11769d94f4cSDag-Erling Smørgrav */ 11869d94f4cSDag-Erling Smørgrav #define TARFS_ZBUF_SIZE 1048576 11969d94f4cSDag-Erling Smørgrav struct tarfs_zbuf { 12069d94f4cSDag-Erling Smørgrav u_char buf[TARFS_ZBUF_SIZE]; 12169d94f4cSDag-Erling Smørgrav size_t off; /* offset of contents */ 12269d94f4cSDag-Erling Smørgrav size_t len; /* length of contents */ 12369d94f4cSDag-Erling Smørgrav }; 12469d94f4cSDag-Erling Smørgrav 12569d94f4cSDag-Erling Smørgrav /* 12669d94f4cSDag-Erling Smørgrav * Internal representation of a tarfs mount point. 12769d94f4cSDag-Erling Smørgrav */ 12869d94f4cSDag-Erling Smørgrav struct tarfs_mount { 12969d94f4cSDag-Erling Smørgrav TAILQ_HEAD(, tarfs_node) allnodes; 13069d94f4cSDag-Erling Smørgrav struct mtx allnode_lock; 13169d94f4cSDag-Erling Smørgrav 13269d94f4cSDag-Erling Smørgrav struct tarfs_node *root; 13369d94f4cSDag-Erling Smørgrav struct vnode *vp; 13469d94f4cSDag-Erling Smørgrav struct mount *vfs; 13569d94f4cSDag-Erling Smørgrav ino_t ino; 13669d94f4cSDag-Erling Smørgrav struct unrhdr *ino_unr; 13769d94f4cSDag-Erling Smørgrav size_t iosize; 13869d94f4cSDag-Erling Smørgrav size_t nblocks; 13969d94f4cSDag-Erling Smørgrav size_t nfiles; 14069d94f4cSDag-Erling Smørgrav time_t mtime; /* default mtime for directories */ 14169d94f4cSDag-Erling Smørgrav 14269d94f4cSDag-Erling Smørgrav struct tarfs_zio *zio; 14369d94f4cSDag-Erling Smørgrav struct vnode *znode; 14469d94f4cSDag-Erling Smørgrav }; 14569d94f4cSDag-Erling Smørgrav 14669d94f4cSDag-Erling Smørgrav struct tarfs_zio { 14769d94f4cSDag-Erling Smørgrav struct tarfs_mount *tmp; 14869d94f4cSDag-Erling Smørgrav 14969d94f4cSDag-Erling Smørgrav /* decompression state */ 15069d94f4cSDag-Erling Smørgrav #ifdef ZSTDIO 15169d94f4cSDag-Erling Smørgrav struct tarfs_zstd *zstd; /* decompression state (zstd) */ 15269d94f4cSDag-Erling Smørgrav #endif 15369d94f4cSDag-Erling Smørgrav off_t ipos; /* current input position */ 15469d94f4cSDag-Erling Smørgrav off_t opos; /* current output position */ 15569d94f4cSDag-Erling Smørgrav 15669d94f4cSDag-Erling Smørgrav /* index of compression frames */ 15769d94f4cSDag-Erling Smørgrav unsigned int curidx; /* current index position*/ 15869d94f4cSDag-Erling Smørgrav unsigned int nidx; /* number of index entries */ 15969d94f4cSDag-Erling Smørgrav unsigned int szidx; /* index capacity */ 16069d94f4cSDag-Erling Smørgrav struct tarfs_idx { off_t i, o; } *idx; 16169d94f4cSDag-Erling Smørgrav }; 16269d94f4cSDag-Erling Smørgrav 16369d94f4cSDag-Erling Smørgrav struct tarfs_fid { 16469d94f4cSDag-Erling Smørgrav u_short len; /* length of data in bytes */ 165*cf0ede72SOlivier Certner uint32_t gen; 16669d94f4cSDag-Erling Smørgrav ino_t ino; 167*cf0ede72SOlivier Certner }; 16869d94f4cSDag-Erling Smørgrav 16969d94f4cSDag-Erling Smørgrav #define TARFS_NODE_LOCK(tnp) \ 17069d94f4cSDag-Erling Smørgrav mtx_lock(&(tnp)->lock) 17169d94f4cSDag-Erling Smørgrav #define TARFS_NODE_UNLOCK(tnp) \ 17269d94f4cSDag-Erling Smørgrav mtx_unlock(&(tnp)->lock) 17369d94f4cSDag-Erling Smørgrav #define TARFS_ALLNODES_LOCK(tnp) \ 17469d94f4cSDag-Erling Smørgrav mtx_lock(&(tmp)->allnode_lock) 17569d94f4cSDag-Erling Smørgrav #define TARFS_ALLNODES_UNLOCK(tnp) \ 17669d94f4cSDag-Erling Smørgrav mtx_unlock(&(tmp)->allnode_lock) 17769d94f4cSDag-Erling Smørgrav 17869d94f4cSDag-Erling Smørgrav /* 17969d94f4cSDag-Erling Smørgrav * Data and metadata within tar files are aligned on 512-byte boundaries, 18069d94f4cSDag-Erling Smørgrav * to match the block size of the magnetic tapes they were originally 18169d94f4cSDag-Erling Smørgrav * intended for. 18269d94f4cSDag-Erling Smørgrav */ 18369d94f4cSDag-Erling Smørgrav #define TARFS_BSHIFT 9 18469d94f4cSDag-Erling Smørgrav #define TARFS_BLOCKSIZE (size_t)(1U << TARFS_BSHIFT) 18569d94f4cSDag-Erling Smørgrav #define TARFS_BLKOFF(l) ((l) % TARFS_BLOCKSIZE) 18669d94f4cSDag-Erling Smørgrav #define TARFS_BLKNUM(l) ((l) >> TARFS_BSHIFT) 18769d94f4cSDag-Erling Smørgrav #define TARFS_SZ2BLKS(sz) (((sz) + TARFS_BLOCKSIZE - 1) / TARFS_BLOCKSIZE) 18869d94f4cSDag-Erling Smørgrav 18969d94f4cSDag-Erling Smørgrav /* 19069d94f4cSDag-Erling Smørgrav * Our preferred I/O size. 19169d94f4cSDag-Erling Smørgrav */ 19269d94f4cSDag-Erling Smørgrav extern unsigned int tarfs_ioshift; 19369d94f4cSDag-Erling Smørgrav #define TARFS_IOSHIFT_MIN TARFS_BSHIFT 19469d94f4cSDag-Erling Smørgrav #define TARFS_IOSHIFT_DEFAULT PAGE_SHIFT 19569d94f4cSDag-Erling Smørgrav #define TARFS_IOSHIFT_MAX PAGE_SHIFT 19669d94f4cSDag-Erling Smørgrav 19769d94f4cSDag-Erling Smørgrav #define TARFS_ROOTINO ((ino_t)3) 19869d94f4cSDag-Erling Smørgrav #define TARFS_ZIOINO ((ino_t)4) 19969d94f4cSDag-Erling Smørgrav #define TARFS_MININO ((ino_t)65535) 20069d94f4cSDag-Erling Smørgrav 20169d94f4cSDag-Erling Smørgrav #define TARFS_COOKIE_DOT 0 20269d94f4cSDag-Erling Smørgrav #define TARFS_COOKIE_DOTDOT 1 20369d94f4cSDag-Erling Smørgrav #define TARFS_COOKIE_EOF OFF_MAX 20469d94f4cSDag-Erling Smørgrav 20569d94f4cSDag-Erling Smørgrav #define TARFS_ZIO_NAME ".tar" 20669d94f4cSDag-Erling Smørgrav #define TARFS_ZIO_NAMELEN (sizeof(TARFS_ZIO_NAME) - 1) 20769d94f4cSDag-Erling Smørgrav 20869d94f4cSDag-Erling Smørgrav extern struct vop_vector tarfs_vnodeops; 20969d94f4cSDag-Erling Smørgrav 21069d94f4cSDag-Erling Smørgrav static inline 21169d94f4cSDag-Erling Smørgrav struct tarfs_mount * 21269d94f4cSDag-Erling Smørgrav MP_TO_TARFS_MOUNT(struct mount *mp) 21369d94f4cSDag-Erling Smørgrav { 21469d94f4cSDag-Erling Smørgrav 21569d94f4cSDag-Erling Smørgrav MPASS(mp != NULL && mp->mnt_data != NULL); 21669d94f4cSDag-Erling Smørgrav return (mp->mnt_data); 21769d94f4cSDag-Erling Smørgrav } 21869d94f4cSDag-Erling Smørgrav 21969d94f4cSDag-Erling Smørgrav static inline 22069d94f4cSDag-Erling Smørgrav struct tarfs_node * 22169d94f4cSDag-Erling Smørgrav VP_TO_TARFS_NODE(struct vnode *vp) 22269d94f4cSDag-Erling Smørgrav { 22369d94f4cSDag-Erling Smørgrav 22469d94f4cSDag-Erling Smørgrav MPASS(vp != NULL && vp->v_data != NULL); 22569d94f4cSDag-Erling Smørgrav return (vp->v_data); 22669d94f4cSDag-Erling Smørgrav } 22769d94f4cSDag-Erling Smørgrav 22869d94f4cSDag-Erling Smørgrav int tarfs_alloc_node(struct tarfs_mount *tmp, const char *name, 229ba8cc6d7SMateusz Guzik size_t namelen, __enum_uint8(vtype) type, off_t off, size_t sz, 23069d94f4cSDag-Erling Smørgrav time_t mtime, uid_t uid, gid_t gid, mode_t mode, 23169d94f4cSDag-Erling Smørgrav unsigned int flags, const char *linkname, dev_t rdev, 23269d94f4cSDag-Erling Smørgrav struct tarfs_node *parent, struct tarfs_node **node); 23369d94f4cSDag-Erling Smørgrav int tarfs_load_blockmap(struct tarfs_node *tnp, size_t realsize); 23469d94f4cSDag-Erling Smørgrav void tarfs_free_node(struct tarfs_node *tnp); 23569d94f4cSDag-Erling Smørgrav struct tarfs_node * 23669d94f4cSDag-Erling Smørgrav tarfs_lookup_dir(struct tarfs_node *tnp, off_t cookie); 23769d94f4cSDag-Erling Smørgrav struct tarfs_node * 23869d94f4cSDag-Erling Smørgrav tarfs_lookup_node(struct tarfs_node *tnp, struct tarfs_node *f, 23969d94f4cSDag-Erling Smørgrav struct componentname *cnp); 24069d94f4cSDag-Erling Smørgrav int tarfs_read_file(struct tarfs_node *tnp, size_t len, struct uio *uiop); 24169d94f4cSDag-Erling Smørgrav 24269d94f4cSDag-Erling Smørgrav int tarfs_io_init(struct tarfs_mount *tmp); 24369d94f4cSDag-Erling Smørgrav int tarfs_io_fini(struct tarfs_mount *tmp); 24469d94f4cSDag-Erling Smørgrav int tarfs_io_read(struct tarfs_mount *tmp, bool raw, 24569d94f4cSDag-Erling Smørgrav struct uio *uiop); 24669d94f4cSDag-Erling Smørgrav ssize_t tarfs_io_read_buf(struct tarfs_mount *tmp, bool raw, 24769d94f4cSDag-Erling Smørgrav void *buf, off_t off, size_t len); 24869d94f4cSDag-Erling Smørgrav unsigned int 24969d94f4cSDag-Erling Smørgrav tarfs_strtofflags(const char *str, char **end); 25069d94f4cSDag-Erling Smørgrav 25169d94f4cSDag-Erling Smørgrav #endif /* _FS_TARFS_TARFS_H_ */ 252