Changeset 993d608 in mainline
- Timestamp:
- 2014-08-07T21:29:31Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 238869ca
- Parents:
- 0003e0f5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/cdfs/cdfs_ops.c
r0003e0f5 r993d608 132 132 133 133 typedef struct { 134 uint8_t res0;134 uint8_t flags; /* reserved in primary */ 135 135 136 136 uint8_t system_ident[32]; … … 140 140 uint32_t_lb lba_size; 141 141 142 uint8_t res2[32];142 uint8_t esc_seq[32]; /* reserved in primary */ 143 143 uint16_t_lb set_size; 144 144 uint16_t_lb sequence_nr; … … 170 170 171 171 uint8_t fs_version; 172 } __attribute__((packed)) cdfs_vol_desc_pri mary_t;172 } __attribute__((packed)) cdfs_vol_desc_prisec_t; 173 173 174 174 typedef struct { … … 178 178 union { 179 179 cdfs_vol_desc_boot_t boot; 180 cdfs_vol_desc_pri mary_t primary;180 cdfs_vol_desc_prisec_t prisec; 181 181 } data; 182 182 } __attribute__((packed)) cdfs_vol_desc_t; 183 184 typedef enum { 185 /** ASCII character set / encoding (base ISO 9660) */ 186 enc_ascii, 187 /** UCS-2 character set / encoding (Joliet) */ 188 enc_ucs2 189 } cdfs_enc_t; 183 190 184 191 typedef enum { … … 196 203 typedef uint32_t cdfs_lba_t; 197 204 198 /** Mounted CDFS filesystem */199 205 typedef struct { 200 link_t link; 206 link_t link; /**< Link to list of all instances */ 201 207 service_id_t service_id; /**< Service ID of block device */ 208 cdfs_enc_t enc; /**< Filesystem string encoding */ 202 209 } cdfs_t; 203 210 … … 218 225 unsigned int opened; /**< Opened count */ 219 226 } cdfs_node_t; 227 228 /** String encoding */ 229 enum { 230 /** ASCII - standard ISO 9660 */ 231 ucs2_esc_seq_no = 3, 232 /** USC-2 - Joliet */ 233 ucs2_esc_seq_len = 3 234 }; 235 236 /** Joliet SVD UCS-2 escape sequences */ 237 static uint8_t ucs2_esc_seq[ucs2_esc_seq_no][ucs2_esc_seq_len] = { 238 { 0x25, 0x2f, 0x40 }, 239 { 0x25, 0x2f, 0x43 }, 240 { 0x25, 0x2f, 0x45 } 241 }; 220 242 221 243 /** List of all instances */ … … 406 428 } 407 429 430 /** Decode CDFS string. 431 * 432 * @param data Pointer to string data 433 * @param dsize Size of data in bytes 434 * @param enc String encoding 435 * @return Decoded string 436 */ 437 static char *cdfs_decode_str(void *data, size_t dsize, cdfs_enc_t enc) 438 { 439 int rc; 440 char *str; 441 uint16_t *buf; 442 443 switch (enc) { 444 case enc_ascii: 445 str = malloc(dsize + 1); 446 if (str == NULL) 447 return NULL; 448 memcpy(str, data, dsize); 449 str[dsize] = '\0'; 450 break; 451 case enc_ucs2: 452 buf = calloc(dsize + 2, 1); 453 if (buf == NULL) 454 return NULL; 455 456 size_t i; 457 for (i = 0; i < dsize / sizeof(uint16_t); i++) { 458 buf[i] = uint16_t_be2host(((uint16_t *)data)[i]); 459 } 460 461 size_t dstr_size = dsize / sizeof(uint16_t) * 4 + 1; 462 str = malloc(dstr_size); 463 if (str == NULL) 464 return NULL; 465 466 rc = utf16_to_str(str, dstr_size, buf); 467 free(buf); 468 469 if (rc != EOK) 470 return NULL; 471 break; 472 default: 473 assert(false); 474 str = NULL; 475 } 476 477 return str; 478 } 479 408 480 /** Decode file name. 409 481 * … … 413 485 * @return Decoded file name (allocated string) 414 486 */ 415 static char *cdfs_decode_name(void *data, size_t dsize, 487 static char *cdfs_decode_name(void *data, size_t dsize, cdfs_enc_t enc, 416 488 cdfs_dentry_type_t dtype) 417 489 { … … 419 491 char *dot; 420 492 char *scolon; 421 422 name = malloc(dsize + 1);493 494 name = cdfs_decode_str(data, dsize, enc); 423 495 if (name == NULL) 424 496 return NULL; 425 memcpy(name, data, dsize); 426 name[dsize] = '\0'; 427 497 428 498 if (dtype == CDFS_DIRECTORY) 429 499 return name; 430 500 431 501 dot = str_chr(name, '.'); 432 if (dot == NULL)433 return NULL;434 scolon = str_chr(dot, ';');435 if (scolon == NULL)436 return NULL;437 438 /* Trim version part */439 *scolon = '\0';440 441 /* If the extension is an empty string, trim the dot separator. */442 if (dot[1] == '\0')443 *dot = '\0';444 502 503 if (dot != NULL) { 504 scolon = str_chr(dot, ';'); 505 if (scolon != NULL) { 506 /* Trim version part */ 507 *scolon = '\0'; 508 } 509 510 /* If the extension is an empty string, trim the dot separator. */ 511 if (dot[1] == '\0') 512 *dot = '\0'; 513 } 514 445 515 return name; 446 516 } … … 504 574 505 575 char *name = cdfs_decode_name(dir->name, 506 dir->name_length, dentry_type);576 dir->name_length, node->fs->enc, dentry_type); 507 577 if (name == NULL) 508 578 return false; … … 687 757 { 688 758 *size = BLOCK_SIZE; 689 759 690 760 return EOK; 691 761 } … … 727 797 }; 728 798 799 /** Verify that escape sequence corresonds to one of the allowed encoding 800 * escape sequences allowed for Joliet. */ 801 static int cdfs_verify_joliet_esc_seq(uint8_t *seq) 802 { 803 size_t i, j, k; 804 bool match; 805 806 i = 0; 807 while (i + ucs2_esc_seq_len <= 32) { 808 if (seq[i] == 0) 809 break; 810 811 for (j = 0; j < ucs2_esc_seq_no; j++) { 812 match = true; 813 for (k = 0; k < ucs2_esc_seq_len; k++) 814 if (seq[i + k] != ucs2_esc_seq[j][k]) 815 match = false; 816 if (match) { 817 break; 818 } 819 } 820 821 if (!match) 822 return EINVAL; 823 824 i += ucs2_esc_seq_len; 825 } 826 827 while (i < 32) { 828 if (seq[i] != 0) 829 return EINVAL; 830 ++i; 831 } 832 833 return EOK; 834 } 835 836 /** Find Joliet supplementary volume descriptor. 837 * 838 * @param sid Block device service ID 839 * @param altroot First filesystem block 840 * @param rlba Place to store LBA of root dir 841 * @param rsize Place to store size of root dir 842 * @return EOK if found, ENOENT if not 843 */ 844 static int cdfs_find_joliet_svd(service_id_t sid, cdfs_lba_t altroot, 845 uint32_t *rlba, uint32_t *rsize) 846 { 847 cdfs_lba_t bi; 848 849 for (bi = altroot + 17; ; bi++) { 850 block_t *block; 851 int rc = block_get(&block, sid, bi, BLOCK_FLAGS_NONE); 852 if (rc != EOK) 853 break; 854 855 cdfs_vol_desc_t *vol_desc = (cdfs_vol_desc_t *) block->data; 856 857 if (vol_desc->type == VOL_DESC_SET_TERMINATOR) { 858 block_put(block); 859 break; 860 } 861 862 if ((vol_desc->type != VOL_DESC_SUPPLEMENTARY) || 863 (memcmp(vol_desc->standard_ident, CDFS_STANDARD_IDENT, 5) != 0) || 864 (vol_desc->version != 1)) { 865 block_put(block); 866 continue; 867 } 868 869 uint16_t set_size = uint16_lb(vol_desc->data.prisec.set_size); 870 if (set_size > 1) { 871 /* 872 * Technically, we don't support multi-disc sets. 873 * But one can encounter erroneously mastered 874 * images in the wild and it might actually work 875 * for the first disc in the set. 876 */ 877 } 878 879 uint16_t sequence_nr = uint16_lb(vol_desc->data.prisec.sequence_nr); 880 if (sequence_nr != 1) { 881 /* 882 * We only support the first disc 883 * in multi-disc sets. 884 */ 885 block_put(block); 886 continue; 887 } 888 889 uint16_t block_size = uint16_lb(vol_desc->data.prisec.block_size); 890 if (block_size != BLOCK_SIZE) { 891 block_put(block); 892 continue; 893 } 894 895 rc = cdfs_verify_joliet_esc_seq(vol_desc->data.prisec.esc_seq); 896 if (rc != EOK) 897 continue; 898 *rlba = uint32_lb(vol_desc->data.prisec.root_dir.lba); 899 *rsize = uint32_lb(vol_desc->data.prisec.root_dir.size); 900 block_put(block); 901 return EOK; 902 } 903 904 return ENOENT; 905 } 906 729 907 static bool iso_readfs(cdfs_t *fs, fs_node_t *rfn, 730 908 cdfs_lba_t altroot) … … 749 927 } 750 928 751 uint16_t set_size = uint16_lb(vol_desc->data.pri mary.set_size);929 uint16_t set_size = uint16_lb(vol_desc->data.prisec.set_size); 752 930 if (set_size > 1) { 753 931 /* … … 759 937 } 760 938 761 uint16_t sequence_nr = uint16_lb(vol_desc->data.pri mary.sequence_nr);939 uint16_t sequence_nr = uint16_lb(vol_desc->data.prisec.sequence_nr); 762 940 if (sequence_nr != 1) { 763 941 /* … … 769 947 } 770 948 771 uint16_t block_size = uint16_lb(vol_desc->data.pri mary.block_size);949 uint16_t block_size = uint16_lb(vol_desc->data.prisec.block_size); 772 950 if (block_size != BLOCK_SIZE) { 773 951 block_put(block); … … 778 956 779 957 cdfs_node_t *node = CDFS_NODE(rfn); 780 node->lba = uint32_lb(vol_desc->data.primary.root_dir.lba); 781 node->size = uint32_lb(vol_desc->data.primary.root_dir.size); 958 959 /* Search for Joliet SVD */ 960 961 uint32_t jrlba; 962 uint32_t jrsize; 963 964 rc = cdfs_find_joliet_svd(fs->service_id, altroot, &jrlba, &jrsize); 965 if (rc == EOK) { 966 /* Found */ 967 node->lba = jrlba; 968 node->size = jrsize; 969 fs->enc = enc_ucs2; 970 } else { 971 node->lba = uint32_lb(vol_desc->data.prisec.root_dir.lba); 972 node->size = uint32_lb(vol_desc->data.prisec.root_dir.size); 973 fs->enc = enc_ascii; 974 } 782 975 783 976 if (!cdfs_readdir(fs, rfn)) { … … 801 994 if (fs == NULL) 802 995 goto error; 803 996 804 997 fs->service_id = sid; 805 998 806 999 /* Create root node */ 807 1000 int rc = create_node(&rfn, fs, L_DIRECTORY, cdfs_index++); … … 925 1118 if (fs == NULL) 926 1119 return ENOENT; 927 1120 928 1121 cdfs_fs_destroy(fs); 929 1122 return EOK; … … 1029 1222 /* Some nodes were requested to be removed from the cache. */ 1030 1223 if (0 < *premove_cnt) { 1031 cdfs_node_t *node = 1224 cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link); 1032 1225 1033 1226 if (!node->opened) {
Note:
See TracChangeset
for help on using the changeset viewer.