xref: /minix/minix/fs/isofs/susp.c (revision ebfedea0)
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