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