xref: /freebsd/sys/fs/tarfs/tarfs.h (revision ba8cc6d7)
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;
7769d94f4cSDag-Erling Smørgrav 	unsigned long		 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 */
16569d94f4cSDag-Erling Smørgrav 	u_short			 data0;	/* force alignment */
16669d94f4cSDag-Erling Smørgrav 	ino_t			 ino;
16769d94f4cSDag-Erling Smørgrav 	unsigned long		 gen;
16869d94f4cSDag-Erling Smørgrav };
16969d94f4cSDag-Erling Smørgrav 
17069d94f4cSDag-Erling Smørgrav #define	TARFS_NODE_LOCK(tnp) \
17169d94f4cSDag-Erling Smørgrav 	mtx_lock(&(tnp)->lock)
17269d94f4cSDag-Erling Smørgrav #define	TARFS_NODE_UNLOCK(tnp) \
17369d94f4cSDag-Erling Smørgrav 	mtx_unlock(&(tnp)->lock)
17469d94f4cSDag-Erling Smørgrav #define	TARFS_ALLNODES_LOCK(tnp) \
17569d94f4cSDag-Erling Smørgrav 	mtx_lock(&(tmp)->allnode_lock)
17669d94f4cSDag-Erling Smørgrav #define	TARFS_ALLNODES_UNLOCK(tnp) \
17769d94f4cSDag-Erling Smørgrav 	mtx_unlock(&(tmp)->allnode_lock)
17869d94f4cSDag-Erling Smørgrav 
17969d94f4cSDag-Erling Smørgrav /*
18069d94f4cSDag-Erling Smørgrav  * Data and metadata within tar files are aligned on 512-byte boundaries,
18169d94f4cSDag-Erling Smørgrav  * to match the block size of the magnetic tapes they were originally
18269d94f4cSDag-Erling Smørgrav  * intended for.
18369d94f4cSDag-Erling Smørgrav  */
18469d94f4cSDag-Erling Smørgrav #define	TARFS_BSHIFT		9
18569d94f4cSDag-Erling Smørgrav #define	TARFS_BLOCKSIZE		(size_t)(1U << TARFS_BSHIFT)
18669d94f4cSDag-Erling Smørgrav #define	TARFS_BLKOFF(l)		((l) % TARFS_BLOCKSIZE)
18769d94f4cSDag-Erling Smørgrav #define	TARFS_BLKNUM(l)		((l) >> TARFS_BSHIFT)
18869d94f4cSDag-Erling Smørgrav #define	TARFS_SZ2BLKS(sz)	(((sz) + TARFS_BLOCKSIZE - 1) / TARFS_BLOCKSIZE)
18969d94f4cSDag-Erling Smørgrav 
19069d94f4cSDag-Erling Smørgrav /*
19169d94f4cSDag-Erling Smørgrav  * Our preferred I/O size.
19269d94f4cSDag-Erling Smørgrav  */
19369d94f4cSDag-Erling Smørgrav extern unsigned int tarfs_ioshift;
19469d94f4cSDag-Erling Smørgrav #define	TARFS_IOSHIFT_MIN	TARFS_BSHIFT
19569d94f4cSDag-Erling Smørgrav #define	TARFS_IOSHIFT_DEFAULT	PAGE_SHIFT
19669d94f4cSDag-Erling Smørgrav #define	TARFS_IOSHIFT_MAX	PAGE_SHIFT
19769d94f4cSDag-Erling Smørgrav 
19869d94f4cSDag-Erling Smørgrav #define	TARFS_ROOTINO		((ino_t)3)
19969d94f4cSDag-Erling Smørgrav #define	TARFS_ZIOINO		((ino_t)4)
20069d94f4cSDag-Erling Smørgrav #define	TARFS_MININO		((ino_t)65535)
20169d94f4cSDag-Erling Smørgrav 
20269d94f4cSDag-Erling Smørgrav #define	TARFS_COOKIE_DOT	0
20369d94f4cSDag-Erling Smørgrav #define	TARFS_COOKIE_DOTDOT	1
20469d94f4cSDag-Erling Smørgrav #define	TARFS_COOKIE_EOF	OFF_MAX
20569d94f4cSDag-Erling Smørgrav 
20669d94f4cSDag-Erling Smørgrav #define	TARFS_ZIO_NAME		".tar"
20769d94f4cSDag-Erling Smørgrav #define	TARFS_ZIO_NAMELEN	(sizeof(TARFS_ZIO_NAME) - 1)
20869d94f4cSDag-Erling Smørgrav 
20969d94f4cSDag-Erling Smørgrav extern struct vop_vector tarfs_vnodeops;
21069d94f4cSDag-Erling Smørgrav 
21169d94f4cSDag-Erling Smørgrav static inline
21269d94f4cSDag-Erling Smørgrav struct tarfs_mount *
MP_TO_TARFS_MOUNT(struct mount * mp)21369d94f4cSDag-Erling Smørgrav MP_TO_TARFS_MOUNT(struct mount *mp)
21469d94f4cSDag-Erling Smørgrav {
21569d94f4cSDag-Erling Smørgrav 
21669d94f4cSDag-Erling Smørgrav 	MPASS(mp != NULL && mp->mnt_data != NULL);
21769d94f4cSDag-Erling Smørgrav 	return (mp->mnt_data);
21869d94f4cSDag-Erling Smørgrav }
21969d94f4cSDag-Erling Smørgrav 
22069d94f4cSDag-Erling Smørgrav static inline
22169d94f4cSDag-Erling Smørgrav struct tarfs_node *
VP_TO_TARFS_NODE(struct vnode * vp)22269d94f4cSDag-Erling Smørgrav VP_TO_TARFS_NODE(struct vnode *vp)
22369d94f4cSDag-Erling Smørgrav {
22469d94f4cSDag-Erling Smørgrav 
22569d94f4cSDag-Erling Smørgrav 	MPASS(vp != NULL && vp->v_data != NULL);
22669d94f4cSDag-Erling Smørgrav 	return (vp->v_data);
22769d94f4cSDag-Erling Smørgrav }
22869d94f4cSDag-Erling Smørgrav 
22969d94f4cSDag-Erling Smørgrav int	tarfs_alloc_node(struct tarfs_mount *tmp, const char *name,
230ba8cc6d7SMateusz Guzik 	    size_t namelen, __enum_uint8(vtype) type, off_t off, size_t sz,
23169d94f4cSDag-Erling Smørgrav 	    time_t mtime, uid_t uid, gid_t gid, mode_t mode,
23269d94f4cSDag-Erling Smørgrav 	    unsigned int flags, const char *linkname, dev_t rdev,
23369d94f4cSDag-Erling Smørgrav 	    struct tarfs_node *parent, struct tarfs_node **node);
23469d94f4cSDag-Erling Smørgrav int	tarfs_load_blockmap(struct tarfs_node *tnp, size_t realsize);
23569d94f4cSDag-Erling Smørgrav void	tarfs_free_node(struct tarfs_node *tnp);
23669d94f4cSDag-Erling Smørgrav struct tarfs_node *
23769d94f4cSDag-Erling Smørgrav 	tarfs_lookup_dir(struct tarfs_node *tnp, off_t cookie);
23869d94f4cSDag-Erling Smørgrav struct tarfs_node *
23969d94f4cSDag-Erling Smørgrav 	tarfs_lookup_node(struct tarfs_node *tnp, struct tarfs_node *f,
24069d94f4cSDag-Erling Smørgrav 	    struct componentname *cnp);
24169d94f4cSDag-Erling Smørgrav int	tarfs_read_file(struct tarfs_node *tnp, size_t len, struct uio *uiop);
24269d94f4cSDag-Erling Smørgrav 
24369d94f4cSDag-Erling Smørgrav int	tarfs_io_init(struct tarfs_mount *tmp);
24469d94f4cSDag-Erling Smørgrav int	tarfs_io_fini(struct tarfs_mount *tmp);
24569d94f4cSDag-Erling Smørgrav int	tarfs_io_read(struct tarfs_mount *tmp, bool raw,
24669d94f4cSDag-Erling Smørgrav     struct uio *uiop);
24769d94f4cSDag-Erling Smørgrav ssize_t	tarfs_io_read_buf(struct tarfs_mount *tmp, bool raw,
24869d94f4cSDag-Erling Smørgrav     void *buf, off_t off, size_t len);
24969d94f4cSDag-Erling Smørgrav unsigned int
25069d94f4cSDag-Erling Smørgrav 	tarfs_strtofflags(const char *str, char **end);
25169d94f4cSDag-Erling Smørgrav 
25269d94f4cSDag-Erling Smørgrav #endif	/* _FS_TARFS_TARFS_H_ */
253