1 /* 2 * This file contains support for System Use Sharing Protocol (SUSP) extension 3 * to ISO 9660. 4 */ 5 6 #include "inc.h" 7 #include <sys/stat.h> 8 9 #ifdef ISO9660_OPTION_ROCKRIDGE 10 11 int parse_susp(struct rrii_dir_record *dir, char *buffer) 12 { 13 /* Parse fundamental SUSP entries */ 14 char susp_signature[2]; 15 u8_t susp_length; 16 u8_t susp_version; 17 u32_t ca_block_nr; 18 u32_t ca_offset; 19 u32_t ca_length; 20 struct buf *ca_bp; 21 int r; 22 23 susp_signature[0] = buffer[0]; 24 susp_signature[1] = buffer[1]; 25 susp_length = *((u8_t*)buffer + 2); 26 susp_version = *((u8_t*)buffer + 3); 27 28 if ((susp_signature[0] == 'C') && (susp_signature[1] == 'E') && 29 (susp_length >= 28) && (susp_version >= 1)) { 30 /* 31 * Continuation area, perform a recursion. 32 * 33 * FIXME: Currently we're parsing only first logical block of a 34 * continuation area, and infinite recursion is not checked. 35 */ 36 37 ca_block_nr = *((u32_t*)(buffer + 4)); 38 ca_offset = *((u32_t*)(buffer + 12)); 39 ca_length = *((u32_t*)(buffer + 20)); 40 41 /* Truncate continuation area to fit one logical block. */ 42 if (ca_offset >= v_pri.logical_block_size_l) { 43 return EINVAL; 44 } 45 if (ca_offset + ca_length > v_pri.logical_block_size_l) { 46 ca_length = v_pri.logical_block_size_l - ca_offset; 47 } 48 49 r = lmfs_get_block(&ca_bp, fs_dev, ca_block_nr, NORMAL); 50 if (r != OK) 51 return r; 52 53 parse_susp_buffer(dir, b_data(ca_bp) + ca_offset, ca_length); 54 lmfs_put_block(ca_bp); 55 56 return OK; 57 } 58 else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'D')) { 59 /* Padding, skip. */ 60 return OK; 61 } 62 else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'P')) { 63 /* Ignored, skip. */ 64 return OK; 65 } 66 else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'T')) { 67 /* Terminator entry, stop processing. */ 68 return(ECANCELED); 69 } 70 else if ((susp_signature[0] == 'E') && (susp_signature[1] == 'R')) { 71 /* Ignored, skip. */ 72 return OK; 73 } 74 else if ((susp_signature[0] == 'E') && (susp_signature[1] == 'S')) { 75 /* Ignored, skip. */ 76 return OK; 77 } 78 79 /* Not a SUSP fundamental entry. */ 80 return EINVAL; 81 } 82 83 void parse_susp_buffer(struct rrii_dir_record *dir, char *buffer, u32_t size) 84 { 85 /* 86 * Parse a SUSP system use entry for the ISO 9660. 87 * This is the main entry point for parsing SUSP data : SUSP entries are 88 * routed from here to the relevant handling functions. 89 */ 90 char susp_signature[2]; 91 u8_t susp_length; 92 93 int parser_return; 94 95 while (TRUE) { 96 /* A SUSP entry can't be smaller than 4 bytes. */ 97 if (size < 4) 98 return; 99 100 susp_signature[0] = buffer[0]; 101 susp_signature[1] = buffer[1]; 102 susp_length = *((u8_t*)buffer + 2); 103 104 /* Check if SUSP entry is present. */ 105 if (((susp_signature[0] == 0) && (susp_signature[1] == 0)) || 106 (susp_length > size) || (susp_length < 4)) 107 return; 108 109 /* Check for SUSP fundamental entry. */ 110 parser_return = parse_susp(dir, buffer); 111 if (parser_return == ECANCELED) 112 return; 113 else if (parser_return == OK) 114 goto next_entry; 115 116 /* Check for Rock Ridge entry. */ 117 if (opt.norock == FALSE) { 118 parser_return = parse_susp_rock_ridge(dir, buffer); 119 if (parser_return == ECANCELED) 120 return; 121 else if (parser_return == OK) 122 goto next_entry; 123 } 124 125 /* Parse next SUSP entry. */ 126 next_entry: 127 buffer += susp_length; 128 size -= susp_length; 129 } 130 } 131 132 #endif 133