Changeset 67281 in vbox for trunk/src/VBox
- Timestamp:
- Jun 7, 2017 1:01:09 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/isomaker.cpp
r67278 r67281 62 62 /** Maximum number of objects. */ 63 63 #define RTFSISOMAKER_MAX_OBJECTS _16M 64 /** Maximum number of objects per directory. */ 65 #define RTFSISOMAKER_MAX_OBJECTS_PER_DIR _256K /**< @todo check limit */ 66 64 67 /** UTF-8 name buffer. */ 65 68 #define RTFSISOMAKER_MAX_NAME_BUF 768 … … 78 81 /** Pointer to an ISO maker object name space node. */ 79 82 typedef struct RTFSISOMAKERNAME *PRTFSISOMAKERNAME; 83 /** Pointer to an ISO maker object name space node pointer. */ 84 typedef PRTFSISOMAKERNAME *PPRTFSISOMAKERNAME; 80 85 /** Pointer to a common ISO image maker file system object. */ 81 86 typedef struct RTFSISOMAKEROBJ *PRTFSISOMAKEROBJ; … … 120 125 uint32_t cChildren; 121 126 /** Sorted array of children. */ 122 P RTFSISOMAKERNAME *papChildren;127 PPRTFSISOMAKERNAME papChildren; 123 128 124 129 /** The translate table file. */ … … 162 167 /** The depth in the namespace tree of this name. */ 163 168 uint8_t uDepth; 164 /** Set if pszTransNm is allocated separately. */ 169 /** Set if pszTransNm is allocated separately. Normally same as pszSpecNm. */ 170 bool fRockRidgeNmAlloced : 1; 171 /** Set if pszTransNm is allocated separately. Normally same as pszSpecNm. */ 165 172 bool fTransNmAlloced : 1; 166 /** Set if pszTransNm is allocated separately. */167 bool fRockRidgeNmAlloced : 1;168 173 169 174 /** @todo more rock ridge info here. */ … … 174 179 char szName[RT_FLEXIBLE_ARRAY]; 175 180 } RTFSISOMAKERNAME; 181 182 /** 183 * A ISO maker namespace. 184 */ 185 typedef struct RTFSISOMAKERNAMESPACE 186 { 187 /** The namespace root. */ 188 RTFSISOMAKERNAME pRoot; 189 /** Total number of name nodes in the namespace. */ 190 uint32_t cNames; 191 /** Total number of directories in the namespace. */ 192 uint32_t cDirs; 193 /** The namespace selector (RTFSISOMAKER_NAMESPACE_XXX). */ 194 uint32_t fNamespace; 195 /** The configuration level for this name space. 196 * - For UDF and HFS namespaces this is either @c true or @c false. 197 * - For the primary ISO-9660 namespace this is 1, 2, or 3. 198 * - For the joliet namespace this 0 (joliet disabled), 1, 2, or 3. */ 199 uint8_t uLevel; 200 /** The rock ridge level: 1 - enabled; 2 - with ER tag. 201 * Linux behaves a little different when seeing the ER tag. */ 202 uint8_t uRockRidgeLevel; 203 /** Set if TRANS.TBL files are to be generated for this namespace. */ 204 } RTFSISOMAKERNAMESPACE; 205 /** Pointer to a namespace. */ 206 typedef RTFSISOMAKERNAMESPACE *PRTFSISOMAKERNAMESPACE; 176 207 177 208 … … 272 303 * @todo support mkisofs level 4 (ISO-9660:1990, version 2). */ 273 304 uint8_t uIsoLevel; 274 /** The ISO rock ridge level: 1 - enabled; 2 - with ER tag.275 * Linux behaves a little different when seeing the ER tag. */276 uint8_t uRockRidgeLevel;277 305 /** The joliet UCS level (1, 2, or 3), 0 if joliet is not enabled. */ 278 306 uint8_t uJolietLevel; 279 /** The joliet rock ridge level: 1 - enabled; 2 - with ER tag.280 * @note Nobody seems to do rock ridge with joliet, so this is highly281 * expermental and here just because we can. */282 uint8_t uJolietRockRidgeLevel;283 307 /** Enables UDF. 284 308 * @remarks not yet implemented. */ … … 289 313 /** @} */ 290 314 291 /** The root of the primary ISO-9660 namespace. */292 PRTFSISOMAKERNAME pPrimaryIsoRoot;293 /** The root of the joliet namespace. */294 PRTFSISOMAKERNAME pJolietRoot;295 /** The root of the UDF namespace. */296 PRTFSISOMAKERNAME pUdfRoot;297 /** The root of the hybrid HFS namespace. */298 PRTFSISOMAKERNAME pHfsRoot;315 /** The primary ISO-9660 namespace. */ 316 RTFSISOMAKERNAMESPACE PrimaryIso; 317 /** The joliet namespace. */ 318 RTFSISOMAKERNAMESPACE Joliet; 319 /** The UDF namespace. */ 320 RTFSISOMAKERNAMESPACE Udf; 321 /** The hybrid HFS+ namespace. */ 322 RTFSISOMAKERNAMESPACE Hfs; 299 323 300 324 /** The list of objects (RTFSISOMAKEROBJ). */ … … 331 355 /** Namespace name for debugging purposes. */ 332 356 const char *pszName; 333 } g_aRTFsI osNamespaces[] =357 } g_aRTFsIsoNamespaces[] = 334 358 { 335 359 { RTFSISOMAKERNAMESPACE_ISO_9660, RT_OFFSETOF(RTFSISOMAKERINT, pPrimaryIsoRoot), RT_OFFSETOF(RTFSISOMAKEROBJ, pPrimaryName), "iso-9660" }, … … 339 363 }; 340 364 341 342 /** 343 * Creates an ISO creator instance. 365 /** 366 * Translates a single namespace flag (RTFSISOMAKERNAMESPACE_XXX) to an 367 * index into g_aRTFsIsoNamespaces. 368 */ 369 static const uint8_t g_aidxRTFsIsoNamespaceFlagToIdx[] = 370 { 371 /*[0] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 372 /*[RTFSISOMAKERNAMESPACE_ISO_9660] = */ 0, 373 /*[2] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 374 /*[3] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 375 /*[RTFSISOMAKERNAMESPACE_JOLIET] = */ 1, 376 /*[5] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 377 /*[6] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 378 /*[7] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 379 /*[RTFSISOMAKERNAMESPACE_UDF] = */ 2, 380 /*[9] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 381 /*[10] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 382 /*[11] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 383 /*[12] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 384 /*[13] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 385 /*[14] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 386 /*[15] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 387 /*[RTFSISOMAKERNAMESPACE_HFS] = */ 3, 388 /*[17] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 389 /*[18] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 390 /*[19] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 391 /*[20] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 392 /*[21] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 393 /*[22] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 394 /*[23] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 395 /*[24] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 396 /*[25] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 397 /*[26] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 398 /*[27] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 399 /*[28] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 400 /*[29] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 401 /*[30] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 402 /*[31] = */ RT_ELEMENTS(g_aRTFsIsoNamespaces), 403 }; 404 405 406 /********************************************************************************************************************************* 407 * Internal Functions * 408 *********************************************************************************************************************************/ 409 static int rtFsIsoMakerAddUnnamedDirWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKERDIR *ppDir); 410 411 RTDECL(int) RTFsIsoMakerObjSetPath(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t fNamespaces, const char *pszPath); 412 413 414 /** 415 * Creates an ISO maker instance. 344 416 * 345 417 * @returns IPRT status code. … … 348 420 RTDECL(int) RTFsIsoMakerCreate(PRTFSISOMAKER phIsoMaker) 349 421 { 422 /* 423 * Do some integrity checks first. 424 */ 425 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_ISO_9660]].fNamespace == RTFSISOMAKERNAMESPACE_ISO_9660, 426 VERR_INTERNAL_ERROR_5); 427 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_JOLIET]].fNamespace == RTFSISOMAKERNAMESPACE_JOLIET, 428 VERR_INTERNAL_ERROR_5); 429 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_UDF]].fNamespace == RTFSISOMAKERNAMESPACE_UDF, 430 VERR_INTERNAL_ERROR_5); 431 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_HFS]].fNamespace == RTFSISOMAKERNAMESPACE_HFS, 432 VERR_INTERNAL_ERROR_5); 433 434 /* 435 * Create the instance with defaults. 436 */ 350 437 PRTFSISOMAKERINT pThis = (PRTFSISOMAKERINT)RTMemAllocZ(sizeof(*pThis)); 351 438 if (pThis) 352 439 { 353 pThis->uMagic = RTFSISOMAKERINT_MAGIC; 354 pThis->cRefs = 1; 355 //pThis->fSeenContent = false; 356 pThis->uIsoLevel = 3; 357 pThis->uRockRidgeLevel = 1; 358 pThis->uJolietLevel = 3; 359 //pThis->uJolietRockRidgeLevel = 0; 440 pThis->uMagic = RTFSISOMAKERINT_MAGIC; 441 pThis->cRefs = 1; 442 //pThis->fSeenContent = false; 443 444 pThis->PrimaryIso.fNamespace = RTFSISOMAKERNAMESPACE_ISO_9660; 445 pThis->PrimaryIso.uLevel = 3; /* 30 char names, large files */ 446 pThis->PrimaryIso.uRockRidgeLevel = 1; 447 pThis->Joliet.fNamespace = RTFSISOMAKERNAMESPACE_JOLIET; 448 pThis->Joliet.uLevel = 3; 449 //pThis->Joliet.uRockRidgeLevel = 0; 450 pThis->Udf.fNamespace = RTFSISOMAKERNAMESPACE_UDF; 451 //pThis->Udf.uLevel = 0; 452 //pThis->Udf.uRockRidgeLevel = 0; 453 pThis->Hfs.fNamespace = RTFSISOMAKERNAMESPACE_HFS; 454 //pThis->Hfs.uLevel = 0; 455 //pThis->Hfs.uRockRidgeLevel = 0; 456 360 457 RTListInit(&pThis->ObjectHead); 361 pThis->cbTotal = _32K /* The system area size. */ 362 + RTFSISOMAKER_SECTOR_SIZE /* Primary volume descriptor. */ 363 + RTFSISOMAKER_SECTOR_SIZE /* Secondary volume descriptor for joliet. */ 364 + RTFSISOMAKER_SECTOR_SIZE /* Terminator descriptor. */; 458 //pThis->cObjects = 0; 459 //pThis->cNames = 0; 460 //pThis->cbData = 0; 461 pThis->cbTotal = _32K /* The system area size. */ 462 + RTFSISOMAKER_SECTOR_SIZE /* Primary volume descriptor. */ 463 + RTFSISOMAKER_SECTOR_SIZE /* Secondary volume descriptor for joliet. */ 464 + RTFSISOMAKER_SECTOR_SIZE /* Terminator descriptor. */; 365 465 *phIsoMaker = pThis; 366 466 return VINF_SUCCESS; … … 564 664 565 665 666 566 667 /* 567 668 * 568 * Object level config 569 * Object level config 570 * Object level config 571 * 572 */ 573 574 575 /** 576 * Translates an object index number to an object pointer, slow path. 577 * 578 * @returns Pointer to object, NULL if not found. 579 * @param pThis The ISO creator instance. 580 * @param idxObj The object index too resolve. 581 */ 582 DECL_NO_INLINE(static, PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObjSlow(PRTFSISOMAKERINT pThis, uint32_t idxObj) 583 { 584 PRTFSISOMAKEROBJ pObj; 585 RTListForEachReverse(&pThis->ObjectHead, pObj, RTFSISOMAKEROBJ, Entry) 586 { 587 if (pObj->idxObj == idxObj) 588 return pObj; 589 } 590 return NULL; 591 } 592 593 594 /** 595 * Translates an object index number to an object pointer. 596 * 597 * @returns Pointer to object, NULL if not found. 598 * @param pThis The ISO creator instance. 599 * @param idxObj The object index too resolve. 600 */ 601 DECLINLINE(PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj) 602 { 603 PRTFSISOMAKEROBJ pObj = RTListGetLast(&pThis->ObjectHead, RTFSISOMAKEROBJ, Entry); 604 if (!pObj || RT_LIKELY(pObj->idxObj == idxObj)) 605 return pObj; 606 return rtFsIsoMakerIndexToObjSlow(pThis, idxObj); 669 * Name space related internals. 670 * Name space related internals. 671 * Name space related internals. 672 * 673 */ 674 675 676 /** 677 * Gets the pointer to the root member for the given namespace. 678 * 679 * @returns Pointer to root pointer. 680 * @param pThis The ISO maker instance. 681 * @param fNamespace The namespace which name to find. 682 */ 683 static PPRTFSISOMAKERNAME rtFsIsoMakerGetRootForNamespace(PRTFSISOMAKERINT pThis, uint32_t fNamespace) 684 { 685 Assert(RT_IS_POWER_OF_TWO(fNamespace)); 686 Assert(fNamespace); 687 Assert(fNamespace <= RTFSISOMAKERNAMESPACE_HFS); 688 return (PPRTFSISOMAKERNAME)((uintptr_t)pThis + g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[fNamespace]].offRoot); 689 } 690 691 692 /** 693 * Gets the pointer to the name member for the given namespace. 694 * 695 * @returns Pointer to name member. 696 * @param pObj The object to find a name member in. 697 * @param fNamespace The namespace which name to find. 698 */ 699 static PPRTFSISOMAKERNAME rtFsIsoMakerObjGetNameForNamespace(PRTFSISOMAKEROBJ pObj, uint32_t fNamespace) 700 { 701 Assert(RT_IS_POWER_OF_TWO(fNamespace)); 702 Assert(fNamespace); 703 Assert(fNamespace <= RTFSISOMAKERNAMESPACE_HFS); 704 return (PPRTFSISOMAKERNAME)((uintptr_t)pObj + g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[fNamespace]].offName); 607 705 } 608 706 … … 637 735 638 736 /** 639 * Locates a child objectby its specified name.737 * Locates a child entry by its specified name. 640 738 * 641 739 * @returns Pointer to the child if found, NULL if not. 642 * @param pDir Obj The directory objectto search.740 * @param pDirName The directory name to search. 643 741 * @param pszEntry The (specified) entry name. 644 742 * @param cchEntry The length of the name. 645 743 */ 646 static PRTFSISOMAKERNAME rtFsIsoMakerFind ObjInDirBySpec(PRTFSISOMAKERNAME pDirObj, const char *pszEntry, size_t cchEntry)647 { 648 if (pDir Obj)649 { 650 PRTFSISOMAKERNAMEDIR pDir = pDir Obj->pDir;744 static PRTFSISOMAKERNAME rtFsIsoMakerFindEntryInDirBySpec(PRTFSISOMAKERNAME pDirName, const char *pszEntry, size_t cchEntry) 745 { 746 if (pDirName) 747 { 748 PRTFSISOMAKERNAMEDIR pDir = pDirName->pDir; 651 749 AssertReturn(pDir, NULL); 652 750 … … 663 761 } 664 762 763 764 /** 765 * Locates a subdir object in any namespace by its specified name. 766 * 767 * This is used to avoid having one instance of RTFSISOMAKERDIR in each 768 * namespace for the same directory. 769 * 770 * @returns Pointer to the subdir object if found, NULL if not. 771 * @param pDirObj The directory object to search. 772 * @param pszEntry The (specified) entry name. 773 * @param cchEntry The length of the name. 774 * @param fSkipNamespaces Namespaces to skip. 775 * @sa rtFsIsoMakerFindEntryInDirBySpec 776 */ 777 static PRTFSISOMAKERDIR rtFsIsoMakerFindSubdirBySpec(PRTFSISOMAKERDIR pDirObj, const char *pszEntry, size_t cchEntry, 778 uint32_t fSkipNamespaces) 779 { 780 AssertReturn(pDirObj, NULL); 781 AssertReturn(pDirObj->Core.enmType == RTFSISOMAKEROBJTYPE_DIR, NULL); 782 for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIsoNamespaces); i++) 783 if (!(fSkipNamespaces & g_aRTFsIsoNamespaces[i].fNamespace)) 784 { 785 PRTFSISOMAKERNAME pDirName = *(PPRTFSISOMAKERNAME)((uintptr_t)pDirObj + g_aRTFsIsoNamespaces[i].offName); 786 if (pDirName) 787 { 788 PRTFSISOMAKERNAMEDIR pDir = pDirName->pDir; 789 AssertStmt(pDir, continue); 790 791 uint32_t i = pDir->cChildren; 792 while (i-- > 0) 793 { 794 PRTFSISOMAKERNAME pChild = pDir->papChildren[i]; 795 if ( pChild->cchSpecNm == cchEntry 796 && pChild->pDir != NULL 797 && RTStrNICmp(pChild->pszSpecNm, pszEntry, cchEntry) == 0) 798 return (PRTFSISOMAKERDIR)pChild->pObj; 799 } 800 } 801 } 802 return NULL; 803 } 804 805 665 806 /** 666 807 * Copy and convert a name to valid ISO-9660 (d-characters only). … … 670 811 * 671 812 * @returns Length of the resulting string. 672 * @param pszDst 673 * @param cchDstMax The maximum number of (d-chars) to put in the674 * output buffer.675 * @param p szSrc The UTF-8 source string.676 * @param cchSrc The maximum number of chars to copy from the677 * sourcestring.678 */ 679 static size_t rtFsIsoMakerCopyIso9660Name(char *pszDst, size_t cchDstMax, const char *p szSrc, size_t cchSrc)680 { 681 const char *p szSrcIn = pszSrc;813 * @param pszDst The output buffer. 814 * @param cchDstMax The maximum number of (d-chars) to put in the output 815 * buffer. 816 * @param pchSrc The UTF-8 source string (not neccessarily terminated). 817 * @param cchSrc The maximum number of chars to copy from the source 818 * string. 819 */ 820 static size_t rtFsIsoMakerCopyIso9660Name(char *pszDst, size_t cchDstMax, const char *pchSrc, size_t cchSrc) 821 { 822 const char *pchSrcIn = pchSrc; 682 823 size_t offDst = 0; 683 while ((size_t)(p szSrc - pszSrcIn) < cchSrc)824 while ((size_t)(pchSrc - pchSrcIn) < cchSrc) 684 825 { 685 826 RTUNICP uc; 686 int rc = RTStrGetCpEx(&p szSrc, &uc);827 int rc = RTStrGetCpEx(&pchSrc, &uc); 687 828 if (RT_SUCCESS(rc)) 688 829 { … … 702 843 703 844 /** 704 * Normalizes a name for the specified namespace.845 * Normalizes a name for the primary ISO-9660 namespace. 705 846 * 706 847 * @returns IPRT status code. 707 848 * @param pThis The ISO maker instance. 708 849 * @param pParent The parent directory. NULL if root. 709 * @param pszSrc The specified name to normalize. 710 * @param fNamespace The namespace rulez to normalize it according to. 850 * @param pchSrc The specified name to normalize (not necessarily zero 851 * terminated). 852 * @param cchSrc The length of the specified name. 711 853 * @param fIsDir Indicates whether it's a directory or file (like). 712 854 * @param pszDst The output buffer. Must be at least 32 bytes. … … 715 857 * not counting the terminator). 716 858 */ 717 static int rtFsIsoMakerNormalizeNameForNamespace(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME pParent, const char *pszSrc, 718 uint32_t fNamespace, bool fIsDir, char *pszDst, size_t cbDst, size_t *pcchDst) 719 { 720 size_t cchSrc = strlen(pszSrc); 721 if (cchSrc) 859 static int rtFsIsoMakerNormalizeNameForPrimaryIso9660(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME pParent, 860 const char *pchSrc, size_t cchSrc, bool fIsDir, 861 char *pszDst, size_t cbDst, size_t *pcchDst) 862 { 863 AssertReturn(cbDst > ISO9660_MAX_NAME_LEN, VERR_INTERNAL_ERROR_3); 864 865 /* Skip leading dots. */ 866 while (cchSrc > 0 && *pchSrc == '.') 867 pchSrc++, cchSrc--; 868 if (!cchSrc) 869 { 870 pchSrc = "DOTS"; 871 cchSrc = 4; 872 } 873 874 /* 875 * Produce a first name. 876 */ 877 size_t cchDst; 878 size_t offDstDot; 879 if (fIsDir) 880 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8, 881 pchSrc, cchSrc); 882 else 883 { 884 /* Look for the last dot and try preserve the extension when doing the conversion. */ 885 size_t offLastDot = cchSrc; 886 for (size_t off = 0; off < cchSrc; off++) 887 if (pchSrc[off] == '.') 888 offLastDot = off; 889 890 if (offLastDot == cchSrc) 891 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8, 892 pchSrc, cchSrc); 893 else 894 { 895 const char * const pchSrcExt = &pchSrc[offLastDot + 1]; 896 size_t const cchSrcExt = cchSrc - offLastDot - 1; 897 if (pThis->uIsoLevel < 2) 898 { 899 cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, 8, pchSrc, cchSrc); 900 offDstDot = cchDst; 901 pszDst[cchDst++] = '.'; 902 cchDst += rtFsIsoMakerCopyIso9660Name(&pszDst[cchDst], 3, pchSrcExt, cchSrcExt); 903 } 904 else 905 { 906 size_t cchDstExt = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2, pchSrcExt, cchSrcExt); 907 if (cchDstExt > 0) 908 { 909 size_t cchBasename = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2, 910 pchSrc, offLastDot); 911 if (cchBasename + 1 + cchDstExt <= ISO9660_MAX_NAME_LEN) 912 cchDst = cchBasename; 913 else 914 cchDst = ISO9660_MAX_NAME_LEN - 1 - RT_MIN(cchDstExt, 4); 915 offDstDot = cchDst; 916 pszDst[cchDst++] = '.'; 917 cchDst += rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 1 - cchDst, 918 pchSrcExt, cchSrcExt); 919 } 920 else 921 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN, pchSrc, cchSrc); 922 } 923 } 924 } 925 926 /* 927 * Unique name? 928 */ 929 if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst)) 930 { 931 *pcchDst = cchDst; 932 return VINF_SUCCESS; 933 } 934 935 /* 936 * Mangle the name till we've got a unique one. 937 */ 938 size_t const cchMaxBasename = (pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8) - (cchDst - offDstDot); 939 size_t cchInserted = 0; 940 for (uint32_t i = 0; i < _32K; i++) 941 { 942 /* Add a numberic infix. */ 943 char szOrd[64]; 944 size_t cchOrd = RTStrFormatU32(szOrd, sizeof(szOrd), i + 1, 10, -1, -1, 0 /*fFlags*/); 945 Assert((ssize_t)cchOrd > 0); 946 947 /* Do we need to shuffle the suffix? */ 948 if (cchOrd > cchInserted) 949 { 950 if (offDstDot < cchMaxBasename) 951 { 952 memmove(&pszDst[offDstDot + 1], &pszDst[offDstDot], cchDst + 1 - offDstDot); 953 cchDst++; 954 offDstDot++; 955 } 956 cchInserted = cchOrd; 957 } 958 959 /* Insert the new infix and try again. */ 960 memcpy(&pszDst[offDstDot - cchOrd], szOrd, cchOrd); 961 if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst)) 962 { 963 *pcchDst = cchDst; 964 return VINF_SUCCESS; 965 } 966 } 967 AssertFailed(); 968 return VERR_DUPLICATE; 969 } 970 971 972 /** 973 * Normalizes a name for the specified name space. 974 * 975 * @returns IPRT status code. 976 * @param pThis The ISO maker instance. 977 * @param pParent The parent directory. NULL if root. 978 * @param pchSrc The specified name to normalize (not necessarily zero 979 * terminated). 980 * @param cchSrc The length of the specified name. 981 * @param fNamespace The namespace rules to normalize it according to. 982 * @param fIsDir Indicates whether it's a directory or file (like). 983 * @param pszDst The output buffer. Must be at least 32 bytes. 984 * @param cbDst The size of the output buffer. 985 * @param pcchDst Where to return the length of the returned string (i.e. 986 * not counting the terminator). 987 */ 988 static int rtFsIsoMakerNormalizeNameForNamespace(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME pParent, 989 const char *pchSrc, size_t cchSrc, uint32_t fNamespace, bool fIsDir, 990 char *pszDst, size_t cbDst, size_t *pcchDst) 991 { 992 if (cchSrc > 0) 722 993 { 723 994 /* 724 995 * Check that the object doesn't already exist. 725 996 */ 726 AssertReturn(!rtFsIsoMakerFind ObjInDirBySpec(pParent, pszSrc, cchSrc), VERR_ALREADY_EXISTS);997 AssertReturn(!rtFsIsoMakerFindEntryInDirBySpec(pParent, pchSrc, cchSrc), VERR_ALREADY_EXISTS); 727 998 switch (fNamespace) 728 999 { 729 1000 /* 730 * This one is fun. :)1001 * This one is a lot of work, so separate function. 731 1002 */ 732 1003 case RTFSISOMAKERNAMESPACE_ISO_9660: 733 { 734 AssertReturn(cbDst > ISO9660_MAX_NAME_LEN, VERR_INTERNAL_ERROR_3); 735 736 /* Skip leading dots. */ 737 while (*pszSrc == '.') 738 pszSrc++, cchSrc--; 739 if (!cchSrc) 740 { 741 pszSrc = "DOTS"; 742 cchSrc = 4; 743 } 744 745 /* 746 * Produce a first name. 747 */ 748 size_t cchDst; 749 size_t offDstDot; 750 if (fIsDir) 751 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8, 752 pszSrc, cchSrc); 753 else 754 { 755 /* Look for the last dot and try preserve the extension when doing the conversion. */ 756 size_t offLastDot = cchSrc; 757 for (size_t off = 0; off < cchSrc; off++) 758 if (pszSrc[off] == '.') 759 offLastDot = off; 760 761 if (offLastDot == cchSrc) 762 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8, 763 pszSrc, cchSrc); 764 else 765 { 766 const char * const pszSrcExt = &pszSrc[offLastDot + 1]; 767 size_t const cchSrcExt = cchSrc - offLastDot - 1; 768 if (pThis->uIsoLevel < 2) 769 { 770 cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, 8, pszSrc, cchSrc); 771 offDstDot = cchDst; 772 pszDst[cchDst++] = '.'; 773 cchDst += rtFsIsoMakerCopyIso9660Name(&pszDst[cchDst], 3, pszSrcExt, cchSrcExt); 774 } 775 else 776 { 777 size_t cchDstExt = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2, pszSrcExt, cchSrcExt); 778 if (cchDstExt > 0) 779 { 780 size_t cchBasename = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2, 781 pszSrc, offLastDot); 782 if (cchBasename + 1 + cchDstExt <= ISO9660_MAX_NAME_LEN) 783 cchDst = cchBasename; 784 else 785 cchDst = ISO9660_MAX_NAME_LEN - 1 - RT_MIN(cchDstExt, 4); 786 offDstDot = cchDst; 787 pszDst[cchDst++] = '.'; 788 cchDst += rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 1 - cchDst, 789 pszSrcExt, cchSrcExt); 790 } 791 else 792 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN, pszSrc, cchSrc); 793 } 794 } 795 } 796 797 /* 798 * Unique name? 799 */ 800 if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst)) 801 { 802 *pcchDst = cchDst; 803 return VINF_SUCCESS; 804 } 805 806 /* 807 * Mangle the name till we've got a unique one. 808 */ 809 size_t const cchMaxBasename = (pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8) - (cchDst - offDstDot); 810 size_t cchInserted = 0; 811 for (uint32_t i = 0; i < _32K; i++) 812 { 813 /* Add a numberic infix. */ 814 char szOrd[64]; 815 size_t cchOrd = RTStrFormatU32(szOrd, sizeof(szOrd), i + 1, 10, -1, -1, 0 /*fFlags*/); 816 Assert((ssize_t)cchOrd > 0); 817 818 /* Do we need to shuffle the suffix? */ 819 if (cchOrd > cchInserted) 820 { 821 if (offDstDot < cchMaxBasename) 822 { 823 memmove(&pszDst[offDstDot + 1], &pszDst[offDstDot], cchDst + 1 - offDstDot); 824 cchDst++; 825 offDstDot++; 826 } 827 cchInserted = cchOrd; 828 } 829 830 /* Insert the new infix and try again. */ 831 memcpy(&pszDst[offDstDot - cchOrd], szOrd, cchOrd); 832 if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst)) 833 { 834 *pcchDst = cchDst; 835 return VINF_SUCCESS; 836 } 837 } 838 AssertFailed(); 839 return VERR_DUPLICATE; 840 } 1004 return rtFsIsoMakerNormalizeNameForPrimaryIso9660(pThis, pParent, pchSrc, cchSrc, fIsDir, pszDst, cbDst, pcchDst); 841 1005 842 1006 /* … … 845 1009 case RTFSISOMAKERNAMESPACE_JOLIET: 846 1010 { 1011 /** @todo Joliet name limit. */ 847 1012 AssertReturn(cbDst > cchSrc, VERR_BUFFER_OVERFLOW); 848 memcpy(pszDst, p szSrc, cchSrc);1013 memcpy(pszDst, pchSrc, cchSrc); 849 1014 pszDst[cchSrc] = '\0'; 850 1015 *pcchDst = cchSrc; … … 873 1038 874 1039 875 static int rtFsIsoMakerPathToParent(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME *ppRoot, uint32_t fNamespace, const char *pszPath, 876 PRTFSISOMAKERNAME *ppParent, const char **ppszEntry) 877 { 878 RT_NOREF(pThis, ppRoot, fNamespace, pszPath, ppParent, ppszEntry); 879 return -1; 880 } 881 882 883 static int rtFsIsoMakerObjSetPathInOne(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pEntry, uint32_t fNamespace, const char *pszPath, 884 PRTFSISOMAKERNAME *ppRoot, PRTFSISOMAKERNAME *ppName) 1040 /** 1041 * Sets the name of an object in a namespace. 1042 * 1043 * The object cannot currently have a name in that namespace. 1044 * 1045 * @returns IPRT status code. 1046 * @param pThis The ISO maker instance. 1047 * @param pNamespace The namespace. 1048 * @param pObj The object to name. 1049 * @param ppName The pointer to the object's namespace member. 1050 * @param pParent The parent namespace entry 1051 * @param pchSpec The specified name (not necessarily terminated). 1052 * @param cchSpec The specified name length. 1053 * @param ppNewName Where to return the name entry. Optional. 1054 */ 1055 static int rtFsIsoMakerObjSetName(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace, PRTFSISOMAKEROBJ pObj, 1056 PPRTFSISOMAKERNAME ppName, PRTFSISOMAKERNAME pParent, const char *pchSpec, size_t cchSpec, 1057 PPRTFSISOMAKERNAME ppNewName) 1058 { 1059 Assert(cchSpec < _32K); 1060 1061 /* 1062 * To avoid need to revert anything, make sure papChildren in the parent is 1063 * large enough. If root object, make sure we haven't got a root already. 1064 */ 1065 PPRTFSISOMAKERNAME ppRoot; 1066 if (pParent) 1067 { 1068 AssertReturn(pParent->pDir, VERR_INTERNAL_ERROR_5); 1069 uint32_t cChildren = pParent->pDir->cChildren; 1070 if (cChildren & 31) 1071 { /* likely */ } 1072 else 1073 { 1074 AssertReturn(cChildren < RTFSISOMAKER_MAX_OBJECTS_PER_DIR, VERR_TOO_MUCH_DATA); 1075 void *pvNew = RTMemRealloc(pParent->pDir->papChildren, (cChildren + 32) * sizeof(pParent->pDir->papChildren[0])); 1076 AssertReturn(pvNew, VERR_NO_MEMORY); 1077 pParent->pDir->papChildren = (PPRTFSISOMAKERNAME)pvNew; 1078 } 1079 ppRoot = NULL; 1080 } 1081 else 1082 { 1083 ppRoot = rtFsIsoMakerGetRootForNamespace(pThis, fNamespace); 1084 AssertReturn(*ppRoot, VERR_INTERNAL_ERROR_5); 1085 } 1086 1087 /* 1088 * Normalize the name for this namespace. 1089 */ 1090 size_t cchName; 1091 char szName[RTFSISOMAKER_MAX_NAME_BUF]; 1092 int rc = rtFsIsoMakerNormalizeNameForNamespace(pThis, pParent, pchSpec, cchSpec, fNamespace, 1093 pObj->enmType == RTFSISOMAKEROBJTYPE_DIR, 1094 szName, sizeof(szName), &cchName); 1095 if (RT_SUCCESS(rc)) 1096 { 1097 size_t cbName = sizeof(RTFSISOMAKERNAME) 1098 + cchName + 1 1099 + cchSpec + 1; 1100 if (pObj->enmType == RTFSISOMAKEROBJTYPE_DIR) 1101 cbName = RT_ALIGN_Z(cbName, 8) + sizeof(RTFSISOMAKERNAMEDIR); 1102 PRTFSISOMAKERNAME pName = (PRTFSISOMAKERNAME)RTMemAllocZ(cbName); 1103 if (pName) 1104 { 1105 pName->pObj = pObj; 1106 pName->pParent = pParent; 1107 pName->cchName = (uint16_t)cchName; 1108 1109 char *pszDst = &pName->szName[cchName + 1]; 1110 memcpy(pszDst, pchSpec, cchSpec); 1111 pszDst[cchSpec] = '\0'; 1112 pName->pszSpecNm = pszDst; 1113 pName->pszRockRidgeNm = pszDst; 1114 pName->pszTransNm = pszDst; 1115 pName->cchSpecNm = (uint16_t)cchSpec; 1116 pName->cchRockRidgeNm = 0; 1117 pName->cchTransNm = 0; 1118 pName->uDepth = pParent->uDepth + 1; 1119 pName->fRockRidgeNmAlloced = false; 1120 pName->fTransNmAlloced = false; 1121 1122 memcpy(pName->szName, szName, cchName); 1123 pName->szName[cchName] = '\0'; 1124 1125 if (pObj->enmType != RTFSISOMAKEROBJTYPE_DIR) 1126 pName->pDir = NULL; 1127 else 1128 { 1129 size_t offDir = RT_UOFFSETOF(RTFSISOMAKERNAME, szName) + cchName + 1 + cchSpec + 1; 1130 offDir = RT_ALIGN_Z(offDir, 8); 1131 PRTFSISOMAKERNAMEDIR pDir = (PRTFSISOMAKERNAMEDIR)((uintptr_t)pName + offDir); 1132 pDir->offDir = UINT64_MAX; 1133 pDir->cbDir = 0; 1134 pDir->cChildren = 0; 1135 pDir->papChildren = NULL; 1136 pDir->pTransTblFile = NULL; 1137 /** @todo TRANS.TBL files. */ 1138 1139 pName->pDir = pDir; 1140 } 1141 1142 /* 1143 * Do the linking and stats. 1144 */ 1145 if (pParent) 1146 pParent->pDir->papChildren[pParent->pDir->cChildren++] = pName; 1147 else 1148 *ppRoot = pName; 1149 *ppName = pName; 1150 pThis->cNames++; 1151 1152 /* 1153 * Done. 1154 */ 1155 if (ppNewName) 1156 *ppNewName = pName; 1157 return VINF_SUCCESS; 1158 } 1159 } 1160 return rc; 1161 } 1162 1163 1164 static int rtFsIsoMakerPathToParent(PRTFSISOMAKERINT pThis, PPRTFSISOMAKERNAME ppRoot, uint32_t fNamespace, const char *pszPath, 1165 PPRTFSISOMAKERNAME ppParent, const char **ppszEntry, size_t *pcchEntry) 1166 { 1167 int rc; 1168 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INTERNAL_ERROR_4); 1169 1170 /* 1171 * Deal with the special case of the root. 1172 */ 1173 while (RTPATH_IS_SLASH(*pszPath)) 1174 pszPath++; 1175 AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4); 1176 1177 PRTFSISOMAKERNAME pParent = *ppRoot; 1178 if (!pParent) 1179 { 1180 PRTFSISOMAKERDIR pDir; 1181 if (pThis->cObjects == 0) 1182 { 1183 rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pDir); 1184 AssertRCReturn(rc, rc); 1185 } 1186 else 1187 { 1188 pDir = RTListGetFirst(&pThis->ObjectHead, RTFSISOMAKERDIR, Core.Entry); 1189 #ifdef RT_STRICT 1190 Assert(pDir); 1191 Assert(pDir->Core.idxObj == 0); 1192 Assert(pDir->Core.enmType == RTFSISOMAKEROBJTYPE_DIR); 1193 Assert(*rtFsIsoMakerObjGetNameForNamespace(&pDir->Core, fNamespace) == NULL); 1194 #endif 1195 } 1196 1197 rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pDir->Core, rtFsIsoMakerObjGetNameForNamespace(&pDir->Core, fNamespace), 1198 NULL /*pParent*/, "", 0, &pParent); 1199 AssertRCReturn(rc, rc); 1200 AssertReturn(*ppRoot, VERR_INTERNAL_ERROR_4); 1201 pParent = *ppRoot; 1202 } 1203 1204 /* 1205 * Now, do the rest of the path. 1206 */ 1207 for (;;) 1208 { 1209 /* 1210 * Find the end of the component and see if its the final one or not. 1211 */ 1212 char ch; 1213 size_t cchComponent = 0; 1214 while ((ch = pszPath[cchComponent]) != '\0' && RTPATH_IS_SLASH(ch)) 1215 cchComponent++; 1216 AssertReturn(cchComponent > 0, VERR_INTERNAL_ERROR_4); 1217 1218 size_t offNext = cchComponent; 1219 while (RTPATH_IS_SLASH(ch)) 1220 ch = pszPath[offNext++]; 1221 1222 if (ch == '\0') 1223 { 1224 /* 1225 * Final component. Make sure it is not dot or dot-dot before returning. 1226 */ 1227 AssertReturn( pszPath[0] != '.' 1228 || cchComponent > 2 1229 || ( cchComponent == 2 1230 && pszPath[1] != '.'), 1231 VERR_INVALID_NAME); 1232 1233 *ppParent = pParent; 1234 *ppszEntry = pszPath; 1235 *pcchEntry = cchComponent; 1236 return VINF_SUCCESS; 1237 } 1238 1239 /* 1240 * Deal with dot and dot-dot. 1241 */ 1242 if (cchComponent == 1 && pszPath[0] == '.') 1243 { /* nothing to do */ } 1244 else if (cchComponent == 2 && pszPath[0] == '.' && pszPath[1] == '.') 1245 { 1246 if (pParent->pParent) 1247 pParent = pParent->pParent; 1248 } 1249 else 1250 { 1251 /* 1252 * Look it up. 1253 */ 1254 PRTFSISOMAKERNAME pChild = rtFsIsoMakerFindEntryInDirBySpec(pParent, pszPath, cchComponent); 1255 if (pChild) 1256 pParent = pChild; 1257 else 1258 { 1259 /* Try see if we've got a directory with the same spec name in a different namespace. 1260 (We don't want to waste heap by creating a directory instance per namespace.) */ 1261 PRTFSISOMAKERDIR pChildObj = rtFsIsoMakerFindSubdirBySpec((PRTFSISOMAKERDIR)pParent->pObj, 1262 pszPath, cchComponent, fNamespace); 1263 if (pChildObj) 1264 { 1265 PPRTFSISOMAKERNAME ppChildName = rtFsIsoMakerObjGetNameForNamespace(&pChildObj->Core, fNamespace); 1266 if (!*ppChildName) 1267 { 1268 rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pChildObj->Core, ppChildName, pParent, 1269 pszPath, cchComponent, &pChild); 1270 if (RT_FAILURE(rc)) 1271 return rc; 1272 AssertReturn(pChild != NULL, VERR_INTERNAL_ERROR_4); 1273 } 1274 } 1275 /* If we didn't have luck in other namespaces, create a new directory. */ 1276 if (!pChild) 1277 { 1278 rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pChildObj); 1279 if (RT_SUCCESS(rc)) 1280 rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pChildObj->Core, 1281 rtFsIsoMakerObjGetNameForNamespace(&pChildObj->Core, fNamespace), 1282 pParent, pszPath, cchComponent, &pChild); 1283 if (RT_FAILURE(rc)) 1284 return rc; 1285 AssertReturn(pChild != NULL, VERR_INTERNAL_ERROR_4); 1286 } 1287 } 1288 } 1289 1290 /* 1291 * Skip ahead in the path. 1292 */ 1293 pszPath += offNext; 1294 } 1295 } 1296 1297 1298 /** 1299 * Worker for RTFsIsoMakerObjSetPath that operates on a single namespace. 1300 * 1301 * @returns IPRT status code. 1302 * @param pThis The ISO maker instance. 1303 * @param pObj The filesystem object to name. 1304 * @param fNamespace The namespace to name it in. 1305 * @param pszPath The path to the entry in the namespace. 1306 * @param ppRoot The namespace root. 1307 * @param ppName The namespace name member in @a paEntry. 1308 */ 1309 static int rtFsIsoMakerObjSetPathInOne(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj, uint32_t fNamespace, const char *pszPath, 1310 PPRTFSISOMAKERNAME ppRoot, PPRTFSISOMAKERNAME ppName) 885 1311 { 886 1312 AssertReturn(!*ppName, VERR_WRONG_ORDER); 1313 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INTERNAL_ERROR_5); 887 1314 888 1315 /* … … 892 1319 PRTFSISOMAKERNAME pParent; 893 1320 const char *pszEntry; 1321 size_t cchEntry; 894 1322 int rc; 895 1323 if (pszPath[1] != '\0') 896 rc = rtFsIsoMakerPathToParent(pThis, ppRoot, fNamespace, pszPath, &pParent, &pszEntry );1324 rc = rtFsIsoMakerPathToParent(pThis, ppRoot, fNamespace, pszPath, &pParent, &pszEntry, &cchEntry); 897 1325 else 898 1326 { … … 900 1328 * Special case for the root directory. 901 1329 */ 1330 Assert(pObj->enmType == RTFSISOMAKEROBJTYPE_DIR); 902 1331 AssertReturn(!*ppRoot, VERR_WRONG_ORDER); 903 pszEntry = &pszPath[1]; 904 pParent = NULL; 905 rc = VINF_SUCCESS; 906 Assert(pEntry->enmType == RTFSISOMAKEROBJTYPE_DIR); 907 } 1332 pszEntry = "/"; 1333 cchEntry = 0; 1334 pParent = NULL; 1335 rc = VINF_SUCCESS; 1336 } 1337 1338 /* 1339 * Do the job on the final path component. 1340 */ 908 1341 if (RT_SUCCESS(rc)) 909 1342 { 910 /* 911 * . 912 */ 913 //size_t cchEntry = strlen(pszEntry); 914 size_t cchName; 915 char szName[RTFSISOMAKER_MAX_NAME_BUF]; 916 rc = rtFsIsoMakerNormalizeNameForNamespace(pThis, pParent, pszEntry, fNamespace, 917 pEntry->enmType == RTFSISOMAKEROBJTYPE_DIR, szName, sizeof(szName), &cchName); 918 if (RT_SUCCESS(rc)) 919 { 920 921 //PRTFSISOMAKERNAME pNameEntry = RTMemAllocZ() 922 } 923 } 924 1343 AssertReturn(!RTPATH_IS_SLASH(pszEntry[cchEntry]) || pObj->enmType == RTFSISOMAKEROBJTYPE_DIR, 1344 VERR_NOT_A_DIRECTORY); 1345 rc = rtFsIsoMakerObjSetName(pThis, pNamespace, pObj, ppName, pParent, pszEntry, cchEntry, NULL); 1346 } 925 1347 return rc; 1348 } 1349 1350 1351 1352 /* 1353 * 1354 * Object level config 1355 * Object level config 1356 * Object level config 1357 * 1358 */ 1359 1360 1361 /** 1362 * Translates an object index number to an object pointer, slow path. 1363 * 1364 * @returns Pointer to object, NULL if not found. 1365 * @param pThis The ISO maker instance. 1366 * @param idxObj The object index too resolve. 1367 */ 1368 DECL_NO_INLINE(static, PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObjSlow(PRTFSISOMAKERINT pThis, uint32_t idxObj) 1369 { 1370 PRTFSISOMAKEROBJ pObj; 1371 RTListForEachReverse(&pThis->ObjectHead, pObj, RTFSISOMAKEROBJ, Entry) 1372 { 1373 if (pObj->idxObj == idxObj) 1374 return pObj; 1375 } 1376 return NULL; 1377 } 1378 1379 1380 /** 1381 * Translates an object index number to an object pointer. 1382 * 1383 * @returns Pointer to object, NULL if not found. 1384 * @param pThis The ISO maker instance. 1385 * @param idxObj The object index too resolve. 1386 */ 1387 DECLINLINE(PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj) 1388 { 1389 PRTFSISOMAKEROBJ pObj = RTListGetLast(&pThis->ObjectHead, RTFSISOMAKEROBJ, Entry); 1390 if (!pObj || RT_LIKELY(pObj->idxObj == idxObj)) 1391 return pObj; 1392 return rtFsIsoMakerIndexToObjSlow(pThis, idxObj); 926 1393 } 927 1394 … … 959 1426 */ 960 1427 int rc = VINF_SUCCESS; 961 for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsI osNamespaces); i++)962 if (fNamespaces & g_aRTFsI osNamespaces[i].fNamespace)963 { 964 int rc2 = rtFsIsoMakerObjSetPathInOne(pThis, pObj, g_aRTFsI osNamespaces[i].fNamespace, pszPath,965 (P RTFSISOMAKERNAME *)((uintptr_t)pThis + g_aRTFsIosNamespaces[i].offRoot),966 (P RTFSISOMAKERNAME *)((uintptr_t)pObj + g_aRTFsIosNamespaces[i].offName));1428 for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIsoNamespaces); i++) 1429 if (fNamespaces & g_aRTFsIsoNamespaces[i].fNamespace) 1430 { 1431 int rc2 = rtFsIsoMakerObjSetPathInOne(pThis, pObj, g_aRTFsIsoNamespaces[i].fNamespace, pszPath, 1432 (PPRTFSISOMAKERNAME)((uintptr_t)pThis + g_aRTFsIsoNamespaces[i].offRoot), 1433 (PPRTFSISOMAKERNAME)((uintptr_t)pObj + g_aRTFsIsoNamespaces[i].offName)); 967 1434 if (RT_SUCCESS(rc2) || RT_FAILURE(rc)) 968 1435 continue; … … 997 1464 998 1465 /** 1466 * Internal function for adding an unnamed directory. 1467 * 1468 * @returns IPRT status code. 1469 * @param pThis The ISO make instance. 1470 * @param ppDir Where to return the directory. 1471 */ 1472 static int rtFsIsoMakerAddUnnamedDirWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKERDIR *ppDir) 1473 { 1474 PRTFSISOMAKERDIR pDir = (PRTFSISOMAKERDIR)RTMemAllocZ(sizeof(*pDir)); 1475 AssertReturn(pDir, VERR_NO_MEMORY); 1476 int rc = rtFsIsoMakerInitCommonObj(pThis, &pDir->Core, RTFSISOMAKEROBJTYPE_DIR); 1477 if (RT_SUCCESS(rc)) 1478 { 1479 *ppDir = pDir; 1480 return VINF_SUCCESS; 1481 } 1482 RTMemFree(pDir); 1483 return rc; 1484 1485 } 1486 1487 1488 /** 999 1489 * Adds an unnamed directory to the image. 1000 1490 * … … 1013 1503 AssertPtrReturn(pidxObj, VERR_INVALID_POINTER); 1014 1504 1015 PRTFSISOMAKERDIR pDir = (PRTFSISOMAKERDIR)RTMemAllocZ(sizeof(*pDir)); 1016 AssertReturn(pDir, VERR_NO_MEMORY); 1017 int rc = rtFsIsoMakerInitCommonObj(pThis, &pDir->Core, RTFSISOMAKEROBJTYPE_DIR); 1018 if (RT_SUCCESS(rc)) 1019 { 1020 *pidxObj = pDir->Core.idxObj; 1021 return VINF_SUCCESS; 1022 } 1023 RTMemFree(pDir); 1505 PRTFSISOMAKERDIR pDir; 1506 int rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pDir); 1507 *pidxObj = RT_SUCCESS(rc) ? pDir->Core.idxObj : UINT32_MAX; 1024 1508 return rc; 1025 1509 }
Note:
See TracChangeset
for help on using the changeset viewer.