1 | /* $Id: isomaker.cpp 67271 2017-06-06 13:30:41Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * IPRT - ISO Image Maker.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2017 Oracle Corporation
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
12 | * General Public License (GPL) as published by the Free Software
|
---|
13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
16 | *
|
---|
17 | * The contents of this file may alternatively be used under the terms
|
---|
18 | * of the Common Development and Distribution License Version 1.0
|
---|
19 | * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
|
---|
20 | * VirtualBox OSE distribution, in which case the provisions of the
|
---|
21 | * CDDL are applicable instead of those of the GPL.
|
---|
22 | *
|
---|
23 | * You may elect to license modified versions of this file under the
|
---|
24 | * terms and conditions of either the GPL or the CDDL or both.
|
---|
25 | */
|
---|
26 |
|
---|
27 |
|
---|
28 | /*********************************************************************************************************************************
|
---|
29 | * Header Files *
|
---|
30 | *********************************************************************************************************************************/
|
---|
31 | #define LOG_GROUP RTLOGGROUP_FS
|
---|
32 | #include "internal/iprt.h"
|
---|
33 | #include <iprt/fsvfs.h>
|
---|
34 |
|
---|
35 | #include <iprt/asm.h>
|
---|
36 | #include <iprt/assert.h>
|
---|
37 | #include <iprt/err.h>
|
---|
38 | #include <iprt/file.h>
|
---|
39 | #include <iprt/list.h>
|
---|
40 | #include <iprt/log.h>
|
---|
41 | #include <iprt/mem.h>
|
---|
42 | #include <iprt/string.h>
|
---|
43 | #include <iprt/vfs.h>
|
---|
44 | #include <iprt/formats/iso9660.h>
|
---|
45 |
|
---|
46 | #include <internal/magics.h>
|
---|
47 |
|
---|
48 |
|
---|
49 | /*********************************************************************************************************************************
|
---|
50 | * Defined Constants And Macros *
|
---|
51 | *********************************************************************************************************************************/
|
---|
52 | /** Asserts valid handle, returns VERR_INVALID_HANDLE if not. */
|
---|
53 | #define RTFSISOMAKER_ASSER_VALID_HANDLE_RET(a_pThis) \
|
---|
54 | do { AssertPtrReturn(a_pThis, VERR_INVALID_HANDLE); \
|
---|
55 | AssertPtrReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, VERR_INVALID_HANDLE); \
|
---|
56 | } while (0)
|
---|
57 |
|
---|
58 | /** The sector size. */
|
---|
59 | #define RTFSISOMAKER_SECTOR_SIZE _2K
|
---|
60 | /** Maximum number of objects. */
|
---|
61 | #define RTFSISOMAKER_MAX_OBJECTS _16M
|
---|
62 |
|
---|
63 |
|
---|
64 | /*********************************************************************************************************************************
|
---|
65 | * Structures and Typedefs *
|
---|
66 | *********************************************************************************************************************************/
|
---|
67 | /** Pointer to an ISO maker object name space node. */
|
---|
68 | typedef struct RTFSISOMAKERNAME *PRTFSISOMAKERNAME;
|
---|
69 | /** Pointer to a common ISO image maker file system object. */
|
---|
70 | typedef struct RTFSISOMAKEROBJ *PRTFSISOMAKEROBJ;
|
---|
71 | /** Pointer to a ISO maker file object. */
|
---|
72 | typedef struct RTFSISOMAKERFILE *PRTFSISOMAKERFILE;
|
---|
73 |
|
---|
74 |
|
---|
75 | /** @name RTFSISOMAKER_NAMESPACE_XXX - Namespace selector.
|
---|
76 | * @{
|
---|
77 | */
|
---|
78 | #define RTFSISOMAKERNAMESPACE_ISO_9660 RT_BIT_32(0) /**< The primary ISO-9660 namespace. */
|
---|
79 | #define RTFSISOMAKERNAMESPACE_JOLIET RT_BIT_32(1) /**< The joliet namespace. */
|
---|
80 | #define RTFSISOMAKERNAMESPACE_UDF RT_BIT_32(2) /**< The UDF namespace. */
|
---|
81 | #define RTFSISOMAKERNAMESPACE_HFS RT_BIT_32(3) /**< The HFS namespace */
|
---|
82 | #define RTFSISOMAKERNAMESPACE_ALL UINT32_C(0x0000000f) /**< All namespaces. */
|
---|
83 | #define RTFSISOMAKERNAMESPACE_VALID_MASK UINT32_C(0x0000000f) /**< Valid namespace bits. */
|
---|
84 | /** @} */
|
---|
85 |
|
---|
86 |
|
---|
87 | /**
|
---|
88 | * Filesystem object type.
|
---|
89 | */
|
---|
90 | typedef enum RTFSISOMAKEROBJTYPE
|
---|
91 | {
|
---|
92 | RTFSISOMAKEROBJTYPE_INVALID = 0,
|
---|
93 | RTFSISOMAKEROBJTYPE_DIR,
|
---|
94 | RTFSISOMAKEROBJTYPE_FILE,
|
---|
95 | //RTFSISOMAKEROBJTYPE_SYMLINK,
|
---|
96 | RTFSISOMAKEROBJTYPE_END
|
---|
97 | } RTFSISOMAKEROBJTYPE;
|
---|
98 |
|
---|
99 | /**
|
---|
100 | * Extra name space information required for directories.
|
---|
101 | */
|
---|
102 | typedef struct RTFSISOMAKERNAMEDIR
|
---|
103 | {
|
---|
104 | /** The location of the directory data. */
|
---|
105 | uint64_t offDir;
|
---|
106 | /** The size of the directory. */
|
---|
107 | uint32_t cbDir;
|
---|
108 | /** Number of children. */
|
---|
109 | uint32_t cChildren;
|
---|
110 | /** Sorted array of children. */
|
---|
111 | PRTFSISOMAKERNAME *papChildren;
|
---|
112 |
|
---|
113 | /** The translate table file. */
|
---|
114 | PRTFSISOMAKERFILE pTransTblFile;
|
---|
115 | } RTFSISOMAKERNAMEDIR;
|
---|
116 | /** Pointer to directory specfic name space node info. */
|
---|
117 | typedef RTFSISOMAKERNAMEDIR *PRTFSISOMAKERNAMEDIR;
|
---|
118 |
|
---|
119 |
|
---|
120 | /**
|
---|
121 | * ISO maker object namespace node.
|
---|
122 | */
|
---|
123 | typedef struct RTFSISOMAKERNAME
|
---|
124 | {
|
---|
125 | /** Pointer to the file system object. */
|
---|
126 | PRTFSISOMAKEROBJ pObj;
|
---|
127 | /** Pointer to the partent directory, NULL if root dir. */
|
---|
128 | PRTFSISOMAKERNAME pParent;
|
---|
129 |
|
---|
130 | /** Pointer to the directory information if this is a directory, NULL if not a
|
---|
131 | * directory. This is allocated together with this structure, so it doesn't need
|
---|
132 | * freeing. */
|
---|
133 | PRTFSISOMAKERNAMEDIR pDir;
|
---|
134 |
|
---|
135 | /** The name specified when creating this namespace node. Helps navigating
|
---|
136 | * the namespace when we mangle or otherwise change the names.
|
---|
137 | * Allocated together with of this structure, no spearate free necessary. */
|
---|
138 | const char *pszSpecNm;
|
---|
139 |
|
---|
140 | /** Alternative rock ridge name. */
|
---|
141 | char *pszRockRidgeNm;
|
---|
142 | /** Alternative TRANS.TBL name. */
|
---|
143 | char *pszTransNm;
|
---|
144 | /** Length of pszRockRidgeNm. */
|
---|
145 | uint16_t cchRockRidgeNm;
|
---|
146 | /** Length of pszTransNm. */
|
---|
147 | uint16_t cchTransNm;
|
---|
148 |
|
---|
149 | /** The depth in the namespace tree of this name. */
|
---|
150 | uint8_t uDepth;
|
---|
151 | /** Set if pszTransNm is allocated separately. */
|
---|
152 | bool fTransNmAlloced : 1;
|
---|
153 | /** Set if pszTransNm is allocated separately. */
|
---|
154 | bool fRockRidgeNmAlloced : 1;
|
---|
155 |
|
---|
156 | /** @todo more rock ridge info here. */
|
---|
157 |
|
---|
158 | /** The name length. */
|
---|
159 | uint16_t cchName;
|
---|
160 | /** The name. */
|
---|
161 | char szName[RT_FLEXIBLE_ARRAY];
|
---|
162 | } RTFSISOMAKERNAME;
|
---|
163 |
|
---|
164 |
|
---|
165 | /**
|
---|
166 | * Common base structure for the file system objects.
|
---|
167 | */
|
---|
168 | typedef struct RTFSISOMAKEROBJ
|
---|
169 | {
|
---|
170 | /** The linear list entry of the image content. */
|
---|
171 | RTLISTNODE Entry;
|
---|
172 | /** The object index. */
|
---|
173 | uint32_t idxObj;
|
---|
174 | /** The type of this object. */
|
---|
175 | RTFSISOMAKEROBJTYPE enmType;
|
---|
176 |
|
---|
177 | /** The primary ISO-9660 name space name. */
|
---|
178 | PRTFSISOMAKERNAME pPrimaryName;
|
---|
179 | /** The joliet name space name. */
|
---|
180 | PRTFSISOMAKERNAME pJolietName;
|
---|
181 | /** The UDF name space name. */
|
---|
182 | PRTFSISOMAKERNAME pUdfName;
|
---|
183 | /** The HFS name space name. */
|
---|
184 | PRTFSISOMAKERNAME pHfsName;
|
---|
185 |
|
---|
186 | } RTFSISOMAKEROBJ;
|
---|
187 |
|
---|
188 |
|
---|
189 | /**
|
---|
190 | * File source type.
|
---|
191 | */
|
---|
192 | typedef enum RTFSISOMAKERSRCTYPE
|
---|
193 | {
|
---|
194 | RTFSISOMAKERSRCTYPE_INVALID = 0,
|
---|
195 | RTFSISOMAKERSRCTYPE_PATH,
|
---|
196 | RTFSISOMAKERSRCTYPE_VFS_IO_STREAM,
|
---|
197 | RTFSISOMAKERSRCTYPE_END
|
---|
198 | } RTFSISOMAKERSRCTYPE;
|
---|
199 |
|
---|
200 | /**
|
---|
201 | * ISO maker file object.
|
---|
202 | */
|
---|
203 | typedef struct RTFSISOMAKERFILE
|
---|
204 | {
|
---|
205 | /** The common bit. */
|
---|
206 | RTFSISOMAKEROBJ Core;
|
---|
207 | /** The file data size. */
|
---|
208 | uint64_t cbData;
|
---|
209 | /** Byte offset of the data in the image. */
|
---|
210 | uint64_t offData;
|
---|
211 |
|
---|
212 | /** The type of source object. */
|
---|
213 | RTFSISOMAKERSRCTYPE enmSrcType;
|
---|
214 | /** The source data. */
|
---|
215 | union
|
---|
216 | {
|
---|
217 | /** Path to the source file. */
|
---|
218 | const char *pszSrcPath;
|
---|
219 | /** Source I/O stream (or file). */
|
---|
220 | RTVFSIOSTREAM hVfsIoStr;
|
---|
221 | } u;
|
---|
222 | } RTFSISOMAKERFILE;
|
---|
223 |
|
---|
224 |
|
---|
225 | /**
|
---|
226 | * ISO maker directory object.
|
---|
227 | *
|
---|
228 | * Unlike files, the allocation info is name space specific and lives in the
|
---|
229 | * corresponding RTFSISOMAKERNAMEDIR structures.
|
---|
230 | */
|
---|
231 | typedef struct RTFSISOMAKERDIR
|
---|
232 | {
|
---|
233 | /** The common bit. */
|
---|
234 | RTFSISOMAKEROBJ Core;
|
---|
235 | } RTFSISOMAKERDIR;
|
---|
236 | /** Pointer to an ISO maker directory object. */
|
---|
237 | typedef RTFSISOMAKERDIR *PRTFSISOMAKERDIR;
|
---|
238 |
|
---|
239 |
|
---|
240 |
|
---|
241 | /**
|
---|
242 | * Instance data for a ISO image maker.
|
---|
243 | */
|
---|
244 | typedef struct RTFSISOMAKERINT
|
---|
245 | {
|
---|
246 | /** Magic value (RTFSISOMAKERINT_MAGIC). */
|
---|
247 | uint32_t uMagic;
|
---|
248 | /** Reference counter. */
|
---|
249 | uint32_t volatile cRefs;
|
---|
250 |
|
---|
251 | /** @name Name space configuration.
|
---|
252 | * @{ */
|
---|
253 | /** Set after we've been fed the first bit of content.
|
---|
254 | * This means that the namespace configuration has been finalized and can no
|
---|
255 | * longer be changed because it's simply too much work to do adjustments
|
---|
256 | * after having started to add files. */
|
---|
257 | bool fSeenContent;
|
---|
258 | /** The ISO level (1-3), default is 3.
|
---|
259 | * @todo support mkisofs level 4 (ISO-9660:1990, version 2). */
|
---|
260 | uint8_t uIsoLevel;
|
---|
261 | /** The ISO rock ridge level: 1 - enabled; 2 - with ER tag.
|
---|
262 | * Linux behaves a little different when seeing the ER tag. */
|
---|
263 | uint8_t uRockRidgeLevel;
|
---|
264 | /** The joliet UCS level (1, 2, or 3), 0 if joliet is not enabled. */
|
---|
265 | uint8_t uJolietLevel;
|
---|
266 | /** The joliet rock ridge level: 1 - enabled; 2 - with ER tag.
|
---|
267 | * @note Nobody seems to do rock ridge with joliet, so this is highly
|
---|
268 | * expermental and here just because we can. */
|
---|
269 | uint8_t uJolietRockRidgeLevel;
|
---|
270 | /** Enables UDF.
|
---|
271 | * @remarks not yet implemented. */
|
---|
272 | bool fUdf;
|
---|
273 | /** Enables HFS
|
---|
274 | * @remarks not yet implemented. */
|
---|
275 | bool fHfs;
|
---|
276 | /** @} */
|
---|
277 |
|
---|
278 | /** The root of the primary ISO-9660 name space. */
|
---|
279 | PRTFSISOMAKERNAME pPrimaryIsoRoot;
|
---|
280 | /** The root of the joliet name space. */
|
---|
281 | PRTFSISOMAKERNAME pJolietRoot;
|
---|
282 | /** The root of the UDF name space. */
|
---|
283 | PRTFSISOMAKERNAME pUdfRoot;
|
---|
284 | /** The root of the hybrid HFS name space. */
|
---|
285 | PRTFSISOMAKERNAME pHfsRoot;
|
---|
286 |
|
---|
287 | /** The list of objects (RTFSISOMAKEROBJ). */
|
---|
288 | RTLISTANCHOR ObjectHead;
|
---|
289 |
|
---|
290 | /** The total image size. */
|
---|
291 | uint64_t cbTotal;
|
---|
292 |
|
---|
293 | } RTFSISOMAKERINT;
|
---|
294 | /** Pointer to an ISO maker instance. */
|
---|
295 | typedef RTFSISOMAKERINT *PRTFSISOMAKERINT;
|
---|
296 |
|
---|
297 |
|
---|
298 | /*********************************************************************************************************************************
|
---|
299 | * Structures and Typedefs *
|
---|
300 | *********************************************************************************************************************************/
|
---|
301 | /**
|
---|
302 | * Help for iterating over namespaces.
|
---|
303 | */
|
---|
304 | static const struct
|
---|
305 | {
|
---|
306 | /** The RTFSISOMAKERNAMESPACE_XXX indicator. */
|
---|
307 | uint32_t fNamespace;
|
---|
308 | /** Offset into RTFSISOMAKERINT of the root member. */
|
---|
309 | uintptr_t offRoot;
|
---|
310 | /** Offset into RTFSISOMAKERNAMESPACE of the name member. */
|
---|
311 | uintptr_t offName;
|
---|
312 | /** Namespace name for debugging purposes. */
|
---|
313 | const char *pszName;
|
---|
314 | } g_aRTFsIosNamespaces[] =
|
---|
315 | {
|
---|
316 | { RTFSISOMAKERNAMESPACE_ISO_9660, RT_OFFSETOF(RTFSISOMAKERINT, pPrimaryIsoRoot), RT_OFFSETOF(RTFSISOMAKEROBJ, pPrimaryName), "iso-9660" },
|
---|
317 | { RTFSISOMAKERNAMESPACE_JOLIET, RT_OFFSETOF(RTFSISOMAKERINT, pJolietRoot), RT_OFFSETOF(RTFSISOMAKEROBJ, pJolietName), "joliet" },
|
---|
318 | { RTFSISOMAKERNAMESPACE_UDF, RT_OFFSETOF(RTFSISOMAKERINT, pUdfRoot), RT_OFFSETOF(RTFSISOMAKEROBJ, pUdfName), "udf" },
|
---|
319 | { RTFSISOMAKERNAMESPACE_HFS, RT_OFFSETOF(RTFSISOMAKERINT, pHfsRoot), RT_OFFSETOF(RTFSISOMAKEROBJ, pHfsName), "hfs" },
|
---|
320 | };
|
---|
321 |
|
---|
322 |
|
---|
323 | /**
|
---|
324 | * Creates an ISO creator instance.
|
---|
325 | *
|
---|
326 | * @returns IPRT status code.
|
---|
327 | * @param phIsoMaker Where to return the handle to the new ISO maker.
|
---|
328 | */
|
---|
329 | RTDECL(int) RTFsIsoMakerCreate(PRTFSISOMAKER phIsoMaker)
|
---|
330 | {
|
---|
331 | PRTFSISOMAKERINT pThis = (PRTFSISOMAKERINT)RTMemAllocZ(sizeof(*pThis));
|
---|
332 | if (pThis)
|
---|
333 | {
|
---|
334 | pThis->uMagic = RTFSISOMAKERINT_MAGIC;
|
---|
335 | pThis->cRefs = 1;
|
---|
336 | //pThis->fSeenContent = false;
|
---|
337 | pThis->uIsoLevel = 3;
|
---|
338 | pThis->uRockRidgeLevel = 1;
|
---|
339 | pThis->uJolietLevel = 3;
|
---|
340 | //pThis->uJolietRockRidgeLevel = 0;
|
---|
341 | RTListInit(&pThis->ObjectHead);
|
---|
342 | pThis->cbTotal = _32K /* The system area size. */
|
---|
343 | + RTFSISOMAKER_SECTOR_SIZE /* Primary volume descriptor. */
|
---|
344 | + RTFSISOMAKER_SECTOR_SIZE /* Secondary volume descriptor for joliet. */
|
---|
345 | + RTFSISOMAKER_SECTOR_SIZE /* Terminator descriptor. */;
|
---|
346 | *phIsoMaker = pThis;
|
---|
347 | return VINF_SUCCESS;
|
---|
348 | }
|
---|
349 | return VERR_NO_MEMORY;
|
---|
350 | }
|
---|
351 |
|
---|
352 |
|
---|
353 | /**
|
---|
354 | * Recursively destroy a name space tree.
|
---|
355 | * @param pRoot The root node.
|
---|
356 | */
|
---|
357 | static void rtFsIsoMakerDestroyTree(PRTFSISOMAKERNAME pRoot)
|
---|
358 | {
|
---|
359 | Assert(!pRoot->pParent);
|
---|
360 | PRTFSISOMAKERNAME pCur = pRoot;
|
---|
361 |
|
---|
362 | for (;;)
|
---|
363 | {
|
---|
364 | if ( pCur->pDir
|
---|
365 | && pCur->pDir->cChildren)
|
---|
366 | pCur = pCur->pDir->papChildren[pCur->pDir->cChildren - 1];
|
---|
367 | else
|
---|
368 | {
|
---|
369 | RTMemFree(pCur->pszRockRidgeNm);
|
---|
370 | pCur->pszRockRidgeNm = NULL;
|
---|
371 | RTMemFree(pCur->pszTransNm);
|
---|
372 | pCur->pszTransNm = NULL;
|
---|
373 | PRTFSISOMAKERNAME pNext = pCur->pParent;
|
---|
374 | RTMemFree(pCur);
|
---|
375 |
|
---|
376 | /* Unlink from parent, we're the last entry. */
|
---|
377 | if (pNext)
|
---|
378 | {
|
---|
379 | Assert(pNext->pDir->cChildren > 0);
|
---|
380 | pNext->pDir->cChildren--;
|
---|
381 | Assert(pNext->pDir->papChildren[pNext->pDir->cChildren] == pCur);
|
---|
382 | pNext->pDir->papChildren[pNext->pDir->cChildren] = NULL;
|
---|
383 | pCur = pNext;
|
---|
384 | }
|
---|
385 | else
|
---|
386 | {
|
---|
387 | Assert(pRoot == pCur);
|
---|
388 | break;
|
---|
389 | }
|
---|
390 | }
|
---|
391 | }
|
---|
392 | }
|
---|
393 |
|
---|
394 |
|
---|
395 | /**
|
---|
396 | * Destroys an ISO maker instance.
|
---|
397 | *
|
---|
398 | * @param pThis The ISO maker instance to destroy.
|
---|
399 | */
|
---|
400 | static void rtFsIsoMakerDestroy(PRTFSISOMAKERINT pThis)
|
---|
401 | {
|
---|
402 | rtFsIsoMakerDestroyTree(pThis->pPrimaryIsoRoot);
|
---|
403 | rtFsIsoMakerDestroyTree(pThis->pJolietRoot);
|
---|
404 | rtFsIsoMakerDestroyTree(pThis->pUdfRoot);
|
---|
405 | rtFsIsoMakerDestroyTree(pThis->pHfsRoot);
|
---|
406 |
|
---|
407 | PRTFSISOMAKEROBJ pCur;
|
---|
408 | PRTFSISOMAKEROBJ pNext;
|
---|
409 | RTListForEachSafe(&pThis->ObjectHead, pCur, pNext, RTFSISOMAKEROBJ, Entry)
|
---|
410 | {
|
---|
411 | RTListNodeRemove(&pCur->Entry);
|
---|
412 | RTMemFree(pCur);
|
---|
413 | }
|
---|
414 | }
|
---|
415 |
|
---|
416 |
|
---|
417 | /**
|
---|
418 | * Retains a references to an ISO maker instance.
|
---|
419 | *
|
---|
420 | * @returns New reference count on success, UINT32_MAX if invalid handle.
|
---|
421 | * @param hIsoMaker The ISO maker handle.
|
---|
422 | */
|
---|
423 | RTDECL(uint32_t) RTFsIsoMakerRetain(RTFSISOMAKER hIsoMaker)
|
---|
424 | {
|
---|
425 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
426 | AssertPtrReturn(pThis, UINT32_MAX);
|
---|
427 | AssertReturn(pThis->uMagic == RTFSISOMAKERINT_MAGIC, UINT32_MAX);
|
---|
428 | uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
|
---|
429 | Assert(cRefs > 1);
|
---|
430 | Assert(cRefs < _64K);
|
---|
431 | return cRefs;
|
---|
432 | }
|
---|
433 |
|
---|
434 |
|
---|
435 | /**
|
---|
436 | * Releases a references to an ISO maker instance.
|
---|
437 | *
|
---|
438 | * @returns New reference count on success, UINT32_MAX if invalid handle.
|
---|
439 | * @param hIsoMaker The ISO maker handle. NIL is ignored.
|
---|
440 | */
|
---|
441 | RTDECL(uint32_t) RTFsIsoMakerRelease(RTFSISOMAKER hIsoMaker)
|
---|
442 | {
|
---|
443 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
444 | uint32_t cRefs;
|
---|
445 | if (pThis == NIL_RTFSISOMAKER)
|
---|
446 | cRefs = 0;
|
---|
447 | else
|
---|
448 | {
|
---|
449 | AssertPtrReturn(pThis, UINT32_MAX);
|
---|
450 | AssertReturn(pThis->uMagic == RTFSISOMAKERINT_MAGIC, UINT32_MAX);
|
---|
451 | cRefs = ASMAtomicDecU32(&pThis->cRefs);
|
---|
452 | Assert(cRefs < _64K);
|
---|
453 | if (!cRefs)
|
---|
454 | rtFsIsoMakerDestroy(pThis);
|
---|
455 | }
|
---|
456 | return cRefs;
|
---|
457 | }
|
---|
458 |
|
---|
459 |
|
---|
460 | /**
|
---|
461 | * Sets the ISO-9660 level.
|
---|
462 | *
|
---|
463 | * @returns IPRT status code
|
---|
464 | * @param hIsoMaker The ISO maker handle.
|
---|
465 | * @param uIsoLevel The level, 1-3.
|
---|
466 | */
|
---|
467 | RTDECL(int) RTFsIsoMakerSetIso9660Level(RTFSISOMAKER hIsoMaker, uint8_t uIsoLevel)
|
---|
468 | {
|
---|
469 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
470 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
471 | AssertReturn(uIsoLevel <= 3, VERR_INVALID_PARAMETER);
|
---|
472 | AssertReturn(uIsoLevel > 0, VERR_INVALID_PARAMETER); /* currently not possible to disable this */
|
---|
473 | AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
|
---|
474 |
|
---|
475 | pThis->uIsoLevel = uIsoLevel;
|
---|
476 | return VINF_SUCCESS;
|
---|
477 | }
|
---|
478 |
|
---|
479 |
|
---|
480 | /**
|
---|
481 | * Sets the joliet level.
|
---|
482 | *
|
---|
483 | * @returns IPRT status code
|
---|
484 | * @param hIsoMaker The ISO maker handle.
|
---|
485 | * @param uJolietLevel The joliet UCS-2 level 1-3, or 0 to disable
|
---|
486 | * joliet.
|
---|
487 | */
|
---|
488 | RTDECL(int) RTFsIsoMakerSetJolietUcs2Level(RTFSISOMAKER hIsoMaker, uint8_t uJolietLevel)
|
---|
489 | {
|
---|
490 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
491 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
492 | AssertReturn(uJolietLevel <= 3, VERR_INVALID_PARAMETER);
|
---|
493 | AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
|
---|
494 |
|
---|
495 | if (pThis->uJolietLevel != uJolietLevel)
|
---|
496 | {
|
---|
497 | if (uJolietLevel == 0)
|
---|
498 | pThis->cbTotal -= RTFSISOMAKER_SECTOR_SIZE;
|
---|
499 | else if (pThis->uJolietLevel == 0)
|
---|
500 | pThis->cbTotal += RTFSISOMAKER_SECTOR_SIZE;
|
---|
501 | pThis->uJolietLevel = uJolietLevel;
|
---|
502 | }
|
---|
503 | return VINF_SUCCESS;
|
---|
504 | }
|
---|
505 |
|
---|
506 |
|
---|
507 | /**
|
---|
508 | * Sets the rock ridge support level (on the primary ISO-9660 namespace).
|
---|
509 | *
|
---|
510 | * @returns IPRT status code
|
---|
511 | * @param hIsoMaker The ISO maker handle.
|
---|
512 | * @param uLevel 0 if disabled, 1 to just enable, 2 to enable and
|
---|
513 | * write the ER tag.
|
---|
514 | */
|
---|
515 | RTDECL(int) RTFsIsoMakerSetRockRidgeLevel(RTFSISOMAKER hIsoMaker, uint8_t uLevel)
|
---|
516 | {
|
---|
517 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
518 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
519 | AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
|
---|
520 | AssertReturn(uLevel <= 2, VERR_INVALID_PARAMETER);
|
---|
521 |
|
---|
522 | pThis->uRockRidgeLevel = uLevel;
|
---|
523 | return VINF_SUCCESS;
|
---|
524 | }
|
---|
525 |
|
---|
526 |
|
---|
527 | /**
|
---|
528 | * Sets the rock ridge support level on the joliet namespace (experimental).
|
---|
529 | *
|
---|
530 | * @returns IPRT status code
|
---|
531 | * @param hIsoMaker The ISO maker handle.
|
---|
532 | * @param uLevel 0 if disabled, 1 to just enable, 2 to enable and
|
---|
533 | * write the ER tag.
|
---|
534 | */
|
---|
535 | RTDECL(int) RTFsIsoMakerSetJolietRockRidgeLevel(RTFSISOMAKER hIsoMaker, uint8_t uLevel)
|
---|
536 | {
|
---|
537 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
538 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
539 | AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
|
---|
540 | AssertReturn(uLevel <= 2, VERR_INVALID_PARAMETER);
|
---|
541 |
|
---|
542 | pThis->uJolietRockRidgeLevel = uLevel;
|
---|
543 | return VINF_SUCCESS;
|
---|
544 | }
|
---|
545 |
|
---|
546 |
|
---|
547 | /*
|
---|
548 | *
|
---|
549 | * Object level config
|
---|
550 | * Object level config
|
---|
551 | * Object level config
|
---|
552 | *
|
---|
553 | */
|
---|
554 |
|
---|
555 |
|
---|
556 | DECL_NO_INLINE(static, PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj)
|
---|
557 | {
|
---|
558 | PRTFSISOMAKEROBJ pObj;
|
---|
559 | RTListForEachReverse(&pThis->ObjectHead, pObj, RTFSISOMAKEROBJ, Entry)
|
---|
560 | {
|
---|
561 | if (pObj->idxObj == idxObj)
|
---|
562 | return pObj;
|
---|
563 | }
|
---|
564 | return NULL;
|
---|
565 | }
|
---|
566 |
|
---|
567 |
|
---|
568 | DECLINLINE(PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj)
|
---|
569 | {
|
---|
570 | PRTFSISOMAKEROBJ pObj = RTListGetLast(&pThis->ObjectHead, RTFSISOMAKEROBJ, Entry);
|
---|
571 | if (!pObj || RT_LIKELY(pObj->idxObj == idxObj))
|
---|
572 | return pObj;
|
---|
573 | return rtFsIsoMakerIndexToObjSlow(pThis, idxObj)
|
---|
574 | }
|
---|
575 |
|
---|
576 |
|
---|
577 | static int rtTFsIsoMakerObjSetPathInOne(RTFSISOMAKER hIsoMaker, uint32_t idxEntry,
|
---|
578 | uint32_t fNamespace, const char *pszPath)
|
---|
579 | {
|
---|
580 |
|
---|
581 | }
|
---|
582 |
|
---|
583 |
|
---|
584 | /**
|
---|
585 | * Sets the path (name) of an object in the selected namespaces.
|
---|
586 | *
|
---|
587 | * The name will be transformed as necessary.
|
---|
588 | *
|
---|
589 | * The initial implementation does not allow this function to be called more
|
---|
590 | * than once on an object.
|
---|
591 | *
|
---|
592 | * @returns IPRT status code.
|
---|
593 | * @param hIsoMaker The ISO maker handle.
|
---|
594 | * @param idxObj The configuration index of to name.
|
---|
595 | * @param fNamespaces The namespaces to apply the path to
|
---|
596 | * (RTFSISOMAKERNAMESPACE_XXX).
|
---|
597 | * @param pszPath The ISO-9660 path.
|
---|
598 | */
|
---|
599 | RTDECL(int) RTFsIsoMakerObjSetPath(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t fNamespaces, const char *pszPath)
|
---|
600 | {
|
---|
601 | /*
|
---|
602 | * Validate and translate input.
|
---|
603 | */
|
---|
604 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
605 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
606 | AssertReturn(!(fNamespaces & ~RTFSISOMAKERNAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
|
---|
607 | AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
|
---|
608 | AssertReturn(RTPATH_IS_SLASH(pszPath == '/'), VERR_INVALID_NAME);
|
---|
609 | PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj);
|
---|
610 | AssertReturn(pObj, VERR_OUT_OF_RANGE);
|
---|
611 |
|
---|
612 | /*
|
---|
613 | * Execute requested actions.
|
---|
614 | */
|
---|
615 | int rc = VINF_SUCCESS;
|
---|
616 | for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIosNamespaces); i++)
|
---|
617 | if (fNamespace & g_aRTFsIosNamespaces[i].fNamespace)
|
---|
618 | {
|
---|
619 | int rc2 = rtTFsIsoMakerObjSetPathInOne(pThis, pEntry, g_aRTFsIosNamespaces[i].fNamespace, pszPath,
|
---|
620 | (PRTFSISOMAKERNAME *)((uintptr_t)pThis + g_aRTFsIosNamespaces[i].offRoot),
|
---|
621 | (PRTFSISOMAKERNAMESPACE *)((uintptr_t)pEntry + g_aRTFsIosNamespaces[i].offName));
|
---|
622 | if (RT_SUCCESS(rc2) || RT_FAILURE(rc))
|
---|
623 | continue;
|
---|
624 | rc = rc2;
|
---|
625 | }
|
---|
626 | return rc;
|
---|
627 | }
|
---|
628 |
|
---|
629 |
|
---|
630 | /**
|
---|
631 | * Initalizes the common part of a file system object and links it into global
|
---|
632 | * chain.
|
---|
633 | *
|
---|
634 | * @returns IPRT status code
|
---|
635 | * @param pThis The ISO maker instance.
|
---|
636 | * @param pObj The common object.
|
---|
637 | * @param enmType The object type.
|
---|
638 | */
|
---|
639 | static void rtFsIsoMakerInitCommonObj(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj, RTFSISOMAKEROBJTYPE enmType)
|
---|
640 | {
|
---|
641 | AssertReturn(pThis->cObjects < RTFSISOMAKER_MAX_OBJECTS, VERR_OUT_OF_RANGE);
|
---|
642 | pObj->enmType = enmType;
|
---|
643 | pObj->pPrimaryName = NULL;
|
---|
644 | pObj->pJolietName = NULL;
|
---|
645 | pObj->pUdfName = NULL;
|
---|
646 | pObj->pHfsName = NULL;
|
---|
647 | pObj->idxObj = pThis->cObjects++;
|
---|
648 | RTListAppend(&pThis->ObjectHead, &pObj->Entry);
|
---|
649 | return VINF_SUCCESS;
|
---|
650 | }
|
---|
651 |
|
---|
652 |
|
---|
653 | /**
|
---|
654 | * Adds an unnamed directory to the image.
|
---|
655 | *
|
---|
656 | * The directory must explictly be entered into the desired namespaces.
|
---|
657 | *
|
---|
658 | * @returns IPRT status code
|
---|
659 | * @param hIsoMaker The ISO maker handle.
|
---|
660 | * @param pidxObj Where to return the configuration index of the
|
---|
661 | * directory.
|
---|
662 | * @sa RTFsIsoMakerAddDir, RTFsIsoMakerObjSetPath
|
---|
663 | */
|
---|
664 | RTDECL(int) RTFsIsoMakerAddUnnamedDir(RTFSISOMAKER hIsoMaker, uint32_t *pidxObj)
|
---|
665 | {
|
---|
666 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
667 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
668 | AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
|
---|
669 |
|
---|
670 | PRTFSISOMAKERDIR pDir = (PRTFSISOMAKERDIR)RTMemAllocZ(sizeof(*pDir));
|
---|
671 | AssertReturn(pDir, VERR_NO_MEMORY);
|
---|
672 | int rc = rtFsIsoMakerInitCommonObj(&pDir->Core, RTFSISOMAKEROBJTYPE_DIR);
|
---|
673 | if (RT_SUCCESS(rc))
|
---|
674 | {
|
---|
675 | *pidxObj = pObj->idxObj;
|
---|
676 | return VINF_SUCCESS;
|
---|
677 | }
|
---|
678 | RTMemFree(pDir);
|
---|
679 | return rc;
|
---|
680 | }
|
---|
681 |
|
---|
682 |
|
---|
683 | /**
|
---|
684 | * Adds a directory to the image in all namespaces and default attributes.
|
---|
685 | *
|
---|
686 | * @returns IPRT status code
|
---|
687 | * @param hIsoMaker The ISO maker handle.
|
---|
688 | * @param pszDir The path (UTF-8) to the directory in the ISO.
|
---|
689 | *
|
---|
690 | * @param pidxObj Where to return the configuration index of the
|
---|
691 | * directory. Optional.
|
---|
692 | * @sa RTFsIsoMakerAddUnnamedDir, RTFsIsoMakerObjSetPath
|
---|
693 | */
|
---|
694 | RTDECL(int) RTFsIsoMakerAddDir(RTFSISOMAKER hIsoMaker, const char *pszDir, uint32_t *pidxObj)
|
---|
695 | {
|
---|
696 | PRTFSISOMAKERINT pThis = hIsoMaker;
|
---|
697 | RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
|
---|
698 | AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
|
---|
699 | AssertReturn(RTPATH_IS_SLASH(pszPath == '/'), VERR_INVALID_NAME);
|
---|
700 |
|
---|
701 | uint32_t idxObj;
|
---|
702 | int rc = RTFsIsoMakerAddUnnamedDir(hIsoMaker, &idxObj);
|
---|
703 | if (RT_SUCCESS(rc))
|
---|
704 | {
|
---|
705 | rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKERNAMESPACE_ALL);
|
---|
706 | if (RT_SUCCESS(rc))
|
---|
707 | {
|
---|
708 | if (pidxObj)
|
---|
709 | *pidxObj = idxObj;
|
---|
710 | }
|
---|
711 | /** @todo else: back out later? */
|
---|
712 | }
|
---|
713 | return rc;
|
---|
714 | }
|
---|
715 |
|
---|