2 * linux/fs/hfs/file_hdr.c
4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU Public License.
7 * This file contains the file_ops and inode_ops for the metadata
8 * files under the AppleDouble and Netatalk representations.
10 * The source code distributions of Netatalk, versions 1.3.3b2 and
11 * 1.4b2, were used as a specification of the location and format of
12 * files used by Netatalk's afpd. No code from Netatalk appears in
13 * hfs_fs. hfs_fs is not a work ``derived'' from Netatalk in the
14 * sense of intellectual property law.
16 * "XXX" in a comment is a note to myself to consider changing something.
18 * In function preconditions the term "valid" applied to a pointer to
19 * a structure means that the pointer is non-NULL and the structure it
20 * points to has all fields initialized to consistent values.
22 * XXX: Note the reason that there is not bmap() for AppleDouble
23 * header files is that dynamic nature of their structure make it
24 * very difficult to safely mmap them. Maybe in the distant future
25 * I'll get bored enough to implement it.
29 #include <linux/hfs_fs_sb.h>
30 #include <linux/hfs_fs_i.h>
31 #include <linux/hfs_fs.h>
33 /*================ Forward declarations ================*/
35 static hfs_rwret_t
hdr_read(struct file
*, char *, hfs_rwarg_t
, loff_t
*);
36 static hfs_rwret_t
hdr_write(struct file
*, const char *,
37 hfs_rwarg_t
, loff_t
*);
38 static void hdr_truncate(struct inode
*);
40 /*================ Global variables ================*/
42 static struct file_operations hfs_hdr_operations
= {
43 NULL
, /* lseek - default */
45 hdr_write
, /* write */
46 NULL
, /* readdir - bad */
47 NULL
, /* select - default */
48 NULL
, /* ioctl - default */
49 NULL
, /* mmap - XXX: not yet */
50 NULL
, /* no special open code */
52 NULL
, /* no special release code */
53 file_fsync
, /* fsync - default */
54 NULL
, /* fasync - default */
55 NULL
, /* check_media_change - none */
56 NULL
, /* revalidate - none */
57 NULL
/* lock - none */
60 struct inode_operations hfs_hdr_inode_operations
= {
61 &hfs_hdr_operations
, /* default file operations */
72 NULL
, /* follow_link */
75 NULL
, /* bmap - XXX: not available since
76 header part has no disk block */
77 hdr_truncate
, /* truncate */
78 NULL
, /* permission */
80 NULL
, /* updatepage */
84 const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout
= {
85 __constant_htonl(HFS_DBL_MAGIC
), /* magic */
86 __constant_htonl(HFS_HDR_VERSION_2
), /* version */
89 {HFS_HDR_DATES
, offsetof(struct hfs_dbl_hdr
, create_time
), 16},
90 {HFS_HDR_FINFO
, offsetof(struct hfs_dbl_hdr
, finderinfo
), 32},
91 {HFS_HDR_MACI
, offsetof(struct hfs_dbl_hdr
, fileinfo
), 4},
92 {HFS_HDR_FNAME
, offsetof(struct hfs_dbl_hdr
, real_name
), ~0},
93 {HFS_HDR_RSRC
, HFS_DBL_HDR_LEN
, ~0},
96 (struct hfs_hdr_descr
*)&hfs_dbl_fil_hdr_layout
.descr
[0],
97 (struct hfs_hdr_descr
*)&hfs_dbl_fil_hdr_layout
.descr
[1],
98 (struct hfs_hdr_descr
*)&hfs_dbl_fil_hdr_layout
.descr
[2],
99 (struct hfs_hdr_descr
*)&hfs_dbl_fil_hdr_layout
.descr
[3],
100 (struct hfs_hdr_descr
*)&hfs_dbl_fil_hdr_layout
.descr
[4],
104 const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout
= {
105 __constant_htonl(HFS_DBL_MAGIC
), /* magic */
106 __constant_htonl(HFS_HDR_VERSION_2
), /* version */
109 {HFS_HDR_DATES
, offsetof(struct hfs_dbl_hdr
, create_time
), 16},
110 {HFS_HDR_FINFO
, offsetof(struct hfs_dbl_hdr
, finderinfo
), 32},
111 {HFS_HDR_MACI
, offsetof(struct hfs_dbl_hdr
, fileinfo
), 4},
112 {HFS_HDR_FNAME
, offsetof(struct hfs_dbl_hdr
, real_name
), ~0},
115 (struct hfs_hdr_descr
*)&hfs_dbl_dir_hdr_layout
.descr
[0],
116 (struct hfs_hdr_descr
*)&hfs_dbl_dir_hdr_layout
.descr
[1],
117 (struct hfs_hdr_descr
*)&hfs_dbl_dir_hdr_layout
.descr
[2],
118 (struct hfs_hdr_descr
*)&hfs_dbl_dir_hdr_layout
.descr
[3],
122 const struct hfs_hdr_layout hfs_nat_hdr_layout
= {
123 __constant_htonl(HFS_DBL_MAGIC
), /* magic */
124 __constant_htonl(HFS_HDR_VERSION_1
), /* version */
127 {HFS_HDR_RSRC
, HFS_NAT_HDR_LEN
, ~0},
128 {HFS_HDR_FNAME
, offsetof(struct hfs_nat_hdr
, real_name
), ~0},
129 {HFS_HDR_COMNT
, offsetof(struct hfs_nat_hdr
, comment
), 0},
130 {HFS_HDR_OLDI
, offsetof(struct hfs_nat_hdr
, create_time
), 16},
131 {HFS_HDR_FINFO
, offsetof(struct hfs_nat_hdr
, finderinfo
), 32},
134 (struct hfs_hdr_descr
*)&hfs_nat_hdr_layout
.descr
[1],
135 (struct hfs_hdr_descr
*)&hfs_nat_hdr_layout
.descr
[2],
136 (struct hfs_hdr_descr
*)&hfs_nat_hdr_layout
.descr
[3],
137 (struct hfs_hdr_descr
*)&hfs_nat_hdr_layout
.descr
[4],
138 (struct hfs_hdr_descr
*)&hfs_nat_hdr_layout
.descr
[0],
142 /*================ File-local variables ================*/
144 static const char fstype
[16] =
145 {'M','a','c','i','n','t','o','s','h',' ',' ',' ',' ',' ',' ',' '};
147 /*================ File-local data types ================*/
152 hfs_byte_t filler
[16];
154 hfs_byte_t descrs
[12*HFS_HDR_MAX
];
157 /*================ File-local functions ================*/
162 static int dlength(const struct hfs_hdr_descr
*descr
,
163 const struct hfs_cat_entry
*entry
)
165 hfs_u32 length
= descr
->length
;
167 /* handle auto-sized entries */
171 if (entry
->type
== HFS_CDR_FIL
) {
172 length
= entry
->u
.file
.data_fork
.lsize
;
179 if (entry
->type
== HFS_CDR_FIL
) {
180 length
= entry
->u
.file
.rsrc_fork
.lsize
;
187 length
= entry
->key
.CName
.Len
;
200 static void hdr_build_meta(struct hdr_hdr
*meta
,
201 const struct hfs_hdr_layout
*layout
,
202 const struct hfs_cat_entry
*entry
)
204 const struct hfs_hdr_descr
*descr
;
208 hfs_put_nl(layout
->magic
, meta
->magic
);
209 hfs_put_nl(layout
->version
, meta
->version
);
210 if (layout
->version
== htonl(HFS_HDR_VERSION_1
)) {
211 memcpy(meta
->filler
, fstype
, 16);
213 memset(meta
->filler
, 0, 16);
215 hfs_put_hs(layout
->entries
, meta
->entries
);
216 memset(meta
->descrs
, 0, sizeof(meta
->descrs
));
217 for (lcv
= 0, descr
= layout
->descr
, ptr
= meta
->descrs
;
218 lcv
< layout
->entries
; ++lcv
, ++descr
, ptr
+= 12) {
219 hfs_put_hl(descr
->id
, ptr
);
220 hfs_put_hl(descr
->offset
, ptr
+ 4);
221 hfs_put_hl(dlength(descr
, entry
), ptr
+ 8);
228 static struct hfs_hdr_layout
*dup_layout(const struct hfs_hdr_layout
*old
)
230 struct hfs_hdr_layout
*new;
234 memcpy(new, old
, sizeof(*new));
235 for (lcv
= 0; lcv
< new->entries
; ++lcv
) {
236 (char *)(new->order
[lcv
]) += (char *)new - (char *)old
;
245 static inline void init_layout(struct hfs_hdr_layout
*layout
,
246 const hfs_byte_t
*descrs
)
248 struct hfs_hdr_descr
**base
, **p
, **q
, *tmp
;
249 int lcv
, entries
= layout
->entries
;
251 for (lcv
= 0; lcv
< entries
; ++lcv
, descrs
+= 12) {
252 layout
->order
[lcv
] = &layout
->descr
[lcv
];
253 layout
->descr
[lcv
].id
= hfs_get_hl(descrs
);
254 layout
->descr
[lcv
].offset
= hfs_get_hl(descrs
+ 4);
255 layout
->descr
[lcv
].length
= hfs_get_hl(descrs
+ 8);
257 for (lcv
= layout
->entries
; lcv
< HFS_HDR_MAX
; ++lcv
) {
258 layout
->order
[lcv
] = NULL
;
259 layout
->descr
[lcv
].id
= 0;
260 layout
->descr
[lcv
].offset
= 0;
261 layout
->descr
[lcv
].length
= 0;
264 /* Sort the 'order' array using an insertion sort */
265 base
= &layout
->order
[0];
266 for (p
= (base
+1); p
< (base
+entries
); ++p
) {
268 while ((*q
)->offset
< (*(q
-1))->offset
) {
272 if (q
== base
) break;
280 static inline void adjust_forks(struct hfs_cat_entry
*entry
,
281 const struct hfs_hdr_layout
*layout
)
285 for (lcv
= 0; lcv
< layout
->entries
; ++lcv
) {
286 const struct hfs_hdr_descr
*descr
= &layout
->descr
[lcv
];
288 if ((descr
->id
== HFS_HDR_DATA
) &&
289 (descr
->length
!= entry
->u
.file
.data_fork
.lsize
)) {
290 entry
->u
.file
.data_fork
.lsize
= descr
->length
;
291 hfs_extent_adj(&entry
->u
.file
.data_fork
);
292 } else if ((descr
->id
== HFS_HDR_RSRC
) &&
293 (descr
->length
!= entry
->u
.file
.rsrc_fork
.lsize
)) {
294 entry
->u
.file
.rsrc_fork
.lsize
= descr
->length
;
295 hfs_extent_adj(&entry
->u
.file
.rsrc_fork
);
303 static void get_dates(const struct hfs_cat_entry
*entry
,
304 const struct inode
*inode
, hfs_u32 dates
[3])
306 if (HFS_SB(inode
->i_sb
)->s_afpd
) {
307 /* AFPD compatible: use un*x times */
308 dates
[0] = htonl(hfs_m_to_utime(entry
->create_date
));
309 dates
[1] = htonl(hfs_m_to_utime(entry
->modify_date
));
310 dates
[2] = htonl(hfs_m_to_utime(entry
->backup_date
));
312 dates
[0] = hfs_m_to_htime(entry
->create_date
);
313 dates
[1] = hfs_m_to_htime(entry
->modify_date
);
314 dates
[2] = hfs_m_to_htime(entry
->backup_date
);
321 static void set_dates(struct hfs_cat_entry
*entry
, struct inode
*inode
,
322 const hfs_u32
*dates
)
325 if (HFS_SB(inode
->i_sb
)->s_afpd
) {
326 /* AFPD compatible: use un*x times */
327 tmp
= hfs_u_to_mtime(ntohl(dates
[0]));
328 if (entry
->create_date
!= tmp
) {
329 entry
->create_date
= tmp
;
330 hfs_cat_mark_dirty(entry
);
332 tmp
= hfs_u_to_mtime(ntohl(dates
[1]));
333 if (entry
->modify_date
!= tmp
) {
334 entry
->modify_date
= tmp
;
335 inode
->i_ctime
= inode
->i_atime
= inode
->i_mtime
=
337 hfs_cat_mark_dirty(entry
);
339 tmp
= hfs_u_to_mtime(ntohl(dates
[2]));
340 if (entry
->backup_date
!= tmp
) {
341 entry
->backup_date
= tmp
;
342 hfs_cat_mark_dirty(entry
);
345 tmp
= hfs_h_to_mtime(dates
[0]);
346 if (entry
->create_date
!= tmp
) {
347 entry
->create_date
= tmp
;
348 hfs_cat_mark_dirty(entry
);
350 tmp
= hfs_h_to_mtime(dates
[1]);
351 if (entry
->modify_date
!= tmp
) {
352 entry
->modify_date
= tmp
;
353 inode
->i_ctime
= inode
->i_atime
= inode
->i_mtime
=
354 hfs_h_to_utime(dates
[1]);
355 hfs_cat_mark_dirty(entry
);
357 tmp
= hfs_h_to_mtime(dates
[2]);
358 if (entry
->backup_date
!= tmp
) {
359 entry
->backup_date
= tmp
;
360 hfs_cat_mark_dirty(entry
);
368 * This is the read field in the inode_operations structure for
369 * header files. The purpose is to transfer up to 'count' bytes
370 * from the file corresponding to 'inode', beginning at
371 * 'filp->offset' bytes into the file. The data is transfered to
372 * user-space at the address 'buf'. Returns the number of bytes
373 * successfully transfered.
375 /* XXX: what about the entry count changing on us? */
376 static hfs_rwret_t
hdr_read(struct file
* filp
, char * buf
,
377 hfs_rwarg_t count
, loff_t
*ppos
)
379 struct inode
*inode
= filp
->f_dentry
->d_inode
;
380 struct hfs_cat_entry
*entry
= HFS_I(inode
)->entry
;
381 const struct hfs_hdr_layout
*layout
;
382 off_t start
, length
, offset
;
384 int left
, lcv
, read
= 0;
386 if (!S_ISREG(inode
->i_mode
)) {
387 hfs_warn("hfs_hdr_read: mode = %07o\n",inode
->i_mode
);
391 if (HFS_I(inode
)->layout
) {
392 layout
= HFS_I(inode
)->layout
;
394 layout
= HFS_I(inode
)->default_layout
;
397 /* Adjust count to fit within the bounds of the file */
398 if ((pos
>= inode
->i_size
) || (count
<= 0)) {
400 } else if (count
> inode
->i_size
- pos
) {
401 count
= inode
->i_size
- pos
;
404 /* Handle the fixed-location portion */
405 length
= sizeof(hfs_u32
) + sizeof(hfs_u32
) + 16 +
406 sizeof(hfs_u16
) + layout
->entries
* (3 * sizeof(hfs_u32
));
415 hdr_build_meta(&meta
, layout
, entry
);
416 left
-= copy_to_user(buf
, ((char *)&meta
) + pos
, left
);
426 /* Handle the actual data */
427 for (lcv
= 0; count
&& (lcv
< layout
->entries
); ++lcv
) {
428 const struct hfs_hdr_descr
*descr
= layout
->order
[lcv
];
429 struct hfs_fork
*fork
;
433 /* stop reading if we run out of descriptors early */
438 /* find start and length of this entry */
439 start
= descr
->offset
;
440 length
= dlength(descr
, entry
);
442 /* Skip to next entry if this one is empty or isn't needed */
443 if (!length
|| (pos
>= start
+ length
)) {
447 /* Pad with zeros to the start of this entry if needed */
453 clear_user(buf
, left
);
463 /* locate and/or construct the data for this entry */
468 fork
= &entry
->u
.file
.data_fork
;
473 fork
= &entry
->u
.file
.rsrc_fork
;
478 p
= entry
->key
.CName
.Name
;
479 limit
= entry
->key
.CName
.Len
;
484 get_dates(entry
, inode
, (hfs_u32
*)tmp
);
485 if (descr
->id
== HFS_HDR_DATES
) {
486 memcpy(tmp
+ 12, tmp
+ 4, 4);
487 } else if ((entry
->type
== HFS_CDR_FIL
) &&
488 (entry
->u
.file
.flags
& HFS_FIL_LOCK
)) {
489 hfs_put_hl(HFS_AFP_RDONLY
, tmp
+ 12);
491 hfs_put_nl(0, tmp
+ 12);
498 p
= (char *)&entry
->info
;
504 if (entry
->type
== HFS_CDR_FIL
) {
505 hfs_put_hs(entry
->u
.file
.flags
, tmp
+ 2);
507 hfs_put_ns(entry
->u
.dir
.flags
, tmp
+ 2);
517 /* limit the transfer to the available data
518 of to the stated length of the entry. */
519 if (length
> limit
) {
522 offset
= pos
- start
;
523 left
= length
- offset
;
531 /* transfer the data */
533 left
-= copy_to_user(buf
, p
+ offset
, left
);
535 left
= hfs_do_read(inode
, fork
, offset
, buf
, left
,
551 /* Pad the file out with zeros */
553 clear_user(buf
, count
);
560 inode
->i_atime
= CURRENT_TIME
;
569 * This is the write() entry in the file_operations structure for
570 * header files. The purpose is to transfer up to 'count' bytes
571 * to the file corresponding to 'inode' beginning at offset
572 * '*ppos' from user-space at the address 'buf'.
573 * The return value is the number of bytes actually transferred.
575 static hfs_rwret_t
hdr_write(struct file
*filp
, const char *buf
,
576 hfs_rwarg_t count
, loff_t
*ppos
)
578 struct inode
*inode
= filp
->f_dentry
->d_inode
;
579 struct hfs_cat_entry
*entry
= HFS_I(inode
)->entry
;
580 struct hfs_hdr_layout
*layout
;
581 off_t start
, length
, offset
;
582 int left
, lcv
, written
= 0;
587 if (!S_ISREG(inode
->i_mode
)) {
588 hfs_warn("hfs_hdr_write: mode = %07o\n", inode
->i_mode
);
595 pos
= (filp
->f_flags
& O_APPEND
) ? inode
->i_size
: *ppos
;
597 if (!HFS_I(inode
)->layout
) {
598 HFS_I(inode
)->layout
= dup_layout(HFS_I(inode
)->default_layout
);
600 layout
= HFS_I(inode
)->layout
;
602 /* Handle the 'magic', 'version', 'filler' and 'entries' fields */
603 length
= sizeof(hfs_u32
) + sizeof(hfs_u32
) + 16 + sizeof(hfs_u16
);
605 hdr_build_meta(&meta
, layout
, entry
);
613 copy_from_user(((char *)&meta
) + pos
, buf
, left
);
614 layout
->magic
= hfs_get_nl(meta
.magic
);
615 layout
->version
= hfs_get_nl(meta
.version
);
616 layout
->entries
= hfs_get_hs(meta
.entries
);
617 if (layout
->entries
> HFS_HDR_MAX
) {
618 /* XXX: should allocate slots dynamically */
619 hfs_warn("hfs_hdr_write: TRUNCATING TO %d "
620 "DESCRIPTORS\n", HFS_HDR_MAX
);
621 layout
->entries
= HFS_HDR_MAX
;
633 /* We know for certain how many entries we have, so process them */
634 length
+= layout
->entries
* 3 * sizeof(hfs_u32
);
637 hdr_build_meta(&meta
, layout
, entry
);
645 copy_from_user(((char *)&meta
) + pos
, buf
, left
);
646 init_layout(layout
, meta
.descrs
);
653 /* Handle possible size changes for the forks */
654 if (entry
->type
== HFS_CDR_FIL
) {
655 adjust_forks(entry
, layout
);
656 hfs_cat_mark_dirty(entry
);
660 /* Handle the actual data */
661 for (lcv
= 0; count
&& (lcv
< layout
->entries
); ++lcv
) {
662 struct hfs_hdr_descr
*descr
= layout
->order
[lcv
];
663 struct hfs_fork
*fork
;
667 /* stop writing if we run out of descriptors early */
672 /* find start and length of this entry */
673 start
= descr
->offset
;
674 if ((descr
->id
== HFS_HDR_DATA
) ||
675 (descr
->id
== HFS_HDR_RSRC
)) {
676 if (entry
->type
== HFS_CDR_FIL
) {
677 length
= 0x7fffffff - start
;
682 length
= dlength(descr
, entry
);
685 /* Trim length to avoid overlap with the next entry */
686 if (layout
->order
[lcv
+1] &&
687 ((start
+ length
) > layout
->order
[lcv
+1]->offset
)) {
688 length
= layout
->order
[lcv
+1]->offset
- start
;
691 /* Skip to next entry if this one is empty or isn't needed */
692 if (!length
|| (pos
>= start
+ length
)) {
696 /* Skip any padding that may exist between entries */
711 /* locate and/or construct the data for this entry */
717 /* Can't yet write to the data fork via a header file, since there is the
718 * possibility to write via the data file, and the only locking is at the
721 fork
= &entry
->u
.file
.data_fork
;
729 fork
= &entry
->u
.file
.rsrc_fork
;
735 get_dates(entry
, inode
, (hfs_u32
*)tmp
);
736 if (descr
->id
== HFS_HDR_DATES
) {
737 memcpy(tmp
+ 12, tmp
+ 4, 4);
738 } else if ((entry
->type
== HFS_CDR_FIL
) &&
739 (entry
->u
.file
.flags
& HFS_FIL_LOCK
)) {
740 hfs_put_hl(HFS_AFP_RDONLY
, tmp
+ 12);
742 hfs_put_nl(0, tmp
+ 12);
749 p
= (char *)&entry
->info
;
755 if (entry
->type
== HFS_CDR_FIL
) {
756 hfs_put_hs(entry
->u
.file
.flags
, tmp
+ 2);
758 hfs_put_ns(entry
->u
.dir
.flags
, tmp
+ 2);
764 case HFS_HDR_FNAME
: /* Can't rename a file this way */
769 /* limit the transfer to the available data
770 of to the stated length of the entry. */
771 if (length
> limit
) {
774 offset
= pos
- start
;
775 left
= length
- offset
;
783 /* transfer the data from user space */
785 copy_from_user(p
+ offset
, buf
, left
);
787 left
= hfs_do_write(inode
, fork
, offset
, buf
, left
);
790 /* process the data */
793 set_dates(entry
, inode
, (hfs_u32
*)tmp
);
794 if (entry
->type
== HFS_CDR_FIL
) {
795 hfs_u8 new_flags
= entry
->u
.file
.flags
;
797 if (hfs_get_nl(tmp
+12) & htonl(HFS_AFP_WRI
)) {
798 new_flags
|= HFS_FIL_LOCK
;
800 new_flags
&= ~HFS_FIL_LOCK
;
803 if (new_flags
!= entry
->u
.file
.flags
) {
804 entry
->u
.file
.flags
= new_flags
;
805 hfs_cat_mark_dirty(entry
);
806 hfs_file_fix_mode(entry
);
812 set_dates(entry
, inode
, (hfs_u32
*)tmp
);
816 hfs_cat_mark_dirty(entry
);
820 if (entry
->type
== HFS_CDR_DIR
) {
821 hfs_u16 new_flags
= hfs_get_ns(tmp
+ 2);
823 if (entry
->u
.dir
.flags
!= new_flags
) {
824 entry
->u
.dir
.flags
= new_flags
;
825 hfs_cat_mark_dirty(entry
);
828 hfs_u8 new_flags
= tmp
[3];
829 hfs_u8 changed
= entry
->u
.file
.flags
^new_flags
;
832 entry
->u
.file
.flags
= new_flags
;
833 hfs_cat_mark_dirty(entry
);
834 if (changed
& HFS_FIL_LOCK
) {
835 hfs_file_fix_mode(entry
);
849 } else if (fork
->lsize
> descr
->length
) {
850 descr
->length
= fork
->lsize
;
854 case HFS_HDR_FNAME
: /* Can't rename a file this way */
865 /* Skip any padding at the end */
874 if (pos
> inode
->i_size
)
876 inode
->i_mtime
= inode
->i_atime
= CURRENT_TIME
;
884 * This is the truncate field in the inode_operations structure for
885 * header files. The purpose is to allocate or release blocks as needed
886 * to satisfy a change in file length.
888 static void hdr_truncate(struct inode
*inode
)
890 /*struct inode *inode = dentry->d_inode;*/
891 struct hfs_cat_entry
*entry
= HFS_I(inode
)->entry
;
892 struct hfs_hdr_layout
*layout
;
893 size_t size
= inode
->i_size
;
896 if (!HFS_I(inode
)->layout
) {
897 HFS_I(inode
)->layout
= dup_layout(HFS_I(inode
)->default_layout
);
899 layout
= HFS_I(inode
)->layout
;
901 last
= layout
->entries
- 1;
902 for (lcv
= 0; lcv
<= last
; ++lcv
) {
903 struct hfs_hdr_descr
*descr
= layout
->order
[lcv
];
904 struct hfs_fork
*fork
;
911 if (descr
->id
== HFS_HDR_RSRC
) {
912 fork
= &entry
->u
.file
.rsrc_fork
;
914 /* Can't yet truncate the data fork via a header file, since there is the
915 * possibility to truncate via the data file, and the only locking is at
918 } else if (descr
->id
== HFS_HDR_DATA
) {
919 fork
= &entry
->u
.file
.data_fork
;
925 offset
= descr
->offset
;
927 if ((lcv
!= last
) && ((offset
+ descr
->length
) <= size
)) {
932 descr
->length
= size
- offset
;
936 if (fork
->lsize
!= descr
->length
) {
937 fork
->lsize
= descr
->length
;
938 hfs_extent_adj(fork
);
939 hfs_cat_mark_dirty(HFS_I(inode
)->entry
);