aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2006-01-24 15:34:47 -0500
committerDave Kleikamp <shaggy@austin.ibm.com>2006-01-24 15:34:47 -0500
commit0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch)
tree7b42490a676cf39ae0691b6859ecf7fd410f229b /fs/hfsplus
parent4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff)
parent3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff)
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/hfsplus')
-rw-r--r--fs/hfsplus/bfind.c3
-rw-r--r--fs/hfsplus/bitmap.c8
-rw-r--r--fs/hfsplus/bnode.c11
-rw-r--r--fs/hfsplus/brec.c2
-rw-r--r--fs/hfsplus/btree.c37
-rw-r--r--fs/hfsplus/catalog.c44
-rw-r--r--fs/hfsplus/dir.c47
-rw-r--r--fs/hfsplus/extents.c6
-rw-r--r--fs/hfsplus/hfsplus_fs.h16
-rw-r--r--fs/hfsplus/hfsplus_raw.h25
-rw-r--r--fs/hfsplus/inode.c25
-rw-r--r--fs/hfsplus/ioctl.c1
-rw-r--r--fs/hfsplus/options.c24
-rw-r--r--fs/hfsplus/super.c87
-rw-r--r--fs/hfsplus/unicode.c30
-rw-r--r--fs/hfsplus/wrapper.c17
16 files changed, 228 insertions, 155 deletions
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 257cdde0514b..5007a41f1be9 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
64 else 64 else
65 e = rec - 1; 65 e = rec - 1;
66 } while (b <= e); 66 } while (b <= e);
67 //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
68 if (rec != e && e >= 0) { 67 if (rec != e && e >= 0) {
69 len = hfs_brec_lenoff(bnode, e, &off); 68 len = hfs_brec_lenoff(bnode, e, &off);
70 keylen = hfs_brec_keylen(bnode, e); 69 keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd)
127 return res; 126 return res;
128 127
129invalid: 128invalid:
130 printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", 129 printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
131 height, bnode->height, bnode->type, nidx, parent); 130 height, bnode->height, bnode->type, nidx, parent);
132 res = -EIO; 131 res = -EIO;
133release: 132release:
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index c7d316455fa0..9fb51632303c 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -29,7 +29,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
29 return size; 29 return size;
30 30
31 dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); 31 dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
32 down(&HFSPLUS_SB(sb).alloc_file->i_sem); 32 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
33 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; 33 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
34 page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, 34 page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
35 (filler_t *)mapping->a_ops->readpage, NULL); 35 (filler_t *)mapping->a_ops->readpage, NULL);
@@ -143,7 +143,7 @@ done:
143 sb->s_dirt = 1; 143 sb->s_dirt = 1;
144 dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); 144 dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
145out: 145out:
146 up(&HFSPLUS_SB(sb).alloc_file->i_sem); 146 mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
147 return start; 147 return start;
148} 148}
149 149
@@ -164,7 +164,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
164 if ((offset + count) > HFSPLUS_SB(sb).total_blocks) 164 if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
165 return -2; 165 return -2;
166 166
167 down(&HFSPLUS_SB(sb).alloc_file->i_sem); 167 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
168 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; 168 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
169 pnr = offset / PAGE_CACHE_BITS; 169 pnr = offset / PAGE_CACHE_BITS;
170 page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); 170 page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL);
@@ -215,7 +215,7 @@ out:
215 kunmap(page); 215 kunmap(page);
216 HFSPLUS_SB(sb).free_blocks += len; 216 HFSPLUS_SB(sb).free_blocks += len;
217 sb->s_dirt = 1; 217 sb->s_dirt = 1;
218 up(&HFSPLUS_SB(sb).alloc_file->i_sem); 218 mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
219 219
220 return 0; 220 return 0;
221} 221}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 930cd9212de8..8f07e8fbd03d 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -358,7 +358,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
358 358
359 // move down? 359 // move down?
360 if (!node->prev && !node->next) { 360 if (!node->prev && !node->next) {
361 printk("hfs_btree_del_level\n"); 361 printk(KERN_DEBUG "hfs_btree_del_level\n");
362 } 362 }
363 if (!node->parent) { 363 if (!node->parent) {
364 tree->root = 0; 364 tree->root = 0;
@@ -379,7 +379,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
379 struct hfs_bnode *node; 379 struct hfs_bnode *node;
380 380
381 if (cnid >= tree->node_count) { 381 if (cnid >= tree->node_count) {
382 printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); 382 printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
383 return NULL; 383 return NULL;
384 } 384 }
385 385
@@ -402,7 +402,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
402 loff_t off; 402 loff_t off;
403 403
404 if (cnid >= tree->node_count) { 404 if (cnid >= tree->node_count) {
405 printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); 405 printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
406 return NULL; 406 return NULL;
407 } 407 }
408 408
@@ -576,8 +576,9 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
576 node = hfs_bnode_findhash(tree, num); 576 node = hfs_bnode_findhash(tree, num);
577 spin_unlock(&tree->hash_lock); 577 spin_unlock(&tree->hash_lock);
578 if (node) { 578 if (node) {
579 printk("new node %u already hashed?\n", num); 579 printk(KERN_CRIT "new node %u already hashed?\n", num);
580 BUG(); 580 WARN_ON(1);
581 return node;
581 } 582 }
582 node = __hfs_bnode_create(tree, num); 583 node = __hfs_bnode_create(tree, num);
583 if (!node) 584 if (!node)
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 0ccef2ab790c..c88e5d72a402 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -360,7 +360,7 @@ again:
360 end_off = hfs_bnode_read_u16(parent, end_rec_off); 360 end_off = hfs_bnode_read_u16(parent, end_rec_off);
361 if (end_rec_off - end_off < diff) { 361 if (end_rec_off - end_off < diff) {
362 362
363 printk("splitting index node...\n"); 363 printk(KERN_DEBUG "hfs: splitting index node...\n");
364 fd->bnode = parent; 364 fd->bnode = parent;
365 new_node = hfs_bnode_split(fd); 365 new_node = hfs_bnode_split(fd);
366 if (IS_ERR(new_node)) 366 if (IS_ERR(new_node))
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 44326aa2bd34..a67edfa34e9e 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -31,17 +31,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
31 31
32 init_MUTEX(&tree->tree_lock); 32 init_MUTEX(&tree->tree_lock);
33 spin_lock_init(&tree->hash_lock); 33 spin_lock_init(&tree->hash_lock);
34 /* Set the correct compare function */
35 tree->sb = sb; 34 tree->sb = sb;
36 tree->cnid = id; 35 tree->cnid = id;
37 if (id == HFSPLUS_EXT_CNID) {
38 tree->keycmp = hfsplus_ext_cmp_key;
39 } else if (id == HFSPLUS_CAT_CNID) {
40 tree->keycmp = hfsplus_cat_cmp_key;
41 } else {
42 printk("HFS+-fs: unknown B*Tree requested\n");
43 goto free_tree;
44 }
45 tree->inode = iget(sb, id); 36 tree->inode = iget(sb, id);
46 if (!tree->inode) 37 if (!tree->inode)
47 goto free_tree; 38 goto free_tree;
@@ -64,6 +55,20 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
64 tree->max_key_len = be16_to_cpu(head->max_key_len); 55 tree->max_key_len = be16_to_cpu(head->max_key_len);
65 tree->depth = be16_to_cpu(head->depth); 56 tree->depth = be16_to_cpu(head->depth);
66 57
58 /* Set the correct compare function */
59 if (id == HFSPLUS_EXT_CNID) {
60 tree->keycmp = hfsplus_ext_cmp_key;
61 } else if (id == HFSPLUS_CAT_CNID) {
62 if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
63 (head->key_type == HFSPLUS_KEY_BINARY))
64 tree->keycmp = hfsplus_cat_bin_cmp_key;
65 else
66 tree->keycmp = hfsplus_cat_case_cmp_key;
67 } else {
68 printk(KERN_ERR "hfs: unknown B*Tree requested\n");
69 goto fail_page;
70 }
71
67 size = tree->node_size; 72 size = tree->node_size;
68 if (!size || size & (size - 1)) 73 if (!size || size & (size - 1))
69 goto fail_page; 74 goto fail_page;
@@ -99,7 +104,7 @@ void hfs_btree_close(struct hfs_btree *tree)
99 while ((node = tree->node_hash[i])) { 104 while ((node = tree->node_hash[i])) {
100 tree->node_hash[i] = node->next_hash; 105 tree->node_hash[i] = node->next_hash;
101 if (atomic_read(&node->refcnt)) 106 if (atomic_read(&node->refcnt))
102 printk("HFS+: node %d:%d still has %d user(s)!\n", 107 printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n",
103 node->tree->cnid, node->this, atomic_read(&node->refcnt)); 108 node->tree->cnid, node->this, atomic_read(&node->refcnt));
104 hfs_bnode_free(node); 109 hfs_bnode_free(node);
105 tree->node_hash_cnt--; 110 tree->node_hash_cnt--;
@@ -223,10 +228,6 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
223 tree->free_nodes--; 228 tree->free_nodes--;
224 mark_inode_dirty(tree->inode); 229 mark_inode_dirty(tree->inode);
225 hfs_bnode_put(node); 230 hfs_bnode_put(node);
226 if (!idx) {
227 printk("unexpected idx %u (%u)\n", idx, node->this);
228 BUG();
229 }
230 return hfs_bnode_create(tree, idx); 231 return hfs_bnode_create(tree, idx);
231 } 232 }
232 } 233 }
@@ -242,7 +243,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
242 kunmap(*pagep); 243 kunmap(*pagep);
243 nidx = node->next; 244 nidx = node->next;
244 if (!nidx) { 245 if (!nidx) {
245 printk("create new bmap node...\n"); 246 printk(KERN_DEBUG "hfs: create new bmap node...\n");
246 next_node = hfs_bmap_new_bmap(node, idx); 247 next_node = hfs_bmap_new_bmap(node, idx);
247 } else 248 } else
248 next_node = hfs_bnode_find(tree, nidx); 249 next_node = hfs_bnode_find(tree, nidx);
@@ -284,7 +285,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
284 hfs_bnode_put(node); 285 hfs_bnode_put(node);
285 if (!i) { 286 if (!i) {
286 /* panic */; 287 /* panic */;
287 printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); 288 printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
288 return; 289 return;
289 } 290 }
290 node = hfs_bnode_find(tree, i); 291 node = hfs_bnode_find(tree, i);
@@ -292,7 +293,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
292 return; 293 return;
293 if (node->type != HFS_NODE_MAP) { 294 if (node->type != HFS_NODE_MAP) {
294 /* panic */; 295 /* panic */;
295 printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); 296 printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
296 hfs_bnode_put(node); 297 hfs_bnode_put(node);
297 return; 298 return;
298 } 299 }
@@ -305,7 +306,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
305 m = 1 << (~nidx & 7); 306 m = 1 << (~nidx & 7);
306 byte = data[off]; 307 byte = data[off];
307 if (!(byte & m)) { 308 if (!(byte & m)) {
308 printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); 309 printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
309 kunmap(page); 310 kunmap(page);
310 hfs_bnode_put(node); 311 hfs_bnode_put(node);
311 return; 312 return;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 94712790c8b3..f2d7c49ce759 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -13,7 +13,8 @@
13#include "hfsplus_fs.h" 13#include "hfsplus_fs.h"
14#include "hfsplus_raw.h" 14#include "hfsplus_raw.h"
15 15
16int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) 16int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1,
17 const hfsplus_btree_key *k2)
17{ 18{
18 __be32 k1p, k2p; 19 __be32 k1p, k2p;
19 20
@@ -22,7 +23,20 @@ int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
22 if (k1p != k2p) 23 if (k1p != k2p)
23 return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; 24 return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
24 25
25 return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name); 26 return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name);
27}
28
29int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
30 const hfsplus_btree_key *k2)
31{
32 __be32 k1p, k2p;
33
34 k1p = k1->cat.parent;
35 k2p = k2->cat.parent;
36 if (k1p != k2p)
37 return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
38
39 return hfsplus_strcmp(&k1->cat.name, &k2->cat.name);
26} 40}
27 41
28void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, 42void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
@@ -80,8 +94,11 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
80 memset(folder, 0, sizeof(*folder)); 94 memset(folder, 0, sizeof(*folder));
81 folder->type = cpu_to_be16(HFSPLUS_FOLDER); 95 folder->type = cpu_to_be16(HFSPLUS_FOLDER);
82 folder->id = cpu_to_be32(inode->i_ino); 96 folder->id = cpu_to_be32(inode->i_ino);
83 folder->create_date = folder->content_mod_date = 97 HFSPLUS_I(inode).create_date =
84 folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); 98 folder->create_date =
99 folder->content_mod_date =
100 folder->attribute_mod_date =
101 folder->access_date = hfsp_now2mt();
85 hfsplus_set_perms(inode, &folder->permissions); 102 hfsplus_set_perms(inode, &folder->permissions);
86 if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) 103 if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
87 /* invisible and namelocked */ 104 /* invisible and namelocked */
@@ -95,18 +112,27 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
95 file->type = cpu_to_be16(HFSPLUS_FILE); 112 file->type = cpu_to_be16(HFSPLUS_FILE);
96 file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); 113 file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
97 file->id = cpu_to_be32(cnid); 114 file->id = cpu_to_be32(cnid);
98 file->create_date = file->content_mod_date = 115 HFSPLUS_I(inode).create_date =
99 file->attribute_mod_date = file->access_date = hfsp_now2mt(); 116 file->create_date =
117 file->content_mod_date =
118 file->attribute_mod_date =
119 file->access_date = hfsp_now2mt();
100 if (cnid == inode->i_ino) { 120 if (cnid == inode->i_ino) {
101 hfsplus_set_perms(inode, &file->permissions); 121 hfsplus_set_perms(inode, &file->permissions);
102 file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); 122 if (S_ISLNK(inode->i_mode)) {
103 file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); 123 file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
124 file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
125 } else {
126 file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
127 file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
128 }
104 if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) 129 if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
105 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); 130 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
106 } else { 131 } else {
107 file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); 132 file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
108 file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); 133 file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
109 file->user_info.fdFlags = cpu_to_be16(0x100); 134 file->user_info.fdFlags = cpu_to_be16(0x100);
135 file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
110 file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); 136 file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
111 } 137 }
112 return sizeof(*file); 138 return sizeof(*file);
@@ -139,7 +165,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
139 165
140 type = be16_to_cpu(tmp.type); 166 type = be16_to_cpu(tmp.type);
141 if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) { 167 if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) {
142 printk("HFS+-fs: Found bad thread record in catalog\n"); 168 printk(KERN_ERR "hfs: found bad thread record in catalog\n");
143 return -EIO; 169 return -EIO;
144 } 170 }
145 171
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 50c8f44b6c66..01a6fe3a395c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -66,25 +66,32 @@ again:
66 } 66 }
67 cnid = be32_to_cpu(entry.file.id); 67 cnid = be32_to_cpu(entry.file.id);
68 if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && 68 if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
69 entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) { 69 entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
70 (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
71 entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
72 HFSPLUS_SB(sb).hidden_dir) {
70 struct qstr str; 73 struct qstr str;
71 char name[32]; 74 char name[32];
72 75
73 if (dentry->d_fsdata) { 76 if (dentry->d_fsdata) {
74 err = -ENOENT; 77 /*
75 inode = NULL; 78 * We found a link pointing to another link,
76 goto out; 79 * so ignore it and treat it as regular file.
80 */
81 cnid = (unsigned long)dentry->d_fsdata;
82 linkid = 0;
83 } else {
84 dentry->d_fsdata = (void *)(unsigned long)cnid;
85 linkid = be32_to_cpu(entry.file.permissions.dev);
86 str.len = sprintf(name, "iNode%d", linkid);
87 str.name = name;
88 hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
89 goto again;
77 } 90 }
78 dentry->d_fsdata = (void *)(unsigned long)cnid;
79 linkid = be32_to_cpu(entry.file.permissions.dev);
80 str.len = sprintf(name, "iNode%d", linkid);
81 str.name = name;
82 hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
83 goto again;
84 } else if (!dentry->d_fsdata) 91 } else if (!dentry->d_fsdata)
85 dentry->d_fsdata = (void *)(unsigned long)cnid; 92 dentry->d_fsdata = (void *)(unsigned long)cnid;
86 } else { 93 } else {
87 printk("HFS+-fs: Illegal catalog entry type in lookup\n"); 94 printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n");
88 err = -EIO; 95 err = -EIO;
89 goto fail; 96 goto fail;
90 } 97 }
@@ -132,12 +139,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
132 case 1: 139 case 1:
133 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); 140 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
134 if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { 141 if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
135 printk("HFS+-fs: bad catalog folder thread\n"); 142 printk(KERN_ERR "hfs: bad catalog folder thread\n");
136 err = -EIO; 143 err = -EIO;
137 goto out; 144 goto out;
138 } 145 }
139 if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { 146 if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
140 printk("HFS+-fs: truncated catalog thread\n"); 147 printk(KERN_ERR "hfs: truncated catalog thread\n");
141 err = -EIO; 148 err = -EIO;
142 goto out; 149 goto out;
143 } 150 }
@@ -156,7 +163,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
156 163
157 for (;;) { 164 for (;;) {
158 if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { 165 if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
159 printk("HFS+-fs: walked past end of dir\n"); 166 printk(KERN_ERR "hfs: walked past end of dir\n");
160 err = -EIO; 167 err = -EIO;
161 goto out; 168 goto out;
162 } 169 }
@@ -168,7 +175,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
168 goto out; 175 goto out;
169 if (type == HFSPLUS_FOLDER) { 176 if (type == HFSPLUS_FOLDER) {
170 if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { 177 if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
171 printk("HFS+-fs: small dir entry\n"); 178 printk(KERN_ERR "hfs: small dir entry\n");
172 err = -EIO; 179 err = -EIO;
173 goto out; 180 goto out;
174 } 181 }
@@ -180,7 +187,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
180 break; 187 break;
181 } else if (type == HFSPLUS_FILE) { 188 } else if (type == HFSPLUS_FILE) {
182 if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { 189 if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
183 printk("HFS+-fs: small file entry\n"); 190 printk(KERN_ERR "hfs: small file entry\n");
184 err = -EIO; 191 err = -EIO;
185 goto out; 192 goto out;
186 } 193 }
@@ -188,7 +195,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
188 be32_to_cpu(entry.file.id), DT_REG)) 195 be32_to_cpu(entry.file.id), DT_REG))
189 break; 196 break;
190 } else { 197 } else {
191 printk("HFS+-fs: bad catalog entry type\n"); 198 printk(KERN_ERR "hfs: bad catalog entry type\n");
192 err = -EIO; 199 err = -EIO;
193 goto out; 200 goto out;
194 } 201 }
@@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
330 if (res) 337 if (res)
331 return res; 338 return res;
332 339
333 inode->i_nlink--; 340 if (inode->i_nlink > 0)
341 inode->i_nlink--;
334 hfsplus_delete_inode(inode); 342 hfsplus_delete_inode(inode);
335 if (inode->i_ino != cnid && !inode->i_nlink) { 343 if (inode->i_ino != cnid && !inode->i_nlink) {
336 if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { 344 if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
@@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
339 hfsplus_delete_inode(inode); 347 hfsplus_delete_inode(inode);
340 } else 348 } else
341 inode->i_flags |= S_DEAD; 349 inode->i_flags |= S_DEAD;
342 } 350 } else
351 inode->i_nlink = 0;
343 inode->i_ctime = CURRENT_TIME_SEC; 352 inode->i_ctime = CURRENT_TIME_SEC;
344 mark_inode_dirty(inode); 353 mark_inode_dirty(inode);
345 354
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index e3ff56a03011..1a7480089e82 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -16,7 +16,8 @@
16#include "hfsplus_raw.h" 16#include "hfsplus_raw.h"
17 17
18/* Compare two extents keys, returns 0 on same, pos/neg for difference */ 18/* Compare two extents keys, returns 0 on same, pos/neg for difference */
19int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) 19int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1,
20 const hfsplus_btree_key *k2)
20{ 21{
21 __be32 k1id, k2id; 22 __be32 k1id, k2id;
22 __be32 k1s, k2s; 23 __be32 k1s, k2s;
@@ -349,10 +350,9 @@ int hfsplus_file_extend(struct inode *inode)
349 350
350 if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { 351 if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
351 // extend alloc file 352 // extend alloc file
352 printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, 353 printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
353 HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); 354 HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
354 return -ENOSPC; 355 return -ENOSPC;
355 //BUG();
356 } 356 }
357 357
358 down(&HFSPLUS_I(inode).extents_lock); 358 down(&HFSPLUS_I(inode).extents_lock);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index c60e5635498d..7ae393637a0c 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -36,7 +36,7 @@
36#define HFSPLUS_TYPE_DATA 0x00 36#define HFSPLUS_TYPE_DATA 0x00
37#define HFSPLUS_TYPE_RSRC 0xFF 37#define HFSPLUS_TYPE_RSRC 0xFF
38 38
39typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *); 39typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *);
40 40
41#define NODE_HASH_SIZE 256 41#define NODE_HASH_SIZE 256
42 42
@@ -143,14 +143,13 @@ struct hfsplus_sb_info {
143 143
144 unsigned long flags; 144 unsigned long flags;
145 145
146 atomic_t inode_cnt;
147 u32 last_inode_cnt;
148
149 struct hlist_head rsrc_inodes; 146 struct hlist_head rsrc_inodes;
150}; 147};
151 148
152#define HFSPLUS_SB_WRITEBACKUP 0x0001 149#define HFSPLUS_SB_WRITEBACKUP 0x0001
153#define HFSPLUS_SB_NODECOMPOSE 0x0002 150#define HFSPLUS_SB_NODECOMPOSE 0x0002
151#define HFSPLUS_SB_FORCE 0x0004
152#define HFSPLUS_SB_HFSX 0x0008
154 153
155 154
156struct hfsplus_inode_info { 155struct hfsplus_inode_info {
@@ -167,6 +166,7 @@ struct hfsplus_inode_info {
167 struct inode *rsrc_inode; 166 struct inode *rsrc_inode;
168 unsigned long flags; 167 unsigned long flags;
169 168
169 __be32 create_date;
170 /* Device number in hfsplus_permissions in catalog */ 170 /* Device number in hfsplus_permissions in catalog */
171 u32 dev; 171 u32 dev;
172 /* BSD system and user file flags */ 172 /* BSD system and user file flags */
@@ -305,7 +305,8 @@ int hfs_brec_read(struct hfs_find_data *, void *, int);
305int hfs_brec_goto(struct hfs_find_data *, int); 305int hfs_brec_goto(struct hfs_find_data *, int);
306 306
307/* catalog.c */ 307/* catalog.c */
308int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); 308int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
309int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
309void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); 310void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
310int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); 311int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
311int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); 312int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
@@ -314,7 +315,7 @@ int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
314 struct inode *, struct qstr *); 315 struct inode *, struct qstr *);
315 316
316/* extents.c */ 317/* extents.c */
317int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); 318int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
318void hfsplus_ext_write_extent(struct inode *); 319void hfsplus_ext_write_extent(struct inode *);
319int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); 320int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
320int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); 321int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
@@ -352,7 +353,8 @@ extern u16 hfsplus_decompose_table[];
352extern u16 hfsplus_compose_table[]; 353extern u16 hfsplus_compose_table[];
353 354
354/* unicode.c */ 355/* unicode.c */
355int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); 356int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
357int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
356int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); 358int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
357int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); 359int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
358 360
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 5bad37cfdb29..49205531a500 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -22,8 +22,10 @@
22#define HFSPLUS_SECTOR_SHIFT 9 22#define HFSPLUS_SECTOR_SHIFT 9
23#define HFSPLUS_VOLHEAD_SECTOR 2 23#define HFSPLUS_VOLHEAD_SECTOR 2
24#define HFSPLUS_VOLHEAD_SIG 0x482b 24#define HFSPLUS_VOLHEAD_SIG 0x482b
25#define HFSPLUS_VOLHEAD_SIGX 0x4858
25#define HFSPLUS_SUPER_MAGIC 0x482b 26#define HFSPLUS_SUPER_MAGIC 0x482b
26#define HFSPLUS_CURRENT_VERSION 4 27#define HFSPLUS_MIN_VERSION 4
28#define HFSPLUS_CURRENT_VERSION 5
27 29
28#define HFSP_WRAP_MAGIC 0x4244 30#define HFSP_WRAP_MAGIC 0x4244
29#define HFSP_WRAP_ATTRIB_SLOCK 0x8000 31#define HFSP_WRAP_ATTRIB_SLOCK 0x8000
@@ -41,6 +43,9 @@
41#define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */ 43#define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */
42#define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */ 44#define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */
43 45
46#define HFSP_SYMLINK_TYPE 0x736c6e6b /* 'slnk' */
47#define HFSP_SYMLINK_CREATOR 0x72686170 /* 'rhap' */
48
44#define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */ 49#define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */
45 50
46/* Structures used on disk */ 51/* Structures used on disk */
@@ -123,11 +128,13 @@ struct hfsplus_vh {
123} __packed; 128} __packed;
124 129
125/* HFS+ volume attributes */ 130/* HFS+ volume attributes */
126#define HFSPLUS_VOL_UNMNT (1 << 8) 131#define HFSPLUS_VOL_UNMNT (1 << 8)
127#define HFSPLUS_VOL_SPARE_BLK (1 << 9) 132#define HFSPLUS_VOL_SPARE_BLK (1 << 9)
128#define HFSPLUS_VOL_NOCACHE (1 << 10) 133#define HFSPLUS_VOL_NOCACHE (1 << 10)
129#define HFSPLUS_VOL_INCNSTNT (1 << 11) 134#define HFSPLUS_VOL_INCNSTNT (1 << 11)
130#define HFSPLUS_VOL_SOFTLOCK (1 << 15) 135#define HFSPLUS_VOL_NODEID_REUSED (1 << 12)
136#define HFSPLUS_VOL_JOURNALED (1 << 13)
137#define HFSPLUS_VOL_SOFTLOCK (1 << 15)
131 138
132/* HFS+ BTree node descriptor */ 139/* HFS+ BTree node descriptor */
133struct hfs_bnode_desc { 140struct hfs_bnode_desc {
@@ -159,7 +166,7 @@ struct hfs_btree_header_rec {
159 u16 reserved1; 166 u16 reserved1;
160 __be32 clump_size; 167 __be32 clump_size;
161 u8 btree_type; 168 u8 btree_type;
162 u8 reserved2; 169 u8 key_type;
163 __be32 attributes; 170 __be32 attributes;
164 u32 reserved3[16]; 171 u32 reserved3[16];
165} __packed; 172} __packed;
@@ -184,6 +191,10 @@ struct hfs_btree_header_rec {
184#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */ 191#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */
185#define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */ 192#define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */
186 193
194/* btree key type */
195#define HFSPLUS_KEY_CASEFOLDING 0xCF /* case-insensitive */
196#define HFSPLUS_KEY_BINARY 0xBC /* case-sensitive */
197
187/* HFS+ catalog entry key */ 198/* HFS+ catalog entry key */
188struct hfsplus_cat_key { 199struct hfsplus_cat_key {
189 __be16 key_len; 200 __be16 key_len;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index fc98583cf045..12ed2b7d046b 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -18,13 +18,11 @@
18 18
19static int hfsplus_readpage(struct file *file, struct page *page) 19static int hfsplus_readpage(struct file *file, struct page *page)
20{ 20{
21 //printk("readpage: %lu\n", page->index);
22 return block_read_full_page(page, hfsplus_get_block); 21 return block_read_full_page(page, hfsplus_get_block);
23} 22}
24 23
25static int hfsplus_writepage(struct page *page, struct writeback_control *wbc) 24static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
26{ 25{
27 //printk("writepage: %lu\n", page->index);
28 return block_write_full_page(page, hfsplus_get_block, wbc); 26 return block_write_full_page(page, hfsplus_get_block, wbc);
29} 27}
30 28
@@ -92,7 +90,6 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
92 } while (--i && nidx < tree->node_count); 90 } while (--i && nidx < tree->node_count);
93 spin_unlock(&tree->hash_lock); 91 spin_unlock(&tree->hash_lock);
94 } 92 }
95 //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
96 return res ? try_to_free_buffers(page) : 0; 93 return res ? try_to_free_buffers(page) : 0;
97} 94}
98 95
@@ -182,11 +179,6 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
182 igrab(dir); 179 igrab(dir);
183 hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); 180 hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes);
184 mark_inode_dirty(inode); 181 mark_inode_dirty(inode);
185 {
186 void hfsplus_inode_check(struct super_block *sb);
187 atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
188 hfsplus_inode_check(sb);
189 }
190out: 182out:
191 d_add(dentry, inode); 183 d_add(dentry, inode);
192 return NULL; 184 return NULL;
@@ -276,13 +268,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
276 if (atomic_read(&file->f_count) != 0) 268 if (atomic_read(&file->f_count) != 0)
277 return 0; 269 return 0;
278 if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { 270 if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
279 down(&inode->i_sem); 271 mutex_lock(&inode->i_mutex);
280 hfsplus_file_truncate(inode); 272 hfsplus_file_truncate(inode);
281 if (inode->i_flags & S_DEAD) { 273 if (inode->i_flags & S_DEAD) {
282 hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); 274 hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
283 hfsplus_delete_inode(inode); 275 hfsplus_delete_inode(inode);
284 } 276 }
285 up(&inode->i_sem); 277 mutex_unlock(&inode->i_mutex);
286 } 278 }
287 return 0; 279 return 0;
288} 280}
@@ -317,11 +309,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
317 if (!inode) 309 if (!inode)
318 return NULL; 310 return NULL;
319 311
320 {
321 void hfsplus_inode_check(struct super_block *sb);
322 atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
323 hfsplus_inode_check(sb);
324 }
325 inode->i_ino = HFSPLUS_SB(sb).next_cnid++; 312 inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
326 inode->i_mode = mode; 313 inode->i_mode = mode;
327 inode->i_uid = current->fsuid; 314 inode->i_uid = current->fsuid;
@@ -444,7 +431,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
444 inode->i_size = 2 + be32_to_cpu(folder->valence); 431 inode->i_size = 2 + be32_to_cpu(folder->valence);
445 inode->i_atime = hfsp_mt2ut(folder->access_date); 432 inode->i_atime = hfsp_mt2ut(folder->access_date);
446 inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); 433 inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
447 inode->i_ctime = inode->i_mtime; 434 inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
435 HFSPLUS_I(inode).create_date = folder->create_date;
448 HFSPLUS_I(inode).fs_blocks = 0; 436 HFSPLUS_I(inode).fs_blocks = 0;
449 inode->i_op = &hfsplus_dir_inode_operations; 437 inode->i_op = &hfsplus_dir_inode_operations;
450 inode->i_fop = &hfsplus_dir_operations; 438 inode->i_fop = &hfsplus_dir_operations;
@@ -475,9 +463,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
475 } 463 }
476 inode->i_atime = hfsp_mt2ut(file->access_date); 464 inode->i_atime = hfsp_mt2ut(file->access_date);
477 inode->i_mtime = hfsp_mt2ut(file->content_mod_date); 465 inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
478 inode->i_ctime = inode->i_mtime; 466 inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
467 HFSPLUS_I(inode).create_date = file->create_date;
479 } else { 468 } else {
480 printk("HFS+-fs: bad catalog entry used to create inode\n"); 469 printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
481 res = -EIO; 470 res = -EIO;
482 } 471 }
483 return res; 472 return res;
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index e07aa096e07c..13cf848ac833 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -12,6 +12,7 @@
12 * hfsplus ioctls 12 * hfsplus ioctls
13 */ 13 */
14 14
15#include <linux/capability.h>
15#include <linux/fs.h> 16#include <linux/fs.h>
16#include <linux/sched.h> 17#include <linux/sched.h>
17#include <linux/xattr.h> 18#include <linux/xattr.h>
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index cca0818aa4ca..dc64fac00831 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -22,7 +22,7 @@ enum {
22 opt_umask, opt_uid, opt_gid, 22 opt_umask, opt_uid, opt_gid,
23 opt_part, opt_session, opt_nls, 23 opt_part, opt_session, opt_nls,
24 opt_nodecompose, opt_decompose, 24 opt_nodecompose, opt_decompose,
25 opt_err 25 opt_force, opt_err
26}; 26};
27 27
28static match_table_t tokens = { 28static match_table_t tokens = {
@@ -36,6 +36,7 @@ static match_table_t tokens = {
36 { opt_nls, "nls=%s" }, 36 { opt_nls, "nls=%s" },
37 { opt_decompose, "decompose" }, 37 { opt_decompose, "decompose" },
38 { opt_nodecompose, "nodecompose" }, 38 { opt_nodecompose, "nodecompose" },
39 { opt_force, "force" },
39 { opt_err, NULL } 40 { opt_err, NULL }
40}; 41};
41 42
@@ -82,58 +83,58 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
82 switch (token) { 83 switch (token) {
83 case opt_creator: 84 case opt_creator:
84 if (match_fourchar(&args[0], &sbi->creator)) { 85 if (match_fourchar(&args[0], &sbi->creator)) {
85 printk("HFS+-fs: creator requires a 4 character value\n"); 86 printk(KERN_ERR "hfs: creator requires a 4 character value\n");
86 return 0; 87 return 0;
87 } 88 }
88 break; 89 break;
89 case opt_type: 90 case opt_type:
90 if (match_fourchar(&args[0], &sbi->type)) { 91 if (match_fourchar(&args[0], &sbi->type)) {
91 printk("HFS+-fs: type requires a 4 character value\n"); 92 printk(KERN_ERR "hfs: type requires a 4 character value\n");
92 return 0; 93 return 0;
93 } 94 }
94 break; 95 break;
95 case opt_umask: 96 case opt_umask:
96 if (match_octal(&args[0], &tmp)) { 97 if (match_octal(&args[0], &tmp)) {
97 printk("HFS+-fs: umask requires a value\n"); 98 printk(KERN_ERR "hfs: umask requires a value\n");
98 return 0; 99 return 0;
99 } 100 }
100 sbi->umask = (umode_t)tmp; 101 sbi->umask = (umode_t)tmp;
101 break; 102 break;
102 case opt_uid: 103 case opt_uid:
103 if (match_int(&args[0], &tmp)) { 104 if (match_int(&args[0], &tmp)) {
104 printk("HFS+-fs: uid requires an argument\n"); 105 printk(KERN_ERR "hfs: uid requires an argument\n");
105 return 0; 106 return 0;
106 } 107 }
107 sbi->uid = (uid_t)tmp; 108 sbi->uid = (uid_t)tmp;
108 break; 109 break;
109 case opt_gid: 110 case opt_gid:
110 if (match_int(&args[0], &tmp)) { 111 if (match_int(&args[0], &tmp)) {
111 printk("HFS+-fs: gid requires an argument\n"); 112 printk(KERN_ERR "hfs: gid requires an argument\n");
112 return 0; 113 return 0;
113 } 114 }
114 sbi->gid = (gid_t)tmp; 115 sbi->gid = (gid_t)tmp;
115 break; 116 break;
116 case opt_part: 117 case opt_part:
117 if (match_int(&args[0], &sbi->part)) { 118 if (match_int(&args[0], &sbi->part)) {
118 printk("HFS+-fs: part requires an argument\n"); 119 printk(KERN_ERR "hfs: part requires an argument\n");
119 return 0; 120 return 0;
120 } 121 }
121 break; 122 break;
122 case opt_session: 123 case opt_session:
123 if (match_int(&args[0], &sbi->session)) { 124 if (match_int(&args[0], &sbi->session)) {
124 printk("HFS+-fs: session requires an argument\n"); 125 printk(KERN_ERR "hfs: session requires an argument\n");
125 return 0; 126 return 0;
126 } 127 }
127 break; 128 break;
128 case opt_nls: 129 case opt_nls:
129 if (sbi->nls) { 130 if (sbi->nls) {
130 printk("HFS+-fs: unable to change nls mapping\n"); 131 printk(KERN_ERR "hfs: unable to change nls mapping\n");
131 return 0; 132 return 0;
132 } 133 }
133 p = match_strdup(&args[0]); 134 p = match_strdup(&args[0]);
134 sbi->nls = load_nls(p); 135 sbi->nls = load_nls(p);
135 if (!sbi->nls) { 136 if (!sbi->nls) {
136 printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p); 137 printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
137 kfree(p); 138 kfree(p);
138 return 0; 139 return 0;
139 } 140 }
@@ -145,6 +146,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
145 case opt_nodecompose: 146 case opt_nodecompose:
146 sbi->flags |= HFSPLUS_SB_NODECOMPOSE; 147 sbi->flags |= HFSPLUS_SB_NODECOMPOSE;
147 break; 148 break;
149 case opt_force:
150 sbi->flags |= HFSPLUS_SB_FORCE;
151 break;
148 default: 152 default:
149 return 0; 153 return 0;
150 } 154 }
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 0ce1c455ae55..7843f792a4b7 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -22,29 +22,12 @@ static void hfsplus_destroy_inode(struct inode *inode);
22 22
23#include "hfsplus_fs.h" 23#include "hfsplus_fs.h"
24 24
25void hfsplus_inode_check(struct super_block *sb)
26{
27#if 0
28 u32 cnt = atomic_read(&HFSPLUS_SB(sb).inode_cnt);
29 u32 last_cnt = HFSPLUS_SB(sb).last_inode_cnt;
30
31 if (cnt <= (last_cnt / 2) ||
32 cnt >= (last_cnt * 2)) {
33 HFSPLUS_SB(sb).last_inode_cnt = cnt;
34 printk("inode_check: %u,%u,%u\n", cnt, last_cnt,
35 HFSPLUS_SB(sb).cat_tree ? HFSPLUS_SB(sb).cat_tree->node_hash_cnt : 0);
36 }
37#endif
38}
39
40static void hfsplus_read_inode(struct inode *inode) 25static void hfsplus_read_inode(struct inode *inode)
41{ 26{
42 struct hfs_find_data fd; 27 struct hfs_find_data fd;
43 struct hfsplus_vh *vhdr; 28 struct hfsplus_vh *vhdr;
44 int err; 29 int err;
45 30
46 atomic_inc(&HFSPLUS_SB(inode->i_sb).inode_cnt);
47 hfsplus_inode_check(inode->i_sb);
48 INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); 31 INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
49 init_MUTEX(&HFSPLUS_I(inode).extents_lock); 32 init_MUTEX(&HFSPLUS_I(inode).extents_lock);
50 HFSPLUS_I(inode).flags = 0; 33 HFSPLUS_I(inode).flags = 0;
@@ -155,12 +138,10 @@ static int hfsplus_write_inode(struct inode *inode, int unused)
155static void hfsplus_clear_inode(struct inode *inode) 138static void hfsplus_clear_inode(struct inode *inode)
156{ 139{
157 dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino); 140 dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino);
158 atomic_dec(&HFSPLUS_SB(inode->i_sb).inode_cnt);
159 if (HFSPLUS_IS_RSRC(inode)) { 141 if (HFSPLUS_IS_RSRC(inode)) {
160 HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; 142 HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL;
161 iput(HFSPLUS_I(inode).rsrc_inode); 143 iput(HFSPLUS_I(inode).rsrc_inode);
162 } 144 }
163 hfsplus_inode_check(inode->i_sb);
164} 145}
165 146
166static void hfsplus_write_super(struct super_block *sb) 147static void hfsplus_write_super(struct super_block *sb)
@@ -188,7 +169,7 @@ static void hfsplus_write_super(struct super_block *sb)
188 block = HFSPLUS_SB(sb).blockoffset; 169 block = HFSPLUS_SB(sb).blockoffset;
189 block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); 170 block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
190 offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); 171 offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
191 printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, 172 printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
192 HFSPLUS_SB(sb).sect_count, block, offset); 173 HFSPLUS_SB(sb).sect_count, block, offset);
193 bh = sb_bread(sb, block); 174 bh = sb_bread(sb, block);
194 if (bh) { 175 if (bh) {
@@ -198,7 +179,7 @@ static void hfsplus_write_super(struct super_block *sb)
198 mark_buffer_dirty(bh); 179 mark_buffer_dirty(bh);
199 brelse(bh); 180 brelse(bh);
200 } else 181 } else
201 printk("backup not found!\n"); 182 printk(KERN_WARNING "hfs: backup not found!\n");
202 } 183 }
203 } 184 }
204 HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; 185 HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
@@ -251,14 +232,26 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
251 return 0; 232 return 0;
252 if (!(*flags & MS_RDONLY)) { 233 if (!(*flags & MS_RDONLY)) {
253 struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; 234 struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
235 struct hfsplus_sb_info sbi;
236
237 memset(&sbi, 0, sizeof(struct hfsplus_sb_info));
238 sbi.nls = HFSPLUS_SB(sb).nls;
239 if (!hfsplus_parse_options(data, &sbi))
240 return -EINVAL;
254 241
255 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 242 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
256 printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " 243 printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
257 "running fsck.hfsplus is recommended. leaving read-only.\n"); 244 "running fsck.hfsplus is recommended. leaving read-only.\n");
258 sb->s_flags |= MS_RDONLY; 245 sb->s_flags |= MS_RDONLY;
259 *flags |= MS_RDONLY; 246 *flags |= MS_RDONLY;
247 } else if (sbi.flags & HFSPLUS_SB_FORCE) {
248 /* nothing */
260 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 249 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
261 printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); 250 printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
251 sb->s_flags |= MS_RDONLY;
252 *flags |= MS_RDONLY;
253 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
254 printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n");
262 sb->s_flags |= MS_RDONLY; 255 sb->s_flags |= MS_RDONLY;
263 *flags |= MS_RDONLY; 256 *flags |= MS_RDONLY;
264 } 257 }
@@ -299,8 +292,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
299 INIT_HLIST_HEAD(&sbi->rsrc_inodes); 292 INIT_HLIST_HEAD(&sbi->rsrc_inodes);
300 hfsplus_fill_defaults(sbi); 293 hfsplus_fill_defaults(sbi);
301 if (!hfsplus_parse_options(data, sbi)) { 294 if (!hfsplus_parse_options(data, sbi)) {
302 if (!silent) 295 printk(KERN_ERR "hfs: unable to parse mount options\n");
303 printk("HFS+-fs: unable to parse mount options\n");
304 err = -EINVAL; 296 err = -EINVAL;
305 goto cleanup; 297 goto cleanup;
306 } 298 }
@@ -308,8 +300,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
308 /* temporarily use utf8 to correctly find the hidden dir below */ 300 /* temporarily use utf8 to correctly find the hidden dir below */
309 nls = sbi->nls; 301 nls = sbi->nls;
310 sbi->nls = load_nls("utf8"); 302 sbi->nls = load_nls("utf8");
311 if (!nls) { 303 if (!sbi->nls) {
312 printk("HFS+: unable to load nls for utf8\n"); 304 printk(KERN_ERR "hfs: unable to load nls for utf8\n");
313 err = -EINVAL; 305 err = -EINVAL;
314 goto cleanup; 306 goto cleanup;
315 } 307 }
@@ -317,17 +309,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
317 /* Grab the volume header */ 309 /* Grab the volume header */
318 if (hfsplus_read_wrapper(sb)) { 310 if (hfsplus_read_wrapper(sb)) {
319 if (!silent) 311 if (!silent)
320 printk("HFS+-fs: unable to find HFS+ superblock\n"); 312 printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n");
321 err = -EINVAL; 313 err = -EINVAL;
322 goto cleanup; 314 goto cleanup;
323 } 315 }
324 vhdr = HFSPLUS_SB(sb).s_vhdr; 316 vhdr = HFSPLUS_SB(sb).s_vhdr;
325 317
326 /* Copy parts of the volume header into the superblock */ 318 /* Copy parts of the volume header into the superblock */
327 sb->s_magic = be16_to_cpu(vhdr->signature); 319 sb->s_magic = HFSPLUS_VOLHEAD_SIG;
328 if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) { 320 if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION ||
329 if (!silent) 321 be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) {
330 printk("HFS+-fs: wrong filesystem version\n"); 322 printk(KERN_ERR "hfs: wrong filesystem version\n");
331 goto cleanup; 323 goto cleanup;
332 } 324 }
333 HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); 325 HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
@@ -348,34 +340,36 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
348 sb->s_maxbytes = MAX_LFS_FILESIZE; 340 sb->s_maxbytes = MAX_LFS_FILESIZE;
349 341
350 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 342 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
351 if (!silent) 343 printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
352 printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " 344 "running fsck.hfsplus is recommended. mounting read-only.\n");
353 "running fsck.hfsplus is recommended. mounting read-only.\n");
354 sb->s_flags |= MS_RDONLY; 345 sb->s_flags |= MS_RDONLY;
346 } else if (sbi->flags & HFSPLUS_SB_FORCE) {
347 /* nothing */
355 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 348 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
356 if (!silent) 349 printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
357 printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); 350 sb->s_flags |= MS_RDONLY;
351 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
352 printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, "
353 "use the force option at your own risk, mounting read-only.\n");
358 sb->s_flags |= MS_RDONLY; 354 sb->s_flags |= MS_RDONLY;
359 } 355 }
356 sbi->flags &= ~HFSPLUS_SB_FORCE;
360 357
361 /* Load metadata objects (B*Trees) */ 358 /* Load metadata objects (B*Trees) */
362 HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); 359 HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
363 if (!HFSPLUS_SB(sb).ext_tree) { 360 if (!HFSPLUS_SB(sb).ext_tree) {
364 if (!silent) 361 printk(KERN_ERR "hfs: failed to load extents file\n");
365 printk("HFS+-fs: failed to load extents file\n");
366 goto cleanup; 362 goto cleanup;
367 } 363 }
368 HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); 364 HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
369 if (!HFSPLUS_SB(sb).cat_tree) { 365 if (!HFSPLUS_SB(sb).cat_tree) {
370 if (!silent) 366 printk(KERN_ERR "hfs: failed to load catalog file\n");
371 printk("HFS+-fs: failed to load catalog file\n");
372 goto cleanup; 367 goto cleanup;
373 } 368 }
374 369
375 HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID); 370 HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID);
376 if (!HFSPLUS_SB(sb).alloc_file) { 371 if (!HFSPLUS_SB(sb).alloc_file) {
377 if (!silent) 372 printk(KERN_ERR "hfs: failed to load allocation file\n");
378 printk("HFS+-fs: failed to load allocation file\n");
379 goto cleanup; 373 goto cleanup;
380 } 374 }
381 375
@@ -383,8 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
383 root = iget(sb, HFSPLUS_ROOT_CNID); 377 root = iget(sb, HFSPLUS_ROOT_CNID);
384 sb->s_root = d_alloc_root(root); 378 sb->s_root = d_alloc_root(root);
385 if (!sb->s_root) { 379 if (!sb->s_root) {
386 if (!silent) 380 printk(KERN_ERR "hfs: failed to load root directory\n");
387 printk("HFS+-fs: failed to load root directory\n");
388 iput(root); 381 iput(root);
389 goto cleanup; 382 goto cleanup;
390 } 383 }
@@ -418,7 +411,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
418 sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); 411 sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
419 412
420 if (!HFSPLUS_SB(sb).hidden_dir) { 413 if (!HFSPLUS_SB(sb).hidden_dir) {
421 printk("HFS+: create hidden dir...\n"); 414 printk(KERN_DEBUG "hfs: create hidden dir...\n");
422 HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); 415 HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
423 hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, 416 hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
424 &str, HFSPLUS_SB(sb).hidden_dir); 417 &str, HFSPLUS_SB(sb).hidden_dir);
@@ -498,7 +491,7 @@ static void __exit exit_hfsplus_fs(void)
498{ 491{
499 unregister_filesystem(&hfsplus_fs_type); 492 unregister_filesystem(&hfsplus_fs_type);
500 if (kmem_cache_destroy(hfsplus_inode_cachep)) 493 if (kmem_cache_destroy(hfsplus_inode_cachep))
501 printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n"); 494 printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n");
502} 495}
503 496
504module_init(init_hfsplus_fs) 497module_init(init_hfsplus_fs)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 060c69048c3d..689c8bd721fb 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -28,7 +28,8 @@ static inline u16 case_fold(u16 c)
28} 28}
29 29
30/* Compare unicode strings, return values like normal strcmp */ 30/* Compare unicode strings, return values like normal strcmp */
31int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2) 31int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
32 const struct hfsplus_unistr *s2)
32{ 33{
33 u16 len1, len2, c1, c2; 34 u16 len1, len2, c1, c2;
34 const hfsplus_unichr *p1, *p2; 35 const hfsplus_unichr *p1, *p2;
@@ -59,6 +60,33 @@ int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unis
59 } 60 }
60} 61}
61 62
63/* Compare names as a sequence of 16-bit unsigned integers */
64int hfsplus_strcmp(const struct hfsplus_unistr *s1,
65 const struct hfsplus_unistr *s2)
66{
67 u16 len1, len2, c1, c2;
68 const hfsplus_unichr *p1, *p2;
69 int len;
70
71 len1 = be16_to_cpu(s1->length);
72 len2 = be16_to_cpu(s2->length);
73 p1 = s1->unicode;
74 p2 = s2->unicode;
75
76 for (len = min(len1, len2); len > 0; len--) {
77 c1 = be16_to_cpu(*p1);
78 c2 = be16_to_cpu(*p2);
79 if (c1 != c2)
80 return c1 < c2 ? -1 : 1;
81 p1++;
82 p2++;
83 }
84
85 return len1 < len2 ? -1 :
86 len1 > len2 ? 1 : 0;
87}
88
89
62#define Hangul_SBase 0xac00 90#define Hangul_SBase 0xac00
63#define Hangul_LBase 0x1100 91#define Hangul_LBase 0x1100
64#define Hangul_VBase 0x1161 92#define Hangul_VBase 0x1161
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 95455e839231..72cab78f0509 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -28,8 +28,11 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
28{ 28{
29 u32 extent; 29 u32 extent;
30 u16 attrib; 30 u16 attrib;
31 __be16 sig;
31 32
32 if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG) 33 sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG);
34 if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) &&
35 sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
33 return 0; 36 return 0;
34 37
35 attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB)); 38 attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
@@ -70,7 +73,7 @@ static int hfsplus_get_last_session(struct super_block *sb,
70 *start = (sector_t)te.cdte_addr.lba << 2; 73 *start = (sector_t)te.cdte_addr.lba << 2;
71 return 0; 74 return 0;
72 } 75 }
73 printk(KERN_ERR "HFS: Invalid session number or type of track\n"); 76 printk(KERN_ERR "hfs: invalid session number or type of track\n");
74 return -EINVAL; 77 return -EINVAL;
75 } 78 }
76 ms_info.addr_format = CDROM_LBA; 79 ms_info.addr_format = CDROM_LBA;
@@ -114,6 +117,10 @@ int hfsplus_read_wrapper(struct super_block *sb)
114 } 117 }
115 if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) 118 if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
116 break; 119 break;
120 if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
121 HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
122 break;
123 }
117 brelse(bh); 124 brelse(bh);
118 125
119 /* check for a partition block 126 /* check for a partition block
@@ -143,7 +150,7 @@ int hfsplus_read_wrapper(struct super_block *sb)
143 blocksize >>= 1; 150 blocksize >>= 1;
144 151
145 if (sb_set_blocksize(sb, blocksize) != blocksize) { 152 if (sb_set_blocksize(sb, blocksize) != blocksize) {
146 printk("HFS+: unable to blocksize to %u!\n", blocksize); 153 printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize);
147 return -EINVAL; 154 return -EINVAL;
148 } 155 }
149 156
@@ -158,7 +165,9 @@ int hfsplus_read_wrapper(struct super_block *sb)
158 return -EIO; 165 return -EIO;
159 166
160 /* should still be the same... */ 167 /* should still be the same... */
161 if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG) 168 if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
169 cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
170 cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
162 goto error; 171 goto error;
163 HFSPLUS_SB(sb).s_vhbh = bh; 172 HFSPLUS_SB(sb).s_vhbh = bh;
164 HFSPLUS_SB(sb).s_vhdr = vhdr; 173 HFSPLUS_SB(sb).s_vhdr = vhdr;