#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/random.h>
-#include <linux/version.h>
#include "hfsplus_fs.h"
#include "hfsplus_raw.h"
sb = dir->i_sb;
dentry->d_fsdata = NULL;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
- hfsplus_cat_build_key(fd.search_key, dir->i_ino, &dentry->d_name);
+ hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
again:
err = hfs_brec_read(&fd, &entry, sizeof(entry));
if (err) {
}
cnid = be32_to_cpu(entry.file.id);
if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
- entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) {
+ entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
+ (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
+ entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
+ HFSPLUS_SB(sb).hidden_dir) {
struct qstr str;
char name[32];
if (dentry->d_fsdata) {
- err = -ENOENT;
- inode = NULL;
- goto out;
+ /*
+ * We found a link pointing to another link,
+ * so ignore it and treat it as regular file.
+ */
+ cnid = (unsigned long)dentry->d_fsdata;
+ linkid = 0;
+ } else {
+ dentry->d_fsdata = (void *)(unsigned long)cnid;
+ linkid = be32_to_cpu(entry.file.permissions.dev);
+ str.len = sprintf(name, "iNode%d", linkid);
+ str.name = name;
+ hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+ goto again;
}
- dentry->d_fsdata = (void *)(unsigned long)cnid;
- linkid = be32_to_cpu(entry.file.permissions.dev);
- str.len = sprintf(name, "iNode%d", linkid);
- str.name = name;
- hfsplus_cat_build_key(fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
- goto again;
} else if (!dentry->d_fsdata)
dentry->d_fsdata = (void *)(unsigned long)cnid;
} else {
- printk("HFS+-fs: Illegal catalog entry type in lookup\n");
+ printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n");
err = -EIO;
goto fail;
}
return 0;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
- hfsplus_cat_build_key(fd.search_key, inode->i_ino, NULL);
+ hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
err = hfs_brec_find(&fd);
if (err)
goto out;
case 1:
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
- printk("HFS+-fs: bad catalog folder thread\n");
+ printk(KERN_ERR "hfs: bad catalog folder thread\n");
err = -EIO;
goto out;
}
if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
- printk("HFS+-fs: truncated catalog thread\n");
+ printk(KERN_ERR "hfs: truncated catalog thread\n");
err = -EIO;
goto out;
}
for (;;) {
if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
- printk("HFS+-fs: walked past end of dir\n");
+ printk(KERN_ERR "hfs: walked past end of dir\n");
err = -EIO;
goto out;
}
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
type = be16_to_cpu(entry.type);
len = HFSPLUS_MAX_STRLEN;
- err = hfsplus_uni2asc(&fd.key->cat.name, strbuf, &len);
+ err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len);
if (err)
goto out;
if (type == HFSPLUS_FOLDER) {
if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
- printk("HFS+-fs: small dir entry\n");
+ printk(KERN_ERR "hfs: small dir entry\n");
err = -EIO;
goto out;
}
break;
} else if (type == HFSPLUS_FILE) {
if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
- printk("HFS+-fs: small file entry\n");
+ printk(KERN_ERR "hfs: small file entry\n");
err = -EIO;
goto out;
}
be32_to_cpu(entry.file.id), DT_REG))
break;
} else {
- printk("HFS+-fs: bad catalog entry type\n");
+ printk(KERN_ERR "hfs: bad catalog entry type\n");
err = -EIO;
goto out;
}
return 0;
}
-int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct inode *inode;
int res;
return 0;
}
-int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry *dst_dentry)
+static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
+ struct dentry *dst_dentry)
{
struct super_block *sb = dst_dir->i_sb;
struct inode *inode = src_dentry->d_inode;
inode->i_nlink++;
hfsplus_instantiate(dst_dentry, inode, cnid);
atomic_inc(&inode->i_count);
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
HFSPLUS_SB(sb).file_count++;
sb->s_dirt = 1;
return 0;
}
-int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
+static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = dentry->d_inode;
if (res)
return res;
- inode->i_nlink--;
+ if (inode->i_nlink > 0)
+ inode->i_nlink--;
hfsplus_delete_inode(inode);
if (inode->i_ino != cnid && !inode->i_nlink) {
if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
hfsplus_delete_inode(inode);
} else
inode->i_flags |= S_DEAD;
- }
- inode->i_ctime = CURRENT_TIME;
+ } else
+ inode->i_nlink = 0;
+ inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
return res;
}
-int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct inode *inode;
int res;
return 0;
}
-int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
+static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode;
int res;
if (res)
return res;
inode->i_nlink = 0;
- inode->i_ctime = CURRENT_TIME;
+ inode->i_ctime = CURRENT_TIME_SEC;
hfsplus_delete_inode(inode);
mark_inode_dirty(inode);
return 0;
}
-int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname)
{
struct super_block *sb;
struct inode *inode;
return res;
}
-int hfsplus_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
+ int mode, dev_t rdev)
{
struct super_block *sb;
struct inode *inode;
return 0;
}
-int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
int res;