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