- Timestamp:
- Jun 6, 2017 4:49:24 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
-
include/iprt/formats/iso9660.h (modified) (1 diff)
-
src/VBox/Runtime/common/fs/isomaker.cpp (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/formats/iso9660.h
r66735 r67278 40 40 /** The (default) logical sectors size of ISO 9660. */ 41 41 #define ISO9660_SECTOR_SIZE 2048 42 /** Maximum filename length (level 2 & 3). */ 43 #define ISO9660_MAX_NAME_LEN 30 44 42 45 43 46 /** Accessor for ISO9660U16 and ISO9660U32 that retrievs the member value for -
trunk/src/VBox/Runtime/common/fs/isomaker.cpp
r67271 r67278 36 36 #include <iprt/assert.h> 37 37 #include <iprt/err.h> 38 #include <iprt/ctype.h> 38 39 #include <iprt/file.h> 39 40 #include <iprt/list.h> 40 41 #include <iprt/log.h> 41 42 #include <iprt/mem.h> 43 #include <iprt/path.h> 42 44 #include <iprt/string.h> 43 45 #include <iprt/vfs.h> … … 60 62 /** Maximum number of objects. */ 61 63 #define RTFSISOMAKER_MAX_OBJECTS _16M 64 /** UTF-8 name buffer. */ 65 #define RTFSISOMAKER_MAX_NAME_BUF 768 66 67 /** Tests if @a a_ch is in the set of d-characters. */ 68 #define RTFSISOMAKER_IS_IN_D_CHARS(a_ch) (RT_C_IS_UPPER(a_ch) || RT_C_IS_DIGIT(a_ch) || (a_ch) == '_') 69 70 /** Tests if @a a_ch is in the set of d-characters when uppercased. */ 71 #define RTFSISOMAKER_IS_UPPER_IN_D_CHARS(a_ch) (RT_C_IS_ALNUM(a_ch) || (a_ch) == '_') 72 62 73 63 74 … … 142 153 /** Alternative TRANS.TBL name. */ 143 154 char *pszTransNm; 155 /** Length of pszSpecNm. */ 156 uint16_t cchSpecNm; 144 157 /** Length of pszRockRidgeNm. */ 145 158 uint16_t cchRockRidgeNm; … … 287 300 /** The list of objects (RTFSISOMAKEROBJ). */ 288 301 RTLISTANCHOR ObjectHead; 289 290 /** The total image size. */ 302 /** Number of objects in the image (ObjectHead). 303 * This is used to number them, i.e. create RTFSISOMAKEROBJ::idxObj. */ 304 uint32_t cObjects; 305 306 /** Amount of file data. */ 307 uint64_t cbData; 308 /** The total image size. 309 * @todo not sure if this is desirable. */ 291 310 uint64_t cbTotal; 292 311 … … 554 573 555 574 556 DECL_NO_INLINE(static, PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj) 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) 557 583 { 558 584 PRTFSISOMAKEROBJ pObj; … … 566 592 567 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 */ 568 601 DECLINLINE(PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj) 569 602 { … … 571 604 if (!pObj || RT_LIKELY(pObj->idxObj == idxObj)) 572 605 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 606 return rtFsIsoMakerIndexToObjSlow(pThis, idxObj); 607 } 608 609 610 /** 611 * Locates a child object by its namespace name. 612 * 613 * @returns Pointer to the child if found, NULL if not. 614 * @param pDirObj The directory object to search. 615 * @param pszEntry The (namespace) entry name. 616 * @param cchEntry The length of the name. 617 */ 618 static PRTFSISOMAKERNAME rtFsIsoMakerFindObjInDir(PRTFSISOMAKERNAME pDirObj, const char *pszEntry, size_t cchEntry) 619 { 620 if (pDirObj) 621 { 622 PRTFSISOMAKERNAMEDIR pDir = pDirObj->pDir; 623 AssertReturn(pDir, NULL); 624 625 uint32_t i = pDir->cChildren; 626 while (i-- > 0) 627 { 628 PRTFSISOMAKERNAME pChild = pDir->papChildren[i]; 629 if ( pChild->cchName == cchEntry 630 && RTStrNICmp(pChild->szName, pszEntry, cchEntry) == 0) 631 return pChild; 632 } 633 } 634 return NULL; 635 } 636 637 638 /** 639 * Locates a child object by its specified name. 640 * 641 * @returns Pointer to the child if found, NULL if not. 642 * @param pDirObj The directory object to search. 643 * @param pszEntry The (specified) entry name. 644 * @param cchEntry The length of the name. 645 */ 646 static PRTFSISOMAKERNAME rtFsIsoMakerFindObjInDirBySpec(PRTFSISOMAKERNAME pDirObj, const char *pszEntry, size_t cchEntry) 647 { 648 if (pDirObj) 649 { 650 PRTFSISOMAKERNAMEDIR pDir = pDirObj->pDir; 651 AssertReturn(pDir, NULL); 652 653 uint32_t i = pDir->cChildren; 654 while (i-- > 0) 655 { 656 PRTFSISOMAKERNAME pChild = pDir->papChildren[i]; 657 if ( pChild->cchSpecNm == cchEntry 658 && RTStrNICmp(pChild->pszSpecNm, pszEntry, cchEntry) == 0) 659 return pChild; 660 } 661 } 662 return NULL; 663 } 664 665 /** 666 * Copy and convert a name to valid ISO-9660 (d-characters only). 667 * 668 * Worker for rtFsIsoMakerNormalizeNameForNamespace. ASSUMES it deals with 669 * dots. 670 * 671 * @returns Length of the resulting string. 672 * @param pszDst The output buffer. 673 * @param cchDstMax The maximum number of (d-chars) to put in the 674 * output buffer . 675 * @param pszSrc The UTF-8 source string. 676 * @param cchSrc The maximum number of chars to copy from the 677 * source string. 678 */ 679 static size_t rtFsIsoMakerCopyIso9660Name(char *pszDst, size_t cchDstMax, const char *pszSrc, size_t cchSrc) 680 { 681 const char *pszSrcIn = pszSrc; 682 size_t offDst = 0; 683 while ((size_t)(pszSrc - pszSrcIn) < cchSrc) 684 { 685 RTUNICP uc; 686 int rc = RTStrGetCpEx(&pszSrc, &uc); 687 if (RT_SUCCESS(rc)) 688 { 689 if ( uc < 128 690 && RTFSISOMAKER_IS_UPPER_IN_D_CHARS((char)uc)) 691 { 692 pszDst[offDst++] = RT_C_TO_UPPER((char)uc); 693 if (offDst >= cchDstMax) 694 break; 695 } 696 } 697 } 698 pszDst[offDst] = '\0'; 699 return offDst; 700 } 701 702 703 /** 704 * Normalizes a name for the specified name space. 705 * 706 * @returns IPRT status code. 707 * @param pThis The ISO maker instance. 708 * @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. 711 * @param fIsDir Indicates whether it's a directory or file (like). 712 * @param pszDst The output buffer. Must be at least 32 bytes. 713 * @param cbDst The size of the output buffer. 714 * @param pcchDst Where to return the length of the returned string (i.e. 715 * not counting the terminator). 716 */ 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) 722 { 723 /* 724 * Check that the object doesn't already exist. 725 */ 726 AssertReturn(!rtFsIsoMakerFindObjInDirBySpec(pParent, pszSrc, cchSrc), VERR_ALREADY_EXISTS); 727 switch (fNamespace) 728 { 729 /* 730 * This one is fun. :) 731 */ 732 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 } 841 842 /* 843 * At the moment we don't give darn about UCS-2 limitations here... 844 */ 845 case RTFSISOMAKERNAMESPACE_JOLIET: 846 { 847 AssertReturn(cbDst > cchSrc, VERR_BUFFER_OVERFLOW); 848 memcpy(pszDst, pszSrc, cchSrc); 849 pszDst[cchSrc] = '\0'; 850 *pcchDst = cchSrc; 851 return VINF_SUCCESS; 852 } 853 854 case RTFSISOMAKERNAMESPACE_UDF: 855 case RTFSISOMAKERNAMESPACE_HFS: 856 AssertFailedReturn(VERR_NOT_IMPLEMENTED); 857 858 default: 859 AssertFailedReturn(VERR_INTERNAL_ERROR_2); 860 } 861 } 862 else 863 { 864 /* 865 * Root special case. 866 */ 867 AssertReturn(pParent, VERR_INTERNAL_ERROR_3); 868 *pszDst = '\0'; 869 *pcchDst = 0; 870 return VINF_SUCCESS; 871 } 872 } 873 874 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) 885 { 886 AssertReturn(!*ppName, VERR_WRONG_ORDER); 887 888 /* 889 * Figure out where the parent is. 890 * This will create missing parent name space entries and directory nodes. 891 */ 892 PRTFSISOMAKERNAME pParent; 893 const char *pszEntry; 894 int rc; 895 if (pszPath[1] != '\0') 896 rc = rtFsIsoMakerPathToParent(pThis, ppRoot, fNamespace, pszPath, &pParent, &pszEntry); 897 else 898 { 899 /* 900 * Special case for the root directory. 901 */ 902 AssertReturn(!*ppRoot, VERR_WRONG_ORDER); 903 pszEntry = &pszPath[1]; 904 pParent = NULL; 905 rc = VINF_SUCCESS; 906 Assert(pEntry->enmType == RTFSISOMAKEROBJTYPE_DIR); 907 } 908 if (RT_SUCCESS(rc)) 909 { 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 925 return rc; 581 926 } 582 927 … … 606 951 AssertReturn(!(fNamespaces & ~RTFSISOMAKERNAMESPACE_VALID_MASK), VERR_INVALID_FLAGS); 607 952 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 608 AssertReturn(RTPATH_IS_SLASH( pszPath == '/'), VERR_INVALID_NAME);953 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INVALID_NAME); 609 954 PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj); 610 955 AssertReturn(pObj, VERR_OUT_OF_RANGE); … … 615 960 int rc = VINF_SUCCESS; 616 961 for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIosNamespaces); i++) 617 if (fNamespace & g_aRTFsIosNamespaces[i].fNamespace)962 if (fNamespaces & g_aRTFsIosNamespaces[i].fNamespace) 618 963 { 619 int rc2 = rt TFsIsoMakerObjSetPathInOne(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));964 int rc2 = rtFsIsoMakerObjSetPathInOne(pThis, pObj, g_aRTFsIosNamespaces[i].fNamespace, pszPath, 965 (PRTFSISOMAKERNAME *)((uintptr_t)pThis + g_aRTFsIosNamespaces[i].offRoot), 966 (PRTFSISOMAKERNAME *)((uintptr_t)pObj + g_aRTFsIosNamespaces[i].offName)); 622 967 if (RT_SUCCESS(rc2) || RT_FAILURE(rc)) 623 968 continue; … … 637 982 * @param enmType The object type. 638 983 */ 639 static voidrtFsIsoMakerInitCommonObj(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj, RTFSISOMAKEROBJTYPE enmType)984 static int rtFsIsoMakerInitCommonObj(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj, RTFSISOMAKEROBJTYPE enmType) 640 985 { 641 986 AssertReturn(pThis->cObjects < RTFSISOMAKER_MAX_OBJECTS, VERR_OUT_OF_RANGE); … … 670 1015 PRTFSISOMAKERDIR pDir = (PRTFSISOMAKERDIR)RTMemAllocZ(sizeof(*pDir)); 671 1016 AssertReturn(pDir, VERR_NO_MEMORY); 672 int rc = rtFsIsoMakerInitCommonObj( &pDir->Core, RTFSISOMAKEROBJTYPE_DIR);1017 int rc = rtFsIsoMakerInitCommonObj(pThis, &pDir->Core, RTFSISOMAKEROBJTYPE_DIR); 673 1018 if (RT_SUCCESS(rc)) 674 1019 { 675 *pidxObj = p Obj->idxObj;1020 *pidxObj = pDir->Core.idxObj; 676 1021 return VINF_SUCCESS; 677 1022 } … … 697 1042 RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis); 698 1043 AssertPtrReturn(pszDir, VERR_INVALID_POINTER); 699 AssertReturn(RTPATH_IS_SLASH( pszPath == '/'), VERR_INVALID_NAME);1044 AssertReturn(RTPATH_IS_SLASH(*pszDir), VERR_INVALID_NAME); 700 1045 701 1046 uint32_t idxObj; … … 703 1048 if (RT_SUCCESS(rc)) 704 1049 { 705 rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKERNAMESPACE_ALL );1050 rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKERNAMESPACE_ALL, pszDir); 706 1051 if (RT_SUCCESS(rc)) 707 1052 {
Note:
See TracChangeset
for help on using the changeset viewer.

