OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [hfs/] [inode.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/fs/hfs/inode.c
3
 *
4
 * Copyright (C) 1995-1997  Paul H. Hargrove
5
 * This file may be distributed under the terms of the GNU General Public License.
6
 *
7
 * This file contains inode-related functions which do not depend on
8
 * which scheme is being used to represent forks.
9
 *
10
 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
11
 *
12
 * "XXX" in a comment is a note to myself to consider changing something.
13
 *
14
 * In function preconditions the term "valid" applied to a pointer to
15
 * a structure means that the pointer is non-NULL and the structure it
16
 * points to has all fields initialized to consistent values.
17
 */
18
 
19
#include "hfs.h"
20
#include <linux/hfs_fs_sb.h>
21
#include <linux/hfs_fs_i.h>
22
#include <linux/hfs_fs.h>
23
#include <linux/smp_lock.h>
24
 
25
/*================ Variable-like macros ================*/
26
 
27
#define HFS_VALID_MODE_BITS  (S_IFREG | S_IFDIR | S_IRWXUGO)
28
 
29
/*================ File-local functions ================*/
30
 
31
/*
32
 * init_file_inode()
33
 *
34
 * Given an HFS catalog entry initialize an inode for a file.
35
 */
36
static void init_file_inode(struct inode *inode, hfs_u8 fork)
37
{
38
        struct hfs_fork *fk;
39
        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
40
 
41
        if (fork == HFS_FK_DATA) {
42
                inode->i_mode = S_IRWXUGO | S_IFREG;
43
        } else {
44
                inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
45
        }
46
 
47
        if (fork == HFS_FK_DATA) {
48
#if 0 /* XXX: disable crlf translations for now */
49
                hfs_u32 type = hfs_get_nl(entry->info.file.finfo.fdType);
50
 
51
                HFS_I(inode)->convert =
52
                        ((HFS_SB(inode->i_sb)->s_conv == 't') ||
53
                         ((HFS_SB(inode->i_sb)->s_conv == 'a') &&
54
                          ((type == htonl(0x54455854)) ||   /* "TEXT" */
55
                           (type == htonl(0x7474726f)))));  /* "ttro" */
56
#else
57
                HFS_I(inode)->convert = 0;
58
#endif
59
                fk = &entry->u.file.data_fork;
60
        } else {
61
                fk = &entry->u.file.rsrc_fork;
62
                HFS_I(inode)->convert = 0;
63
        }
64
        HFS_I(inode)->fork = fk;
65
        inode->i_size = fk->lsize;
66
        inode->i_blocks = fk->psize;
67
        inode->i_nlink = 1;
68
}
69
 
70
/*================ Global functions ================*/
71
 
72
/*
73
 * hfs_put_inode()
74
 *
75
 * This is the put_inode() entry in the super_operations for HFS
76
 * filesystems.  The purpose is to perform any filesystem-dependent
77
 * cleanup necessary when the use-count of an inode falls to zero.
78
 */
79
void hfs_put_inode(struct inode * inode)
80
{
81
        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
82
 
83
        lock_kernel();
84
        hfs_cat_put(entry);
85
        if (atomic_read(&inode->i_count) == 1) {
86
          struct hfs_hdr_layout *tmp = HFS_I(inode)->layout;
87
 
88
          if (tmp) {
89
                HFS_I(inode)->layout = NULL;
90
                HFS_DELETE(tmp);
91
          }
92
        }
93
        unlock_kernel();
94
}
95
 
96
/*
97
 * hfs_notify_change()
98
 *
99
 * Based very closely on fs/msdos/inode.c by Werner Almesberger
100
 *
101
 * This is the notify_change() field in the super_operations structure
102
 * for HFS file systems.  The purpose is to take that changes made to
103
 * an inode and apply then in a filesystem-dependent manner.  In this
104
 * case the process has a few of tasks to do:
105
 *  1) prevent changes to the i_uid and i_gid fields.
106
 *  2) map file permissions to the closest allowable permissions
107
 *  3) Since multiple Linux files can share the same on-disk inode under
108
 *     HFS (for instance the data and resource forks of a file) a change
109
 *     to permissions must be applied to all other in-core inodes which
110
 *     correspond to the same HFS file.
111
 */
112
enum {HFS_NORM, HFS_HDR, HFS_CAP};
113
 
114
static int __hfs_notify_change(struct dentry *dentry, struct iattr * attr, int kind)
115
{
116
        struct inode *inode = dentry->d_inode;
117
        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
118
        struct dentry **de = entry->sys_entry;
119
        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
120
        int error, i;
121
 
122
        error = inode_change_ok(inode, attr); /* basic permission checks */
123
        if (error) {
124
                /* Let netatalk's afpd think chmod() always succeeds */
125
                if (hsb->s_afpd &&
126
                    (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) {
127
                        return 0;
128
                } else {
129
                        return error;
130
                }
131
        }
132
 
133
        /* no uig/gid changes and limit which mode bits can be set */
134
        if (((attr->ia_valid & ATTR_UID) &&
135
             (attr->ia_uid != hsb->s_uid)) ||
136
            ((attr->ia_valid & ATTR_GID) &&
137
             (attr->ia_gid != hsb->s_gid)) ||
138
            ((attr->ia_valid & ATTR_MODE) &&
139
             (((entry->type == HFS_CDR_DIR) &&
140
               (attr->ia_mode != inode->i_mode))||
141
              (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
142
                return hsb->s_quiet ? 0 : error;
143
        }
144
 
145
        if (entry->type == HFS_CDR_DIR) {
146
                attr->ia_valid &= ~ATTR_MODE;
147
        } else if (attr->ia_valid & ATTR_MODE) {
148
                /* Only the 'w' bits can ever change and only all together. */
149
                if (attr->ia_mode & S_IWUSR) {
150
                        attr->ia_mode = inode->i_mode | S_IWUGO;
151
                } else {
152
                        attr->ia_mode = inode->i_mode & ~S_IWUGO;
153
                }
154
                attr->ia_mode &= ~hsb->s_umask;
155
        }
156
        /*
157
         * Normal files handle size change in normal way.
158
         * Oddballs are served here.
159
         */
160
        if (attr->ia_valid & ATTR_SIZE) {
161
                if (kind == HFS_CAP) {
162
                        inode->i_size = attr->ia_size;
163
                        if (inode->i_size > HFS_FORK_MAX)
164
                                inode->i_size = HFS_FORK_MAX;
165
                        mark_inode_dirty(inode);
166
                        attr->ia_valid &= ~ATTR_SIZE;
167
                } else if (kind == HFS_HDR) {
168
                        hdr_truncate(inode, attr->ia_size);
169
                        attr->ia_valid &= ~ATTR_SIZE;
170
                }
171
        }
172
        error = inode_setattr(inode, attr);
173
        if (error)
174
                return error;
175
 
176
        /* We wouldn't want to mess with the sizes of the other fork */
177
        attr->ia_valid &= ~ATTR_SIZE;
178
 
179
        /* We must change all in-core inodes corresponding to this file. */
180
        for (i = 0; i < 4; ++i) {
181
          if (de[i] && (de[i] != dentry)) {
182
                inode_setattr(de[i]->d_inode, attr);
183
          }
184
        }
185
 
186
        /* Change the catalog entry if needed */
187
        if (attr->ia_valid & ATTR_MTIME) {
188
                entry->modify_date = hfs_u_to_mtime(inode->i_mtime);
189
                hfs_cat_mark_dirty(entry);
190
        }
191
        if (attr->ia_valid & ATTR_MODE) {
192
                hfs_u8 new_flags;
193
 
194
                if (inode->i_mode & S_IWUSR) {
195
                        new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
196
                } else {
197
                        new_flags = entry->u.file.flags | HFS_FIL_LOCK;
198
                }
199
 
200
                if (new_flags != entry->u.file.flags) {
201
                        entry->u.file.flags = new_flags;
202
                        hfs_cat_mark_dirty(entry);
203
                }
204
        }
205
        /* size changes handled in hfs_extent_adj() */
206
 
207
        return 0;
208
}
209
 
210
int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
211
{
212
        return __hfs_notify_change(dentry, attr, HFS_NORM);
213
}
214
 
215
int hfs_notify_change_cap(struct dentry *dentry, struct iattr * attr)
216
{
217
        return __hfs_notify_change(dentry, attr, HFS_CAP);
218
}
219
 
220
int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
221
{
222
        return __hfs_notify_change(dentry, attr, HFS_HDR);
223
}
224
 
225
static int hfs_writepage(struct page *page)
226
{
227
        return block_write_full_page(page,hfs_get_block);
228
}
229
static int hfs_readpage(struct file *file, struct page *page)
230
{
231
        return block_read_full_page(page,hfs_get_block);
232
}
233
static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
234
{
235
        return cont_prepare_write(page,from,to,hfs_get_block,
236
                &page->mapping->host->u.hfs_i.mmu_private);
237
}
238
static int hfs_bmap(struct address_space *mapping, long block)
239
{
240
        return generic_block_bmap(mapping,block,hfs_get_block);
241
}
242
struct address_space_operations hfs_aops = {
243
        readpage: hfs_readpage,
244
        writepage: hfs_writepage,
245
        sync_page: block_sync_page,
246
        prepare_write: hfs_prepare_write,
247
        commit_write: generic_commit_write,
248
        bmap: hfs_bmap
249
};
250
 
251
/*
252
 * __hfs_iget()
253
 *
254
 * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in
255
 * the catalog B-tree and the 'type' of the desired file return the
256
 * inode for that file/directory or NULL.  Note that 'type' indicates
257
 * whether we want the actual file or directory, or the corresponding
258
 * metadata (AppleDouble header file or CAP metadata file).
259
 *
260
 * In an ideal world we could call iget() and would not need this
261
 * function.  However, since there is no way to even know the inode
262
 * number until we've found the file/directory in the catalog B-tree
263
 * that simply won't happen.
264
 *
265
 * The main idea here is to look in the catalog B-tree to get the
266
 * vital info about the file or directory (including the file id which
267
 * becomes the inode number) and then to call iget() and return the
268
 * inode if it is complete.  If it is not then we use the catalog
269
 * entry to fill in the missing info, by calling the appropriate
270
 * 'fillin' function.  Note that these fillin functions are
271
 * essentially hfs_*_read_inode() functions, but since there is no way
272
 * to pass the catalog entry through iget() to such a read_inode()
273
 * function, we have to call them after iget() returns an incomplete
274
 * inode to us.  This is pretty much the same problem faced in the NFS
275
 * code, and pretty much the same solution. The SMB filesystem deals
276
 * with this in a different way: by using the address of the
277
 * kmalloc()'d space which holds the data as the inode number.
278
 *
279
 * XXX: Both this function and NFS's corresponding nfs_fhget() would
280
 * benefit from a way to pass an additional (void *) through iget() to
281
 * the VFS read_inode() function.
282
 *
283
 * this will hfs_cat_put() the entry if it fails.
284
 */
285
struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
286
                       struct dentry *dentry)
287
{
288
        struct dentry **sys_entry;
289
        struct super_block *sb;
290
        struct inode *inode;
291
 
292
        if (!entry) {
293
                return NULL;
294
        }
295
 
296
        /* If there are several processes all calling __iget() for
297
           the same inode then they will all get the same one back.
298
           The first one to return from __iget() will notice that the
299
           i_mode field of the inode is blank and KNOW that it is
300
           the first to return.  Therefore, it will set the appropriate
301
           'sys_entry' field in the entry and initialize the inode.
302
           All the initialization must be done without sleeping,
303
           or else other processes could end up using a partially
304
           initialized inode.                           */
305
 
306
        sb = entry->mdb->sys_mdb;
307
        sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)];
308
 
309
        if (!(inode = iget(sb, ntohl(entry->cnid) | type))) {
310
                hfs_cat_put(entry);
311
                return NULL;
312
        }
313
 
314
        if (inode->i_dev != sb->s_dev) {
315
                iput(inode); /* automatically does an hfs_cat_put */
316
                inode = NULL;
317
        } else if (!inode->i_mode || (*sys_entry == NULL)) {
318
                /* Initialize the inode */
319
                struct hfs_sb_info *hsb = HFS_SB(sb);
320
 
321
                inode->i_rdev = 0;
322
                inode->i_ctime = inode->i_atime = inode->i_mtime =
323
                                        hfs_m_to_utime(entry->modify_date);
324
                inode->i_blksize = HFS_SECTOR_SIZE;
325
                inode->i_uid = hsb->s_uid;
326
                inode->i_gid = hsb->s_gid;
327
 
328
                memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info));
329
                HFS_I(inode)->magic = HFS_INO_MAGIC;
330
                HFS_I(inode)->entry = entry;
331
                HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
332
 
333
                hsb->s_ifill(inode, type, hsb->s_version);
334
                if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
335
                    (entry->u.file.flags & HFS_FIL_LOCK)) {
336
                        inode->i_mode &= ~S_IWUGO;
337
                }
338
                inode->i_mode &= ~hsb->s_umask;
339
 
340
                if (!inode->i_mode) {
341
                        iput(inode); /* does an hfs_cat_put */
342
                        inode = NULL;
343
                } else
344
                        *sys_entry = dentry; /* cache dentry */
345
 
346
        }
347
 
348
        return inode;
349
}
350
 
351
/*================ Scheme-specific functions ================*/
352
 
353
/*
354
 * hfs_cap_ifill()
355
 *
356
 * This function serves the same purpose as a read_inode() function does
357
 * in other filesystems.  It is called by __hfs_iget() to fill in
358
 * the missing fields of an uninitialized inode under the CAP scheme.
359
 */
360
void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
361
{
362
        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
363
 
364
        HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry;
365
        if (type == HFS_CAP_FNDR) {
366
                inode->i_size = sizeof(struct hfs_cap_info);
367
                inode->i_blocks = 0;
368
                inode->i_nlink = 1;
369
                inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
370
                inode->i_op = &hfs_cap_info_inode_operations;
371
                inode->i_fop = &hfs_cap_info_operations;
372
        } else if (entry->type == HFS_CDR_FIL) {
373
                init_file_inode(inode, (type == HFS_CAP_DATA) ?
374
                                                HFS_FK_DATA : HFS_FK_RSRC);
375
                inode->i_op = &hfs_file_inode_operations;
376
                inode->i_fop = &hfs_file_operations;
377
                inode->i_mapping->a_ops = &hfs_aops;
378
                inode->u.hfs_i.mmu_private = inode->i_size;
379
        } else { /* Directory */
380
                struct hfs_dir *hdir = &entry->u.dir;
381
 
382
                inode->i_blocks = 0;
383
                inode->i_size = hdir->files + hdir->dirs + 5;
384
                HFS_I(inode)->dir_size = 1;
385
                if (type == HFS_CAP_NDIR) {
386
                        inode->i_mode = S_IRWXUGO | S_IFDIR;
387
                        inode->i_nlink = hdir->dirs + 4;
388
                        inode->i_op = &hfs_cap_ndir_inode_operations;
389
                        inode->i_fop = &hfs_cap_dir_operations;
390
                        HFS_I(inode)->file_type = HFS_CAP_NORM;
391
                } else if (type == HFS_CAP_FDIR) {
392
                        inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
393
                        inode->i_nlink = 2;
394
                        inode->i_op = &hfs_cap_fdir_inode_operations;
395
                        inode->i_fop = &hfs_cap_dir_operations;
396
                        HFS_I(inode)->file_type = HFS_CAP_FNDR;
397
                } else if (type == HFS_CAP_RDIR) {
398
                        inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
399
                        inode->i_nlink = 2;
400
                        inode->i_op = &hfs_cap_rdir_inode_operations;
401
                        inode->i_fop = &hfs_cap_dir_operations;
402
                        HFS_I(inode)->file_type = HFS_CAP_RSRC;
403
                }
404
        }
405
}
406
 
407
/*
408
 * hfs_dbl_ifill()
409
 *
410
 * This function serves the same purpose as a read_inode() function does
411
 * in other filesystems.  It is called by __hfs_iget() to fill in
412
 * the missing fields of an uninitialized inode under the AppleDouble
413
 * scheme.
414
 */
415
void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
416
{
417
        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
418
 
419
        HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry;
420
        if (type == HFS_DBL_HDR) {
421
                if (entry->type == HFS_CDR_FIL) {
422
                        init_file_inode(inode, HFS_FK_RSRC);
423
                        inode->i_size += HFS_DBL_HDR_LEN;
424
                        HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout;
425
                } else {
426
                        inode->i_size = HFS_DBL_HDR_LEN;
427
                        inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
428
                        inode->i_nlink = 1;
429
                        HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout;
430
                }
431
                inode->i_op = &hfs_hdr_inode_operations;
432
                inode->i_fop = &hfs_hdr_operations;
433
        } else if (entry->type == HFS_CDR_FIL) {
434
                init_file_inode(inode, HFS_FK_DATA);
435
                inode->i_op = &hfs_file_inode_operations;
436
                inode->i_fop = &hfs_file_operations;
437
                inode->i_mapping->a_ops = &hfs_aops;
438
                inode->u.hfs_i.mmu_private = inode->i_size;
439
        } else { /* Directory */
440
                struct hfs_dir *hdir = &entry->u.dir;
441
 
442
                inode->i_blocks = 0;
443
                inode->i_nlink = hdir->dirs + 2;
444
                inode->i_size = 3 + 2 * (hdir->dirs + hdir->files);
445
                inode->i_mode = S_IRWXUGO | S_IFDIR;
446
                inode->i_op = &hfs_dbl_dir_inode_operations;
447
                inode->i_fop = &hfs_dbl_dir_operations;
448
                HFS_I(inode)->file_type = HFS_DBL_NORM;
449
                HFS_I(inode)->dir_size = 2;
450
        }
451
}
452
 
453
/*
454
 * hfs_nat_ifill()
455
 *
456
 * This function serves the same purpose as a read_inode() function does
457
 * in other filesystems.  It is called by __hfs_iget() to fill in
458
 * the missing fields of an uninitialized inode under the Netatalk
459
 * scheme.
460
 */
461
void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
462
{
463
        struct hfs_cat_entry *entry = HFS_I(inode)->entry;
464
 
465
        HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry;
466
        if (type == HFS_NAT_HDR) {
467
                if (entry->type == HFS_CDR_FIL) {
468
                        init_file_inode(inode, HFS_FK_RSRC);
469
                        inode->i_size += HFS_NAT_HDR_LEN;
470
                } else {
471
                        inode->i_size = HFS_NAT_HDR_LEN;
472
                        inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
473
                        inode->i_nlink = 1;
474
                }
475
                inode->i_op = &hfs_hdr_inode_operations;
476
                inode->i_fop = &hfs_hdr_operations;
477
                HFS_I(inode)->default_layout = (version == 2) ?
478
                        &hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
479
        } else if (entry->type == HFS_CDR_FIL) {
480
                init_file_inode(inode, HFS_FK_DATA);
481
                inode->i_op = &hfs_file_inode_operations;
482
                inode->i_fop = &hfs_file_operations;
483
                inode->i_mapping->a_ops = &hfs_aops;
484
                inode->u.hfs_i.mmu_private = inode->i_size;
485
        } else { /* Directory */
486
                struct hfs_dir *hdir = &entry->u.dir;
487
 
488
                inode->i_blocks = 0;
489
                inode->i_size = hdir->files + hdir->dirs + 4;
490
                inode->i_mode = S_IRWXUGO | S_IFDIR;
491
                HFS_I(inode)->dir_size = 1;
492
                if (type == HFS_NAT_NDIR) {
493
                        inode->i_nlink = hdir->dirs + 3;
494
                        inode->i_op = &hfs_nat_ndir_inode_operations;
495
                        HFS_I(inode)->file_type = HFS_NAT_NORM;
496
                } else if (type == HFS_NAT_HDIR) {
497
                        inode->i_nlink = 2;
498
                        inode->i_op = &hfs_nat_hdir_inode_operations;
499
                        HFS_I(inode)->file_type = HFS_NAT_HDR;
500
                }
501
                inode->i_fop = &hfs_nat_dir_operations;
502
        }
503
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.