Import 2.1.118
[davej-history.git] / fs / hfs / file_hdr.c
blobb12a4606b3d5d8210a274f520a0447dadaa228ca
1 /*
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.
28 #include "hfs.h"
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 */
44 hdr_read, /* read */
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 */
51 NULL, /* flush */
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 */
62 NULL, /* create */
63 NULL, /* lookup */
64 NULL, /* link */
65 NULL, /* unlink */
66 NULL, /* symlink */
67 NULL, /* mkdir */
68 NULL, /* rmdir */
69 NULL, /* mknod */
70 NULL, /* rename */
71 NULL, /* readlink */
72 NULL, /* follow_link */
73 NULL, /* readpage */
74 NULL, /* writepage */
75 NULL, /* bmap - XXX: not available since
76 header part has no disk block */
77 hdr_truncate, /* truncate */
78 NULL, /* permission */
79 NULL, /* smap */
80 NULL, /* updatepage */
81 NULL /* revalidate */
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 */
87 5, /* entries */
88 { /* descr[] */
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},
95 { /* order[] */
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 */
107 4, /* entries */
108 { /* descr[] */
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},
114 { /* order[] */
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 */
125 5, /* entries */
126 { /* descr[] */
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},
133 { /* order[] */
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 ================*/
149 struct hdr_hdr {
150 hfs_lword_t magic;
151 hfs_lword_t version;
152 hfs_byte_t filler[16];
153 hfs_word_t entries;
154 hfs_byte_t descrs[12*HFS_HDR_MAX];
157 /*================ File-local functions ================*/
160 * dlength()
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 */
168 if (length == ~0) {
169 switch (descr->id) {
170 case HFS_HDR_DATA:
171 if (entry->type == HFS_CDR_FIL) {
172 length = entry->u.file.data_fork.lsize;
173 } else {
174 length = 0;
176 break;
178 case HFS_HDR_RSRC:
179 if (entry->type == HFS_CDR_FIL) {
180 length = entry->u.file.rsrc_fork.lsize;
181 } else {
182 length = 0;
184 break;
186 case HFS_HDR_FNAME:
187 length = entry->key.CName.Len;
188 break;
190 default:
191 length = 0;
194 return length;
198 * hdr_build_meta()
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;
205 hfs_byte_t *ptr;
206 int lcv;
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);
212 } else {
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);
226 * dup_layout ()
228 static struct hfs_hdr_layout *dup_layout(const struct hfs_hdr_layout *old)
230 struct hfs_hdr_layout *new;
231 int lcv;
233 if (HFS_NEW(new)) {
234 memcpy(new, old, sizeof(*new));
235 for (lcv = 0; lcv < new->entries; ++lcv) {
236 (char *)(new->order[lcv]) += (char *)new - (char *)old;
239 return new;
243 * init_layout()
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) {
267 q=p;
268 while ((*q)->offset < (*(q-1))->offset) {
269 tmp = *q;
270 *q = *(q-1);
271 *(--q) = tmp;
272 if (q == base) break;
278 * adjust_forks()
280 static inline void adjust_forks(struct hfs_cat_entry *entry,
281 const struct hfs_hdr_layout *layout)
283 int lcv;
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);
301 * get_dates()
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));
311 } else {
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);
319 * set_dates()
321 static void set_dates(struct hfs_cat_entry *entry, struct inode *inode,
322 const hfs_u32 *dates)
324 hfs_u32 tmp;
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 =
336 ntohl(dates[1]);
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);
344 } else {
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);
366 * hdr_read()
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;
383 off_t pos = *ppos;
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);
388 return -EINVAL;
391 if (HFS_I(inode)->layout) {
392 layout = HFS_I(inode)->layout;
393 } else {
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)) {
399 return 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));
407 if (pos < length) {
408 struct hdr_hdr meta;
410 left = length - pos;
411 if (left > count) {
412 left = count;
415 hdr_build_meta(&meta, layout, entry);
416 left -= copy_to_user(buf, ((char *)&meta) + pos, left);
417 count -= left;
418 read += left;
419 pos += left;
420 buf += left;
422 if (!count) {
423 goto done;
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;
430 char tmp[16], *p;
431 off_t limit;
433 /* stop reading if we run out of descriptors early */
434 if (!descr) {
435 break;
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)) {
444 continue;
447 /* Pad with zeros to the start of this entry if needed */
448 if (pos < start) {
449 left = start - pos;
450 if (left > count) {
451 left = count;
453 clear_user(buf, left);
454 count -= left;
455 read += left;
456 pos += left;
457 buf += left;
459 if (!count) {
460 goto done;
463 /* locate and/or construct the data for this entry */
464 fork = NULL;
465 p = NULL;
466 switch (descr->id) {
467 case HFS_HDR_DATA:
468 fork = &entry->u.file.data_fork;
469 limit = fork->lsize;
470 break;
472 case HFS_HDR_RSRC:
473 fork = &entry->u.file.rsrc_fork;
474 limit = fork->lsize;
475 break;
477 case HFS_HDR_FNAME:
478 p = entry->key.CName.Name;
479 limit = entry->key.CName.Len;
480 break;
482 case HFS_HDR_OLDI:
483 case HFS_HDR_DATES:
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);
490 } else {
491 hfs_put_nl(0, tmp + 12);
493 p = tmp;
494 limit = 16;
495 break;
497 case HFS_HDR_FINFO:
498 p = (char *)&entry->info;
499 limit = 32;
500 break;
502 case HFS_HDR_MACI:
503 hfs_put_ns(0, tmp);
504 if (entry->type == HFS_CDR_FIL) {
505 hfs_put_hs(entry->u.file.flags, tmp + 2);
506 } else {
507 hfs_put_ns(entry->u.dir.flags, tmp + 2);
509 p = tmp;
510 limit = 4;
511 break;
513 default:
514 limit = 0;
517 /* limit the transfer to the available data
518 of to the stated length of the entry. */
519 if (length > limit) {
520 length = limit;
522 offset = pos - start;
523 left = length - offset;
524 if (left > count) {
525 left = count;
527 if (left <= 0) {
528 continue;
531 /* transfer the data */
532 if (p) {
533 left -= copy_to_user(buf, p + offset, left);
534 } else if (fork) {
535 left = hfs_do_read(inode, fork, offset, buf, left,
536 filp->f_reada != 0);
537 if (left > 0) {
538 filp->f_reada = 1;
539 } else if (!read) {
540 return left;
541 } else {
542 goto done;
545 count -= left;
546 read += left;
547 pos += left;
548 buf += left;
551 /* Pad the file out with zeros */
552 if (count) {
553 clear_user(buf, count);
554 read += count;
555 pos += count;
558 done:
559 if (read) {
560 inode->i_atime = CURRENT_TIME;
561 *ppos = pos;
563 return read;
567 * hdr_write()
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;
583 struct hdr_hdr meta;
584 int built_meta = 0;
585 off_t pos;
587 if (!S_ISREG(inode->i_mode)) {
588 hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);
589 return -EINVAL;
591 if (count <= 0) {
592 return 0;
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);
604 if (pos < length) {
605 hdr_build_meta(&meta, layout, entry);
606 built_meta = 1;
608 left = length - pos;
609 if (left > count) {
610 left = count;
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;
624 count -= left;
625 written += left;
626 pos += left;
627 buf += left;
629 if (!count) {
630 goto done;
633 /* We know for certain how many entries we have, so process them */
634 length += layout->entries * 3 * sizeof(hfs_u32);
635 if (pos < length) {
636 if (!built_meta) {
637 hdr_build_meta(&meta, layout, entry);
640 left = length - pos;
641 if (left > count) {
642 left = count;
645 copy_from_user(((char *)&meta) + pos, buf, left);
646 init_layout(layout, meta.descrs);
648 count -= left;
649 written += left;
650 pos += left;
651 buf += left;
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;
664 char tmp[16], *p;
665 off_t limit;
667 /* stop writing if we run out of descriptors early */
668 if (!descr) {
669 break;
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;
678 } else {
679 continue;
681 } else {
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)) {
693 continue;
696 /* Skip any padding that may exist between entries */
697 if (pos < start) {
698 left = start - pos;
699 if (left > count) {
700 left = count;
702 count -= left;
703 written += left;
704 pos += left;
705 buf += left;
707 if (!count) {
708 goto done;
711 /* locate and/or construct the data for this entry */
712 fork = NULL;
713 p = NULL;
714 switch (descr->id) {
715 case HFS_HDR_DATA:
716 #if 0
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
719 * inode level.
721 fork = &entry->u.file.data_fork;
722 limit = length;
723 #else
724 limit = 0;
725 #endif
726 break;
728 case HFS_HDR_RSRC:
729 fork = &entry->u.file.rsrc_fork;
730 limit = length;
731 break;
733 case HFS_HDR_OLDI:
734 case HFS_HDR_DATES:
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);
741 } else {
742 hfs_put_nl(0, tmp + 12);
744 p = tmp;
745 limit = 16;
746 break;
748 case HFS_HDR_FINFO:
749 p = (char *)&entry->info;
750 limit = 32;
751 break;
753 case HFS_HDR_MACI:
754 hfs_put_ns(0, tmp);
755 if (entry->type == HFS_CDR_FIL) {
756 hfs_put_hs(entry->u.file.flags, tmp + 2);
757 } else {
758 hfs_put_ns(entry->u.dir.flags, tmp + 2);
760 p = tmp;
761 limit = 4;
762 break;
764 case HFS_HDR_FNAME: /* Can't rename a file this way */
765 default:
766 limit = 0;
769 /* limit the transfer to the available data
770 of to the stated length of the entry. */
771 if (length > limit) {
772 length = limit;
774 offset = pos - start;
775 left = length - offset;
776 if (left > count) {
777 left = count;
779 if (left <= 0) {
780 continue;
783 /* transfer the data from user space */
784 if (p) {
785 copy_from_user(p + offset, buf, left);
786 } else if (fork) {
787 left = hfs_do_write(inode, fork, offset, buf, left);
790 /* process the data */
791 switch (descr->id) {
792 case HFS_HDR_OLDI:
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;
799 } else {
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);
809 break;
811 case HFS_HDR_DATES:
812 set_dates(entry, inode, (hfs_u32 *)tmp);
813 break;
815 case HFS_HDR_FINFO:
816 hfs_cat_mark_dirty(entry);
817 break;
819 case HFS_HDR_MACI:
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);
827 } else {
828 hfs_u8 new_flags = tmp[3];
829 hfs_u8 changed = entry->u.file.flags^new_flags;
831 if (changed) {
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);
839 break;
841 case HFS_HDR_DATA:
842 case HFS_HDR_RSRC:
843 if (left <= 0) {
844 if (!written) {
845 return left;
846 } else {
847 goto done;
849 } else if (fork->lsize > descr->length) {
850 descr->length = fork->lsize;
852 break;
854 case HFS_HDR_FNAME: /* Can't rename a file this way */
855 default:
856 break;
859 count -= left;
860 written += left;
861 pos += left;
862 buf += left;
865 /* Skip any padding at the end */
866 if (count) {
867 written += count;
868 pos += count;
871 done:
872 *ppos = pos;
873 if (written > 0) {
874 if (pos > inode->i_size)
875 inode->i_size = pos;
876 inode->i_mtime = inode->i_atime = CURRENT_TIME;
878 return written;
882 * hdr_truncate()
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;
894 int lcv, last;
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;
905 hfs_u32 offset;
907 if (!descr) {
908 break;
911 if (descr->id == HFS_HDR_RSRC) {
912 fork = &entry->u.file.rsrc_fork;
913 #if 0
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
916 * the inode level.
918 } else if (descr->id == HFS_HDR_DATA) {
919 fork = &entry->u.file.data_fork;
920 #endif
921 } else {
922 continue;
925 offset = descr->offset;
927 if ((lcv != last) && ((offset + descr->length) <= size)) {
928 continue;
931 if (offset < size) {
932 descr->length = size - offset;
933 } else {
934 descr->length = 0;
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);