1 |
|
|
/* $OpenBSD: iso9660_rrip.c,v 1.3 2016/10/16 20:26:56 natano Exp $ */ |
2 |
|
|
/* $NetBSD: iso9660_rrip.c,v 1.14 2014/05/30 13:14:47 martin Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan |
6 |
|
|
* Perez-Rathke and Ram Vedam. All rights reserved. |
7 |
|
|
* |
8 |
|
|
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys, |
9 |
|
|
* Alan Perez-Rathke and Ram Vedam. |
10 |
|
|
* |
11 |
|
|
* Redistribution and use in source and binary forms, with or |
12 |
|
|
* without modification, are permitted provided that the following |
13 |
|
|
* conditions are met: |
14 |
|
|
* 1. Redistributions of source code must retain the above copyright |
15 |
|
|
* notice, this list of conditions and the following disclaimer. |
16 |
|
|
* 2. Redistributions in binary form must reproduce the above |
17 |
|
|
* copyright notice, this list of conditions and the following |
18 |
|
|
* disclaimer in the documentation and/or other materials provided |
19 |
|
|
* with the distribution. |
20 |
|
|
* |
21 |
|
|
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN |
22 |
|
|
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR |
23 |
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 |
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
25 |
|
|
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN |
26 |
|
|
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT, |
27 |
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
28 |
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
29 |
|
|
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
30 |
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
31 |
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
33 |
|
|
* OF SUCH DAMAGE. |
34 |
|
|
*/ |
35 |
|
|
/* This will hold all the function definitions |
36 |
|
|
* defined in iso9660_rrip.h |
37 |
|
|
*/ |
38 |
|
|
|
39 |
|
|
#include "makefs.h" |
40 |
|
|
#include "cd9660.h" |
41 |
|
|
#include "iso9660_rrip.h" |
42 |
|
|
#include <sys/queue.h> |
43 |
|
|
#include <stdio.h> |
44 |
|
|
|
45 |
|
|
static void cd9660_rrip_initialize_inode(cd9660node *); |
46 |
|
|
static int cd9660_susp_handle_continuation(iso9660_disk *, cd9660node *); |
47 |
|
|
static int cd9660_susp_handle_continuation_common(iso9660_disk *, cd9660node *, |
48 |
|
|
int); |
49 |
|
|
|
50 |
|
|
int |
51 |
|
|
cd9660_susp_initialize(iso9660_disk *diskStructure, cd9660node *node, |
52 |
|
|
cd9660node *parent, cd9660node *grandparent) |
53 |
|
|
{ |
54 |
|
|
cd9660node *cn; |
55 |
|
|
int r; |
56 |
|
|
|
57 |
|
|
/* Make sure the node is not NULL. If it is, there are major problems */ |
58 |
|
|
assert(node != NULL); |
59 |
|
|
|
60 |
|
|
if (!(node->type & CD9660_TYPE_DOT) && |
61 |
|
|
!(node->type & CD9660_TYPE_DOTDOT)) |
62 |
|
|
TAILQ_INIT(&(node->head)); |
63 |
|
|
if (node->dot_record != 0) |
64 |
|
|
TAILQ_INIT(&(node->dot_record->head)); |
65 |
|
|
if (node->dot_dot_record != 0) |
66 |
|
|
TAILQ_INIT(&(node->dot_dot_record->head)); |
67 |
|
|
|
68 |
|
|
/* SUSP specific entries here */ |
69 |
|
|
if ((r = cd9660_susp_initialize_node(diskStructure, node)) < 0) |
70 |
|
|
return r; |
71 |
|
|
|
72 |
|
|
/* currently called cd9660node_rrip_init_links */ |
73 |
|
|
r = cd9660_rrip_initialize_node(diskStructure, node, parent, grandparent); |
74 |
|
|
if (r < 0) |
75 |
|
|
return r; |
76 |
|
|
|
77 |
|
|
/* |
78 |
|
|
* See if we need a CE record, and set all of the |
79 |
|
|
* associated counters. |
80 |
|
|
* |
81 |
|
|
* This should be called after all extensions. After |
82 |
|
|
* this is called, no new records should be added. |
83 |
|
|
*/ |
84 |
|
|
if ((r = cd9660_susp_handle_continuation(diskStructure, node)) < 0) |
85 |
|
|
return r; |
86 |
|
|
|
87 |
|
|
/* Recurse on children. */ |
88 |
|
|
TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) { |
89 |
|
|
if ((r = cd9660_susp_initialize(diskStructure, cn, node, parent)) < 0) |
90 |
|
|
return 0; |
91 |
|
|
} |
92 |
|
|
return 1; |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
int |
96 |
|
|
cd9660_susp_finalize(iso9660_disk *diskStructure, cd9660node *node) |
97 |
|
|
{ |
98 |
|
|
cd9660node *temp; |
99 |
|
|
int r; |
100 |
|
|
|
101 |
|
|
assert(node != NULL); |
102 |
|
|
|
103 |
|
|
if (node == diskStructure->rootNode) |
104 |
|
|
diskStructure->susp_continuation_area_current_free = 0; |
105 |
|
|
|
106 |
|
|
if ((r = cd9660_susp_finalize_node(diskStructure, node)) < 0) |
107 |
|
|
return r; |
108 |
|
|
if ((r = cd9660_rrip_finalize_node(diskStructure, node)) < 0) |
109 |
|
|
return r; |
110 |
|
|
|
111 |
|
|
TAILQ_FOREACH(temp, &node->cn_children, cn_next_child) { |
112 |
|
|
if ((r = cd9660_susp_finalize(diskStructure, temp)) < 0) |
113 |
|
|
return r; |
114 |
|
|
} |
115 |
|
|
return 1; |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
/* |
119 |
|
|
* If we really wanted to speed things up, we could have some sort of |
120 |
|
|
* lookup table on the SUSP entry type that calls a functor. Or, we could |
121 |
|
|
* combine the functions. These functions are kept separate to allow |
122 |
|
|
* easier addition of other extensions. |
123 |
|
|
|
124 |
|
|
* For the sake of simplicity and clarity, we won't be doing that for now. |
125 |
|
|
*/ |
126 |
|
|
|
127 |
|
|
/* |
128 |
|
|
* SUSP needs to update the following types: |
129 |
|
|
* CE (continuation area) |
130 |
|
|
*/ |
131 |
|
|
int |
132 |
|
|
cd9660_susp_finalize_node(iso9660_disk *diskStructure, cd9660node *node) |
133 |
|
|
{ |
134 |
|
|
struct ISO_SUSP_ATTRIBUTES *t; |
135 |
|
|
|
136 |
|
|
/* Handle CE counters */ |
137 |
|
|
if (node->susp_entry_ce_length > 0) { |
138 |
|
|
node->susp_entry_ce_start = |
139 |
|
|
diskStructure->susp_continuation_area_current_free; |
140 |
|
|
diskStructure->susp_continuation_area_current_free += |
141 |
|
|
node->susp_entry_ce_length; |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
TAILQ_FOREACH(t, &node->head, rr_ll) { |
145 |
|
|
if (t->susp_type != SUSP_TYPE_SUSP || |
146 |
|
|
t->entry_type != SUSP_ENTRY_SUSP_CE) |
147 |
|
|
continue; |
148 |
|
|
cd9660_bothendian_dword( |
149 |
|
|
diskStructure-> |
150 |
|
|
susp_continuation_area_start_sector, |
151 |
|
|
t->attr.su_entry.CE.ca_sector); |
152 |
|
|
|
153 |
|
|
cd9660_bothendian_dword( |
154 |
|
|
diskStructure-> |
155 |
|
|
susp_continuation_area_start_sector, |
156 |
|
|
t->attr.su_entry.CE.ca_sector); |
157 |
|
|
cd9660_bothendian_dword(node->susp_entry_ce_start, |
158 |
|
|
t->attr.su_entry.CE.offset); |
159 |
|
|
cd9660_bothendian_dword(node->susp_entry_ce_length, |
160 |
|
|
t->attr.su_entry.CE.length); |
161 |
|
|
} |
162 |
|
|
return 0; |
163 |
|
|
} |
164 |
|
|
|
165 |
|
|
int |
166 |
|
|
cd9660_rrip_finalize_node(iso9660_disk *diskStructure __unused, |
167 |
|
|
cd9660node *node) |
168 |
|
|
{ |
169 |
|
|
struct ISO_SUSP_ATTRIBUTES *t; |
170 |
|
|
|
171 |
|
|
TAILQ_FOREACH(t, &node->head, rr_ll) { |
172 |
|
|
if (t->susp_type != SUSP_TYPE_RRIP) |
173 |
|
|
continue; |
174 |
|
|
switch (t->entry_type) { |
175 |
|
|
case SUSP_ENTRY_RRIP_CL: |
176 |
|
|
/* Look at rr_relocated*/ |
177 |
|
|
if (node->rr_relocated == NULL) |
178 |
|
|
return -1; |
179 |
|
|
cd9660_bothendian_dword( |
180 |
|
|
node->rr_relocated->fileDataSector, |
181 |
|
|
(unsigned char *) |
182 |
|
|
t->attr.rr_entry.CL.dir_loc); |
183 |
|
|
break; |
184 |
|
|
case SUSP_ENTRY_RRIP_PL: |
185 |
|
|
/* Look at rr_real_parent */ |
186 |
|
|
if (node->parent == NULL || |
187 |
|
|
node->parent->rr_real_parent == NULL) |
188 |
|
|
return -1; |
189 |
|
|
cd9660_bothendian_dword( |
190 |
|
|
node->parent->rr_real_parent->fileDataSector, |
191 |
|
|
(unsigned char *) |
192 |
|
|
t->attr.rr_entry.PL.dir_loc); |
193 |
|
|
break; |
194 |
|
|
} |
195 |
|
|
} |
196 |
|
|
return 0; |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
static int |
200 |
|
|
cd9660_susp_handle_continuation_common(iso9660_disk *diskStructure, |
201 |
|
|
cd9660node *node, int space) |
202 |
|
|
{ |
203 |
|
|
int ca_used, susp_used, susp_used_pre_ce, working; |
204 |
|
|
struct ISO_SUSP_ATTRIBUTES *temp, *pre_ce, *last, *CE, *ST; |
205 |
|
|
|
206 |
|
|
pre_ce = last = NULL; |
207 |
|
|
working = 254 - space; |
208 |
|
|
if (node->su_tail_size > 0) |
209 |
|
|
/* Allow 4 bytes for "ST" record. */ |
210 |
|
|
working -= node->su_tail_size + 4; |
211 |
|
|
/* printf("There are %i bytes to work with\n",working); */ |
212 |
|
|
|
213 |
|
|
susp_used_pre_ce = susp_used = 0; |
214 |
|
|
ca_used = 0; |
215 |
|
|
TAILQ_FOREACH(temp, &node->head, rr_ll) { |
216 |
|
|
if (working < 0) |
217 |
|
|
break; |
218 |
|
|
/* |
219 |
|
|
* printf("SUSP Entry found, length is %i\n", |
220 |
|
|
* CD9660_SUSP_ENTRY_SIZE(temp)); |
221 |
|
|
*/ |
222 |
|
|
working -= CD9660_SUSP_ENTRY_SIZE(temp); |
223 |
|
|
if (working >= 0) { |
224 |
|
|
last = temp; |
225 |
|
|
susp_used += CD9660_SUSP_ENTRY_SIZE(temp); |
226 |
|
|
} |
227 |
|
|
if (working >= 28) { |
228 |
|
|
/* |
229 |
|
|
* Remember the last entry after which we |
230 |
|
|
* could insert a "CE" entry. |
231 |
|
|
*/ |
232 |
|
|
pre_ce = last; |
233 |
|
|
susp_used_pre_ce = susp_used; |
234 |
|
|
} |
235 |
|
|
} |
236 |
|
|
|
237 |
|
|
/* A CE entry is needed */ |
238 |
|
|
if (working <= 0) { |
239 |
|
|
CE = cd9660node_susp_create_node(SUSP_TYPE_SUSP, |
240 |
|
|
SUSP_ENTRY_SUSP_CE, "CE", SUSP_LOC_ENTRY); |
241 |
|
|
cd9660_susp_ce(CE, node); |
242 |
|
|
/* This will automatically insert at the appropriate location */ |
243 |
|
|
if (pre_ce != NULL) |
244 |
|
|
TAILQ_INSERT_AFTER(&node->head, pre_ce, CE, rr_ll); |
245 |
|
|
else |
246 |
|
|
TAILQ_INSERT_HEAD(&node->head, CE, rr_ll); |
247 |
|
|
last = CE; |
248 |
|
|
susp_used = susp_used_pre_ce + 28; |
249 |
|
|
/* Count how much CA data is necessary */ |
250 |
|
|
for (temp = TAILQ_NEXT(last, rr_ll); temp != NULL; |
251 |
|
|
temp = TAILQ_NEXT(temp, rr_ll)) { |
252 |
|
|
ca_used += CD9660_SUSP_ENTRY_SIZE(temp); |
253 |
|
|
} |
254 |
|
|
} |
255 |
|
|
|
256 |
|
|
/* An ST entry is needed */ |
257 |
|
|
if (node->su_tail_size > 0) { |
258 |
|
|
ST = cd9660node_susp_create_node(SUSP_TYPE_SUSP, |
259 |
|
|
SUSP_ENTRY_SUSP_ST, "ST", SUSP_LOC_ENTRY); |
260 |
|
|
cd9660_susp_st(ST, node); |
261 |
|
|
if (last != NULL) |
262 |
|
|
TAILQ_INSERT_AFTER(&node->head, last, ST, rr_ll); |
263 |
|
|
else |
264 |
|
|
TAILQ_INSERT_HEAD(&node->head, ST, rr_ll); |
265 |
|
|
last = ST; |
266 |
|
|
susp_used += 4; |
267 |
|
|
} |
268 |
|
|
if (last != NULL) |
269 |
|
|
last->last_in_suf = 1; |
270 |
|
|
|
271 |
|
|
node->susp_entry_size = susp_used; |
272 |
|
|
node->susp_entry_ce_length = ca_used; |
273 |
|
|
|
274 |
|
|
diskStructure->susp_continuation_area_size += ca_used; |
275 |
|
|
return 1; |
276 |
|
|
} |
277 |
|
|
|
278 |
|
|
/* See if a continuation entry is needed for each of the different types */ |
279 |
|
|
static int |
280 |
|
|
cd9660_susp_handle_continuation(iso9660_disk *diskStructure, cd9660node *node) |
281 |
|
|
{ |
282 |
|
|
assert (node != NULL); |
283 |
|
|
|
284 |
|
|
/* Entry */ |
285 |
|
|
if (cd9660_susp_handle_continuation_common(diskStructure, |
286 |
|
|
node,(int)(node->isoDirRecord->length[0])) < 0) |
287 |
|
|
return 0; |
288 |
|
|
|
289 |
|
|
return 1; |
290 |
|
|
} |
291 |
|
|
|
292 |
|
|
int |
293 |
|
|
cd9660_susp_initialize_node(iso9660_disk *diskStructure, cd9660node *node) |
294 |
|
|
{ |
295 |
|
|
struct ISO_SUSP_ATTRIBUTES *temp; |
296 |
|
|
|
297 |
|
|
/* |
298 |
|
|
* Requirements/notes: |
299 |
|
|
* CE: is added for us where needed |
300 |
|
|
* ST: not sure if it is even required, but if so, should be |
301 |
|
|
* handled by the CE code |
302 |
|
|
* PD: isnt needed (though might be added for testing) |
303 |
|
|
* SP: is stored ONLY on the . record of the root directory |
304 |
|
|
* ES: not sure |
305 |
|
|
*/ |
306 |
|
|
|
307 |
|
|
/* Check for root directory, add SP and ER if needed. */ |
308 |
|
|
if (node->type & CD9660_TYPE_DOT) { |
309 |
|
|
if (node->parent == diskStructure->rootNode) { |
310 |
|
|
temp = cd9660node_susp_create_node(SUSP_TYPE_SUSP, |
311 |
|
|
SUSP_ENTRY_SUSP_SP, "SP", SUSP_LOC_DOT); |
312 |
|
|
cd9660_susp_sp(temp, node); |
313 |
|
|
|
314 |
|
|
/* Should be first entry. */ |
315 |
|
|
TAILQ_INSERT_HEAD(&node->head, temp, rr_ll); |
316 |
|
|
} |
317 |
|
|
} |
318 |
|
|
return 1; |
319 |
|
|
} |
320 |
|
|
|
321 |
|
|
static void |
322 |
|
|
cd9660_rrip_initialize_inode(cd9660node *node) |
323 |
|
|
{ |
324 |
|
|
struct ISO_SUSP_ATTRIBUTES *attr; |
325 |
|
|
|
326 |
|
|
/* |
327 |
|
|
* Inode dependent values - this may change, |
328 |
|
|
* but for now virtual files and directories do |
329 |
|
|
* not have an inode structure |
330 |
|
|
*/ |
331 |
|
|
|
332 |
|
|
if ((node->node != NULL) && (node->node->inode != NULL)) { |
333 |
|
|
/* PX - POSIX attributes */ |
334 |
|
|
attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
335 |
|
|
SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); |
336 |
|
|
cd9660node_rrip_px(attr, node->node); |
337 |
|
|
|
338 |
|
|
TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); |
339 |
|
|
|
340 |
|
|
/* TF - timestamp */ |
341 |
|
|
attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
342 |
|
|
SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY); |
343 |
|
|
cd9660node_rrip_tf(attr, node->node); |
344 |
|
|
TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); |
345 |
|
|
|
346 |
|
|
/* SL - Symbolic link */ |
347 |
|
|
/* ?????????? Dan - why is this here? */ |
348 |
|
|
if (TAILQ_EMPTY(&node->cn_children) && |
349 |
|
|
node->node->inode != NULL && |
350 |
|
|
S_ISLNK(node->node->inode->st.st_mode)) |
351 |
|
|
cd9660_createSL(node); |
352 |
|
|
|
353 |
|
|
/* PN - device number */ |
354 |
|
|
if (node->node->inode != NULL && |
355 |
|
|
((S_ISCHR(node->node->inode->st.st_mode) || |
356 |
|
|
S_ISBLK(node->node->inode->st.st_mode)))) { |
357 |
|
|
attr = |
358 |
|
|
cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
359 |
|
|
SUSP_ENTRY_RRIP_PN, "PN", |
360 |
|
|
SUSP_LOC_ENTRY); |
361 |
|
|
cd9660node_rrip_pn(attr, node->node); |
362 |
|
|
TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); |
363 |
|
|
} |
364 |
|
|
} |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
int |
368 |
|
|
cd9660_rrip_initialize_node(iso9660_disk *diskStructure, cd9660node *node, |
369 |
|
|
cd9660node *parent, cd9660node *grandparent) |
370 |
|
|
{ |
371 |
|
|
struct ISO_SUSP_ATTRIBUTES *current = NULL; |
372 |
|
|
|
373 |
|
|
assert(node != NULL); |
374 |
|
|
|
375 |
|
|
if (node->type & CD9660_TYPE_DOT) { |
376 |
|
|
/* |
377 |
|
|
* Handle ER - should be the only entry to appear on |
378 |
|
|
* a "." record |
379 |
|
|
*/ |
380 |
|
|
if (node->parent == diskStructure->rootNode) { |
381 |
|
|
cd9660_susp_ER(node, 1, SUSP_RRIP_ER_EXT_ID, |
382 |
|
|
SUSP_RRIP_ER_EXT_DES, SUSP_RRIP_ER_EXT_SRC); |
383 |
|
|
} |
384 |
|
|
if (parent != NULL && parent->node != NULL && |
385 |
|
|
parent->node->inode != NULL) { |
386 |
|
|
/* PX - POSIX attributes */ |
387 |
|
|
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
388 |
|
|
SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); |
389 |
|
|
cd9660node_rrip_px(current, parent->node); |
390 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
391 |
|
|
} |
392 |
|
|
} else if (node->type & CD9660_TYPE_DOTDOT) { |
393 |
|
|
if (grandparent != NULL && grandparent->node != NULL && |
394 |
|
|
grandparent->node->inode != NULL) { |
395 |
|
|
/* PX - POSIX attributes */ |
396 |
|
|
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
397 |
|
|
SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); |
398 |
|
|
cd9660node_rrip_px(current, grandparent->node); |
399 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
400 |
|
|
} |
401 |
|
|
/* Handle PL */ |
402 |
|
|
if (parent != NULL && parent->rr_real_parent != NULL) { |
403 |
|
|
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
404 |
|
|
SUSP_ENTRY_RRIP_PL, "PL", SUSP_LOC_DOTDOT); |
405 |
|
|
cd9660_rrip_PL(current,node); |
406 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
407 |
|
|
} |
408 |
|
|
} else { |
409 |
|
|
cd9660_rrip_initialize_inode(node); |
410 |
|
|
|
411 |
|
|
/* |
412 |
|
|
* Not every node needs a NM set - only if the name is |
413 |
|
|
* actually different. IE: If a file is TEST -> TEST, |
414 |
|
|
* no NM. test -> TEST, need a NM |
415 |
|
|
* |
416 |
|
|
* The rr_moved_dir needs to be assigned a NM record as well. |
417 |
|
|
*/ |
418 |
|
|
if (node == diskStructure->rr_moved_dir) { |
419 |
|
|
cd9660_rrip_add_NM(node, RRIP_DEFAULT_MOVE_DIR_NAME); |
420 |
|
|
} |
421 |
|
|
else if ((node->node != NULL) && |
422 |
|
|
((strlen(node->node->name) != |
423 |
|
|
(uint8_t)node->isoDirRecord->name_len[0]) || |
424 |
|
|
(memcmp(node->node->name,node->isoDirRecord->name, |
425 |
|
|
(uint8_t)node->isoDirRecord->name_len[0]) != 0))) { |
426 |
|
|
cd9660_rrip_NM(node); |
427 |
|
|
} |
428 |
|
|
|
429 |
|
|
|
430 |
|
|
|
431 |
|
|
/* Rock ridge directory relocation code here. */ |
432 |
|
|
|
433 |
|
|
/* First handle the CL for the placeholder file. */ |
434 |
|
|
if (node->rr_relocated != NULL) { |
435 |
|
|
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
436 |
|
|
SUSP_ENTRY_RRIP_CL, "CL", SUSP_LOC_ENTRY); |
437 |
|
|
cd9660_rrip_CL(current, node); |
438 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
439 |
|
|
} |
440 |
|
|
|
441 |
|
|
/* Handle RE*/ |
442 |
|
|
if (node->rr_real_parent != NULL) { |
443 |
|
|
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
444 |
|
|
SUSP_ENTRY_RRIP_RE, "RE", SUSP_LOC_ENTRY); |
445 |
|
|
cd9660_rrip_RE(current,node); |
446 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
447 |
|
|
} |
448 |
|
|
} |
449 |
|
|
return 1; |
450 |
|
|
} |
451 |
|
|
|
452 |
|
|
struct ISO_SUSP_ATTRIBUTES* |
453 |
|
|
cd9660node_susp_create_node(int susp_type, int entry_type, const char *type_id, |
454 |
|
|
int write_loc) |
455 |
|
|
{ |
456 |
|
|
struct ISO_SUSP_ATTRIBUTES* temp; |
457 |
|
|
|
458 |
|
|
temp = emalloc(sizeof(*temp)); |
459 |
|
|
temp->susp_type = susp_type; |
460 |
|
|
temp->entry_type = entry_type; |
461 |
|
|
temp->last_in_suf = 0; |
462 |
|
|
/* Phase this out */ |
463 |
|
|
temp->type_of[0] = type_id[0]; |
464 |
|
|
temp->type_of[1] = type_id[1]; |
465 |
|
|
temp->write_location = write_loc; |
466 |
|
|
|
467 |
|
|
/* |
468 |
|
|
* Since the first four bytes is common, lets go ahead and |
469 |
|
|
* set the type identifier, since we are passing that to this |
470 |
|
|
* function anyhow. |
471 |
|
|
*/ |
472 |
|
|
temp->attr.su_entry.SP.h.type[0] = type_id[0]; |
473 |
|
|
temp->attr.su_entry.SP.h.type[1] = type_id[1]; |
474 |
|
|
return temp; |
475 |
|
|
} |
476 |
|
|
|
477 |
|
|
int |
478 |
|
|
cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES* p, cd9660node *node __unused) |
479 |
|
|
{ |
480 |
|
|
p->attr.rr_entry.PL.h.length[0] = 12; |
481 |
|
|
p->attr.rr_entry.PL.h.version[0] = 1; |
482 |
|
|
return 1; |
483 |
|
|
} |
484 |
|
|
|
485 |
|
|
int |
486 |
|
|
cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused) |
487 |
|
|
{ |
488 |
|
|
p->attr.rr_entry.CL.h.length[0] = 12; |
489 |
|
|
p->attr.rr_entry.CL.h.version[0] = 1; |
490 |
|
|
return 1; |
491 |
|
|
} |
492 |
|
|
|
493 |
|
|
int |
494 |
|
|
cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused) |
495 |
|
|
{ |
496 |
|
|
p->attr.rr_entry.RE.h.length[0] = 4; |
497 |
|
|
p->attr.rr_entry.RE.h.version[0] = 1; |
498 |
|
|
return 1; |
499 |
|
|
} |
500 |
|
|
|
501 |
|
|
void |
502 |
|
|
cd9660_createSL(cd9660node *node) |
503 |
|
|
{ |
504 |
|
|
struct ISO_SUSP_ATTRIBUTES* current; |
505 |
|
|
int path_count, dir_count, done, i, j, dir_copied; |
506 |
|
|
char temp_cr[255]; |
507 |
|
|
char temp_sl[255]; /* used in copying continuation entry*/ |
508 |
|
|
char* sl_ptr; |
509 |
|
|
|
510 |
|
|
sl_ptr = node->node->symlink; |
511 |
|
|
|
512 |
|
|
done = 0; |
513 |
|
|
path_count = 0; |
514 |
|
|
dir_count = 0; |
515 |
|
|
dir_copied = 0; |
516 |
|
|
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
517 |
|
|
SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY); |
518 |
|
|
|
519 |
|
|
current->attr.rr_entry.SL.h.version[0] = 1; |
520 |
|
|
current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE; |
521 |
|
|
|
522 |
|
|
if (*sl_ptr == '/') { |
523 |
|
|
temp_cr[0] = SL_FLAGS_ROOT; |
524 |
|
|
temp_cr[1] = 0; |
525 |
|
|
memcpy(current->attr.rr_entry.SL.component + path_count, |
526 |
|
|
temp_cr, 2); |
527 |
|
|
path_count += 2; |
528 |
|
|
sl_ptr++; |
529 |
|
|
} |
530 |
|
|
|
531 |
|
|
for (i = 0; i < (dir_count + 2); i++) |
532 |
|
|
temp_cr[i] = '\0'; |
533 |
|
|
|
534 |
|
|
while (!done) { |
535 |
|
|
while ((*sl_ptr != '/') && (*sl_ptr != '\0')) { |
536 |
|
|
dir_copied = 1; |
537 |
|
|
if (*sl_ptr == '.') { |
538 |
|
|
if ((*(sl_ptr + 1) == '/') || (*(sl_ptr + 1) |
539 |
|
|
== '\0')) { |
540 |
|
|
temp_cr[0] = SL_FLAGS_CURRENT; |
541 |
|
|
sl_ptr++; |
542 |
|
|
} else if(*(sl_ptr + 1) == '.') { |
543 |
|
|
if ((*(sl_ptr + 2) == '/') || |
544 |
|
|
(*(sl_ptr + 2) == '\0')) { |
545 |
|
|
temp_cr[0] = SL_FLAGS_PARENT; |
546 |
|
|
sl_ptr += 2; |
547 |
|
|
} |
548 |
|
|
} else { |
549 |
|
|
temp_cr[dir_count+2] = *sl_ptr; |
550 |
|
|
sl_ptr++; |
551 |
|
|
dir_count++; |
552 |
|
|
} |
553 |
|
|
} else { |
554 |
|
|
temp_cr[dir_count + 2] = *sl_ptr; |
555 |
|
|
sl_ptr++; |
556 |
|
|
dir_count++; |
557 |
|
|
} |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
if ((path_count + dir_count) >= 249) { |
561 |
|
|
current->attr.rr_entry.SL.flags[0] |= SL_FLAGS_CONTINUE; |
562 |
|
|
|
563 |
|
|
j = 0; |
564 |
|
|
|
565 |
|
|
if (path_count <= 249) { |
566 |
|
|
while(j != (249 - path_count)) { |
567 |
|
|
temp_sl[j] = temp_cr[j]; |
568 |
|
|
j++; |
569 |
|
|
} |
570 |
|
|
temp_sl[0] = SL_FLAGS_CONTINUE; |
571 |
|
|
temp_sl[1] = j - 2; |
572 |
|
|
memcpy( |
573 |
|
|
current->attr.rr_entry.SL.component + |
574 |
|
|
path_count, |
575 |
|
|
temp_sl, j); |
576 |
|
|
} |
577 |
|
|
|
578 |
|
|
path_count += j; |
579 |
|
|
current->attr.rr_entry.SL.h.length[0] = path_count + 5; |
580 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
581 |
|
|
current= cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
582 |
|
|
SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY); |
583 |
|
|
current->attr.rr_entry.SL.h.version[0] = 1; |
584 |
|
|
current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE; |
585 |
|
|
|
586 |
|
|
path_count = 0; |
587 |
|
|
|
588 |
|
|
if (dir_count > 2) { |
589 |
|
|
while (j != dir_count + 2) { |
590 |
|
|
current->attr.rr_entry.SL.component[ |
591 |
|
|
path_count + 2] = temp_cr[j]; |
592 |
|
|
j++; |
593 |
|
|
path_count++; |
594 |
|
|
} |
595 |
|
|
current->attr.rr_entry.SL.component[1] |
596 |
|
|
= path_count; |
597 |
|
|
path_count+= 2; |
598 |
|
|
} else { |
599 |
|
|
while(j != dir_count) { |
600 |
|
|
current->attr.rr_entry.SL.component[ |
601 |
|
|
path_count+2] = temp_cr[j]; |
602 |
|
|
j++; |
603 |
|
|
path_count++; |
604 |
|
|
} |
605 |
|
|
} |
606 |
|
|
} else { |
607 |
|
|
if (dir_copied == 1) { |
608 |
|
|
temp_cr[1] = dir_count; |
609 |
|
|
memcpy(current->attr.rr_entry.SL.component + |
610 |
|
|
path_count, |
611 |
|
|
temp_cr, dir_count + 2); |
612 |
|
|
path_count += dir_count + 2; |
613 |
|
|
} |
614 |
|
|
} |
615 |
|
|
|
616 |
|
|
if (*sl_ptr == '\0') { |
617 |
|
|
done = 1; |
618 |
|
|
current->attr.rr_entry.SL.h.length[0] = path_count + 5; |
619 |
|
|
TAILQ_INSERT_TAIL(&node->head, current, rr_ll); |
620 |
|
|
} else { |
621 |
|
|
sl_ptr++; |
622 |
|
|
dir_count = 0; |
623 |
|
|
dir_copied = 0; |
624 |
|
|
for(i = 0; i < 255; i++) { |
625 |
|
|
temp_cr[i] = '\0'; |
626 |
|
|
} |
627 |
|
|
} |
628 |
|
|
} |
629 |
|
|
} |
630 |
|
|
|
631 |
|
|
int |
632 |
|
|
cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo) |
633 |
|
|
{ |
634 |
|
|
v->attr.rr_entry.PX.h.length[0] = 36; |
635 |
|
|
v->attr.rr_entry.PX.h.version[0] = 1; |
636 |
|
|
cd9660_bothendian_dword(pxinfo->inode->st.st_mode, |
637 |
|
|
v->attr.rr_entry.PX.mode); |
638 |
|
|
cd9660_bothendian_dword(pxinfo->inode->st.st_nlink, |
639 |
|
|
v->attr.rr_entry.PX.links); |
640 |
|
|
cd9660_bothendian_dword(pxinfo->inode->st.st_uid, |
641 |
|
|
v->attr.rr_entry.PX.uid); |
642 |
|
|
cd9660_bothendian_dword(pxinfo->inode->st.st_gid, |
643 |
|
|
v->attr.rr_entry.PX.gid); |
644 |
|
|
|
645 |
|
|
/* Ignoring the serial number for now */ |
646 |
|
|
return 1; |
647 |
|
|
} |
648 |
|
|
|
649 |
|
|
int |
650 |
|
|
cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *pn_field, fsnode *fnode) |
651 |
|
|
{ |
652 |
|
|
pn_field->attr.rr_entry.PN.h.length[0] = 20; |
653 |
|
|
pn_field->attr.rr_entry.PN.h.version[0] = 1; |
654 |
|
|
|
655 |
|
|
if (sizeof (fnode->inode->st.st_rdev) > 4) |
656 |
|
|
cd9660_bothendian_dword( |
657 |
|
|
(uint64_t)fnode->inode->st.st_rdev >> 32, |
658 |
|
|
pn_field->attr.rr_entry.PN.high); |
659 |
|
|
else |
660 |
|
|
cd9660_bothendian_dword(0, pn_field->attr.rr_entry.PN.high); |
661 |
|
|
|
662 |
|
|
cd9660_bothendian_dword(fnode->inode->st.st_rdev & 0xffffffff, |
663 |
|
|
pn_field->attr.rr_entry.PN.low); |
664 |
|
|
return 1; |
665 |
|
|
} |
666 |
|
|
|
667 |
|
|
#if 0 |
668 |
|
|
int |
669 |
|
|
cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *file_node) |
670 |
|
|
{ |
671 |
|
|
int nm_length = strlen(file_node->isoDirRecord->name) + 5; |
672 |
|
|
p->attr.rr_entry.NM.h.type[0] = 'N'; |
673 |
|
|
p->attr.rr_entry.NM.h.type[1] = 'M'; |
674 |
|
|
sprintf(p->attr.rr_entry.NM.altname, "%s", file_node->isoDirRecord->name); |
675 |
|
|
p->attr.rr_entry.NM.h.length[0] = (unsigned char)nm_length; |
676 |
|
|
p->attr.rr_entry.NM.h.version[0] = (unsigned char)1; |
677 |
|
|
p->attr.rr_entry.NM.flags[0] = (unsigned char) NM_PARENT; |
678 |
|
|
return 1; |
679 |
|
|
} |
680 |
|
|
#endif |
681 |
|
|
|
682 |
|
|
int |
683 |
|
|
cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *p, fsnode *_node) |
684 |
|
|
{ |
685 |
|
|
p->attr.rr_entry.TF.flags[0] = TF_MODIFY | TF_ACCESS | TF_ATTRIBUTES; |
686 |
|
|
p->attr.rr_entry.TF.h.length[0] = 5; |
687 |
|
|
p->attr.rr_entry.TF.h.version[0] = 1; |
688 |
|
|
|
689 |
|
|
/* |
690 |
|
|
* Need to add creation time, backup time, |
691 |
|
|
* expiration time, and effective time. |
692 |
|
|
*/ |
693 |
|
|
|
694 |
|
|
cd9660_time_915(p->attr.rr_entry.TF.timestamp, |
695 |
|
|
_node->inode->st.st_atime); |
696 |
|
|
p->attr.rr_entry.TF.h.length[0] += 7; |
697 |
|
|
|
698 |
|
|
cd9660_time_915(p->attr.rr_entry.TF.timestamp + 7, |
699 |
|
|
_node->inode->st.st_mtime); |
700 |
|
|
p->attr.rr_entry.TF.h.length[0] += 7; |
701 |
|
|
|
702 |
|
|
cd9660_time_915(p->attr.rr_entry.TF.timestamp + 14, |
703 |
|
|
_node->inode->st.st_ctime); |
704 |
|
|
p->attr.rr_entry.TF.h.length[0] += 7; |
705 |
|
|
return 1; |
706 |
|
|
} |
707 |
|
|
|
708 |
|
|
int |
709 |
|
|
cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused) |
710 |
|
|
{ |
711 |
|
|
p->attr.su_entry.SP.h.length[0] = 7; |
712 |
|
|
p->attr.su_entry.SP.h.version[0] = 1; |
713 |
|
|
p->attr.su_entry.SP.check[0] = 0xBE; |
714 |
|
|
p->attr.su_entry.SP.check[1] = 0xEF; |
715 |
|
|
p->attr.su_entry.SP.len_skp[0] = 0; |
716 |
|
|
return 1; |
717 |
|
|
} |
718 |
|
|
|
719 |
|
|
int |
720 |
|
|
cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *stinfo __unused) |
721 |
|
|
{ |
722 |
|
|
p->attr.su_entry.ST.h.type[0] = 'S'; |
723 |
|
|
p->attr.su_entry.ST.h.type[1] = 'T'; |
724 |
|
|
p->attr.su_entry.ST.h.length[0] = 4; |
725 |
|
|
p->attr.su_entry.ST.h.version[0] = 1; |
726 |
|
|
return 1; |
727 |
|
|
} |
728 |
|
|
|
729 |
|
|
int |
730 |
|
|
cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused) |
731 |
|
|
{ |
732 |
|
|
p->attr.su_entry.CE.h.length[0] = 28; |
733 |
|
|
p->attr.su_entry.CE.h.version[0] = 1; |
734 |
|
|
/* Other attributes dont matter right now, will be updated later */ |
735 |
|
|
return 1; |
736 |
|
|
} |
737 |
|
|
|
738 |
|
|
int |
739 |
|
|
cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES *p __unused, int length __unused) |
740 |
|
|
{ |
741 |
|
|
return 1; |
742 |
|
|
} |
743 |
|
|
|
744 |
|
|
void |
745 |
|
|
cd9660_rrip_add_NM(cd9660node *node, const char *name) |
746 |
|
|
{ |
747 |
|
|
int working,len; |
748 |
|
|
const char *p; |
749 |
|
|
struct ISO_SUSP_ATTRIBUTES *r; |
750 |
|
|
|
751 |
|
|
/* |
752 |
|
|
* Each NM record has 254 byes to work with. This means that |
753 |
|
|
* the name data itself only has 249 bytes to work with. So, a |
754 |
|
|
* name with 251 characters would require two nm records. |
755 |
|
|
*/ |
756 |
|
|
p = name; |
757 |
|
|
working = 1; |
758 |
|
|
while (working) { |
759 |
|
|
r = cd9660node_susp_create_node(SUSP_TYPE_RRIP, |
760 |
|
|
SUSP_ENTRY_RRIP_NM, "NM", SUSP_LOC_ENTRY); |
761 |
|
|
r->attr.rr_entry.NM.h.version[0] = 1; |
762 |
|
|
r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_NONE; |
763 |
|
|
len = strlen(p); |
764 |
|
|
|
765 |
|
|
if (len > 249) { |
766 |
|
|
len = 249; |
767 |
|
|
r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_CONTINUE; |
768 |
|
|
} else { |
769 |
|
|
working = 0; |
770 |
|
|
} |
771 |
|
|
memcpy(r->attr.rr_entry.NM.altname, p, len); |
772 |
|
|
r->attr.rr_entry.NM.h.length[0] = 5 + len; |
773 |
|
|
|
774 |
|
|
TAILQ_INSERT_TAIL(&node->head, r, rr_ll); |
775 |
|
|
|
776 |
|
|
p += len; |
777 |
|
|
} |
778 |
|
|
} |
779 |
|
|
|
780 |
|
|
void |
781 |
|
|
cd9660_rrip_NM(cd9660node *node) |
782 |
|
|
{ |
783 |
|
|
cd9660_rrip_add_NM(node, node->node->name); |
784 |
|
|
} |
785 |
|
|
|
786 |
|
|
struct ISO_SUSP_ATTRIBUTES* |
787 |
|
|
cd9660_susp_ER(cd9660node *node, |
788 |
|
|
u_char ext_version, const char* ext_id, const char* ext_des, |
789 |
|
|
const char* ext_src) |
790 |
|
|
{ |
791 |
|
|
int l; |
792 |
|
|
struct ISO_SUSP_ATTRIBUTES *r; |
793 |
|
|
|
794 |
|
|
r = cd9660node_susp_create_node(SUSP_TYPE_SUSP, |
795 |
|
|
SUSP_ENTRY_SUSP_ER, "ER", SUSP_LOC_DOT); |
796 |
|
|
|
797 |
|
|
/* Fixed data is 8 bytes */ |
798 |
|
|
r->attr.su_entry.ER.h.length[0] = 8; |
799 |
|
|
r->attr.su_entry.ER.h.version[0] = 1; |
800 |
|
|
|
801 |
|
|
r->attr.su_entry.ER.len_id[0] = (u_char)strlen(ext_id); |
802 |
|
|
r->attr.su_entry.ER.len_des[0] = (u_char)strlen(ext_des); |
803 |
|
|
r->attr.su_entry.ER.len_src[0] = (u_char)strlen(ext_src); |
804 |
|
|
|
805 |
|
|
l = r->attr.su_entry.ER.len_id[0] + |
806 |
|
|
r->attr.su_entry.ER.len_src[0] + |
807 |
|
|
r->attr.su_entry.ER.len_des[0]; |
808 |
|
|
|
809 |
|
|
/* Everything must fit. */ |
810 |
|
|
assert(l + r->attr.su_entry.ER.h.length[0] <= 254); |
811 |
|
|
|
812 |
|
|
r->attr.su_entry.ER.h.length[0] += (u_char)l; |
813 |
|
|
|
814 |
|
|
|
815 |
|
|
r->attr.su_entry.ER.ext_ver[0] = ext_version; |
816 |
|
|
memcpy(r->attr.su_entry.ER.ext_data, ext_id, |
817 |
|
|
(int)r->attr.su_entry.ER.len_id[0]); |
818 |
|
|
l = (int) r->attr.su_entry.ER.len_id[0]; |
819 |
|
|
memcpy(r->attr.su_entry.ER.ext_data + l,ext_des, |
820 |
|
|
(int)r->attr.su_entry.ER.len_des[0]); |
821 |
|
|
|
822 |
|
|
l += (int)r->attr.su_entry.ER.len_des[0]; |
823 |
|
|
memcpy(r->attr.su_entry.ER.ext_data + l,ext_src, |
824 |
|
|
(int)r->attr.su_entry.ER.len_src[0]); |
825 |
|
|
|
826 |
|
|
TAILQ_INSERT_TAIL(&node->head, r, rr_ll); |
827 |
|
|
return r; |
828 |
|
|
} |
829 |
|
|
|
830 |
|
|
struct ISO_SUSP_ATTRIBUTES* |
831 |
|
|
cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES *last __unused, cd9660node *node __unused) |
832 |
|
|
{ |
833 |
|
|
return NULL; |
834 |
|
|
} |