xref: /kernel/linux/linux-5.10/fs/hfs/hfs_fs.h (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci *  linux/fs/hfs/hfs_fs.h
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 1995-1997  Paul H. Hargrove
58c2ecf20Sopenharmony_ci * (C) 2003 Ardis Technologies <roman@ardistech.com>
68c2ecf20Sopenharmony_ci * This file may be distributed under the terms of the GNU General Public License.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _LINUX_HFS_FS_H
108c2ecf20Sopenharmony_ci#define _LINUX_HFS_FS_H
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#ifdef pr_fmt
138c2ecf20Sopenharmony_ci#undef pr_fmt
148c2ecf20Sopenharmony_ci#endif
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/types.h>
208c2ecf20Sopenharmony_ci#include <linux/mutex.h>
218c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
228c2ecf20Sopenharmony_ci#include <linux/fs.h>
238c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
268c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include "hfs.h"
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define DBG_BNODE_REFS	0x00000001
318c2ecf20Sopenharmony_ci#define DBG_BNODE_MOD	0x00000002
328c2ecf20Sopenharmony_ci#define DBG_CAT_MOD	0x00000004
338c2ecf20Sopenharmony_ci#define DBG_INODE	0x00000008
348c2ecf20Sopenharmony_ci#define DBG_SUPER	0x00000010
358c2ecf20Sopenharmony_ci#define DBG_EXTENT	0x00000020
368c2ecf20Sopenharmony_ci#define DBG_BITMAP	0x00000040
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci//#define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD|DBG_CAT_MOD|DBG_BITMAP)
398c2ecf20Sopenharmony_ci//#define DBG_MASK	(DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE)
408c2ecf20Sopenharmony_ci//#define DBG_MASK	(DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT)
418c2ecf20Sopenharmony_ci#define DBG_MASK	(0)
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define hfs_dbg(flg, fmt, ...)					\
448c2ecf20Sopenharmony_cido {								\
458c2ecf20Sopenharmony_ci	if (DBG_##flg & DBG_MASK)				\
468c2ecf20Sopenharmony_ci		printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__);	\
478c2ecf20Sopenharmony_ci} while (0)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define hfs_dbg_cont(flg, fmt, ...)				\
508c2ecf20Sopenharmony_cido {								\
518c2ecf20Sopenharmony_ci	if (DBG_##flg & DBG_MASK)				\
528c2ecf20Sopenharmony_ci		pr_cont(fmt, ##__VA_ARGS__);			\
538c2ecf20Sopenharmony_ci} while (0)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/*
578c2ecf20Sopenharmony_ci * struct hfs_inode_info
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci * The HFS-specific part of a Linux (struct inode)
608c2ecf20Sopenharmony_ci */
618c2ecf20Sopenharmony_cistruct hfs_inode_info {
628c2ecf20Sopenharmony_ci	atomic_t opencnt;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	unsigned int flags;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* to deal with localtime ugliness */
678c2ecf20Sopenharmony_ci	int tz_secondswest;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	struct hfs_cat_key cat_key;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	struct list_head open_dir_list;
728c2ecf20Sopenharmony_ci	spinlock_t open_dir_lock;
738c2ecf20Sopenharmony_ci	struct inode *rsrc_inode;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	struct mutex extents_lock;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	u16 alloc_blocks, clump_blocks;
788c2ecf20Sopenharmony_ci	sector_t fs_blocks;
798c2ecf20Sopenharmony_ci	/* Allocation extents from catlog record or volume header */
808c2ecf20Sopenharmony_ci	hfs_extent_rec first_extents;
818c2ecf20Sopenharmony_ci	u16 first_blocks;
828c2ecf20Sopenharmony_ci	hfs_extent_rec cached_extents;
838c2ecf20Sopenharmony_ci	u16 cached_start, cached_blocks;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	loff_t phys_size;
868c2ecf20Sopenharmony_ci	struct inode vfs_inode;
878c2ecf20Sopenharmony_ci};
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define HFS_FLG_RSRC		0x0001
908c2ecf20Sopenharmony_ci#define HFS_FLG_EXT_DIRTY	0x0002
918c2ecf20Sopenharmony_ci#define HFS_FLG_EXT_NEW		0x0004
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci#define HFS_IS_RSRC(inode)	(HFS_I(inode)->flags & HFS_FLG_RSRC)
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/*
968c2ecf20Sopenharmony_ci * struct hfs_sb_info
978c2ecf20Sopenharmony_ci *
988c2ecf20Sopenharmony_ci * The HFS-specific part of a Linux (struct super_block)
998c2ecf20Sopenharmony_ci */
1008c2ecf20Sopenharmony_cistruct hfs_sb_info {
1018c2ecf20Sopenharmony_ci	struct buffer_head *mdb_bh;		/* The hfs_buffer
1028c2ecf20Sopenharmony_ci						   holding the real
1038c2ecf20Sopenharmony_ci						   superblock (aka VIB
1048c2ecf20Sopenharmony_ci						   or MDB) */
1058c2ecf20Sopenharmony_ci	struct hfs_mdb *mdb;
1068c2ecf20Sopenharmony_ci	struct buffer_head *alt_mdb_bh;		/* The hfs_buffer holding
1078c2ecf20Sopenharmony_ci						   the alternate superblock */
1088c2ecf20Sopenharmony_ci	struct hfs_mdb *alt_mdb;
1098c2ecf20Sopenharmony_ci	__be32 *bitmap;				/* The page holding the
1108c2ecf20Sopenharmony_ci						   allocation bitmap */
1118c2ecf20Sopenharmony_ci	struct hfs_btree *ext_tree;			/* Information about
1128c2ecf20Sopenharmony_ci						   the extents b-tree */
1138c2ecf20Sopenharmony_ci	struct hfs_btree *cat_tree;			/* Information about
1148c2ecf20Sopenharmony_ci						   the catalog b-tree */
1158c2ecf20Sopenharmony_ci	u32 file_count;				/* The number of
1168c2ecf20Sopenharmony_ci						   regular files in
1178c2ecf20Sopenharmony_ci						   the filesystem */
1188c2ecf20Sopenharmony_ci	u32 folder_count;			/* The number of
1198c2ecf20Sopenharmony_ci						   directories in the
1208c2ecf20Sopenharmony_ci						   filesystem */
1218c2ecf20Sopenharmony_ci	u32 next_id;				/* The next available
1228c2ecf20Sopenharmony_ci						   file id number */
1238c2ecf20Sopenharmony_ci	u32 clumpablks;				/* The number of allocation
1248c2ecf20Sopenharmony_ci						   blocks to try to add when
1258c2ecf20Sopenharmony_ci						   extending a file */
1268c2ecf20Sopenharmony_ci	u32 fs_start;				/* The first 512-byte
1278c2ecf20Sopenharmony_ci						   block represented
1288c2ecf20Sopenharmony_ci						   in the bitmap */
1298c2ecf20Sopenharmony_ci	u32 part_start;
1308c2ecf20Sopenharmony_ci	u16 root_files;				/* The number of
1318c2ecf20Sopenharmony_ci						   regular
1328c2ecf20Sopenharmony_ci						   (non-directory)
1338c2ecf20Sopenharmony_ci						   files in the root
1348c2ecf20Sopenharmony_ci						   directory */
1358c2ecf20Sopenharmony_ci	u16 root_dirs;				/* The number of
1368c2ecf20Sopenharmony_ci						   directories in the
1378c2ecf20Sopenharmony_ci						   root directory */
1388c2ecf20Sopenharmony_ci	u16 fs_ablocks;				/* The number of
1398c2ecf20Sopenharmony_ci						   allocation blocks
1408c2ecf20Sopenharmony_ci						   in the filesystem */
1418c2ecf20Sopenharmony_ci	u16 free_ablocks;			/* the number of unused
1428c2ecf20Sopenharmony_ci						   allocation blocks
1438c2ecf20Sopenharmony_ci						   in the filesystem */
1448c2ecf20Sopenharmony_ci	u32 alloc_blksz;			/* The size of an
1458c2ecf20Sopenharmony_ci						   "allocation block" */
1468c2ecf20Sopenharmony_ci	int s_quiet;				/* Silent failure when
1478c2ecf20Sopenharmony_ci						   changing owner or mode? */
1488c2ecf20Sopenharmony_ci	__be32 s_type;				/* Type for new files */
1498c2ecf20Sopenharmony_ci	__be32 s_creator;			/* Creator for new files */
1508c2ecf20Sopenharmony_ci	umode_t s_file_umask;			/* The umask applied to the
1518c2ecf20Sopenharmony_ci						   permissions on all files */
1528c2ecf20Sopenharmony_ci	umode_t s_dir_umask;			/* The umask applied to the
1538c2ecf20Sopenharmony_ci						   permissions on all dirs */
1548c2ecf20Sopenharmony_ci	kuid_t s_uid;				/* The uid of all files */
1558c2ecf20Sopenharmony_ci	kgid_t s_gid;				/* The gid of all files */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	int session, part;
1588c2ecf20Sopenharmony_ci	struct nls_table *nls_io, *nls_disk;
1598c2ecf20Sopenharmony_ci	struct mutex bitmap_lock;
1608c2ecf20Sopenharmony_ci	unsigned long flags;
1618c2ecf20Sopenharmony_ci	u16 blockoffset;
1628c2ecf20Sopenharmony_ci	int fs_div;
1638c2ecf20Sopenharmony_ci	struct super_block *sb;
1648c2ecf20Sopenharmony_ci	int work_queued;		/* non-zero delayed work is queued */
1658c2ecf20Sopenharmony_ci	struct delayed_work mdb_work;	/* MDB flush delayed work */
1668c2ecf20Sopenharmony_ci	spinlock_t work_lock;		/* protects mdb_work and work_queued */
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci#define HFS_FLG_BITMAP_DIRTY	0
1708c2ecf20Sopenharmony_ci#define HFS_FLG_MDB_DIRTY	1
1718c2ecf20Sopenharmony_ci#define HFS_FLG_ALT_MDB_DIRTY	2
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/* bitmap.c */
1748c2ecf20Sopenharmony_ciextern u32 hfs_vbm_search_free(struct super_block *, u32, u32 *);
1758c2ecf20Sopenharmony_ciextern int hfs_clear_vbm_bits(struct super_block *, u16, u16);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/* catalog.c */
1788c2ecf20Sopenharmony_ciextern int hfs_cat_keycmp(const btree_key *, const btree_key *);
1798c2ecf20Sopenharmony_cistruct hfs_find_data;
1808c2ecf20Sopenharmony_ciextern int hfs_cat_find_brec(struct super_block *, u32, struct hfs_find_data *);
1818c2ecf20Sopenharmony_ciextern int hfs_cat_create(u32, struct inode *, const struct qstr *, struct inode *);
1828c2ecf20Sopenharmony_ciextern int hfs_cat_delete(u32, struct inode *, const struct qstr *);
1838c2ecf20Sopenharmony_ciextern int hfs_cat_move(u32, struct inode *, const struct qstr *,
1848c2ecf20Sopenharmony_ci			struct inode *, const struct qstr *);
1858c2ecf20Sopenharmony_ciextern void hfs_cat_build_key(struct super_block *, btree_key *, u32, const struct qstr *);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/* dir.c */
1888c2ecf20Sopenharmony_ciextern const struct file_operations hfs_dir_operations;
1898c2ecf20Sopenharmony_ciextern const struct inode_operations hfs_dir_inode_operations;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/* extent.c */
1928c2ecf20Sopenharmony_ciextern int hfs_ext_keycmp(const btree_key *, const btree_key *);
1938c2ecf20Sopenharmony_ciextern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int);
1948c2ecf20Sopenharmony_ciextern int hfs_ext_write_extent(struct inode *);
1958c2ecf20Sopenharmony_ciextern int hfs_extend_file(struct inode *);
1968c2ecf20Sopenharmony_ciextern void hfs_file_truncate(struct inode *);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ciextern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci/* inode.c */
2018c2ecf20Sopenharmony_ciextern const struct address_space_operations hfs_aops;
2028c2ecf20Sopenharmony_ciextern const struct address_space_operations hfs_btree_aops;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ciextern struct inode *hfs_new_inode(struct inode *, const struct qstr *, umode_t);
2058c2ecf20Sopenharmony_ciextern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
2068c2ecf20Sopenharmony_ciextern int hfs_write_inode(struct inode *, struct writeback_control *);
2078c2ecf20Sopenharmony_ciextern int hfs_inode_setattr(struct dentry *, struct iattr *);
2088c2ecf20Sopenharmony_ciextern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
2098c2ecf20Sopenharmony_ci			__be32 log_size, __be32 phys_size, u32 clump_size);
2108c2ecf20Sopenharmony_ciextern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *);
2118c2ecf20Sopenharmony_ciextern void hfs_evict_inode(struct inode *);
2128c2ecf20Sopenharmony_ciextern void hfs_delete_inode(struct inode *);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/* attr.c */
2158c2ecf20Sopenharmony_ciextern const struct xattr_handler *hfs_xattr_handlers[];
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci/* mdb.c */
2188c2ecf20Sopenharmony_ciextern int hfs_mdb_get(struct super_block *);
2198c2ecf20Sopenharmony_ciextern void hfs_mdb_commit(struct super_block *);
2208c2ecf20Sopenharmony_ciextern void hfs_mdb_close(struct super_block *);
2218c2ecf20Sopenharmony_ciextern void hfs_mdb_put(struct super_block *);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci/* part_tbl.c */
2248c2ecf20Sopenharmony_ciextern int hfs_part_find(struct super_block *, sector_t *, sector_t *);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci/* string.c */
2278c2ecf20Sopenharmony_ciextern const struct dentry_operations hfs_dentry_operations;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ciextern int hfs_hash_dentry(const struct dentry *, struct qstr *);
2308c2ecf20Sopenharmony_ciextern int hfs_strcmp(const unsigned char *, unsigned int,
2318c2ecf20Sopenharmony_ci		      const unsigned char *, unsigned int);
2328c2ecf20Sopenharmony_ciextern int hfs_compare_dentry(const struct dentry *dentry,
2338c2ecf20Sopenharmony_ci		unsigned int len, const char *str, const struct qstr *name);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci/* trans.c */
2368c2ecf20Sopenharmony_ciextern void hfs_asc2mac(struct super_block *, struct hfs_name *, const struct qstr *);
2378c2ecf20Sopenharmony_ciextern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci/* super.c */
2408c2ecf20Sopenharmony_ciextern void hfs_mark_mdb_dirty(struct super_block *sb);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci/*
2438c2ecf20Sopenharmony_ci * There are two time systems.  Both are based on seconds since
2448c2ecf20Sopenharmony_ci * a particular time/date.
2458c2ecf20Sopenharmony_ci *	Unix:	signed little-endian since 00:00 GMT, Jan. 1, 1970
2468c2ecf20Sopenharmony_ci *	mac:	unsigned big-endian since 00:00 GMT, Jan. 1, 1904
2478c2ecf20Sopenharmony_ci *
2488c2ecf20Sopenharmony_ci * HFS implementations are highly inconsistent, this one matches the
2498c2ecf20Sopenharmony_ci * traditional behavior of 64-bit Linux, giving the most useful
2508c2ecf20Sopenharmony_ci * time range between 1970 and 2106, by treating any on-disk timestamp
2518c2ecf20Sopenharmony_ci * under HFS_UTC_OFFSET (Jan 1 1970) as a time between 2040 and 2106.
2528c2ecf20Sopenharmony_ci */
2538c2ecf20Sopenharmony_ci#define HFS_UTC_OFFSET 2082844800U
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic inline time64_t __hfs_m_to_utime(__be32 mt)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	time64_t ut = (u32)(be32_to_cpu(mt) - HFS_UTC_OFFSET);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return ut + sys_tz.tz_minuteswest * 60;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic inline __be32 __hfs_u_to_mtime(time64_t ut)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	ut -= sys_tz.tz_minuteswest * 60;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return cpu_to_be32(lower_32_bits(ut) + HFS_UTC_OFFSET);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci#define HFS_I(inode)	(container_of(inode, struct hfs_inode_info, vfs_inode))
2698c2ecf20Sopenharmony_ci#define HFS_SB(sb)	((struct hfs_sb_info *)(sb)->s_fs_info)
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci#define hfs_m_to_utime(time)   (struct timespec64){ .tv_sec = __hfs_m_to_utime(time) }
2728c2ecf20Sopenharmony_ci#define hfs_u_to_mtime(time)   __hfs_u_to_mtime((time).tv_sec)
2738c2ecf20Sopenharmony_ci#define hfs_mtime()		__hfs_u_to_mtime(ktime_get_real_seconds())
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic inline const char *hfs_mdb_name(struct super_block *sb)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	return sb->s_id;
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic inline void hfs_bitmap_dirty(struct super_block *sb)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags);
2838c2ecf20Sopenharmony_ci	hfs_mark_mdb_dirty(sb);
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci#define sb_bread512(sb, sec, data) ({			\
2878c2ecf20Sopenharmony_ci	struct buffer_head *__bh;			\
2888c2ecf20Sopenharmony_ci	sector_t __block;				\
2898c2ecf20Sopenharmony_ci	loff_t __start;					\
2908c2ecf20Sopenharmony_ci	int __offset;					\
2918c2ecf20Sopenharmony_ci							\
2928c2ecf20Sopenharmony_ci	__start = (loff_t)(sec) << HFS_SECTOR_SIZE_BITS;\
2938c2ecf20Sopenharmony_ci	__block = __start >> (sb)->s_blocksize_bits;	\
2948c2ecf20Sopenharmony_ci	__offset = __start & ((sb)->s_blocksize - 1);	\
2958c2ecf20Sopenharmony_ci	__bh = sb_bread((sb), __block);			\
2968c2ecf20Sopenharmony_ci	if (likely(__bh != NULL))			\
2978c2ecf20Sopenharmony_ci		data = (void *)(__bh->b_data + __offset);\
2988c2ecf20Sopenharmony_ci	else						\
2998c2ecf20Sopenharmony_ci		data = NULL;				\
3008c2ecf20Sopenharmony_ci	__bh;						\
3018c2ecf20Sopenharmony_ci})
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci#endif
304