2005-04-17 02:20:36 +04:00
/*
* linux / fs / hfsplus / dir . c
*
* Copyright ( C ) 2001
* Brad Boyer ( flar @ allandria . com )
* ( C ) 2003 Ardis Technologies < roman @ ardistech . com >
*
* Handling of directories
*/
# include <linux/errno.h>
# include <linux/fs.h>
# include <linux/slab.h>
# include <linux/random.h>
# include "hfsplus_fs.h"
# include "hfsplus_raw.h"
static inline void hfsplus_instantiate ( struct dentry * dentry ,
struct inode * inode , u32 cnid )
{
dentry - > d_fsdata = ( void * ) ( unsigned long ) cnid ;
d_instantiate ( dentry , inode ) ;
}
/* Find the entry inside dir named dentry->d_name */
static struct dentry * hfsplus_lookup ( struct inode * dir , struct dentry * dentry ,
struct nameidata * nd )
{
struct inode * inode = NULL ;
struct hfs_find_data fd ;
struct super_block * sb ;
hfsplus_cat_entry entry ;
int err ;
u32 cnid , linkid = 0 ;
u16 type ;
sb = dir - > i_sb ;
2007-07-16 10:41:23 +04:00
2005-04-17 02:20:36 +04:00
dentry - > d_fsdata = NULL ;
2011-07-06 02:29:59 +04:00
err = hfs_find_init ( HFSPLUS_SB ( sb ) - > cat_tree , & fd ) ;
if ( err )
return ERR_PTR ( err ) ;
2005-04-17 02:20:36 +04:00
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 ) {
if ( err = = - ENOENT ) {
hfs_find_exit ( & fd ) ;
/* No such entry */
inode = NULL ;
goto out ;
}
goto fail ;
}
type = be16_to_cpu ( entry . type ) ;
if ( type = = HFSPLUS_FOLDER ) {
if ( fd . entrylength < sizeof ( struct hfsplus_cat_folder ) ) {
err = - EIO ;
goto fail ;
}
cnid = be32_to_cpu ( entry . folder . id ) ;
dentry - > d_fsdata = ( void * ) ( unsigned long ) cnid ;
} else if ( type = = HFSPLUS_FILE ) {
if ( fd . entrylength < sizeof ( struct hfsplus_cat_file ) ) {
err = - EIO ;
goto fail ;
}
cnid = be32_to_cpu ( entry . file . id ) ;
2010-12-16 19:08:38 +03:00
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 . 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 ) {
2005-04-17 02:20:36 +04:00
struct qstr str ;
char name [ 32 ] ;
if ( dentry - > d_fsdata ) {
2006-01-19 04:43:10 +03:00
/*
* 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 ;
2010-12-16 19:08:38 +03:00
linkid =
be32_to_cpu ( entry . file . permissions . dev ) ;
2006-01-19 04:43:10 +03:00
str . len = sprintf ( name , " iNode%d " , linkid ) ;
str . name = name ;
2010-10-01 07:42:59 +04:00
hfsplus_cat_build_key ( sb , fd . search_key ,
2010-12-16 19:08:38 +03:00
HFSPLUS_SB ( sb ) - > hidden_dir - > i_ino ,
& str ) ;
2006-01-19 04:43:10 +03:00
goto again ;
2005-04-17 02:20:36 +04:00
}
} else if ( ! dentry - > d_fsdata )
dentry - > d_fsdata = ( void * ) ( unsigned long ) cnid ;
} else {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: invalid catalog entry type in lookup \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto fail ;
}
hfs_find_exit ( & fd ) ;
2008-02-07 11:15:40 +03:00
inode = hfsplus_iget ( dir - > i_sb , cnid ) ;
if ( IS_ERR ( inode ) )
return ERR_CAST ( inode ) ;
2005-04-17 02:20:36 +04:00
if ( S_ISREG ( inode - > i_mode ) )
2010-10-14 17:54:28 +04:00
HFSPLUS_I ( inode ) - > linkid = linkid ;
2005-04-17 02:20:36 +04:00
out :
d_add ( dentry , inode ) ;
return NULL ;
fail :
hfs_find_exit ( & fd ) ;
return ERR_PTR ( err ) ;
}
static int hfsplus_readdir ( struct file * filp , void * dirent , filldir_t filldir )
{
2006-12-08 13:37:04 +03:00
struct inode * inode = filp - > f_path . dentry - > d_inode ;
2005-04-17 02:20:36 +04:00
struct super_block * sb = inode - > i_sb ;
int len , err ;
char strbuf [ HFSPLUS_MAX_STRLEN + 1 ] ;
hfsplus_cat_entry entry ;
struct hfs_find_data fd ;
struct hfsplus_readdir_data * rd ;
u16 type ;
if ( filp - > f_pos > = inode - > i_size )
return 0 ;
2011-07-06 02:29:59 +04:00
err = hfs_find_init ( HFSPLUS_SB ( sb ) - > cat_tree , & fd ) ;
if ( err )
return err ;
2005-04-17 02:20:36 +04:00
hfsplus_cat_build_key ( sb , fd . search_key , inode - > i_ino , NULL ) ;
err = hfs_brec_find ( & fd ) ;
if ( err )
goto out ;
switch ( ( u32 ) filp - > f_pos ) {
case 0 :
/* This is completely artificial... */
if ( filldir ( dirent , " . " , 1 , 0 , inode - > i_ino , DT_DIR ) )
goto out ;
filp - > f_pos + + ;
/* fall through */
case 1 :
2010-12-16 19:08:38 +03:00
hfs_bnode_read ( fd . bnode , & entry , fd . entryoffset ,
fd . entrylength ) ;
2005-04-17 02:20:36 +04:00
if ( be16_to_cpu ( entry . type ) ! = HFSPLUS_FOLDER_THREAD ) {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: bad catalog folder thread \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto out ;
}
if ( fd . entrylength < HFSPLUS_MIN_THREAD_SZ ) {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: truncated catalog thread \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto out ;
}
if ( filldir ( dirent , " .. " , 2 , 1 ,
be32_to_cpu ( entry . thread . parentID ) , DT_DIR ) )
goto out ;
filp - > f_pos + + ;
/* fall through */
default :
if ( filp - > f_pos > = inode - > i_size )
goto out ;
err = hfs_brec_goto ( & fd , filp - > f_pos - 1 ) ;
if ( err )
goto out ;
}
for ( ; ; ) {
if ( be32_to_cpu ( fd . key - > cat . parent ) ! = inode - > i_ino ) {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: walked past end of dir \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto out ;
}
2010-12-16 19:08:38 +03:00
hfs_bnode_read ( fd . bnode , & entry , fd . entryoffset ,
fd . entrylength ) ;
2005-04-17 02:20:36 +04:00
type = be16_to_cpu ( entry . type ) ;
len = HFSPLUS_MAX_STRLEN ;
err = hfsplus_uni2asc ( sb , & fd . key - > cat . name , strbuf , & len ) ;
if ( err )
goto out ;
if ( type = = HFSPLUS_FOLDER ) {
2010-12-16 19:08:38 +03:00
if ( fd . entrylength <
sizeof ( struct hfsplus_cat_folder ) ) {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: small dir entry \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto out ;
}
2010-10-01 07:42:59 +04:00
if ( HFSPLUS_SB ( sb ) - > hidden_dir & &
HFSPLUS_SB ( sb ) - > hidden_dir - > i_ino = =
be32_to_cpu ( entry . folder . id ) )
2005-04-17 02:20:36 +04:00
goto next ;
if ( filldir ( dirent , strbuf , len , filp - > f_pos ,
be32_to_cpu ( entry . folder . id ) , DT_DIR ) )
break ;
} else if ( type = = HFSPLUS_FILE ) {
if ( fd . entrylength < sizeof ( struct hfsplus_cat_file ) ) {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: small file entry \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto out ;
}
if ( filldir ( dirent , strbuf , len , filp - > f_pos ,
be32_to_cpu ( entry . file . id ) , DT_REG ) )
break ;
} else {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: bad catalog entry type \n " ) ;
2005-04-17 02:20:36 +04:00
err = - EIO ;
goto out ;
}
2010-12-16 19:08:40 +03:00
next :
2005-04-17 02:20:36 +04:00
filp - > f_pos + + ;
if ( filp - > f_pos > = inode - > i_size )
goto out ;
err = hfs_brec_goto ( & fd , 1 ) ;
if ( err )
goto out ;
}
rd = filp - > private_data ;
if ( ! rd ) {
rd = kmalloc ( sizeof ( struct hfsplus_readdir_data ) , GFP_KERNEL ) ;
if ( ! rd ) {
err = - ENOMEM ;
goto out ;
}
filp - > private_data = rd ;
rd - > file = filp ;
2010-10-01 07:43:31 +04:00
list_add ( & rd - > list , & HFSPLUS_I ( inode ) - > open_dir_list ) ;
2005-04-17 02:20:36 +04:00
}
memcpy ( & rd - > key , fd . key , sizeof ( struct hfsplus_cat_key ) ) ;
out :
hfs_find_exit ( & fd ) ;
return err ;
}
static int hfsplus_dir_release ( struct inode * inode , struct file * file )
{
struct hfsplus_readdir_data * rd = file - > private_data ;
if ( rd ) {
2010-10-01 07:45:25 +04:00
mutex_lock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
list_del ( & rd - > list ) ;
2010-10-01 07:45:25 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
kfree ( rd ) ;
}
return 0 ;
}
static int hfsplus_link ( struct dentry * src_dentry , struct inode * dst_dir ,
struct dentry * dst_dentry )
{
2010-10-01 07:42:59 +04:00
struct hfsplus_sb_info * sbi = HFSPLUS_SB ( dst_dir - > i_sb ) ;
2005-04-17 02:20:36 +04:00
struct inode * inode = src_dentry - > d_inode ;
struct inode * src_dir = src_dentry - > d_parent - > d_inode ;
struct qstr str ;
char name [ 32 ] ;
u32 cnid , id ;
int res ;
if ( HFSPLUS_IS_RSRC ( inode ) )
return - EPERM ;
2010-10-14 17:54:28 +04:00
if ( ! S_ISREG ( inode - > i_mode ) )
return - EPERM ;
2005-04-17 02:20:36 +04:00
2010-10-01 07:45:08 +04:00
mutex_lock ( & sbi - > vh_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( inode - > i_ino = = ( u32 ) ( unsigned long ) src_dentry - > d_fsdata ) {
for ( ; ; ) {
get_random_bytes ( & id , sizeof ( cnid ) ) ;
id & = 0x3fffffff ;
str . name = name ;
str . len = sprintf ( name , " iNode%d " , id ) ;
res = hfsplus_rename_cat ( inode - > i_ino ,
src_dir , & src_dentry - > d_name ,
2010-10-01 07:42:59 +04:00
sbi - > hidden_dir , & str ) ;
2005-04-17 02:20:36 +04:00
if ( ! res )
break ;
if ( res ! = - EEXIST )
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
}
2010-10-14 17:54:28 +04:00
HFSPLUS_I ( inode ) - > linkid = id ;
2010-10-01 07:42:59 +04:00
cnid = sbi - > next_cnid + + ;
2005-04-17 02:20:36 +04:00
src_dentry - > d_fsdata = ( void * ) ( unsigned long ) cnid ;
2010-12-16 19:08:38 +03:00
res = hfsplus_create_cat ( cnid , src_dir ,
& src_dentry - > d_name , inode ) ;
2005-04-17 02:20:36 +04:00
if ( res )
/* panic? */
2010-10-01 07:45:08 +04:00
goto out ;
2010-10-01 07:42:59 +04:00
sbi - > file_count + + ;
2005-04-17 02:20:36 +04:00
}
2010-10-01 07:42:59 +04:00
cnid = sbi - > next_cnid + + ;
2005-04-17 02:20:36 +04:00
res = hfsplus_create_cat ( cnid , dst_dir , & dst_dentry - > d_name , inode ) ;
if ( res )
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
2006-10-01 10:29:04 +04:00
inc_nlink ( inode ) ;
2005-04-17 02:20:36 +04:00
hfsplus_instantiate ( dst_dentry , inode , cnid ) ;
2010-10-23 19:11:40 +04:00
ihold ( inode ) ;
2005-04-17 02:20:36 +04:00
inode - > i_ctime = CURRENT_TIME_SEC ;
mark_inode_dirty ( inode ) ;
2010-10-01 07:42:59 +04:00
sbi - > file_count + + ;
dst_dir - > i_sb - > s_dirt = 1 ;
2010-10-01 07:45:08 +04:00
out :
mutex_unlock ( & sbi - > vh_mutex ) ;
return res ;
2005-04-17 02:20:36 +04:00
}
static int hfsplus_unlink ( struct inode * dir , struct dentry * dentry )
{
2010-10-01 07:42:59 +04:00
struct hfsplus_sb_info * sbi = HFSPLUS_SB ( dir - > i_sb ) ;
2005-04-17 02:20:36 +04:00
struct inode * inode = dentry - > d_inode ;
struct qstr str ;
char name [ 32 ] ;
u32 cnid ;
int res ;
if ( HFSPLUS_IS_RSRC ( inode ) )
return - EPERM ;
2010-10-01 07:45:08 +04:00
mutex_lock ( & sbi - > vh_mutex ) ;
2005-04-17 02:20:36 +04:00
cnid = ( u32 ) ( unsigned long ) dentry - > d_fsdata ;
if ( inode - > i_ino = = cnid & &
2010-10-01 07:43:31 +04:00
atomic_read ( & HFSPLUS_I ( inode ) - > opencnt ) ) {
2005-04-17 02:20:36 +04:00
str . name = name ;
str . len = sprintf ( name , " temp%lu " , inode - > i_ino ) ;
res = hfsplus_rename_cat ( inode - > i_ino ,
dir , & dentry - > d_name ,
2010-10-01 07:42:59 +04:00
sbi - > hidden_dir , & str ) ;
2010-10-27 15:45:50 +04:00
if ( ! res ) {
2005-04-17 02:20:36 +04:00
inode - > i_flags | = S_DEAD ;
2010-10-27 15:45:50 +04:00
drop_nlink ( inode ) ;
}
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
}
res = hfsplus_delete_cat ( cnid , dir , & dentry - > d_name ) ;
if ( res )
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
2006-01-19 04:43:10 +03:00
if ( inode - > i_nlink > 0 )
2006-10-01 10:29:03 +04:00
drop_nlink ( inode ) ;
2008-04-09 19:44:07 +04:00
if ( inode - > i_ino = = cnid )
clear_nlink ( inode ) ;
if ( ! inode - > i_nlink ) {
if ( inode - > i_ino ! = cnid ) {
2010-10-01 07:42:59 +04:00
sbi - > file_count - - ;
2010-10-01 07:43:31 +04:00
if ( ! atomic_read ( & HFSPLUS_I ( inode ) - > opencnt ) ) {
2008-04-09 19:44:07 +04:00
res = hfsplus_delete_cat ( inode - > i_ino ,
2010-10-01 07:42:59 +04:00
sbi - > hidden_dir ,
2008-04-09 19:44:07 +04:00
NULL ) ;
if ( ! res )
hfsplus_delete_inode ( inode ) ;
} else
inode - > i_flags | = S_DEAD ;
2005-04-17 02:20:36 +04:00
} else
2008-04-09 19:44:07 +04:00
hfsplus_delete_inode ( inode ) ;
2006-01-19 04:43:10 +03:00
} else
2010-10-01 07:42:59 +04:00
sbi - > file_count - - ;
2005-04-17 02:20:36 +04:00
inode - > i_ctime = CURRENT_TIME_SEC ;
mark_inode_dirty ( inode ) ;
2010-10-01 07:45:08 +04:00
out :
mutex_unlock ( & sbi - > vh_mutex ) ;
2005-04-17 02:20:36 +04:00
return res ;
}
static int hfsplus_rmdir ( struct inode * dir , struct dentry * dentry )
{
2010-10-01 07:45:08 +04:00
struct hfsplus_sb_info * sbi = HFSPLUS_SB ( dir - > i_sb ) ;
struct inode * inode = dentry - > d_inode ;
2005-04-17 02:20:36 +04:00
int res ;
if ( inode - > i_size ! = 2 )
return - ENOTEMPTY ;
2010-10-01 07:45:08 +04:00
mutex_lock ( & sbi - > vh_mutex ) ;
2005-04-17 02:20:36 +04:00
res = hfsplus_delete_cat ( inode - > i_ino , dir , & dentry - > d_name ) ;
if ( res )
2010-10-01 07:45:08 +04:00
goto out ;
2006-10-01 10:29:06 +04:00
clear_nlink ( inode ) ;
2005-04-17 02:20:36 +04:00
inode - > i_ctime = CURRENT_TIME_SEC ;
hfsplus_delete_inode ( inode ) ;
mark_inode_dirty ( inode ) ;
2010-10-01 07:45:08 +04:00
out :
mutex_unlock ( & sbi - > vh_mutex ) ;
return res ;
2005-04-17 02:20:36 +04:00
}
static int hfsplus_symlink ( struct inode * dir , struct dentry * dentry ,
const char * symname )
{
2010-10-01 07:45:08 +04:00
struct hfsplus_sb_info * sbi = HFSPLUS_SB ( dir - > i_sb ) ;
2005-04-17 02:20:36 +04:00
struct inode * inode ;
2010-10-01 07:45:08 +04:00
int res = - ENOSPC ;
2005-04-17 02:20:36 +04:00
2010-10-01 07:45:08 +04:00
mutex_lock ( & sbi - > vh_mutex ) ;
2010-10-01 07:43:54 +04:00
inode = hfsplus_new_inode ( dir - > i_sb , S_IFLNK | S_IRWXUGO ) ;
2005-04-17 02:20:36 +04:00
if ( ! inode )
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
res = page_symlink ( inode , symname , strlen ( symname ) + 1 ) ;
2010-10-01 07:43:54 +04:00
if ( res )
goto out_err ;
2005-04-17 02:20:36 +04:00
res = hfsplus_create_cat ( inode - > i_ino , dir , & dentry - > d_name , inode ) ;
2010-10-01 07:43:54 +04:00
if ( res )
goto out_err ;
2005-04-17 02:20:36 +04:00
2010-10-01 07:43:54 +04:00
hfsplus_instantiate ( dentry , inode , inode - > i_ino ) ;
mark_inode_dirty ( inode ) ;
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
2010-10-01 07:43:54 +04:00
out_err :
2011-10-28 16:13:28 +04:00
clear_nlink ( inode ) ;
2010-10-01 07:43:54 +04:00
hfsplus_delete_inode ( inode ) ;
iput ( inode ) ;
2010-10-01 07:45:08 +04:00
out :
mutex_unlock ( & sbi - > vh_mutex ) ;
2005-04-17 02:20:36 +04:00
return res ;
}
static int hfsplus_mknod ( struct inode * dir , struct dentry * dentry ,
int mode , dev_t rdev )
{
2010-10-01 07:45:08 +04:00
struct hfsplus_sb_info * sbi = HFSPLUS_SB ( dir - > i_sb ) ;
2005-04-17 02:20:36 +04:00
struct inode * inode ;
2010-10-01 07:45:08 +04:00
int res = - ENOSPC ;
2005-04-17 02:20:36 +04:00
2010-10-01 07:45:08 +04:00
mutex_lock ( & sbi - > vh_mutex ) ;
2010-10-01 07:43:50 +04:00
inode = hfsplus_new_inode ( dir - > i_sb , mode ) ;
2005-04-17 02:20:36 +04:00
if ( ! inode )
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
2010-10-14 17:54:39 +04:00
if ( S_ISBLK ( mode ) | | S_ISCHR ( mode ) | | S_ISFIFO ( mode ) | | S_ISSOCK ( mode ) )
init_special_inode ( inode , mode , rdev ) ;
2005-04-17 02:20:36 +04:00
res = hfsplus_create_cat ( inode - > i_ino , dir , & dentry - > d_name , inode ) ;
if ( res ) {
2011-10-28 16:13:28 +04:00
clear_nlink ( inode ) ;
2005-04-17 02:20:36 +04:00
hfsplus_delete_inode ( inode ) ;
iput ( inode ) ;
2010-10-01 07:45:08 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
}
2010-10-01 07:43:50 +04:00
2005-04-17 02:20:36 +04:00
hfsplus_instantiate ( dentry , inode , inode - > i_ino ) ;
mark_inode_dirty ( inode ) ;
2010-10-01 07:45:08 +04:00
out :
mutex_unlock ( & sbi - > vh_mutex ) ;
return res ;
2005-04-17 02:20:36 +04:00
}
2010-10-01 07:43:50 +04:00
static int hfsplus_create ( struct inode * dir , struct dentry * dentry , int mode ,
struct nameidata * nd )
{
return hfsplus_mknod ( dir , dentry , mode , 0 ) ;
}
static int hfsplus_mkdir ( struct inode * dir , struct dentry * dentry , int mode )
{
return hfsplus_mknod ( dir , dentry , mode | S_IFDIR , 0 ) ;
}
2005-04-17 02:20:36 +04:00
static int hfsplus_rename ( struct inode * old_dir , struct dentry * old_dentry ,
struct inode * new_dir , struct dentry * new_dentry )
{
int res ;
/* Unlink destination if it already exists */
if ( new_dentry - > d_inode ) {
2011-05-28 00:42:06 +04:00
if ( S_ISDIR ( new_dentry - > d_inode - > i_mode ) )
2010-10-01 11:12:08 +04:00
res = hfsplus_rmdir ( new_dir , new_dentry ) ;
2011-05-28 00:42:06 +04:00
else
2010-10-01 11:12:08 +04:00
res = hfsplus_unlink ( new_dir , new_dentry ) ;
2005-04-17 02:20:36 +04:00
if ( res )
return res ;
}
res = hfsplus_rename_cat ( ( u32 ) ( unsigned long ) old_dentry - > d_fsdata ,
old_dir , & old_dentry - > d_name ,
new_dir , & new_dentry - > d_name ) ;
if ( ! res )
new_dentry - > d_fsdata = old_dentry - > d_fsdata ;
return res ;
}
2007-02-12 11:55:39 +03:00
const struct inode_operations hfsplus_dir_inode_operations = {
2005-04-17 02:20:36 +04:00
. lookup = hfsplus_lookup ,
. create = hfsplus_create ,
. link = hfsplus_link ,
. unlink = hfsplus_unlink ,
. mkdir = hfsplus_mkdir ,
. rmdir = hfsplus_rmdir ,
. symlink = hfsplus_symlink ,
. mknod = hfsplus_mknod ,
. rename = hfsplus_rename ,
} ;
2006-03-28 13:56:42 +04:00
const struct file_operations hfsplus_dir_operations = {
2010-11-23 16:38:10 +03:00
. fsync = hfsplus_file_fsync ,
2005-04-17 02:20:36 +04:00
. read = generic_read_dir ,
. readdir = hfsplus_readdir ,
2010-04-27 18:24:20 +04:00
. unlocked_ioctl = hfsplus_ioctl ,
2005-04-17 02:20:36 +04:00
. llseek = generic_file_llseek ,
. release = hfsplus_dir_release ,
} ;