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