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