linux/fs/hfs/inode.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/hfs/inode.c
   3 *
   4 * Copyright (C) 1995-1997  Paul H. Hargrove
   5 * (C) 2003 Ardis Technologies <roman@ardistech.com>
   6 * This file may be distributed under the terms of the GNU General Public License.
   7 *
   8 * This file contains inode-related functions which do not depend on
   9 * which scheme is being used to represent forks.
  10 *
  11 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
  12 */
  13
  14#include <linux/pagemap.h>
  15#include <linux/mpage.h>
  16#include <linux/sched.h>
  17#include <linux/aio.h>
  18
  19#include "hfs_fs.h"
  20#include "btree.h"
  21
  22static const struct file_operations hfs_file_operations;
  23static const struct inode_operations hfs_file_inode_operations;
  24
  25/*================ Variable-like macros ================*/
  26
  27#define HFS_VALID_MODE_BITS  (S_IFREG | S_IFDIR | S_IRWXUGO)
  28
  29static int hfs_writepage(struct page *page, struct writeback_control *wbc)
  30{
  31        return block_write_full_page(page, hfs_get_block, wbc);
  32}
  33
  34static int hfs_readpage(struct file *file, struct page *page)
  35{
  36        return block_read_full_page(page, hfs_get_block);
  37}
  38
  39static void hfs_write_failed(struct address_space *mapping, loff_t to)
  40{
  41        struct inode *inode = mapping->host;
  42
  43        if (to > inode->i_size) {
  44                truncate_pagecache(inode, to, inode->i_size);
  45                hfs_file_truncate(inode);
  46        }
  47}
  48
  49static int hfs_write_begin(struct file *file, struct address_space *mapping,
  50                        loff_t pos, unsigned len, unsigned flags,
  51                        struct page **pagep, void **fsdata)
  52{
  53        int ret;
  54
  55        *pagep = NULL;
  56        ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
  57                                hfs_get_block,
  58                                &HFS_I(mapping->host)->phys_size);
  59        if (unlikely(ret))
  60                hfs_write_failed(mapping, pos + len);
  61
  62        return ret;
  63}
  64
  65static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
  66{
  67        return generic_block_bmap(mapping, block, hfs_get_block);
  68}
  69
  70static int hfs_releasepage(struct page *page, gfp_t mask)
  71{
  72        struct inode *inode = page->mapping->host;
  73        struct super_block *sb = inode->i_sb;
  74        struct hfs_btree *tree;
  75        struct hfs_bnode *node;
  76        u32 nidx;
  77        int i, res = 1;
  78
  79        switch (inode->i_ino) {
  80        case HFS_EXT_CNID:
  81                tree = HFS_SB(sb)->ext_tree;
  82                break;
  83        case HFS_CAT_CNID:
  84                tree = HFS_SB(sb)->cat_tree;
  85                break;
  86        default:
  87                BUG();
  88                return 0;
  89        }
  90
  91        if (!tree)
  92                return 0;
  93
  94        if (tree->node_size >= PAGE_CACHE_SIZE) {
  95                nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT);
  96                spin_lock(&tree->hash_lock);
  97                node = hfs_bnode_findhash(tree, nidx);
  98                if (!node)
  99                        ;
 100                else if (atomic_read(&node->refcnt))
 101                        res = 0;
 102                if (res && node) {
 103                        hfs_bnode_unhash(node);
 104                        hfs_bnode_free(node);
 105                }
 106                spin_unlock(&tree->hash_lock);
 107        } else {
 108                nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift);
 109                i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift);
 110                spin_lock(&tree->hash_lock);
 111                do {
 112                        node = hfs_bnode_findhash(tree, nidx++);
 113                        if (!node)
 114                                continue;
 115                        if (atomic_read(&node->refcnt)) {
 116                                res = 0;
 117                                break;
 118                        }
 119                        hfs_bnode_unhash(node);
 120                        hfs_bnode_free(node);
 121                } while (--i && nidx < tree->node_count);
 122                spin_unlock(&tree->hash_lock);
 123        }
 124        return res ? try_to_free_buffers(page) : 0;
 125}
 126
 127static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
 128                const struct iovec *iov, loff_t offset, unsigned long nr_segs)
 129{
 130        struct file *file = iocb->ki_filp;
 131        struct address_space *mapping = file->f_mapping;
 132        struct inode *inode = file_inode(file)->i_mapping->host;
 133        ssize_t ret;
 134
 135        ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
 136                                 hfs_get_block);
 137
 138        /*
 139         * In case of error extending write may have instantiated a few
 140         * blocks outside i_size. Trim these off again.
 141         */
 142        if (unlikely((rw & WRITE) && ret < 0)) {
 143                loff_t isize = i_size_read(inode);
 144                loff_t end = offset + iov_length(iov, nr_segs);
 145
 146                if (end > isize)
 147                        hfs_write_failed(mapping, end);
 148        }
 149
 150        return ret;
 151}
 152
 153static int hfs_writepages(struct address_space *mapping,
 154                          struct writeback_control *wbc)
 155{
 156        return mpage_writepages(mapping, wbc, hfs_get_block);
 157}
 158
 159const struct address_space_operations hfs_btree_aops = {
 160        .readpage       = hfs_readpage,
 161        .writepage      = hfs_writepage,
 162        .write_begin    = hfs_write_begin,
 163        .write_end      = generic_write_end,
 164        .bmap           = hfs_bmap,
 165        .releasepage    = hfs_releasepage,
 166};
 167
 168const struct address_space_operations hfs_aops = {
 169        .readpage       = hfs_readpage,
 170        .writepage      = hfs_writepage,
 171        .write_begin    = hfs_write_begin,
 172        .write_end      = generic_write_end,
 173        .bmap           = hfs_bmap,
 174        .direct_IO      = hfs_direct_IO,
 175        .writepages     = hfs_writepages,
 176};
 177
 178/*
 179 * hfs_new_inode
 180 */
 181struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
 182{
 183        struct super_block *sb = dir->i_sb;
 184        struct inode *inode = new_inode(sb);
 185        if (!inode)
 186                return NULL;
 187
 188        mutex_init(&HFS_I(inode)->extents_lock);
 189        INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
 190        hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
 191        inode->i_ino = HFS_SB(sb)->next_id++;
 192        inode->i_mode = mode;
 193        inode->i_uid = current_fsuid();
 194        inode->i_gid = current_fsgid();
 195        set_nlink(inode, 1);
 196        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 197        HFS_I(inode)->flags = 0;
 198        HFS_I(inode)->rsrc_inode = NULL;
 199        HFS_I(inode)->fs_blocks = 0;
 200        if (S_ISDIR(mode)) {
 201                inode->i_size = 2;
 202                HFS_SB(sb)->folder_count++;
 203                if (dir->i_ino == HFS_ROOT_CNID)
 204                        HFS_SB(sb)->root_dirs++;
 205                inode->i_op = &hfs_dir_inode_operations;
 206                inode->i_fop = &hfs_dir_operations;
 207                inode->i_mode |= S_IRWXUGO;
 208                inode->i_mode &= ~HFS_SB(inode->i_sb)->s_dir_umask;
 209        } else if (S_ISREG(mode)) {
 210                HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
 211                HFS_SB(sb)->file_count++;
 212                if (dir->i_ino == HFS_ROOT_CNID)
 213                        HFS_SB(sb)->root_files++;
 214                inode->i_op = &hfs_file_inode_operations;
 215                inode->i_fop = &hfs_file_operations;
 216                inode->i_mapping->a_ops = &hfs_aops;
 217                inode->i_mode |= S_IRUGO|S_IXUGO;
 218                if (mode & S_IWUSR)
 219                        inode->i_mode |= S_IWUGO;
 220                inode->i_mode &= ~HFS_SB(inode->i_sb)->s_file_umask;
 221                HFS_I(inode)->phys_size = 0;
 222                HFS_I(inode)->alloc_blocks = 0;
 223                HFS_I(inode)->first_blocks = 0;
 224                HFS_I(inode)->cached_start = 0;
 225                HFS_I(inode)->cached_blocks = 0;
 226                memset(HFS_I(inode)->first_extents, 0, sizeof(hfs_extent_rec));
 227                memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec));
 228        }
 229        insert_inode_hash(inode);
 230        mark_inode_dirty(inode);
 231        set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
 232        hfs_mark_mdb_dirty(sb);
 233
 234        return inode;
 235}
 236
 237void hfs_delete_inode(struct inode *inode)
 238{
 239        struct super_block *sb = inode->i_sb;
 240
 241        hfs_dbg(INODE, "delete_inode: %lu\n", inode->i_ino);
 242        if (S_ISDIR(inode->i_mode)) {
 243                HFS_SB(sb)->folder_count--;
 244                if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
 245                        HFS_SB(sb)->root_dirs--;
 246                set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
 247                hfs_mark_mdb_dirty(sb);
 248                return;
 249        }
 250        HFS_SB(sb)->file_count--;
 251        if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
 252                HFS_SB(sb)->root_files--;
 253        if (S_ISREG(inode->i_mode)) {
 254                if (!inode->i_nlink) {
 255                        inode->i_size = 0;
 256                        hfs_file_truncate(inode);
 257                }
 258        }
 259        set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
 260        hfs_mark_mdb_dirty(sb);
 261}
 262
 263void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
 264                         __be32 __log_size, __be32 phys_size, u32 clump_size)
 265{
 266        struct super_block *sb = inode->i_sb;
 267        u32 log_size = be32_to_cpu(__log_size);
 268        u16 count;
 269        int i;
 270
 271        memcpy(HFS_I(inode)->first_extents, ext, sizeof(hfs_extent_rec));
 272        for (count = 0, i = 0; i < 3; i++)
 273                count += be16_to_cpu(ext[i].count);
 274        HFS_I(inode)->first_blocks = count;
 275
 276        inode->i_size = HFS_I(inode)->phys_size = log_size;
 277        HFS_I(inode)->fs_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 278        inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
 279        HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
 280                                     HFS_SB(sb)->alloc_blksz;
 281        HFS_I(inode)->clump_blocks = clump_size / HFS_SB(sb)->alloc_blksz;
 282        if (!HFS_I(inode)->clump_blocks)
 283                HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
 284}
 285
 286struct hfs_iget_data {
 287        struct hfs_cat_key *key;
 288        hfs_cat_rec *rec;
 289};
 290
 291static int hfs_test_inode(struct inode *inode, void *data)
 292{
 293        struct hfs_iget_data *idata = data;
 294        hfs_cat_rec *rec;
 295
 296        rec = idata->rec;
 297        switch (rec->type) {
 298        case HFS_CDR_DIR:
 299                return inode->i_ino == be32_to_cpu(rec->dir.DirID);
 300        case HFS_CDR_FIL:
 301                return inode->i_ino == be32_to_cpu(rec->file.FlNum);
 302        default:
 303                BUG();
 304                return 1;
 305        }
 306}
 307
 308/*
 309 * hfs_read_inode
 310 */
 311static int hfs_read_inode(struct inode *inode, void *data)
 312{
 313        struct hfs_iget_data *idata = data;
 314        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
 315        hfs_cat_rec *rec;
 316
 317        HFS_I(inode)->flags = 0;
 318        HFS_I(inode)->rsrc_inode = NULL;
 319        mutex_init(&HFS_I(inode)->extents_lock);
 320        INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
 321
 322        /* Initialize the inode */
 323        inode->i_uid = hsb->s_uid;
 324        inode->i_gid = hsb->s_gid;
 325        set_nlink(inode, 1);
 326
 327        if (idata->key)
 328                HFS_I(inode)->cat_key = *idata->key;
 329        else
 330                HFS_I(inode)->flags |= HFS_FLG_RSRC;
 331        HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60;
 332
 333        rec = idata->rec;
 334        switch (rec->type) {
 335        case HFS_CDR_FIL:
 336                if (!HFS_IS_RSRC(inode)) {
 337                        hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
 338                                            rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
 339                } else {
 340                        hfs_inode_read_fork(inode, rec->file.RExtRec, rec->file.RLgLen,
 341                                            rec->file.RPyLen, be16_to_cpu(rec->file.ClpSize));
 342                }
 343
 344                inode->i_ino = be32_to_cpu(rec->file.FlNum);
 345                inode->i_mode = S_IRUGO | S_IXUGO;
 346                if (!(rec->file.Flags & HFS_FIL_LOCK))
 347                        inode->i_mode |= S_IWUGO;
 348                inode->i_mode &= ~hsb->s_file_umask;
 349                inode->i_mode |= S_IFREG;
 350                inode->i_ctime = inode->i_atime = inode->i_mtime =
 351                                hfs_m_to_utime(rec->file.MdDat);
 352                inode->i_op = &hfs_file_inode_operations;
 353                inode->i_fop = &hfs_file_operations;
 354                inode->i_mapping->a_ops = &hfs_aops;
 355                break;
 356        case HFS_CDR_DIR:
 357                inode->i_ino = be32_to_cpu(rec->dir.DirID);
 358                inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
 359                HFS_I(inode)->fs_blocks = 0;
 360                inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
 361                inode->i_ctime = inode->i_atime = inode->i_mtime =
 362                                hfs_m_to_utime(rec->dir.MdDat);
 363                inode->i_op = &hfs_dir_inode_operations;
 364                inode->i_fop = &hfs_dir_operations;
 365                break;
 366        default:
 367                make_bad_inode(inode);
 368        }
 369        return 0;
 370}
 371
 372/*
 373 * __hfs_iget()
 374 *
 375 * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in
 376 * the catalog B-tree and the 'type' of the desired file return the
 377 * inode for that file/directory or NULL.  Note that 'type' indicates
 378 * whether we want the actual file or directory, or the corresponding
 379 * metadata (AppleDouble header file or CAP metadata file).
 380 */
 381struct inode *hfs_iget(struct super_block *sb, struct hfs_cat_key *key, hfs_cat_rec *rec)
 382{
 383        struct hfs_iget_data data = { key, rec };
 384        struct inode *inode;
 385        u32 cnid;
 386
 387        switch (rec->type) {
 388        case HFS_CDR_DIR:
 389                cnid = be32_to_cpu(rec->dir.DirID);
 390                break;
 391        case HFS_CDR_FIL:
 392                cnid = be32_to_cpu(rec->file.FlNum);
 393                break;
 394        default:
 395                return NULL;
 396        }
 397        inode = iget5_locked(sb, cnid, hfs_test_inode, hfs_read_inode, &data);
 398        if (inode && (inode->i_state & I_NEW))
 399                unlock_new_inode(inode);
 400        return inode;
 401}
 402
 403void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
 404                          __be32 *log_size, __be32 *phys_size)
 405{
 406        memcpy(ext, HFS_I(inode)->first_extents, sizeof(hfs_extent_rec));
 407
 408        if (log_size)
 409                *log_size = cpu_to_be32(inode->i_size);
 410        if (phys_size)
 411                *phys_size = cpu_to_be32(HFS_I(inode)->alloc_blocks *
 412                                         HFS_SB(inode->i_sb)->alloc_blksz);
 413}
 414
 415int hfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 416{
 417        struct inode *main_inode = inode;
 418        struct hfs_find_data fd;
 419        hfs_cat_rec rec;
 420        int res;
 421
 422        hfs_dbg(INODE, "hfs_write_inode: %lu\n", inode->i_ino);
 423        res = hfs_ext_write_extent(inode);
 424        if (res)
 425                return res;
 426
 427        if (inode->i_ino < HFS_FIRSTUSER_CNID) {
 428                switch (inode->i_ino) {
 429                case HFS_ROOT_CNID:
 430                        break;
 431                case HFS_EXT_CNID:
 432                        hfs_btree_write(HFS_SB(inode->i_sb)->ext_tree);
 433                        return 0;
 434                case HFS_CAT_CNID:
 435                        hfs_btree_write(HFS_SB(inode->i_sb)->cat_tree);
 436                        return 0;
 437                default:
 438                        BUG();
 439                        return -EIO;
 440                }
 441        }
 442
 443        if (HFS_IS_RSRC(inode))
 444                main_inode = HFS_I(inode)->rsrc_inode;
 445
 446        if (!main_inode->i_nlink)
 447                return 0;
 448
 449        if (hfs_find_init(HFS_SB(main_inode->i_sb)->cat_tree, &fd))
 450                /* panic? */
 451                return -EIO;
 452
 453        fd.search_key->cat = HFS_I(main_inode)->cat_key;
 454        if (hfs_brec_find(&fd))
 455                /* panic? */
 456                goto out;
 457
 458        if (S_ISDIR(main_inode->i_mode)) {
 459                if (fd.entrylength < sizeof(struct hfs_cat_dir))
 460                        /* panic? */;
 461                hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
 462                           sizeof(struct hfs_cat_dir));
 463                if (rec.type != HFS_CDR_DIR ||
 464                    be32_to_cpu(rec.dir.DirID) != inode->i_ino) {
 465                }
 466
 467                rec.dir.MdDat = hfs_u_to_mtime(inode->i_mtime);
 468                rec.dir.Val = cpu_to_be16(inode->i_size - 2);
 469
 470                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
 471                            sizeof(struct hfs_cat_dir));
 472        } else if (HFS_IS_RSRC(inode)) {
 473                hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
 474                               sizeof(struct hfs_cat_file));
 475                hfs_inode_write_fork(inode, rec.file.RExtRec,
 476                                     &rec.file.RLgLen, &rec.file.RPyLen);
 477                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
 478                                sizeof(struct hfs_cat_file));
 479        } else {
 480                if (fd.entrylength < sizeof(struct hfs_cat_file))
 481                        /* panic? */;
 482                hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
 483                           sizeof(struct hfs_cat_file));
 484                if (rec.type != HFS_CDR_FIL ||
 485                    be32_to_cpu(rec.file.FlNum) != inode->i_ino) {
 486                }
 487
 488                if (inode->i_mode & S_IWUSR)
 489                        rec.file.Flags &= ~HFS_FIL_LOCK;
 490                else
 491                        rec.file.Flags |= HFS_FIL_LOCK;
 492                hfs_inode_write_fork(inode, rec.file.ExtRec, &rec.file.LgLen, &rec.file.PyLen);
 493                rec.file.MdDat = hfs_u_to_mtime(inode->i_mtime);
 494
 495                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
 496                            sizeof(struct hfs_cat_file));
 497        }
 498out:
 499        hfs_find_exit(&fd);
 500        return 0;
 501}
 502
 503static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
 504                                      unsigned int flags)
 505{
 506        struct inode *inode = NULL;
 507        hfs_cat_rec rec;
 508        struct hfs_find_data fd;
 509        int res;
 510
 511        if (HFS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
 512                goto out;
 513
 514        inode = HFS_I(dir)->rsrc_inode;
 515        if (inode)
 516                goto out;
 517
 518        inode = new_inode(dir->i_sb);
 519        if (!inode)
 520                return ERR_PTR(-ENOMEM);
 521
 522        res = hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
 523        if (res) {
 524                iput(inode);
 525                return ERR_PTR(res);
 526        }
 527        fd.search_key->cat = HFS_I(dir)->cat_key;
 528        res = hfs_brec_read(&fd, &rec, sizeof(rec));
 529        if (!res) {
 530                struct hfs_iget_data idata = { NULL, &rec };
 531                hfs_read_inode(inode, &idata);
 532        }
 533        hfs_find_exit(&fd);
 534        if (res) {
 535                iput(inode);
 536                return ERR_PTR(res);
 537        }
 538        HFS_I(inode)->rsrc_inode = dir;
 539        HFS_I(dir)->rsrc_inode = inode;
 540        igrab(dir);
 541        hlist_add_fake(&inode->i_hash);
 542        mark_inode_dirty(inode);
 543out:
 544        d_add(dentry, inode);
 545        return NULL;
 546}
 547
 548void hfs_evict_inode(struct inode *inode)
 549{
 550        truncate_inode_pages(&inode->i_data, 0);
 551        clear_inode(inode);
 552        if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) {
 553                HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
 554                iput(HFS_I(inode)->rsrc_inode);
 555        }
 556}
 557
 558static int hfs_file_open(struct inode *inode, struct file *file)
 559{
 560        if (HFS_IS_RSRC(inode))
 561                inode = HFS_I(inode)->rsrc_inode;
 562        atomic_inc(&HFS_I(inode)->opencnt);
 563        return 0;
 564}
 565
 566static int hfs_file_release(struct inode *inode, struct file *file)
 567{
 568        //struct super_block *sb = inode->i_sb;
 569
 570        if (HFS_IS_RSRC(inode))
 571                inode = HFS_I(inode)->rsrc_inode;
 572        if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
 573                mutex_lock(&inode->i_mutex);
 574                hfs_file_truncate(inode);
 575                //if (inode->i_flags & S_DEAD) {
 576                //      hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
 577                //      hfs_delete_inode(inode);
 578                //}
 579                mutex_unlock(&inode->i_mutex);
 580        }
 581        return 0;
 582}
 583
 584/*
 585 * hfs_notify_change()
 586 *
 587 * Based very closely on fs/msdos/inode.c by Werner Almesberger
 588 *
 589 * This is the notify_change() field in the super_operations structure
 590 * for HFS file systems.  The purpose is to take that changes made to
 591 * an inode and apply then in a filesystem-dependent manner.  In this
 592 * case the process has a few of tasks to do:
 593 *  1) prevent changes to the i_uid and i_gid fields.
 594 *  2) map file permissions to the closest allowable permissions
 595 *  3) Since multiple Linux files can share the same on-disk inode under
 596 *     HFS (for instance the data and resource forks of a file) a change
 597 *     to permissions must be applied to all other in-core inodes which
 598 *     correspond to the same HFS file.
 599 */
 600
 601int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 602{
 603        struct inode *inode = dentry->d_inode;
 604        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
 605        int error;
 606
 607        error = inode_change_ok(inode, attr); /* basic permission checks */
 608        if (error)
 609                return error;
 610
 611        /* no uig/gid changes and limit which mode bits can be set */
 612        if (((attr->ia_valid & ATTR_UID) &&
 613             (!uid_eq(attr->ia_uid, hsb->s_uid))) ||
 614            ((attr->ia_valid & ATTR_GID) &&
 615             (!gid_eq(attr->ia_gid, hsb->s_gid))) ||
 616            ((attr->ia_valid & ATTR_MODE) &&
 617             ((S_ISDIR(inode->i_mode) &&
 618               (attr->ia_mode != inode->i_mode)) ||
 619              (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
 620                return hsb->s_quiet ? 0 : error;
 621        }
 622
 623        if (attr->ia_valid & ATTR_MODE) {
 624                /* Only the 'w' bits can ever change and only all together. */
 625                if (attr->ia_mode & S_IWUSR)
 626                        attr->ia_mode = inode->i_mode | S_IWUGO;
 627                else
 628                        attr->ia_mode = inode->i_mode & ~S_IWUGO;
 629                attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask;
 630        }
 631
 632        if ((attr->ia_valid & ATTR_SIZE) &&
 633            attr->ia_size != i_size_read(inode)) {
 634                inode_dio_wait(inode);
 635
 636                error = inode_newsize_ok(inode, attr->ia_size);
 637                if (error)
 638                        return error;
 639
 640                truncate_setsize(inode, attr->ia_size);
 641                hfs_file_truncate(inode);
 642        }
 643
 644        setattr_copy(inode, attr);
 645        mark_inode_dirty(inode);
 646        return 0;
 647}
 648
 649static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
 650                          int datasync)
 651{
 652        struct inode *inode = filp->f_mapping->host;
 653        struct super_block * sb;
 654        int ret, err;
 655
 656        ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
 657        if (ret)
 658                return ret;
 659        mutex_lock(&inode->i_mutex);
 660
 661        /* sync the inode to buffers */
 662        ret = write_inode_now(inode, 0);
 663
 664        /* sync the superblock to buffers */
 665        sb = inode->i_sb;
 666        flush_delayed_work(&HFS_SB(sb)->mdb_work);
 667        /* .. finally sync the buffers to disk */
 668        err = sync_blockdev(sb->s_bdev);
 669        if (!ret)
 670                ret = err;
 671        mutex_unlock(&inode->i_mutex);
 672        return ret;
 673}
 674
 675static const struct file_operations hfs_file_operations = {
 676        .llseek         = generic_file_llseek,
 677        .read           = do_sync_read,
 678        .aio_read       = generic_file_aio_read,
 679        .write          = do_sync_write,
 680        .aio_write      = generic_file_aio_write,
 681        .mmap           = generic_file_mmap,
 682        .splice_read    = generic_file_splice_read,
 683        .fsync          = hfs_file_fsync,
 684        .open           = hfs_file_open,
 685        .release        = hfs_file_release,
 686};
 687
 688static const struct inode_operations hfs_file_inode_operations = {
 689        .lookup         = hfs_file_lookup,
 690        .setattr        = hfs_inode_setattr,
 691        .setxattr       = hfs_setxattr,
 692        .getxattr       = hfs_getxattr,
 693        .listxattr      = hfs_listxattr,
 694};
 695
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.