Skip to content

Commit

Permalink
hfsplus: create correct initial catalog entries for device files
Browse files Browse the repository at this point in the history
Make sure the initial insertation of the catalog entry already contains
the device number by calling init_special_inode early and setting writing
out the dev field of the on-disk permission structure.  The latter is
facilitated by sharing the almost identical hfsplus_set_perms helpers
between initial catalog entry creating and ->write_inode.

Unless we crashed just after mknod this bug was harmless as the inode
is marked dirty at the end of hfsplus_mknod, and hfsplus_write_inode
will update the catalog entry to contain the correct value.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
  • Loading branch information
Christoph Hellwig authored and Christoph Hellwig committed Oct 14, 2010
1 parent 722c55d commit 90e6169
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 32 deletions.
16 changes: 12 additions & 4 deletions fs/hfsplus/catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent,
key->key_len = cpu_to_be16(6 + ustrlen);
}

static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms)
{
if (inode->i_flags & S_IMMUTABLE)
perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
Expand All @@ -77,10 +77,18 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
perms->rootflags |= HFSPLUS_FLG_APPEND;
else
perms->rootflags &= ~HFSPLUS_FLG_APPEND;
HFSPLUS_I(inode)->userflags = perms->userflags;

perms->userflags = HFSPLUS_I(inode)->userflags;
perms->mode = cpu_to_be16(inode->i_mode);
perms->owner = cpu_to_be32(inode->i_uid);
perms->group = cpu_to_be32(inode->i_gid);

if (S_ISREG(inode->i_mode))
perms->dev = cpu_to_be32(inode->i_nlink);
else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode))
perms->dev = cpu_to_be32(inode->i_rdev);
else
perms->dev = 0;
}

static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
Expand All @@ -99,7 +107,7 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
folder->content_mod_date =
folder->attribute_mod_date =
folder->access_date = hfsp_now2mt();
hfsplus_set_perms(inode, &folder->permissions);
hfsplus_cat_set_perms(inode, &folder->permissions);
if (inode == sbi->hidden_dir)
/* invisible and namelocked */
folder->user_info.frFlags = cpu_to_be16(0x5000);
Expand All @@ -118,7 +126,7 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
file->attribute_mod_date =
file->access_date = hfsp_now2mt();
if (cnid == inode->i_ino) {
hfsplus_set_perms(inode, &file->permissions);
hfsplus_cat_set_perms(inode, &file->permissions);
if (S_ISLNK(inode->i_mode)) {
file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
Expand Down
6 changes: 3 additions & 3 deletions fs/hfsplus/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,9 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
if (!inode)
goto out;

if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode))
init_special_inode(inode, mode, rdev);

res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
if (res) {
inode->i_nlink = 0;
Expand All @@ -426,9 +429,6 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
goto out;
}

if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode))
init_special_inode(inode, mode, rdev);

hfsplus_instantiate(dentry, inode, inode->i_ino);
mark_inode_dirty(inode);
out:
Expand Down
1 change: 1 addition & 0 deletions fs/hfsplus/hfsplus_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
struct inode *, struct qstr *);
void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms);

/* dir.c */
extern const struct inode_operations hfsplus_dir_inode_operations;
Expand Down
27 changes: 2 additions & 25 deletions fs/hfsplus/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,29 +252,6 @@ static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, i
inode->i_flags &= ~S_APPEND;
}

static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
{
if (inode->i_flags & S_IMMUTABLE)
perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
else
perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
if (inode->i_flags & S_APPEND)
perms->rootflags |= HFSPLUS_FLG_APPEND;
else
perms->rootflags &= ~HFSPLUS_FLG_APPEND;
perms->userflags = HFSPLUS_I(inode)->userflags;
perms->mode = cpu_to_be16(inode->i_mode);
perms->owner = cpu_to_be32(inode->i_uid);
perms->group = cpu_to_be32(inode->i_gid);

if (S_ISREG(inode->i_mode))
perms->dev = cpu_to_be32(inode->i_nlink);
else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode))
perms->dev = cpu_to_be32(inode->i_rdev);
else
perms->dev = 0;
}

static int hfsplus_file_open(struct inode *inode, struct file *file)
{
if (HFSPLUS_IS_RSRC(inode))
Expand Down Expand Up @@ -578,7 +555,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_folder));
/* simple node checks? */
hfsplus_set_perms(inode, &folder->permissions);
hfsplus_cat_set_perms(inode, &folder->permissions);
folder->access_date = hfsp_ut2mt(inode->i_atime);
folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
Expand All @@ -600,7 +577,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_file));
hfsplus_inode_write_fork(inode, &file->data_fork);
hfsplus_set_perms(inode, &file->permissions);
hfsplus_cat_set_perms(inode, &file->permissions);
if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
else
Expand Down

0 comments on commit 90e6169

Please sign in to comment.