* [PATCH 3/6] hfs: add HFSX support
@ 2006-01-16 16:40 Roman Zippel
0 siblings, 0 replies; only message in thread
From: Roman Zippel @ 2006-01-16 16:40 UTC (permalink / raw)
To: Andrew Morton, linux-fsdevel; +Cc: David Elliott
From: David Elliott <elliott@stcnet.com>
Add support for HFSX, which allows for case-sensitive filenames.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
---
fs/hfsplus/btree.c | 23 ++++++++++++++---------
fs/hfsplus/catalog.c | 18 ++++++++++++++++--
fs/hfsplus/extents.c | 3 ++-
fs/hfsplus/hfsplus_fs.h | 11 +++++++----
fs/hfsplus/hfsplus_raw.h | 10 ++++++++--
fs/hfsplus/super.c | 5 +++--
fs/hfsplus/unicode.c | 30 +++++++++++++++++++++++++++++-
fs/hfsplus/wrapper.c | 13 +++++++++++--
8 files changed, 90 insertions(+), 23 deletions(-)
Index: linux-2.6-git/fs/hfsplus/catalog.c
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/catalog.c 2006-01-16 17:33:52.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/catalog.c 2006-01-16 17:36:33.000000000 +0100
@@ -13,7 +13,8 @@
#include "hfsplus_fs.h"
#include "hfsplus_raw.h"
-int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1,
+ const hfsplus_btree_key *k2)
{
__be32 k1p, k2p;
@@ -22,7 +23,20 @@ int hfsplus_cat_cmp_key(hfsplus_btree_ke
if (k1p != k2p)
return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
- return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name);
+ return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name);
+}
+
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
+ const hfsplus_btree_key *k2)
+{
+ __be32 k1p, k2p;
+
+ k1p = k1->cat.parent;
+ k2p = k2->cat.parent;
+ if (k1p != k2p)
+ return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
+
+ return hfsplus_strcmp(&k1->cat.name, &k2->cat.name);
}
void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
Index: linux-2.6-git/fs/hfsplus/btree.c
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/btree.c 2006-01-16 17:33:52.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/btree.c 2006-01-16 17:34:14.000000000 +0100
@@ -31,17 +31,8 @@ struct hfs_btree *hfs_btree_open(struct
init_MUTEX(&tree->tree_lock);
spin_lock_init(&tree->hash_lock);
- /* Set the correct compare function */
tree->sb = sb;
tree->cnid = id;
- if (id == HFSPLUS_EXT_CNID) {
- tree->keycmp = hfsplus_ext_cmp_key;
- } else if (id == HFSPLUS_CAT_CNID) {
- tree->keycmp = hfsplus_cat_cmp_key;
- } else {
- printk(KERN_ERR "hfs: unknown B*Tree requested\n");
- goto free_tree;
- }
tree->inode = iget(sb, id);
if (!tree->inode)
goto free_tree;
@@ -64,6 +55,20 @@ struct hfs_btree *hfs_btree_open(struct
tree->max_key_len = be16_to_cpu(head->max_key_len);
tree->depth = be16_to_cpu(head->depth);
+ /* Set the correct compare function */
+ if (id == HFSPLUS_EXT_CNID) {
+ tree->keycmp = hfsplus_ext_cmp_key;
+ } else if (id == HFSPLUS_CAT_CNID) {
+ if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
+ (head->key_type == HFSPLUS_KEY_BINARY))
+ tree->keycmp = hfsplus_cat_bin_cmp_key;
+ else
+ tree->keycmp = hfsplus_cat_case_cmp_key;
+ } else {
+ printk(KERN_ERR "hfs: unknown B*Tree requested\n");
+ goto fail_page;
+ }
+
size = tree->node_size;
if (!size || size & (size - 1))
goto fail_page;
Index: linux-2.6-git/fs/hfsplus/hfsplus_raw.h
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/hfsplus_raw.h 2006-01-16 17:26:38.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/hfsplus_raw.h 2006-01-16 17:36:29.000000000 +0100
@@ -22,8 +22,10 @@
#define HFSPLUS_SECTOR_SHIFT 9
#define HFSPLUS_VOLHEAD_SECTOR 2
#define HFSPLUS_VOLHEAD_SIG 0x482b
+#define HFSPLUS_VOLHEAD_SIGX 0x4858
#define HFSPLUS_SUPER_MAGIC 0x482b
-#define HFSPLUS_CURRENT_VERSION 4
+#define HFSPLUS_MIN_VERSION 4
+#define HFSPLUS_CURRENT_VERSION 5
#define HFSP_WRAP_MAGIC 0x4244
#define HFSP_WRAP_ATTRIB_SLOCK 0x8000
@@ -161,7 +163,7 @@ struct hfs_btree_header_rec {
u16 reserved1;
__be32 clump_size;
u8 btree_type;
- u8 reserved2;
+ u8 key_type;
__be32 attributes;
u32 reserved3[16];
} __packed;
@@ -186,6 +188,10 @@ struct hfs_btree_header_rec {
#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */
#define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */
+/* btree key type */
+#define HFSPLUS_KEY_CASEFOLDING 0xCF /* case-insensitive */
+#define HFSPLUS_KEY_BINARY 0xBC /* case-sensitive */
+
/* HFS+ catalog entry key */
struct hfsplus_cat_key {
__be16 key_len;
Index: linux-2.6-git/fs/hfsplus/super.c
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/super.c 2006-01-16 17:33:52.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/super.c 2006-01-16 17:34:14.000000000 +0100
@@ -316,8 +316,9 @@ static int hfsplus_fill_super(struct sup
vhdr = HFSPLUS_SB(sb).s_vhdr;
/* Copy parts of the volume header into the superblock */
- sb->s_magic = be16_to_cpu(vhdr->signature);
- if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) {
+ sb->s_magic = HFSPLUS_VOLHEAD_SIG;
+ if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION ||
+ be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) {
printk(KERN_ERR "hfs: wrong filesystem version\n");
goto cleanup;
}
Index: linux-2.6-git/fs/hfsplus/wrapper.c
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/wrapper.c 2006-01-16 17:33:52.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/wrapper.c 2006-01-16 17:34:14.000000000 +0100
@@ -28,8 +28,11 @@ static int hfsplus_read_mdb(void *bufptr
{
u32 extent;
u16 attrib;
+ __be16 sig;
- if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
+ sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG);
+ if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) &&
+ sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
return 0;
attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
@@ -114,6 +117,10 @@ int hfsplus_read_wrapper(struct super_bl
}
if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
break;
+ if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
+ HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
+ break;
+ }
brelse(bh);
/* check for a partition block
@@ -158,7 +165,9 @@ int hfsplus_read_wrapper(struct super_bl
return -EIO;
/* should still be the same... */
- if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
+ if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
+ cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
+ cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
goto error;
HFSPLUS_SB(sb).s_vhbh = bh;
HFSPLUS_SB(sb).s_vhdr = vhdr;
Index: linux-2.6-git/fs/hfsplus/hfsplus_fs.h
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/hfsplus_fs.h 2006-01-16 17:29:15.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/hfsplus_fs.h 2006-01-16 17:36:33.000000000 +0100
@@ -36,7 +36,7 @@
#define HFSPLUS_TYPE_DATA 0x00
#define HFSPLUS_TYPE_RSRC 0xFF
-typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
+typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *);
#define NODE_HASH_SIZE 256
@@ -149,6 +149,7 @@ struct hfsplus_sb_info {
#define HFSPLUS_SB_WRITEBACKUP 0x0001
#define HFSPLUS_SB_NODECOMPOSE 0x0002
#define HFSPLUS_SB_FORCE 0x0004
+#define HFSPLUS_SB_HFSX 0x0008
struct hfsplus_inode_info {
@@ -303,7 +304,8 @@ int hfs_brec_read(struct hfs_find_data *
int hfs_brec_goto(struct hfs_find_data *, int);
/* catalog.c */
-int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
@@ -312,7 +314,7 @@ int hfsplus_rename_cat(u32, struct inode
struct inode *, struct qstr *);
/* extents.c */
-int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
void hfsplus_ext_write_extent(struct inode *);
int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
@@ -350,7 +352,8 @@ extern u16 hfsplus_decompose_table[];
extern u16 hfsplus_compose_table[];
/* unicode.c */
-int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
Index: linux-2.6-git/fs/hfsplus/unicode.c
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/unicode.c 2006-01-16 17:26:38.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/unicode.c 2006-01-16 17:34:14.000000000 +0100
@@ -28,7 +28,8 @@ static inline u16 case_fold(u16 c)
}
/* Compare unicode strings, return values like normal strcmp */
-int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2)
+int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
+ const struct hfsplus_unistr *s2)
{
u16 len1, len2, c1, c2;
const hfsplus_unichr *p1, *p2;
@@ -59,6 +60,33 @@ int hfsplus_unistrcmp(const struct hfspl
}
}
+/* Compare names as a sequence of 16-bit unsigned integers */
+int hfsplus_strcmp(const struct hfsplus_unistr *s1,
+ const struct hfsplus_unistr *s2)
+{
+ u16 len1, len2, c1, c2;
+ const hfsplus_unichr *p1, *p2;
+ int len;
+
+ len1 = be16_to_cpu(s1->length);
+ len2 = be16_to_cpu(s2->length);
+ p1 = s1->unicode;
+ p2 = s2->unicode;
+
+ for (len = min(len1, len2); len > 0; len--) {
+ c1 = be16_to_cpu(*p1);
+ c2 = be16_to_cpu(*p2);
+ if (c1 != c2)
+ return c1 < c2 ? -1 : 1;
+ p1++;
+ p2++;
+ }
+
+ return len1 < len2 ? -1 :
+ len1 > len2 ? 1 : 0;
+}
+
+
#define Hangul_SBase 0xac00
#define Hangul_LBase 0x1100
#define Hangul_VBase 0x1161
Index: linux-2.6-git/fs/hfsplus/extents.c
===================================================================
--- linux-2.6-git.orig/fs/hfsplus/extents.c 2006-01-16 17:33:52.000000000 +0100
+++ linux-2.6-git/fs/hfsplus/extents.c 2006-01-16 17:34:14.000000000 +0100
@@ -16,7 +16,8 @@
#include "hfsplus_raw.h"
/* Compare two extents keys, returns 0 on same, pos/neg for difference */
-int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1,
+ const hfsplus_btree_key *k2)
{
__be32 k1id, k2id;
__be32 k1s, k2s;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-01-16 16:41 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-16 16:40 [PATCH 3/6] hfs: add HFSX support Roman Zippel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).