1 |
1275 |
phoenix |
/*
|
2 |
|
|
* linux/include/linux/hfsplus_fs.h
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1999
|
5 |
|
|
* Brad Boyer (flar@pants.nu)
|
6 |
|
|
* (C) 2003 Ardis Technologies <roman@ardistech.com>
|
7 |
|
|
*
|
8 |
|
|
*/
|
9 |
|
|
|
10 |
|
|
#ifndef _LINUX_HFSPLUS_FS_H
|
11 |
|
|
#define _LINUX_HFSPLUS_FS_H
|
12 |
|
|
|
13 |
|
|
#include <linux/fs.h>
|
14 |
|
|
#include <linux/version.h>
|
15 |
|
|
#include "hfsplus_raw.h"
|
16 |
|
|
|
17 |
|
|
#define DBG_BNODE_REFS 0x00000001
|
18 |
|
|
#define DBG_BNODE_MOD 0x00000002
|
19 |
|
|
#define DBG_CAT_MOD 0x00000004
|
20 |
|
|
#define DBG_INODE 0x00000008
|
21 |
|
|
#define DBG_SUPER 0x00000010
|
22 |
|
|
#define DBG_EXTENT 0x00000020
|
23 |
|
|
|
24 |
|
|
//#define DBG_MASK (DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
|
25 |
|
|
//#define DBG_MASK (DBG_BNODE_MOD|DBG_CAT_MOD)
|
26 |
|
|
//#define DBG_MASK (DBG_BNODE_REFS|DBG_INODE|DBG_BNODE_MOD)
|
27 |
|
|
#define DBG_MASK (0)
|
28 |
|
|
|
29 |
|
|
#define dprint(flg, fmt, args...) \
|
30 |
|
|
if (flg & DBG_MASK) printk(fmt , ## args)
|
31 |
|
|
|
32 |
|
|
/* Runtime config options */
|
33 |
|
|
#define HFSPLUS_CASE_ASIS 0
|
34 |
|
|
#define HFSPLUS_CASE_LOWER 1
|
35 |
|
|
|
36 |
|
|
#define HFSPLUS_FORK_RAW 0
|
37 |
|
|
#define HFSPLUS_FORK_CAP 1
|
38 |
|
|
#define HFSPLUS_FORK_DOUBLE 2
|
39 |
|
|
#define HFSPLUS_FORK_NETATALK 3
|
40 |
|
|
|
41 |
|
|
#define HFSPLUS_NAMES_TRIVIAL 0
|
42 |
|
|
#define HFSPLUS_NAMES_CAP 1
|
43 |
|
|
#define HFSPLUS_NAMES_NETATALK 2
|
44 |
|
|
#define HFSPLUS_NAMES_7BIT 3
|
45 |
|
|
|
46 |
|
|
#define HFSPLUS_DEF_CR_TYPE 0x3F3F3F3F /* '????' */
|
47 |
|
|
|
48 |
|
|
#define HFSPLUS_TYPE_DATA 0x00
|
49 |
|
|
#define HFSPLUS_TYPE_RSRC 0xFF
|
50 |
|
|
|
51 |
|
|
typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
|
52 |
|
|
|
53 |
|
|
#define NODE_HASH_SIZE 256
|
54 |
|
|
|
55 |
|
|
/* An HFS+ BTree held in memory */
|
56 |
|
|
typedef struct hfsplus_btree {
|
57 |
|
|
struct super_block *sb;
|
58 |
|
|
struct inode *inode;
|
59 |
|
|
btree_keycmp keycmp;
|
60 |
|
|
|
61 |
|
|
u32 cnid;
|
62 |
|
|
u32 root;
|
63 |
|
|
u32 leaf_count;
|
64 |
|
|
u32 leaf_head;
|
65 |
|
|
u32 leaf_tail;
|
66 |
|
|
u32 node_count;
|
67 |
|
|
u32 free_nodes;
|
68 |
|
|
u32 attributes;
|
69 |
|
|
|
70 |
|
|
unsigned int node_size;
|
71 |
|
|
unsigned int node_size_shift;
|
72 |
|
|
unsigned int max_key_len;
|
73 |
|
|
unsigned int depth;
|
74 |
|
|
|
75 |
|
|
//unsigned int map1_size, map_size;
|
76 |
|
|
struct semaphore tree_lock;
|
77 |
|
|
|
78 |
|
|
unsigned int pages_per_bnode;
|
79 |
|
|
spinlock_t hash_lock;
|
80 |
|
|
struct hfsplus_bnode *node_hash[NODE_HASH_SIZE];
|
81 |
|
|
int node_hash_cnt;
|
82 |
|
|
} hfsplus_btree;
|
83 |
|
|
|
84 |
|
|
struct page;
|
85 |
|
|
|
86 |
|
|
/* An HFS+ BTree node in memory */
|
87 |
|
|
typedef struct hfsplus_bnode {
|
88 |
|
|
struct hfsplus_btree *tree;
|
89 |
|
|
|
90 |
|
|
u32 prev;
|
91 |
|
|
u32 this;
|
92 |
|
|
u32 next;
|
93 |
|
|
u32 parent;
|
94 |
|
|
|
95 |
|
|
u16 num_recs;
|
96 |
|
|
u8 kind;
|
97 |
|
|
u8 height;
|
98 |
|
|
|
99 |
|
|
struct hfsplus_bnode *next_hash;
|
100 |
|
|
unsigned long flags;
|
101 |
|
|
wait_queue_head_t lock_wq;
|
102 |
|
|
atomic_t refcnt;
|
103 |
|
|
unsigned int page_offset;
|
104 |
|
|
struct page *page[0];
|
105 |
|
|
} hfsplus_bnode;
|
106 |
|
|
|
107 |
|
|
#define HFSPLUS_BNODE_LOCK 0
|
108 |
|
|
#define HFSPLUS_BNODE_ERROR 1
|
109 |
|
|
#define HFSPLUS_BNODE_NEW 2
|
110 |
|
|
#define HFSPLUS_BNODE_DIRTY 3
|
111 |
|
|
#define HFSPLUS_BNODE_DELETED 4
|
112 |
|
|
|
113 |
|
|
/*
|
114 |
|
|
* HFS+ superblock info (built from Volume Header on disk)
|
115 |
|
|
*/
|
116 |
|
|
|
117 |
|
|
struct hfsplus_vh;
|
118 |
|
|
struct hfsplus_btree;
|
119 |
|
|
|
120 |
|
|
struct hfsplus_sb_info {
|
121 |
|
|
struct buffer_head *s_vhbh;
|
122 |
|
|
struct hfsplus_vh *s_vhdr;
|
123 |
|
|
struct hfsplus_btree *ext_tree;
|
124 |
|
|
struct hfsplus_btree *cat_tree;
|
125 |
|
|
struct hfsplus_btree *attr_tree;
|
126 |
|
|
struct inode *alloc_file;
|
127 |
|
|
struct inode *hidden_dir;
|
128 |
|
|
|
129 |
|
|
/* Runtime variables */
|
130 |
|
|
u32 blockoffset;
|
131 |
|
|
u32 sect_count;
|
132 |
|
|
//int a2b_shift;
|
133 |
|
|
|
134 |
|
|
/* Stuff in host order from Vol Header */
|
135 |
|
|
u32 total_blocks;
|
136 |
|
|
u32 free_blocks;
|
137 |
|
|
u32 next_alloc;
|
138 |
|
|
u32 next_cnid;
|
139 |
|
|
u32 file_count;
|
140 |
|
|
u32 folder_count;
|
141 |
|
|
|
142 |
|
|
/* Config options */
|
143 |
|
|
u32 creator;
|
144 |
|
|
u32 type;
|
145 |
|
|
|
146 |
|
|
int charcase;
|
147 |
|
|
int fork;
|
148 |
|
|
int namemap;
|
149 |
|
|
|
150 |
|
|
umode_t umask;
|
151 |
|
|
uid_t uid;
|
152 |
|
|
gid_t gid;
|
153 |
|
|
|
154 |
|
|
unsigned long flags;
|
155 |
|
|
|
156 |
|
|
atomic_t inode_cnt;
|
157 |
|
|
u32 last_inode_cnt;
|
158 |
|
|
|
159 |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
160 |
|
|
struct list_head rsrc_inodes;
|
161 |
|
|
#else
|
162 |
|
|
struct hlist_head rsrc_inodes;
|
163 |
|
|
#endif
|
164 |
|
|
};
|
165 |
|
|
|
166 |
|
|
#define HFSPLUS_SB_WRITEBACKUP 0x0001
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
struct hfsplus_inode_info {
|
170 |
|
|
/* Device number in hfsplus_permissions in catalog */
|
171 |
|
|
u32 dev;
|
172 |
|
|
/* Allocation extents from catlog record or volume header */
|
173 |
|
|
hfsplus_extent_rec extents;
|
174 |
|
|
u32 total_blocks, extent_blocks, alloc_blocks;
|
175 |
|
|
atomic_t opencnt;
|
176 |
|
|
|
177 |
|
|
struct inode *rsrc_inode;
|
178 |
|
|
unsigned long flags;
|
179 |
|
|
|
180 |
|
|
struct list_head open_dir_list;
|
181 |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
182 |
|
|
unsigned long mmu_private;
|
183 |
|
|
#else
|
184 |
|
|
loff_t mmu_private;
|
185 |
|
|
struct inode vfs_inode;
|
186 |
|
|
#endif
|
187 |
|
|
};
|
188 |
|
|
|
189 |
|
|
#define HFSPLUS_FLG_RSRC 0x0001
|
190 |
|
|
#define HFSPLUS_FLG_DIRTYMODE 0x0002
|
191 |
|
|
|
192 |
|
|
#define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC))
|
193 |
|
|
#define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)
|
194 |
|
|
|
195 |
|
|
struct hfsplus_find_data {
|
196 |
|
|
/* filled by caller */
|
197 |
|
|
hfsplus_btree_key *search_key;
|
198 |
|
|
hfsplus_btree_key *key;
|
199 |
|
|
/* filled by find */
|
200 |
|
|
hfsplus_btree *tree;
|
201 |
|
|
hfsplus_bnode *bnode;
|
202 |
|
|
/* filled by findrec */
|
203 |
|
|
int record, exact;
|
204 |
|
|
int keyoffset, keylength;
|
205 |
|
|
int entryoffset, entrylength;
|
206 |
|
|
};
|
207 |
|
|
|
208 |
|
|
struct hfsplus_readdir_data {
|
209 |
|
|
struct list_head list;
|
210 |
|
|
struct file *file;
|
211 |
|
|
hfsplus_cat_key key;
|
212 |
|
|
};
|
213 |
|
|
|
214 |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
215 |
|
|
typedef long sector_t;
|
216 |
|
|
#endif
|
217 |
|
|
|
218 |
|
|
/*
|
219 |
|
|
* Functions in any *.c used in other files
|
220 |
|
|
*/
|
221 |
|
|
|
222 |
|
|
/* bfind.c */
|
223 |
|
|
void hfsplus_find_rec(hfsplus_bnode *, struct hfsplus_find_data *);
|
224 |
|
|
int hfsplus_btree_find(struct hfsplus_find_data *);
|
225 |
|
|
int hfsplus_btree_find_entry(struct hfsplus_find_data *,
|
226 |
|
|
void *, int);
|
227 |
|
|
int hfsplus_btree_move(struct hfsplus_find_data *, int);
|
228 |
|
|
int hfsplus_find_init(hfsplus_btree *, struct hfsplus_find_data *);
|
229 |
|
|
void hfsplus_find_exit(struct hfsplus_find_data *);
|
230 |
|
|
|
231 |
|
|
/* bnode.c */
|
232 |
|
|
struct buffer_head *hfsplus_getblk(struct inode *, unsigned long);
|
233 |
|
|
hfsplus_bnode *__hfsplus_find_bnode(hfsplus_btree *, u32);
|
234 |
|
|
void __hfsplus_bnode_remove(hfsplus_bnode *);
|
235 |
|
|
hfsplus_bnode *hfsplus_create_bnode(hfsplus_btree *, u32);
|
236 |
|
|
hfsplus_bnode *hfsplus_find_bnode(hfsplus_btree *, u32);
|
237 |
|
|
void hfsplus_get_bnode(hfsplus_bnode *);
|
238 |
|
|
void hfsplus_put_bnode(hfsplus_bnode *);
|
239 |
|
|
void hfsplus_bnode_free(hfsplus_bnode *);
|
240 |
|
|
void hfsplus_bnode_readbytes(hfsplus_bnode *, void *, unsigned long, unsigned long);
|
241 |
|
|
u16 hfsplus_bnode_read_u16(hfsplus_bnode *, unsigned long);
|
242 |
|
|
void hfsplus_bnode_writebytes(hfsplus_bnode *, void *, unsigned long, unsigned long);
|
243 |
|
|
void hfsplus_bnode_write_u16(hfsplus_bnode *, unsigned long, u16);
|
244 |
|
|
void hfsplus_bnode_copybytes(hfsplus_bnode *, unsigned long,
|
245 |
|
|
hfsplus_bnode *, unsigned long, unsigned long);
|
246 |
|
|
void hfsplus_bnode_movebytes(hfsplus_bnode *, unsigned long, unsigned long, unsigned long);
|
247 |
|
|
int hfsplus_bnode_insert_rec(struct hfsplus_find_data *, void *, int);
|
248 |
|
|
int hfsplus_bnode_remove_rec(struct hfsplus_find_data *);
|
249 |
|
|
|
250 |
|
|
/* brec.c */
|
251 |
|
|
u16 hfsplus_brec_lenoff(hfsplus_bnode *, u16, u16 *);
|
252 |
|
|
u16 hfsplus_brec_keylen(hfsplus_bnode *, u16);
|
253 |
|
|
|
254 |
|
|
/* btree.c */
|
255 |
|
|
hfsplus_btree *hfsplus_open_btree(struct super_block *, u32);
|
256 |
|
|
void hfsplus_close_btree(struct hfsplus_btree *);
|
257 |
|
|
void hfsplus_write_btree(struct hfsplus_btree *);
|
258 |
|
|
hfsplus_bnode *hfsplus_btree_alloc_node(hfsplus_btree *);
|
259 |
|
|
void hfsplus_btree_remove_node(hfsplus_bnode *);
|
260 |
|
|
void hfsplus_btree_free_node(hfsplus_bnode *);
|
261 |
|
|
|
262 |
|
|
/* catalog.c */
|
263 |
|
|
int hfsplus_cmp_cat_key(hfsplus_btree_key *, hfsplus_btree_key *);
|
264 |
|
|
void hfsplus_fill_cat_key(hfsplus_btree_key *, u32, struct qstr *);
|
265 |
|
|
int hfsplus_find_cat(struct super_block *, unsigned long, struct hfsplus_find_data *);
|
266 |
|
|
int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
|
267 |
|
|
int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
|
268 |
|
|
int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
|
269 |
|
|
struct inode *, struct qstr *);
|
270 |
|
|
|
271 |
|
|
/* extents.c */
|
272 |
|
|
int hfsplus_cmp_ext_key(hfsplus_btree_key *, hfsplus_btree_key *);
|
273 |
|
|
void hfsplus_fill_ext_key(hfsplus_btree_key *, u32, u32, u8);
|
274 |
|
|
int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
|
275 |
|
|
int hfsplus_free_fork(struct super_block *, u32, hfsplus_fork_raw *, int);
|
276 |
|
|
int hfsplus_extend_file(struct inode *);
|
277 |
|
|
void hfsplus_truncate(struct inode *);
|
278 |
|
|
|
279 |
|
|
/* inode.c */
|
280 |
|
|
void hfsplus_inode_read_fork(struct inode *, hfsplus_fork_raw *);
|
281 |
|
|
void hfsplus_inode_write_fork(struct inode *, hfsplus_fork_raw *);
|
282 |
|
|
int hfsplus_cat_read_inode(struct inode *, struct hfsplus_find_data *);
|
283 |
|
|
void hfsplus_cat_write_inode(struct inode *);
|
284 |
|
|
struct inode *hfsplus_new_inode(struct super_block *, int);
|
285 |
|
|
void hfsplus_delete_inode(struct inode *);
|
286 |
|
|
|
287 |
|
|
extern struct address_space_operations hfsplus_btree_aops;
|
288 |
|
|
|
289 |
|
|
/* options.c */
|
290 |
|
|
int parse_options(char *, struct hfsplus_sb_info *);
|
291 |
|
|
void fill_defaults(struct hfsplus_sb_info *);
|
292 |
|
|
void fill_current(struct hfsplus_sb_info *, struct hfsplus_sb_info *);
|
293 |
|
|
|
294 |
|
|
/* tables.c */
|
295 |
|
|
extern u16 case_fold_table[];
|
296 |
|
|
|
297 |
|
|
/* unicode.c */
|
298 |
|
|
int hfsplus_unistrcmp(const hfsplus_unistr *, const hfsplus_unistr *);
|
299 |
|
|
int hfsplus_uni2asc(const hfsplus_unistr *, char *, int *);
|
300 |
|
|
int hfsplus_asc2uni(hfsplus_unistr *, const char *, int);
|
301 |
|
|
|
302 |
|
|
/* wrapper.c */
|
303 |
|
|
int hfsplus_read_wrapper(struct super_block *);
|
304 |
|
|
|
305 |
|
|
/* access macros */
|
306 |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
307 |
|
|
#define HFSPLUS_SB(super) (*(struct hfsplus_sb_info *)&(super)->u)
|
308 |
|
|
#define HFSPLUS_I(inode) (*(struct hfsplus_inode_info *)&(inode)->u)
|
309 |
|
|
#else
|
310 |
|
|
/*
|
311 |
|
|
static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
|
312 |
|
|
{
|
313 |
|
|
return sb->s_fs_info;
|
314 |
|
|
}
|
315 |
|
|
static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
|
316 |
|
|
{
|
317 |
|
|
return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
|
318 |
|
|
}
|
319 |
|
|
*/
|
320 |
|
|
#define HFSPLUS_SB(super) (*(struct hfsplus_sb_info *)(super)->s_fs_info)
|
321 |
|
|
#define HFSPLUS_I(inode) (*list_entry(inode, struct hfsplus_inode_info, vfs_inode))
|
322 |
|
|
#endif
|
323 |
|
|
|
324 |
|
|
#if 1
|
325 |
|
|
#define hfsplus_kmap(p) ({ struct page *__p = (p); kmap(__p); })
|
326 |
|
|
#define hfsplus_kunmap(p) ({ struct page *__p = (p); kunmap(__p); __p; })
|
327 |
|
|
#else
|
328 |
|
|
#define hfsplus_kmap(p) kmap(p)
|
329 |
|
|
#define hfsplus_kunmap(p) kunmap(p)
|
330 |
|
|
#endif
|
331 |
|
|
|
332 |
|
|
/* time macros */
|
333 |
|
|
#define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U)
|
334 |
|
|
#define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U))
|
335 |
|
|
|
336 |
|
|
/* compatibility */
|
337 |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
|
338 |
|
|
#define PageUptodate(page) Page_Uptodate(page)
|
339 |
|
|
#define wait_on_page_locked(page) wait_on_page(page)
|
340 |
|
|
#define get_seconds() CURRENT_TIME
|
341 |
|
|
#define page_symlink(i,n,l) block_symlink(i,n,l)
|
342 |
|
|
#define map_bh(bh, sb, block) ({ \
|
343 |
|
|
bh->b_dev = kdev_t_to_nr(sb->s_dev); \
|
344 |
|
|
bh->b_blocknr = block; \
|
345 |
|
|
bh->b_state |= (1UL << BH_Mapped); \
|
346 |
|
|
})
|
347 |
|
|
#define set_buffer_new(bh) (bh->b_state |= (1UL << BH_New))
|
348 |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21)
|
349 |
|
|
#define new_inode(sb) ({ \
|
350 |
|
|
struct inode *inode = get_empty_inode(); \
|
351 |
|
|
if (inode) { \
|
352 |
|
|
inode->i_sb = sb; \
|
353 |
|
|
inode->i_dev = sb->s_dev; \
|
354 |
|
|
inode->i_blkbits = sb->s_blocksize_bits; \
|
355 |
|
|
} \
|
356 |
|
|
inode; \
|
357 |
|
|
})
|
358 |
|
|
#endif
|
359 |
|
|
#define hfsp_mt2ut(t) __hfsp_mt2ut(t)
|
360 |
|
|
#define hfsp_ut2mt(t) __hfsp_ut2mt(t)
|
361 |
|
|
#define hfsp_now2mt() __hfsp_ut2mt(CURRENT_TIME)
|
362 |
|
|
#else
|
363 |
|
|
#define hfsp_mt2ut(t) (struct timespec){ .tv_sec = __hfsp_mt2ut(t) }
|
364 |
|
|
#define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec)
|
365 |
|
|
#define hfsp_now2mt() __hfsp_ut2mt(get_seconds())
|
366 |
|
|
#endif
|
367 |
|
|
|
368 |
|
|
#endif
|