Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / fs / isofs / susp_rock_ridge.c
blob7c31df214356b5bcd01fd80173bcfd0eb74c899e
1 /*
2 * This file contains support for Rock Ridge Interchange Protocol (RRIP)
3 * extension to ISO 9660.
4 */
6 #include "inc.h"
7 #include <sys/stat.h>
9 #ifdef ISO9660_OPTION_ROCKRIDGE
11 void parse_susp_rock_ridge_plcl(struct rrii_dir_record *dir, u32_t block) {
12 struct inode *rep_inode;
13 struct buf *bp;
14 struct iso9660_dir_record *dir_rec;
15 struct dir_extent extent;
16 struct inode_dir_entry dummy_dir_entry;
17 size_t dummy_offset = 0;
19 /* Check if inode wasn't already parsed. */
20 rep_inode = inode_cache_get(block);
21 if (rep_inode != NULL) {
22 rep_inode->i_refcount++;
23 dir->reparented_inode = rep_inode;
24 return;
27 /* Peek ahead to build extent for read_inode. */
28 if (lmfs_get_block(&bp, fs_dev, block, NORMAL) != OK)
29 return;
31 dir_rec = (struct iso9660_dir_record*)b_data(bp);
33 extent.location = block;
34 extent.length = dir_rec->data_length_l / v_pri.logical_block_size_l;
35 if (dir_rec->data_length_l % v_pri.logical_block_size_l)
36 extent.length++;
37 extent.next = NULL;
38 lmfs_put_block(bp);
40 memset(&dummy_dir_entry, 0, sizeof(struct inode_dir_entry));
41 /* XXX what if this fails? */
42 read_inode(&dummy_dir_entry, &extent, &dummy_offset);
43 free(dummy_dir_entry.r_name);
44 dir->reparented_inode = dummy_dir_entry.i_node;
47 void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer, int length)
49 /* Parse a Rock Ridge SUSP symbolic link entry (SL). */
50 int offset = 0;
51 int slink_size;
52 u8_t flags, component_length;
54 while (offset + 2 <= length) {
55 flags = *((u8_t*)(buffer + offset));
56 component_length = *((u8_t*)(buffer + offset + 1));
58 /* Add directory separator if necessary. */
59 if (strcmp(dir->slink_rrip, "") != 0 &&
60 strcmp(dir->slink_rrip, "/") != 0) {
61 slink_size = strlen(dir->slink_rrip);
62 if (slink_size + 2 >= ISO9660_RRIP_MAX_FILE_ID_LEN)
63 return;
65 dir->slink_rrip[slink_size++] = '/';
66 dir->slink_rrip[slink_size] = '\0';
68 else
69 slink_size = strlen(dir->slink_rrip);
71 switch (flags & 0xF) {
72 case 0:
73 case 1: {
75 * Directory path component.
76 * Check if component fits within SL entry and
77 * within symbolic link field.
79 if ((component_length > length - offset) ||
80 (slink_size + component_length + 1 >=
81 ISO9660_RRIP_MAX_FILE_ID_LEN)) {
82 return;
85 strlcat(&dir->slink_rrip[slink_size],
86 buffer + offset + 2,
87 component_length + 1);
89 break;
91 case 2: {
92 /* Current directory path component. */
93 if (slink_size + 2 >=
94 ISO9660_RRIP_MAX_FILE_ID_LEN) {
95 return;
98 strcat(&dir->slink_rrip[slink_size], ".");
100 break;
102 case 4: {
103 /* Parent directory path component. */
104 if (slink_size + 3 >=
105 ISO9660_RRIP_MAX_FILE_ID_LEN) {
106 return;
109 strcat(&dir->slink_rrip[slink_size], "..");
111 break;
113 case 8: {
114 /* Root directory path component relative to
115 the current process. */
116 if (slink_size + 2 >=
117 ISO9660_RRIP_MAX_FILE_ID_LEN) {
118 return;
121 strcat(&dir->slink_rrip[slink_size], "/");
123 break;
125 default: {
126 /* Unsupported/invalid flags. */
127 return;
131 offset += component_length + 2;
135 int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer)
137 /* Parse Rock Ridge SUSP entries for a directory entry. */
138 char susp_signature[2];
139 u8_t susp_length;
140 u8_t susp_version;
142 int rrii_name_current_size;
143 int rrii_name_append_size;
144 int rrii_tf_flags;
145 int rrii_tf_offset;
146 u32_t rrii_pn_rdev_major;
147 u32_t rrii_pn_rdev_minor;
148 mode_t rrii_px_posix_mode;
149 u32_t rrii_pcl_block;
151 susp_signature[0] = buffer[0];
152 susp_signature[1] = buffer[1];
153 susp_length = *((u8_t*)buffer + 2);
154 susp_version = *((u8_t*)buffer + 3);
156 if ((susp_signature[0] == 'P') && (susp_signature[1] == 'X') &&
157 (susp_length >= 36) && (susp_version >= 1)) {
158 /* POSIX file mode, UID and GID. */
159 dir->d_mode = *((u32_t*)(buffer + 4));
160 dir->uid = *((u32_t*)(buffer + 20));
161 dir->gid = *((u32_t*)(buffer + 28));
163 return OK;
165 else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'N') &&
166 (susp_length >= 20) && (susp_version >= 1)) {
167 /* Device ID (for character or block special inode). */
170 * XXX: Specific to how Minix ISO is generated, will have to
171 * investigate why makefs does that later.
173 #if 0
174 rrii_pn_rdev_major = *((u32_t*)(buffer + 4));
175 rrii_pn_rdev_minor = *((u32_t*)(buffer + 12));
176 #else
177 rrii_pn_rdev_major = *((u32_t*)(buffer + 12)) >> 8;
178 rrii_pn_rdev_minor = *((u32_t*)(buffer + 12)) & 0xFF;
179 #endif
180 dir->rdev = makedev(rrii_pn_rdev_major, rrii_pn_rdev_minor);
182 return OK;
184 else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'L') &&
185 (susp_length > 5) && (susp_version >= 1)) {
186 /* Symbolic link target. Multiple entries may be used to
187 concatenate the complete path target. */
188 parse_susp_rock_ridge_sl(dir, buffer + 5, susp_length - 5);
190 return OK;
192 else if ((susp_signature[0] == 'N') && (susp_signature[1] == 'M') &&
193 (susp_length > 5) && (susp_version >= 1)) {
194 /* Alternate POSIX name. Multiple entries may be used to
195 concatenate the complete filename. */
196 rrii_name_current_size = strlen(dir->file_id_rrip);
197 rrii_name_append_size = susp_length - 5;
199 /* Concatenate only if name component fits. */
200 if (rrii_name_current_size + rrii_name_append_size + 1 <
201 ISO9660_RRIP_MAX_FILE_ID_LEN) {
202 strlcpy(dir->file_id_rrip + rrii_name_current_size,
203 buffer + 5, rrii_name_append_size+1);
206 return OK;
208 else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'L') &&
209 (susp_length >= 12) && (susp_version >= 1)) {
210 /* Reparenting ".." directory entry. */
211 rrii_pcl_block = *((u32_t*)(buffer + 4));
212 parse_susp_rock_ridge_plcl(dir, rrii_pcl_block);
214 return OK;
216 else if ((susp_signature[0] == 'C') && (susp_signature[1] == 'L') &&
217 (susp_length >= 12) && (susp_version >= 1)) {
218 /* Reorganize deep directory entry. */
219 rrii_pcl_block = *((u32_t*)(buffer + 4));
220 parse_susp_rock_ridge_plcl(dir, rrii_pcl_block);
222 return OK;
224 else if ((susp_signature[0] == 'R') && (susp_signature[1] == 'E')) {
225 /* Ignored, skip. */
227 return OK;
229 else if ((susp_signature[0] == 'T') && (susp_signature[1] == 'F') &&
230 (susp_length >= 5) && (susp_version >= 1)) {
231 /* POSIX timestamp. */
232 rrii_tf_flags = buffer[5];
233 rrii_tf_offset = 5;
236 * ISO 9660 17-byte time format.
237 * FIXME: 17-byte time format not supported in TF entry.
239 if (rrii_tf_flags & (1 << 7)) { }
241 /* ISO 9660 7-byte time format. */
242 else {
243 /* Creation time */
244 if ((rrii_tf_flags & (1 << 0)) &&
245 (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
246 memcpy(dir->birthtime, buffer+rrii_tf_offset,
247 ISO9660_SIZE_DATE7);
248 rrii_tf_offset += ISO9660_SIZE_DATE7;
251 /* Modification time */
252 if ((rrii_tf_flags & (1 << 1)) &&
253 (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
254 memcpy(dir->mtime, buffer+rrii_tf_offset,
255 ISO9660_SIZE_DATE7);
256 rrii_tf_offset += ISO9660_SIZE_DATE7;
259 /* Last access time. */
260 if ((rrii_tf_flags & (1 << 2)) &&
261 (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
262 memcpy(dir->atime, buffer+rrii_tf_offset,
263 ISO9660_SIZE_DATE7);
264 rrii_tf_offset += ISO9660_SIZE_DATE7;
267 /* Last attribute change time. */
268 if ((rrii_tf_flags & (1 << 3)) &&
269 (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
270 memcpy(dir->ctime, buffer+rrii_tf_offset,
271 ISO9660_SIZE_DATE7);
272 rrii_tf_offset += ISO9660_SIZE_DATE7;
275 /* The rest is ignored. */
278 return OK;
280 else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'F')) {
281 /* Ignored, skip. */
282 return OK;
285 /* Not a Rock Ridge entry. */
286 return EINVAL;
289 #endif