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 *
MP_TO_TARFS_MOUNT(struct mount * mp)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 *
VP_TO_TARFS_NODE(struct vnode * vp)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