1 /*
2 * linux/fs/hfs/file_hdr.c
3 *
4 * Copyright (C) 1995-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU Public License.
6 *
7 * This file contains the file_ops and inode_ops for the metadata
8 * files under the AppleDouble and Netatalk representations.
9 *
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.
15 *
16 * "XXX" in a comment is a note to myself to consider changing something.
17 *
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.
21 *
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.
26 */
27
28 #include "hfs.h"
29 #include <linux/hfs_fs_sb.h>
30 #include <linux/hfs_fs_i.h>
31 #include <linux/hfs_fs.h>
32
33 /* prodos types */
34 #define PRODOSI_FTYPE_DIR 0x0F
35 #define PRODOSI_FTYPE_TEXT 0x04
36 #define PRODOSI_FTYPE_8BIT 0xFF
37 #define PRODOSI_FTYPE_16BIT 0xB3
38
39 #define PRODOSI_AUXTYPE_DIR 0x0200
40
41 /*================ Forward declarations ================*/
42
43 static hfs_rwret_t hdr_read(struct file *, char *, hfs_rwarg_t, loff_t *);
44 static hfs_rwret_t hdr_write(struct file *, const char *,
45 hfs_rwarg_t, loff_t *);
46 /*================ Global variables ================*/
47
48 struct file_operations hfs_hdr_operations = {
49 read: hdr_read,
50 write: hdr_write,
51 fsync: file_fsync,
52 };
53
54 struct inode_operations hfs_hdr_inode_operations = {
55 setattr: hfs_notify_change_hdr,
56 };
57
58 const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
59 __constant_htonl(HFS_DBL_MAGIC), /* magic */
60 __constant_htonl(HFS_HDR_VERSION_2), /* version */
61 6, /* entries */
62 { /* descr[] */
63 {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
64 {HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
65 {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
66 {HFS_HDR_MACI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
67 {HFS_HDR_DID, offsetof(struct hfs_dbl_hdr, cnid), 4},
68 {HFS_HDR_RSRC, HFS_DBL_HDR_LEN, ~0}
69 },
70 { /* order[] */
71 (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[0],
72 (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[1],
73 (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[2],
74 (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[3],
75 (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[4],
76 (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[5]
77 }
78 };
79
80 const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {
81 __constant_htonl(HFS_DBL_MAGIC), /* magic */
82 __constant_htonl(HFS_HDR_VERSION_2), /* version */
83 5, /* entries */
84 { /* descr[] */
85 {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
86 {HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
87 {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
88 {HFS_HDR_MACI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
89 {HFS_HDR_DID, offsetof(struct hfs_dbl_hdr, cnid), 4}
90 },
91 { /* order[] */
92 (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[0],
93 (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[1],
94 (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[2],
95 (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[3],
96 (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[4]
97 }
98 };
99
100 const struct hfs_hdr_layout hfs_nat2_hdr_layout = {
101 __constant_htonl(HFS_DBL_MAGIC), /* magic */
102 __constant_htonl(HFS_HDR_VERSION_2), /* version */
103 9, /* entries */
104 { /* descr[] */
105 {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
106 {HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment), 0},
107 {HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
108 {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
109 {HFS_HDR_AFPI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
110 {HFS_HDR_DID, offsetof(struct hfs_dbl_hdr, cnid), 4},
111 {HFS_HDR_SNAME, offsetof(struct hfs_dbl_hdr, short_name), ~0},
112 {HFS_HDR_PRODOSI, offsetof(struct hfs_dbl_hdr, prodosi), 8},
113 {HFS_HDR_RSRC, HFS_NAT_HDR_LEN, ~0}
114 },
115 { /* order[] */
116 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
117 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
118 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
119 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
120 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
121 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[5],
122 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[6],
123 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[7],
124 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[8]
125 }
126 };
127
128 const struct hfs_hdr_layout hfs_nat_hdr_layout = {
129 __constant_htonl(HFS_DBL_MAGIC), /* magic */
130 __constant_htonl(HFS_HDR_VERSION_1), /* version */
131 5, /* entries */
132 { /* descr[] */
133 {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
134 {HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment), 0},
135 {HFS_HDR_OLDI, offsetof(struct hfs_dbl_hdr, create_time), 16},
136 {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
137 {HFS_HDR_RSRC, HFS_NAT_HDR_LEN, ~0},
138 },
139 { /* order[] */
140 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
141 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
142 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
143 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
144 (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4]
145 }
146 };
147
148 /*================ File-local variables ================*/
149
150 static const char fstype[16] =
151 {'M','a','c','i','n','t','o','s','h',' ',' ',' ',' ',' ',' ',' '};
152
153 /*================ File-local data types ================*/
154
155 struct hdr_hdr {
156 hfs_lword_t magic;
157 hfs_lword_t version;
158 hfs_byte_t filler[16];
159 hfs_word_t entries;
160 hfs_byte_t descrs[12*HFS_HDR_MAX];
161 } __attribute__((packed));
162
163 /*================ File-local functions ================*/
164
165 /*
166 * dlength()
167 */
168 static int dlength(const struct hfs_hdr_descr *descr,
169 const struct hfs_cat_entry *entry)
170 {
171 hfs_u32 length = descr->length;
172
173 /* handle auto-sized entries */
174 if (length == ~0) {
175 switch (descr->id) {
176 case HFS_HDR_DATA:
177 if (entry->type == HFS_CDR_FIL) {
178 length = entry->u.file.data_fork.lsize;
179 } else {
180 length = 0;
181 }
182 break;
183
184 case HFS_HDR_RSRC:
185 if (entry->type == HFS_CDR_FIL) {
186 length = entry->u.file.rsrc_fork.lsize;
187 } else {
188 length = 0;
189 }
190 break;
191
192 case HFS_HDR_FNAME:
193 length = entry->key.CName.Len;
194 break;
195
196 case HFS_HDR_SNAME:
197 default:
198 length = 0;
199 }
200 }
201 return length;
202 }
203
204 /*
205 * hdr_build_meta()
206 */
207 static void hdr_build_meta(struct hdr_hdr *meta,
208 const struct hfs_hdr_layout *layout,
209 const struct hfs_cat_entry *entry)
210 {
211 const struct hfs_hdr_descr *descr;
212 hfs_byte_t *ptr;
213 int lcv;
214
215 hfs_put_nl(layout->magic, meta->magic);
216 hfs_put_nl(layout->version, meta->version);
217 if (layout->version == htonl(HFS_HDR_VERSION_1)) {
218 memcpy(meta->filler, fstype, 16);
219 } else {
220 memset(meta->filler, 0, 16);
221 }
222 hfs_put_hs(layout->entries, meta->entries);
223 memset(meta->descrs, 0, sizeof(meta->descrs));
224 for (lcv = 0, descr = layout->descr, ptr = meta->descrs;
225 lcv < layout->entries; ++lcv, ++descr, ptr += 12) {
226 hfs_put_hl(descr->id, ptr);
227 hfs_put_hl(descr->offset, ptr + 4);
228 hfs_put_hl(dlength(descr, entry), ptr + 8);
229 }
230 }
231
232 /*
233 * dup_layout ()
234 */
235 static struct hfs_hdr_layout *dup_layout(const struct hfs_hdr_layout *old)
236 {
237 struct hfs_hdr_layout *new;
238 int lcv;
239
240 if (HFS_NEW(new)) {
241 memcpy(new, old, sizeof(*new));
242 for (lcv = 0; lcv < new->entries; ++lcv) {
243 (char *)(new->order[lcv]) += (char *)new - (char *)old;
244 }
245 }
246 return new;
247 }
248
249 /*
250 * init_layout()
251 */
252 static inline void init_layout(struct hfs_hdr_layout *layout,
253 const hfs_byte_t *descrs)
254 {
255 struct hfs_hdr_descr **base, **p, **q, *tmp;
256 int lcv, entries = layout->entries;
257
258 for (lcv = 0; lcv < entries; ++lcv, descrs += 12) {
259 layout->order[lcv] = &layout->descr[lcv];
260 layout->descr[lcv].id = hfs_get_hl(descrs);
261 layout->descr[lcv].offset = hfs_get_hl(descrs + 4);
262 layout->descr[lcv].length = hfs_get_hl(descrs + 8);
263 }
264 for (lcv = layout->entries; lcv < HFS_HDR_MAX; ++lcv) {
265 layout->order[lcv] = NULL;
266 layout->descr[lcv].id = 0;
267 layout->descr[lcv].offset = 0;
268 layout->descr[lcv].length = 0;
269 }
270
271 /* Sort the 'order' array using an insertion sort */
272 base = &layout->order[0];
273 for (p = (base+1); p < (base+entries); ++p) {
274 q=p;
275 while ((*q)->offset < (*(q-1))->offset) {
276 tmp = *q;
277 *q = *(q-1);
278 *(--q) = tmp;
279 if (q == base) break;
280 }
281 }
282 }
283
284 /*
285 * adjust_forks()
286 */
287 static inline void adjust_forks(struct hfs_cat_entry *entry,
288 const struct hfs_hdr_layout *layout)
289 {
290 int lcv;
291
292 for (lcv = 0; lcv < layout->entries; ++lcv) {
293 const struct hfs_hdr_descr *descr = &layout->descr[lcv];
294
295 if ((descr->id == HFS_HDR_DATA) &&
296 (descr->length != entry->u.file.data_fork.lsize)) {
297 entry->u.file.data_fork.lsize = descr->length;
298 hfs_extent_adj(&entry->u.file.data_fork);
299 } else if ((descr->id == HFS_HDR_RSRC) &&
300 (descr->length != entry->u.file.rsrc_fork.lsize)) {
301 entry->u.file.rsrc_fork.lsize = descr->length;
302 hfs_extent_adj(&entry->u.file.rsrc_fork);
303 }
304 }
305 }
306
307 /*
308 * get_dates()
309 */
310 static void get_dates(const struct hfs_cat_entry *entry,
311 const struct inode *inode, hfs_u32 dates[3])
312 {
313 dates[0] = hfs_m_to_htime(entry->create_date);
314 dates[1] = hfs_m_to_htime(entry->modify_date);
315 dates[2] = hfs_m_to_htime(entry->backup_date);
316 }
317
318 /*
319 * set_dates()
320 */
321 static void set_dates(struct hfs_cat_entry *entry, struct inode *inode,
322 const hfs_u32 *dates)
323 {
324 hfs_u32 tmp;
325
326 tmp = hfs_h_to_mtime(dates[0]);
327 if (entry->create_date != tmp) {
328 entry->create_date = tmp;
329 hfs_cat_mark_dirty(entry);
330 }
331 tmp = hfs_h_to_mtime(dates[1]);
332 if (entry->modify_date != tmp) {
333 entry->modify_date = tmp;
334 inode->i_ctime = inode->i_atime = inode->i_mtime =
335 hfs_h_to_utime(dates[1]);
336 hfs_cat_mark_dirty(entry);
337 }
338 tmp = hfs_h_to_mtime(dates[2]);
339 if (entry->backup_date != tmp) {
340 entry->backup_date = tmp;
341 hfs_cat_mark_dirty(entry);
342 }
343 }
344
345 /*
346 * hdr_read()
347 *
348 * This is the read field in the inode_operations structure for
349 * header files. The purpose is to transfer up to 'count' bytes
350 * from the file corresponding to 'inode', beginning at
351 * 'filp->offset' bytes into the file. The data is transfered to
352 * user-space at the address 'buf'. Returns the number of bytes
353 * successfully transfered.
354 */
355 /* XXX: what about the entry count changing on us? */
356 static hfs_rwret_t hdr_read(struct file * filp, char * buf,
357 hfs_rwarg_t count, loff_t *ppos)
358 {
359 struct inode *inode = filp->f_dentry->d_inode;
360 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
361 const struct hfs_hdr_layout *layout;
362 off_t start, length, offset;
363 off_t pos = *ppos;
364 int left, lcv, read = 0;
365
366 if (!S_ISREG(inode->i_mode)) {
367 hfs_warn("hfs_hdr_read: mode = %07o\n",inode->i_mode);
368 return -EINVAL;
369 }
370
371 if (HFS_I(inode)->layout) {
372 layout = HFS_I(inode)->layout;
373 } else {
374 layout = HFS_I(inode)->default_layout;
375 }
376
377 /* Adjust count to fit within the bounds of the file */
378 if ((pos >= inode->i_size) || (count <= 0)) {
379 return 0;
380 } else if (count > inode->i_size - pos) {
381 count = inode->i_size - pos;
382 }
383
384 /* Handle the fixed-location portion */
385 length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 +
386 sizeof(hfs_u16) + layout->entries * (3 * sizeof(hfs_u32));
387 if (pos < length) {
388 struct hdr_hdr meta;
389
390 left = length - pos;
391 if (left > count) {
392 left = count;
393 }
394
395 hdr_build_meta(&meta, layout, entry);
396 left -= copy_to_user(buf, ((char *)&meta) + pos, left);
397 count -= left;
398 read += left;
399 pos += left;
400 buf += left;
401 }
402 if (!count) {
403 goto done;
404 }
405
406 /* Handle the actual data */
407 for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
408 const struct hfs_hdr_descr *descr = layout->order[lcv];
409 struct hfs_fork *fork;
410 char tmp[16], *p;
411 off_t limit;
412
413 /* stop reading if we run out of descriptors early */
414 if (!descr) {
415 break;
416 }
417
418 /* find start and length of this entry */
419 start = descr->offset;
420 length = dlength(descr, entry);
421
422 /* Skip to next entry if this one is empty or isn't needed */
423 if (!length || (pos >= start + length)) {
424 continue;
425 }
426
427 /* Pad with zeros to the start of this entry if needed */
428 if (pos < start) {
429 left = start - pos;
430 if (left > count) {
431 left = count;
432 }
433 clear_user(buf, left);
434 count -= left;
435 read += left;
436 pos += left;
437 buf += left;
438 }
439 if (!count) {
440 goto done;
441 }
442
443 /* locate and/or construct the data for this entry */
444 fork = NULL;
445 p = NULL;
446 switch (descr->id) {
447 case HFS_HDR_DATA:
448 fork = &entry->u.file.data_fork;
449 limit = fork->lsize;
450 break;
451
452 case HFS_HDR_RSRC:
453 fork = &entry->u.file.rsrc_fork;
454 limit = fork->lsize;
455 break;
456
457 case HFS_HDR_FNAME:
458 p = entry->key.CName.Name;
459 limit = entry->key.CName.Len;
460 break;
461
462 case HFS_HDR_OLDI:
463 case HFS_HDR_DATES:
464 get_dates(entry, inode, (hfs_u32 *)tmp);
465 if (descr->id == HFS_HDR_DATES) {
466 /* XXX: access date. hfsplus actually
467 has this. */
468 memcpy(tmp + 12, tmp + 4, 4);
469 } else if ((entry->type == HFS_CDR_FIL) &&
470 (entry->u.file.flags & HFS_FIL_LOCK)) {
471 hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
472 } else {
473 hfs_put_nl(0, tmp + 12);
474 }
475 p = tmp;
476 limit = 16;
477 break;
478
479 case HFS_HDR_FINFO:
480 p = (char *)&entry->info;
481 limit = 32;
482 break;
483
484 case HFS_HDR_AFPI:
485 /* XXX: this needs to do more mac->afp mappings */
486 hfs_put_ns(0, tmp);
487 if ((entry->type == HFS_CDR_FIL) &&
488 (entry->u.file.flags & HFS_FIL_LOCK)) {
489 hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
490 } else {
491 hfs_put_ns(0, tmp + 2);
492 }
493 p = tmp;
494 limit = 4;
495 break;
496
497 case HFS_HDR_PRODOSI:
498 /* XXX: this needs to do mac->prodos translations */
499 memset(tmp, 0, 8);
500 #if 0
501 hfs_put_ns(0, tmp); /* access */
502 hfs_put_ns(0, tmp); /* type */
503 hfs_put_nl(0, tmp); /* aux type */
504 #endif
505 p = tmp;
506 limit = 8;
507 break;
508
509 case HFS_HDR_MACI:
510 hfs_put_ns(0, tmp);
511 if (entry->type == HFS_CDR_FIL) {
512 hfs_put_hs(entry->u.file.flags, tmp + 2);
513 } else {
514 hfs_put_ns(entry->u.dir.flags, tmp + 2);
515 }
516 p = tmp;
517 limit = 4;
518 break;
519
520 case HFS_HDR_DID:
521 /* if it's rootinfo, stick the next available did in
522 * the did slot. */
523 limit = 4;
524 if (entry->cnid == htonl(HFS_ROOT_CNID)) {
525 struct hfs_mdb *mdb = entry->mdb;
526 const struct hfs_name *reserved =
527 HFS_SB(mdb->sys_mdb)->s_reserved2;
528
529 while (reserved->Len) {
530 if (hfs_streq(reserved->Name,
531 reserved->Len,
532 entry->key.CName.Name,
533 entry->key.CName.Len)) {
534 hfs_put_hl(mdb->next_id, tmp);
535 p = tmp;
536 goto hfs_did_done;
537 }
538 reserved++;
539 }
540 }
541 p = (char *) &entry->cnid;
542 hfs_did_done:
543 break;
544
545 case HFS_HDR_SNAME:
546 default:
547 limit = 0;
548 }
549
550 /* limit the transfer to the available data
551 of to the stated length of the entry. */
552 if (length > limit) {
553 length = limit;
554 }
555 offset = pos - start;
556 left = length - offset;
557 if (left > count) {
558 left = count;
559 }
560 if (left <= 0) {
561 continue;
562 }
563
564 /* transfer the data */
565 if (p) {
566 left -= copy_to_user(buf, p + offset, left);
567 } else if (fork) {
568 left = hfs_do_read(inode, fork, offset, buf, left,
569 filp->f_reada != 0);
570 if (left > 0) {
571 filp->f_reada = 1;
572 } else if (!read) {
573 return left;
574 } else {
575 goto done;
576 }
577 }
578 count -= left;
579 read += left;
580 pos += left;
581 buf += left;
582 }
583
584 /* Pad the file out with zeros */
585 if (count) {
586 clear_user(buf, count);
587 read += count;
588 pos += count;
589 }
590
591 done:
592 if (read) {
593 inode->i_atime = CURRENT_TIME;
594 *ppos = pos;
595 mark_inode_dirty(inode);
596 }
597 return read;
598 }
599
600 /*
601 * hdr_write()
602 *
603 * This is the write() entry in the file_operations structure for
604 * header files. The purpose is to transfer up to 'count' bytes
605 * to the file corresponding to 'inode' beginning at offset
606 * '*ppos' from user-space at the address 'buf'.
607 * The return value is the number of bytes actually transferred.
608 */
609 static hfs_rwret_t hdr_write(struct file *filp, const char *buf,
610 hfs_rwarg_t count, loff_t *ppos)
611 {
612 struct inode *inode = filp->f_dentry->d_inode;
613 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
614 struct hfs_hdr_layout *layout;
615 off_t start, length, offset;
616 int left, lcv, written = 0;
617 struct hdr_hdr meta;
618 int built_meta = 0;
619 off_t pos;
620
621 if (!S_ISREG(inode->i_mode)) {
622 hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);
623 return -EINVAL;
624 }
625 if (count <= 0) {
626 return 0;
627 }
628
629 pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
630
631 if (!HFS_I(inode)->layout) {
632 HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
633 }
634 layout = HFS_I(inode)->layout;
635
636 /* Handle the 'magic', 'version', 'filler' and 'entries' fields */
637 length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 + sizeof(hfs_u16);
638 if (pos < length) {
639 hdr_build_meta(&meta, layout, entry);
640 built_meta = 1;
641
642 left = length - pos;
643 if (left > count) {
644 left = count;
645 }
646
647 left -= copy_from_user(((char *)&meta) + pos, buf, left);
648 layout->magic = hfs_get_nl(meta.magic);
649 layout->version = hfs_get_nl(meta.version);
650 layout->entries = hfs_get_hs(meta.entries);
651 if (layout->entries > HFS_HDR_MAX) {
652 /* XXX: should allocate slots dynamically */
653 hfs_warn("hfs_hdr_write: TRUNCATING TO %d "
654 "DESCRIPTORS\n", HFS_HDR_MAX);
655 layout->entries = HFS_HDR_MAX;
656 }
657
658 count -= left;
659 written += left;
660 pos += left;
661 buf += left;
662 }
663 if (!count) {
664 goto done;
665 }
666
667 /* We know for certain how many entries we have, so process them */
668 length += layout->entries * 3 * sizeof(hfs_u32);
669 if (pos < length) {
670 if (!built_meta) {
671 hdr_build_meta(&meta, layout, entry);
672 }
673
674 left = length - pos;
675 if (left > count) {
676 left = count;
677 }
678
679 left -= copy_from_user(((char *)&meta) + pos, buf, left);
680 init_layout(layout, meta.descrs);
681
682 count -= left;
683 written += left;
684 pos += left;
685 buf += left;
686
687 /* Handle possible size changes for the forks */
688 if (entry->type == HFS_CDR_FIL) {
689 adjust_forks(entry, layout);
690 hfs_cat_mark_dirty(entry);
691 }
692 }
693
694 /* Handle the actual data */
695 for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
696 struct hfs_hdr_descr *descr = layout->order[lcv];
697 struct hfs_fork *fork;
698 char tmp[16], *p;
699 off_t limit;
700
701 /* stop writing if we run out of descriptors early */
702 if (!descr) {
703 break;
704 }
705
706 /* find start and length of this entry */
707 start = descr->offset;
708 if ((descr->id == HFS_HDR_DATA) ||
709 (descr->id == HFS_HDR_RSRC)) {
710 if (entry->type == HFS_CDR_FIL) {
711 length = 0x7fffffff - start;
712 } else {
713 continue;
714 }
715 } else {
716 length = dlength(descr, entry);
717 }
718
719 /* Trim length to avoid overlap with the next entry */
720 if (layout->order[lcv+1] &&
721 ((start + length) > layout->order[lcv+1]->offset)) {
722 length = layout->order[lcv+1]->offset - start;
723 }
724
725 /* Skip to next entry if this one is empty or isn't needed */
726 if (!length || (pos >= start + length)) {
727 continue;
728 }
729
730 /* Skip any padding that may exist between entries */
731 if (pos < start) {
732 left = start - pos;
733 if (left > count) {
734 left = count;
735 }
736 count -= left;
737 written += left;
738 pos += left;
739 buf += left;
740 }
741 if (!count) {
742 goto done;
743 }
744
745 /* locate and/or construct the data for this entry */
746 fork = NULL;
747 p = NULL;
748 switch (descr->id) {
749 case HFS_HDR_DATA:
750 #if 0
751 /* Can't yet write to the data fork via a header file, since there is the
752 * possibility to write via the data file, and the only locking is at the
753 * inode level.
754 */
755 fork = &entry->u.file.data_fork;
756 limit = length;
757 #else
758 limit = 0;
759 #endif
760 break;
761
762 case HFS_HDR_RSRC:
763 fork = &entry->u.file.rsrc_fork;
764 limit = length;
765 break;
766
767 case HFS_HDR_OLDI:
768 case HFS_HDR_DATES:
769 get_dates(entry, inode, (hfs_u32 *)tmp);
770 if (descr->id == HFS_HDR_DATES) {
771 memcpy(tmp + 12, tmp + 4, 4);
772 } else if ((entry->type == HFS_CDR_FIL) &&
773 (entry->u.file.flags & HFS_FIL_LOCK)) {
774 hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
775 } else {
776 hfs_put_nl(0, tmp + 12);
777 }
778 p = tmp;
779 limit = 16;
780 break;
781
782 case HFS_HDR_FINFO:
783 p = (char *)&entry->info;
784 limit = 32;
785 break;
786
787 case HFS_HDR_AFPI:
788 hfs_put_ns(0, tmp);
789 if ((entry->type == HFS_CDR_FIL) &&
790 (entry->u.file.flags & HFS_FIL_LOCK)) {
791 hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
792 } else {
793 hfs_put_ns(0, tmp + 2);
794 }
795 p = tmp;
796 limit = 4;
797 break;
798
799 case HFS_HDR_PRODOSI:
800 /* XXX: this needs to do mac->prodos translations */
801 memset(tmp, 0, 8);
802 #if 0
803 hfs_put_ns(0, tmp); /* access */
804 hfs_put_ns(0, tmp); /* type */
805 hfs_put_nl(0, tmp); /* aux type */
806 #endif
807 p = tmp;
808 limit = 8;
809 break;
810
811 case HFS_HDR_MACI:
812 hfs_put_ns(0, tmp);
813 if (entry->type == HFS_CDR_FIL) {
814 hfs_put_hs(entry->u.file.flags, tmp + 2);
815 } else {
816 hfs_put_ns(entry->u.dir.flags, tmp + 2);
817 }
818 p = tmp;
819 limit = 4;
820 break;
821
822 case HFS_HDR_FNAME: /* Can't rename a file this way */
823 case HFS_HDR_DID: /* can't specify a did this way */
824 default:
825 limit = 0;
826 }
827
828 /* limit the transfer to the available data
829 of to the stated length of the entry. */
830 if (length > limit) {
831 length = limit;
832 }
833 offset = pos - start;
834 left = length - offset;
835 if (left > count) {
836 left = count;
837 }
838 if (left <= 0) {
839 continue;
840 }
841
842 /* transfer the data from user space */
843 if (p) {
844 left -= copy_from_user(p + offset, buf, left);
845 } else if (fork) {
846 left = hfs_do_write(inode, fork, offset, buf, left);
847 }
848
849 /* process the data */
850 switch (descr->id) {
851 case HFS_HDR_OLDI:
852 set_dates(entry, inode, (hfs_u32 *)tmp);
853 if (entry->type == HFS_CDR_FIL) {
854 hfs_u8 new_flags = entry->u.file.flags;
855
856 if (hfs_get_nl(tmp+12) & htonl(HFS_AFP_WRI)) {
857 new_flags |= HFS_FIL_LOCK;
858 } else {
859 new_flags &= ~HFS_FIL_LOCK;
860 }
861
862 if (new_flags != entry->u.file.flags) {
863 entry->u.file.flags = new_flags;
864 hfs_cat_mark_dirty(entry);
865 hfs_file_fix_mode(entry);
866 }
867 }
868 break;
869
870 case HFS_HDR_DATES:
871 set_dates(entry, inode, (hfs_u32 *)tmp);
872 break;
873
874 case HFS_HDR_FINFO:
875 hfs_cat_mark_dirty(entry);
876 break;
877
878 case HFS_HDR_MACI:
879 if (entry->type == HFS_CDR_DIR) {
880 hfs_u16 new_flags = hfs_get_ns(tmp + 2);
881
882 if (entry->u.dir.flags != new_flags) {
883 entry->u.dir.flags = new_flags;
884 hfs_cat_mark_dirty(entry);
885 }
886 } else {
887 hfs_u8 new_flags = tmp[3];
888 hfs_u8 changed = entry->u.file.flags^new_flags;
889
890 if (changed) {
891 entry->u.file.flags = new_flags;
892 hfs_cat_mark_dirty(entry);
893 if (changed & HFS_FIL_LOCK) {
894 hfs_file_fix_mode(entry);
895 }
896 }
897 }
898 break;
899
900 case HFS_HDR_DATA:
901 case HFS_HDR_RSRC:
902 if (left <= 0) {
903 if (!written) {
904 return left;
905 } else {
906 goto done;
907 }
908 } else if (fork->lsize > descr->length) {
909 descr->length = fork->lsize;
910 }
911 break;
912
913 case HFS_HDR_FNAME: /* Can't rename a file this way */
914 case HFS_HDR_DID: /* Can't specify a did this way */
915 case HFS_HDR_PRODOSI: /* not implemented yet */
916 case HFS_HDR_AFPI: /* ditto */
917 default:
918 break;
919 }
920
921 count -= left;
922 written += left;
923 pos += left;
924 buf += left;
925 }
926
927 /* Skip any padding at the end */
928 if (count) {
929 written += count;
930 pos += count;
931 }
932
933 done:
934 *ppos = pos;
935 if (written > 0) {
936 if (pos > inode->i_size)
937 inode->i_size = pos;
938 inode->i_mtime = inode->i_atime = CURRENT_TIME;
939 mark_inode_dirty(inode);
940 }
941 return written;
942 }
943
944 /*
945 * hdr_truncate()
946 *
947 * This is the truncate field in the inode_operations structure for
948 * header files. The purpose is to allocate or release blocks as needed
949 * to satisfy a change in file length.
950 */
951 void hdr_truncate(struct inode *inode, size_t size)
952 {
953 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
954 struct hfs_hdr_layout *layout;
955 int lcv, last;
956
957 inode->i_size = size;
958 if (!HFS_I(inode)->layout) {
959 HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
960 }
961 layout = HFS_I(inode)->layout;
962
963 last = layout->entries - 1;
964 for (lcv = 0; lcv <= last; ++lcv) {
965 struct hfs_hdr_descr *descr = layout->order[lcv];
966 struct hfs_fork *fork;
967 hfs_u32 offset;
968
969 if (!descr) {
970 break;
971 }
972
973 if (descr->id == HFS_HDR_RSRC) {
974 fork = &entry->u.file.rsrc_fork;
975 #if 0
976 /* Can't yet truncate the data fork via a header file, since there is the
977 * possibility to truncate via the data file, and the only locking is at
978 * the inode level.
979 */
980 } else if (descr->id == HFS_HDR_DATA) {
981 fork = &entry->u.file.data_fork;
982 #endif
983 } else {
984 continue;
985 }
986
987 offset = descr->offset;
988
989 if ((lcv != last) && ((offset + descr->length) <= size)) {
990 continue;
991 }
992
993 if (offset < size) {
994 descr->length = size - offset;
995 } else {
996 descr->length = 0;
997 }
998 if (fork->lsize != descr->length) {
999 fork->lsize = descr->length;
1000 hfs_extent_adj(fork);
1001 hfs_cat_mark_dirty(entry);
1002 }
1003 }
1004 }
1005
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.